test unitaires - refactoring - clean code
TRANSCRIPT
I am Hadrien Blanc
Responsable pédagogique Epitech
@hadrienblanc
www.linkedin.com/in/hadrienblanc
HELLO!
Ariane 5 1/2
Ariane 5 cas "funny":▸Explosion après 40
secondes▸10 ans et 7 milliards de $▸Conversion d'un float 64 bit
vers un entier non signé 16 bit
Ariane 5 2/2
Principale explication:"no test was performed to verify that the Inertial Reference System would behave correctly when being subjected to the count-down and flight time sequence and the trajectory of Ariane 5."▸ ARIANE 5 Flight 501 Failure Report by the Inquiry Board
The Chairman of the Board : Prof. J. L. LIONS
“Software must be soft: it has to be easy to change because it will change despite our misguided efforts otherwise.”
The pragmatic Programmers
Lisibilité du code
Pistes sur la lisibilité du code:
▸ Style d’Indentation cohérent▸ Éviter les commentaires évidents ▸ Nommage des variables et fonctions
cohérents▸ DRY - Don’t Repeat Yourself▸ Niveaux multiples de parenthèses▸ Taille limite de la ligne▸ Organisation des dossiers ▸ KISS ▸ Utilisation de Design pattern
Style d'indentation cohérent 1/2
while (x == y) {
something();
somethingelse();
}
K&R and variants:
1TBS, Stroustrup, Linux kernel, BSD KNF
while (x == y)
{
something();
somethingelse();
}
Allman style (Bsd)
while (x == y)
{
something();
somethingelse();
}
Gnu
while (x == y)
{
something();
somethingelse();
}
Whitesmiths
Style d'indentation cohérent 2/2
while (x == y)
{ something();
somethingelse();
}
Horstmann style
while (x == y)
{ something();
somethingelse(); }
Pico
while (x == y) {
something();
somethingelse();
}
Ratliff
while (x == y) {
something();
somethingelse(); }
Lisp
Éviter les commentaires évidents 1/2
//Extraire les données de l’ancien système
functionD1();
//Transformer les données
functionD2();
//Charger les données dans le nouveau système
functionD3();
VS
Extract();
Transform();
Load();
"Si le code est tellement compliqué que cela doit
être expliqué, il est presque toujours préférable
d’améliorer le code que d’ajouter des
commentaires"
▸ Steve Mcconnell
Nommages de variable cohérent 1/2
Les noms des constantes symboliques et des
macros instructions doivent être écrits en
majuscule.
#define LONGUEUR_NOM_FICHIER 15
#define STR(s) #s
#define XSTR(s) STR(s)
DRY Don't Repeat Yourself 1/2
"Every piece of knowledge must have a single, unambiguous, authoritative representation within a system."
Livre The Pragmatic Programmer
VSWET
"Write Everything Twice""We Enjoy Typing""Waste Everyone's Time"
DRY 2/2
Echo "Hello Hadrien, how are you doing ?";Echo "Hello Sergei, how are you doing ?";Echo "Hello you, how are you doing ?";
VS
function greetings($str) { echo "Hello $str, how are you doing ? " }greetings("Hadrien");greetings("Sergei");greetings("you");
Niveau multiple de parenthèses
If (((2 + $x) > 3) || (($y + 2) > 6)) && ($x + $y > 1)) {...}
VS$cond1 = (2 + x) > 3;$cond2 = ((y + 2) > 6);$cond1_ou_2 = $cond1 || $cond2;$cond3 = $x + $y > 1;$cond1_ou_2_et_cond3 =
$cond1_ou_2 && $cond3;If ($cond1_ou_2_et_cond3)
{...}
Organisation des dossiers
app/The application configuration, templates and
translations.bin/
Executable files (e.g. bin/console).src/
The project's PHP code.tests/
Automatic tests (e.g. Unit tests).var/
Generated files (cache, logs, etc.).vendor/
The third-party dependencies.web/
The web root directory.
KISS
KISS - Keep It Simple
1.D'abord un code fonctionnel
2.Puis optimisation
3.En gardant un code
fonctionnel
Design Pattern
▸ Factory MethodCréation d'objet sans spécifier la classe exacte$factory = new SedanFactory();
$car = $factory->makeCar();
print $car->getType();
▸ SingletonUtilisation d'un objet dans le code▸ FacadeSimplifier une interface
S'améliorer
Comment améliorer la lisibilité, simplicité, éviter la duplication du code ?
Pistes: ▸ Parcourir du code open-source
(contribuer ?)▸ Lire des blogs▸ Lire des livres▸ ...
Code metrics
▸Information hiding▸Encapsulation▸Coupling
Loose coupling / tight coupling
▸Dependency▸Cyclomatic complexity
The number of linearly independent paths through a program's source code. (Foret de IF IF IF IF …)
WHY ?
Unit test : pourquoi ?Le métier d'ingénieur logiciel évolue :▸ Désign▸ Développement ▸ Test▸ Déploiement ▸ Résolution de bugs
Concepteur/Architecte + Développeur + Ingénieur qualité + administrateur système +
ingénieur production
Objectif
Objectif du test:▸Démonstration que le
programme fonctionne sans erreur▸Avoir le comportement
logiciel voulu▸Augmenter la qualité
logicielle
"Le test-driven development (TDD) ou en français développement piloté par les tests est une technique de développement de logiciel qui préconise d'écrire les tests unitaires avant d'écrire le code source d'un logiciel."
-- Wikipedia
Ne pas confondre
1. Écrire du code
2. Ajout des tests
3. Modification du code pour passer
VS
1. Écrire des tests
2. Écrire du code qui passe les tests
(Test Driven Development)
TDD En détail
Le cycle TDD en détail : 1. Écrire un premier test2. Vérifier qu'il échoue (car le code
n'existe pas encore)3. Écrire juste le code suffisant pour
passer le test4. Vérifier que le test passe5. Puis réusiner le code, refactoring.
Réusiner ?Refactoring ?
Réusiner /
Refactoring (in english)
Changer le code existant sans
changer son comportement
extérieur
Nouvelle fonctionnalité
Scénario #1 : Développer une
nouvelle fonctionnalité
1. Écrire un test pour une nouvelle
fonctionnalité (tests KO)
2. Lancer le test, il échoue (tests KO)
3. Écrire assez de code pour passer le
test (tests OK)
4. Refactoring pour faire le code de
meilleure qualité (tests OK)
Correction de bug
Scénario #2 : Correction de bug
/ erreur
1. Écrire un test du code avec un bug
- documentation (tests KO)
2. Faire les modification, le test
passe (tests OK)
3. Refactoring (tests OK)
Refactoring
Scénario #3 : Refactoring
1.Écrire/modifier les tests
unitaires (tests KO)
2.Écrire le code (tests KO)
3.Refactoring (tests OK)
Legacy code
Scénario #4 : Legacy code
▸Écrire des tests unitaires
pour commencer à
comprendre du vieux code
ou un système déjà en place
Learning
Scénario #5 : Learning
▸Utiliser une nouvelle API
▸Faire un nouvel algorithme
▸Le test est maintenant une
base de savoir réutilisable
Knowledge Management
Découverte d'une API / outils▸Permet d'avoir une base de
connaissance partagé sur la nouvelle technologie : Knowledge Management
Diagram AAA "Arrange-Act-Assert"
A pattern for arranging and
formatting code :
1.Arrange all necessary
preconditions and inputs.
2.Act on the object or method
under test.
3.Assert that the expected results
have occurred.
Diagram "AAA" 1/3
Diagram "AAA" 2/3
Example:
@Testpublic void test() {
String input = "abc";
String result = Util.reverse(input);
assertEquals("cba", result);}
Diagram "AAA" 3/3
Avantages:
▸ Séparation clair de ce qui est testé : entrée, fonction, résultat
▸ Met la priorité aux paliers nécessaires dans le test du code
▸ Ne pas faire trop de choses différentes à la fois
Continuous Integration
Intégration continue
▸Lancer les tests unitaires
lorsqu'il y a un changement
dans le code
Continuous Integration
"In software engineering, continuous integration (CI) is the practice of merging all developer working copies to a shared mainline several times a day.Grady Booch first named and proposed CI in his 1991 method, although he did not advocate integrating several times a day. Extreme programming (XP) adopted the concept of CI and did advocate integrating more than once per day -perhaps as many as tens of times per day."
-- wikipedia
Extreme Programming :▸ Objectif : produire du code de qualité de
manière productive▸ Cycles de développement courts▸ Changer le code n'affecte pas les
fonctionnalités▸ Le code est au centre▸ Unit tests / acceptance tests (client)▸ Communication, simplicity, feedback, and
courage▸ Peer-programming
XP
Nouvel arrivant : unit test
Nouvel arrivant :
▸Permet de se familiariser
avec du code.
▸Documentation et
spécification de comment
utiliser le code
Contrôle de la régression
En cas de gros changement de codebase : outils contre la Régression
Lors de :
▸Refactoring
▸De grands changements
Libcheck 1/2
#include <stdlib.h>
#include <check.h>
#include "../src/money.h"
START_TEST(test_money_create)
{
Money *m;
m = money_create(5, "USD");
ck_assert_int_eq(money_amount(m), 5);
ck_assert_str_eq(money_currency(m), "USD");
money_free(m);
}
END_TEST
More on https://github.com/libcheck/check
Libcheck 2/2
Running suite(s): Money
0%: Checks: 1, Failures: 1, Errors: 0
check_money.c:9:F:Core:test_money_create:0: Assertion
'money_amount (m)==5' failed:
money_amount (m)==0, 5==5
FAIL: check_money
=====================================================
1 of 1 test failed
Please report to check-devel AT lists.sourceforge.net
=====================================================
Ruby on Rails
Rails test
require 'test_helper'
class modelTest < ActiveSupport::TestCasetest "the truth" doassert true
endEnd
bin/rake test test/models/project_test.rb
Run options: --seed 227
# Running:
.
Finished in 0.173677s, 5.7578 runs/s, 5.7578 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
Available assertions
Assertion Purpose
assert( test, [msg] ) Ensures that test is true.
assert_not( test, [msg] ) Ensures that test is false.
assert_equal( expected, actual,
[msg] )
Ensures that expected == actual is
true.
assert_not_equal( expected,
actual, [msg] )
Ensures that expected != actual is
true.
assert_same( expected, actual,
[msg] )
Ensures that
expected.equal?(actual) is true.
assert_not_same( expected,
actual, [msg] )
Ensures that
expected.equal?(actual) is false.
assert_nil( obj, [msg] ) Ensures that obj.nil? is true.
assert_not_nil( obj, [msg] ) Ensures that obj.nil? is false.
assert_empty( obj, [msg] ) Ensures that obj is empty?.
*http://guides.rubyonrails.org/testing.html
Rails
FixturesFixtures are a way of organizing data that you
want to test against; in short, sample data.
rubyonrails:
id: 1
name: Ruby on Rails
url: http://www.rubyonrails.org
google:
id: 2
name: Google
url: http://www.google.com