SlideShare una empresa de Scribd logo
1 de 111
Moles, Stubs et PexTest UnitairesIsolés et Paramétrisés Jonathan “Peli” de Halleux Microsoft Research
Objectifs de cette sessionA la fin de cette session, je saurai Ecrire des tests unitaires UtiliserMoles et Stubs pour isoler les tests Ecrire des test unitairesparamétriséavec Pex Ecrire des tests baséssur des transitions d’états
Test Unitaire
A test unitaireest un programmecontenant des assertions qui testeuneunité de code Test Unitaire void PushNonEmpty() { var stack = new Stack(); stack.Push(3); Assert.IsFalse(stack.Empty); }
Quiz Les thèmes des questions du quiz… Couverture de code Assertions Isolation La définition de tests unitaires
Le Code à Tester string ReadFooValue() {  string[] lines = File.ReadAllLines(@"t:yapp.ini"); foreach(var line in lines){ intindex = line.IndexOf('=');     string name = line.Substring(index); if (name == "Foo") {     string value = line.Substring(index); return value; }  }   return null; }
Quiz: Couverture Combien de couverture de blocs a-t-on besoin? 50% 80% 100% La couverture de blocs n’est pas suffisante
Quiz: Couverture Combien de couverture de blocs a-t-on besoin? 50% 80% 100% La couverture de blocs n’est pas suffisante
Quiz: Couverture Combien de tests pour 100%  de couverture de blocs? 1 2 3 10 1000
Quiz: Couverture Combien de tests pour 100%  de couverture de blocs? 1 2  3 10 1000
Quiz: Couverture [TestMethod] void ExistingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“Foo=b”}); Reader.ReadFooValue();} Quelautre test pour 100% cov.?
Quiz: Couverture [TestMethod] void ExistingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“Foo=b”}); Reader.ReadFooValue();} Quelautre test pour 100% cov.? [TestMethod] void MissingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“a=b”}); Reader.ReadFooValue();}
Quiz: Assertions Pourquoiécrire des Assertions? Documentation S’assurerque le code est correct Faire plaisir au chef Prévenir de futursfautes Validater des entrées utilisateur Capturer les fautestôtdansl’exécution
Quiz: Assertions Pourquoiécrire des Assertions? Documentation S’assurerque le code est correct Faire plaisir au chef Prévenir de futursfautes Validater des entrées utilisateur Capturer les fautestôtdansl’exécution
Quiz: Assertions if (name == "Foo") { var value = line.Substring(index); Debug.Assert(???);      return value; } Quelssont de bonsexemplesd’assertions? Debug.Assert(true); Debug.Assert(value != null); Debug.Assert(value.Length == line.Length – (index + 1)); No assertions
Quiz: Assertions if (name == "Foo") { var value = line.Substring(index); Debug.Assert(???);      return value; } Quelssont de bonsexemplesd’assertions? Debug.Assert(true); Debug.Assert(value != null); Debug.Assert(value.Length == line.Length – (index + 1)); No assertions
Quiz: Assertions Quelssont de bonsexemplesd’assertions? Assert.IsTrue(value == “b”); Assert.IsTrue(value == null); Assert.IsTrue(String.IsNullOrEmpty(value)) Assert.IsTrue(false); No assertions [TestMethod] void MissingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“a=b”});    string value = Reader.ReadFooValue(); Assert.IsTrue(????);}
Quiz: Assertions Quelssont de bonsexemplesd’assertions? Assert.IsTrue(value == “b”); Assert.IsTrue(value == null); Assert.IsTrue(String.IsNullOrEmpty(value)) Assert.IsTrue(false); No assertions [TestMethod] void MissingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“a=b”});    string value = Reader.ReadFooValue(); Assert.IsTrue(????);}
Quiz: Couverture +Assertions Comment avoirconfiancedans le code? Haute couverture, peuxd’assertions Bassecouverture, beaucoup d’assertions Haute couverture, peuxd’assertions Bassecouverture, beaucoup d’assertions “Je l’aiécrit”
Quiz: Couverture +Assertions Comment avoirconfiancedans le code? Haute couverture, peuxd’assertions Bassecouverture, beaucoup d’assertions Haute couverture, beaucoup d’assertions Bassecouverture, peuxd’assertions “Je l’aiécrit”
Quiz: Couverture +Assertions Considéronsuneexécution de  tests  automatisée Comment iplementerune assertion,e.g. Debug.Assert? { /* ignore */ } Log(c); if(!c) MessageBox.Show(“Assert!”); if(!c) throw new AssertionException(); Kill process
Quiz: Couverture +Assertions Considéronsuneexécution de  tests  automatisée Comment iplementerune assertion,e.g. Debug.Assert? { /* ignore */ } Log(c); if(!c) MessageBox.Show(“Assert!”); if(!c) throw new AssertionException(); Kill process
Quiz: Couverture +Assertions Considéronsuneexécution de  tests  automatisée Comment iplementerune assertion,e.g. Debug.Assert? { /* ignore */ } Log(c); if(!c) MessageBox.Show(“Assert!”); if(!c) throw new AssertionException(); Kill process 1 assertion =  1 branch
The Code à Tester string ReadFooValue() {  string[] lines = File.ReadAllLines(@"t:yapp.ini"); foreach(var line in lines){ intindex = line.IndexOf('=');     string name = line.Substring(index); if (name == "Foo") {     string value = line.Substring(index); return value; }  }   return null; }
Quiz: Isolation string ReadFooValue() {  string[] lines = File.ReadAllLines(@"t:yapp.ini");  ... } Quellessont les dépendancesexternes? Réseau Disque local Températureambiante
Quiz: Isolation string ReadFooValue() {  string[] lines = File.ReadAllLines(@"t:yapp.ini");  ... } Quellessont les dépendancesexternes? Réseau Disquedur Températureambiante
Quiz: Isolation Quelest le problème du disquedur? Le Mappingexiste déjà Les tests ne peuventêtreexécuté en parralèle Le disqueestplein Droitd’accès Pas de problèmes
Quiz: Isolation Quelest le problème du disquedur? Le Mappingexiste déjà Les tests ne peuventêtreexécuté en parralèle Le disqueestplein Droitd’accès Pas de problèmes
Quiz: Isolation Comment gérer le problème? Toujoursexécuterdans le même environment Refactoring: utiliser des Streams Refactoring: introduireIFileSystem Refactoring: passer lines comme argument Change l’implémentation de File.ReadAllLines
Quiz: Isolation Abstractiondevraitêtre la première option Comment gérer le problème? Toujoursexécuterdans le même environment Refactoring: utiliser des Streams Refactoring: introduireIFileSystem Refactoring: passer lines comme argument Change l’implémentation de File.ReadAllLines
Quiz: Isolation Comment gérer le problème? Toujoursexécuterdans le même environment Refactoring: utiliser des Streams Refactoring: introduireIFileSystem Refactoring: passer lines comme argument Change l’implémentation de File.ReadAllLines Dernier ressort
Quiz: Isolation Comment changer File.ReadAllLines? Surcharger la procédure Recompiler le CLR Instrumentation du code Demander poliment
Quiz: Isolation Comment changer File.ReadAllLines? Surcharger la procédure Recompiler le CLR Instrumentation du code Demander poliment
Quiz: Test Unitaire Propriétés de test unitaires? Connection au réseau Exécutelongtemps En mémoire Lit le disquedur Exécuterapidement Reproducible Exécute 10 mèthodes Exécute 100 mèthodes Exécute 10000 mèthodes Requiertune base de données SQL
Quiz: Test Unitaire Propriétés de test unitaires? Connection au réseau Exécutelongtemps En mémoire Lit le disquedur Exécuterapidement Reproducible Exécute 10 mèthodes Exécute 100 mèthodes Exécute 10000 mèthodes Requiertune base de données SQL
Quiz: La Définition d’un Test Unitaire Qu’est-cequ’un Test Unitaire? Un test unitaireest un programme qui exécute (lentement/rapidement) le code à tester, (avec/sans) dépendences à l’environement, (avec/sans) assertions. Qu’est-cequ’unebatterie de tests unitaires? Un ensemble de test unitaires qui atteint un  (haut/bas) taux de couverture de code
Quiz: La Définition d’un Test Unitaire Qu’est-cequ’un Test Unitaire? Un test unitaireest un programme qui exécuterapidement  le code à tester,       sansdépendences à l’environement, avec   assertions. Qu’est-cequ’unebatterie de tests unitaires? Un ensemble de test unitaires qui atteint un  hauttaux de couverture de code
Isolation avecMoles
Le code à tester ne devrait pas dépendre de l’environement: Comment changerFile.ReadAllLines? Surchargeruneméthodestatique Changer le CLR (et le recompiler) Ecrirel’application en javascript Instrumentation de code Le casse tête du testeur var lines = File.ReadAllLines(@"t:yapp.ini");
Le code à tester ne devrait pas dépendre de l’environement: Comment changerFile.ReadAllLines? Surchargeruneméthodestatique Changer le CLR (et le recompiler) Ecrirel’application en javascript Instrumentation de code Le casse tête du testeur var lines = File.ReadAllLines(@"t:yapp.ini");
Et si on savait changer File.ReadAllLinesfacilementdans un contexte de test? Faisons un voeux var lines = File.ReadAllLines(@"t:yapp.ini"); File.ReadAllLines =   delegate(string fileName) {    return new string[]{“a=b”};   }
Avec Moles, on peux le faire:redirigertoutes les futures exécutions de ReadAllLinesvers un délégué qui renvoie{“a=b”}: Molerdes méthodes var lines = File.ReadAllLines(@"t:yapp.ini"); MFile.ReadAllLinesString =   delegate(string fileName) {    return new string[]{“a=b”};   }
Avec Moles, on peux le faire:redirigertoutes les futures exécutions de ReadAllLinesvers un délégué qui renvoie{“a=b”}: Molerdes méthodes var lines = File.ReadAllLines(@"t:yapp.ini"); string[] ReadAllLines(string fileName); MFile.ReadAllLinesString =   delegate(string fileName) {    return new string[]{“a=b”};   } Func<string,string[]> ReadAllLines{ set; }
Quiz: Func<T> Associez les délégués et méthodes Func<string> Action Action<string> Func<bool,string> Func<string, bool> Action<int> Action<List<T>, int> boolFile.Exists(string) Console.WriteLine(string) void Flush() String.Empty {get;} List<T>.Capacity {set;}
Quiz: Func<T> Associez les délégués et méthodes Func<string> Action Action<string> Func<bool,string> Func<string, bool> Action<int> boolFile.Exists(string) Console.WriteLine(string) void Flush() String.Empty {get;} List<T>.Capacity {set;}
C# 3.0 Lambdas MFile.ReadAllLinesString =  delegate(string fileName) {    return new string[]{“a=b”};   }
C# 3.0 Lambdas MFile.ReadAllLinesString =  (fileName) => {     return new string[]{“a=b”};   }
C# 3.0 Lambdas MFile.ReadAllLinesString =  (fileName) =>            new string[]{“a=b”};
C# 3.0 Lambdas MFile.ReadAllLinesString =  fileName  =>            new string[]{“a=b”};
Quiz: Lambdas Associez les lambdas et méthodes () => “” () => {} s => {} (s) => “” (s) => false boolFile.Exists(string) Console.WriteLine(string) void Flush(); String.Empty {get;} string ToString();
Quiz: Lambdas Associez les lambdas et méthodes () => “” () => {} s => {} (s) => “” (s) => false boolFile.Exists(string) Console.WriteLine(string) void Flush(); String.Empty {get;} string ToString();
Pour chaqueclasseuneclasse mole Unepropriété par méthode Conventions de noms Structure d’un Mole class File {  static string[] FileReadAllLines(string f); } class MFile { Func<string, string[]>  FileReadAllLinesString { set; } }
Quiz: Moles Convention de noms: ‘M’ + nom de classe Nom de méthode+ noms des classes des paramètres Accesseur de propriétés: Get Quelest le mole de boolFile.Exists(string)? SFile.ExistsString MFile.Exists MFile.ExistsStringBool MFile.ExistsString
Quiz: Moles Convention de noms: ‘M’ + nom de classe Nom de méthode+ noms des classes des paramètres Accesseur de propriétés: Get Quelest le mole de boolFile.Exists(string)? SFile.ExistsString MFile.Exists MFile.ExistsStringBool MFile.ExistsString
Injection de détoursdans le corps des méthodes avec un profiler DétoursCourt circuit de méthodes
Injection de détoursdans le corps des méthodes avec un profiler DétoursCourt circuit de méthodes structDateTime{    static DateTime Now { 	return InternalNow();    } }
Injection de détoursdans le corps des méthodes avec un profiler DétoursCourt circuit de méthodes structDateTime{    static DateTime Now { 	return InternalNow();    } } Func<DateTime> f = GetDetour(...);      if(f != null) return f();
Demo
Molesen action “Remplacerquelconqueméthode .NET avec un délégué” L’instrumentationrequiertune configuration spéciale: [HostType(“Moles”)] avec MSTest MFile.ReadAllLinesString= (f) => new string[0];
Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles Identifier les dépendencesexternes Replacer chaque API externe avec un délégué
Pause 10 Minutes
Isolation avecStubs
The Code à Tester string ReadFooValue() {  string[] lines = File.ReadAllLines(@"t:yapp.ini"); foreach(var line in lines){ intindex = line.IndexOf('=');     string name = line.Substring(index); if (name == "Foo") {     string value = line.Substring(index); return value; }  }   return null; }
Dependency Injection interface IFileSystem {    string[] ReadAllLines(string fileName);} string ReadFooValue(IFileSystemfs) {  string[] lines = fs.ReadAllLines(@"t:yapp.ini");  ... }
Structure d’un Stub interface IFileSystem {    string[] ReadAllLines(string fileName);} class SIFileSystem : IFileSystem, IStub {  public Func<string,string[]> ReadAllLinesString;  string[] IFileSystem.ReadAllLines(string name){     return this.ReadAllLinesString(name);  } }
Stub en action class SIFileSystem : IFileSystem, IStub {  public Func<string,string[]> ReadAllLinesString;  string[] IFileSystem.ReadAllLines(string name){     return this.ReadAllLinesString(name);  } } var lines = { “foo=a”, “b=c”}; varfs = new SIFileSystem{ReadAllLinesString = f => lines }; ReadFooValue(fs);
Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles L’isolation de tests unitaires avec Stubs
Stubs vsMoles Moles pour le code des autres “pas le choix” Stubs pour votre code Refactoring + interfaces + Stubs
Test UnitaireParamétrisé
The recette d’un Test Unitaire 3 ingrédientsétentiels: Données Séquence de méthodes Assertions void PushIsNotEmpty() { int item = 3; var stack = new Stack(); stack.Push(item);  Assert.IsTrue(stack.IsEmpty); }
Quiz: stack.Push (???) stack.Push(???); Quelledonnéeutiliser? 0 1 int.MaxValue, int.MinValue -1 1000 Peuimporte Il faux d’abord lire le code
Quiz: stack.Push (???) stack.Push(???); Quelledonnéeutiliser? 0 1 int.MaxValue, int.MinValue -1 1000 Peuimporte Il faux d’abord lire le code
Test UnitaireParamétrisé =  	Test Unitaire avec Parametres Separation de concepts Spécification Données pour avoir de la couverture de code Test UnitaireParamétrisé void PushIsNotEmpty(Stack stack, int item) { stack.Push(item); Assert.IsFalse(stack.IsEmpty); }
Test UnitaireParamétrisé void PushIsNotEmpty(Stack stack, int item) { stack.Push(item); Assert.IsFalse(stack.IsEmpty); } Test UnitaireParamétrisé =  	Test Unitaire avec Parametres Separation de concepts Spécification Données pour avoir de la couverture de code pour tout stack, pour tout item, … ajouter un element et le stack n’est pas vide
Génération de donnéesavec l’exécutiondynamiquesymbolique
Goal: Soit un programmeparamétrisé, générerautomaticement un ensemble de donnéesqui, à l’exécution, vontatteindre un maximum de cheminsd’exécution Quelle technique pourrait-on utiliser? 76 Le challengede la génération de données
ExécutiondynamiquesymboliqueExample Choiser le prochain chemin Exécuter&Observer Résoudre void CoverMe(int[] a) {   if (a == null) return;   if (a.Length > 0)     if (a[0] == 1234567890) throw new Exception("bug"); } Observed constraints a==null a!=null && !(a.Length>0) a!=null && a.Length>0 && a[0]!=1234567890 a!=null && a.Length>0 && a[0]==1234567890 Data null {} {0} {123…} Constraints to solve a!=null a!=null && a.Length>0 a!=null && a.Length>0 && a[0]==1234567890 a==null F T a.Length>0 T F Done: There is no path left. a[0]==123… T F
ExécutiondynamiquesymboliqueExample Choose next path Quelstests Pex générera-t-il? Execute&Monitor Solve void CoverMe2( int[] a, int index)  {   if (a[index] ==       1 + a[index + 1])  throw new Exception("bug"); } Observed constraints Data Constraints to solve F T T F T F
Quiz: Exécutiondynamiquesymbolique Quels tests Pex générera-t-il? (null, 0),  ({0,1}, 0) (null, 0),  ({0,1}, 0),  ({0,1}, 1) ({}, 1),    ({0,0,0,0}, 3) (null, 0),  ({}, 0),   ({0}, 0),  ({0}, 1), ({1}, 0),   ({0,0},0), ({0,1}, 0) void CoverMe2(int[] a, int index) {   if (a[index] == 1 + a[index + 1])          throw new Exception("bug"); }
Demo
Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles L’isolation de tests unitaires avec Stubs Test unitairesparamétrisés avec Pex
Behaved TypesTests à base de transition d’état
Behaved file system interface IFileSystem {    string[] ReadAllLines(string fileName);} class BIFileSystem : SIFileSystem { BehavedDictionary<string, string[]> files;    public BIFileSystem() { this.files=       new BehavedDictionary<string, string[]>(this,”Files”); this.ReadAllLinesString= fn => {       string[] lines;       if (!this.files.TryGetValue(fn, out lines))         throw new FileNotFoundException(fn);       return (string[])lines.Clone();    };   } }
Behaved file system interface IFileSystem {    string[] ReadAllLines(string fileName);} On approxime le systême de fichiers par un dictionnaire fileName->lignes  
Behaved file system interface IFileSystem {    string[] ReadAllLines(string fileName);} class BIFileSystem : SIFileSystem { BehavedDictionary<string, string[]> files;    public BIFileSystem() { this.files=       new BehavedDictionary<string, string[]>(this,”Files”); this.ReadAllLinesString= fn => {       string[] lines;       if (!this.files.TryGetValue(fn, out lines))         throw new FileNotFoundException(fn);       return (string[])lines.Clone();    };   } } Undefined state
Démo
What you learnedso far The Definition of Test Unitaire Unit Test Isolation through Moles Unit Tests Isolation through Stubs Stated-based Unit Tests with Behaved Types
Break 2 Minutes
Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles L’isolation de tests unitaires avec Stubs Test unitairesparamétrisés avec Pex Test à base de transition d’état avec Behaved Types
Patterns
PatternNormalized Roundtrip For an API f(x),      f-1(f(f-1(x)) = f-1(x)       for all x void ParseToString(string x) { varnormalized = int.Parse(x);  var intermediate = normalized.ToString();  varroundtripped = int.Parse(intermediate);     // assert quiz 1.  Assert(x == intermediate); 2.  Assert(intermediate == roundtripped); 3.  Assert(normalized == roundtripped); 4.  Assert(x == roundtripped);     }
PatternState Relation Observe a state change void ContainedAfterAdd(string value) { var list = new List<string>(); list.Add(value);     // assert quiz 1.  Assert(value != null); 2.  Assert(list.Contains(value)); 3.  Assert(list.IndexOf(value) < 0); 4.  Assert(list[0] == value); }
PatternSame Observable Behavior Given two methods f(x) and g(x), and a method b(y) that observes the result or the exception behavior of a method, assert that f(x) and g(x) have same observable behavior under b, i.e.   b(f(x)) = b(g(x))   for all x. public void ConcatsBehaveTheSame(   string left, string right)  { PexAssert.AreBehaviorsEqual(     () => StringFormatter.ConcatV1(left, right),     () => StringFormatter.ConcatV2(left, right)); }
PatternAllowed Exception Allowed exception -> negative test case [PexAllowedException(typeof(ArgumentException))] void Test(object item) { varfoo = new Foo(item) // validates item // generated test (C#)[ExpectedException(typeof(ArgumentException))]void Test01() {        Test(null); // argument check }
PatternReachability Indicate which portions of a PUT should be reachable. [PexAssertReachEventually] public void Constructor(object input) {   new Foo(input); PexAssert.ReachEventually();   }
PatternRegression Tests Generated test asserts any observed value Return value, out parameters, PexGoal When code evolves, breaking changes in observable will be discovered intAddTest(int a, int b) {     return a + b; } void AddTest01() { varresult = AddTest(0, 0); Assert.AreEqual(0, result); }
More Patterns Read patterns paper:patterns.pdf http://research.microsoft.com/Pex/patterns.pdf
Limitationsand other Details
The yellow event bar notifies about important events, including certain limitations Event Bar Click on issue kind for more information
Events View You should act on these events: Refactor your code, or tell Pex to ignore it in the future, let Pex analyze (“instrument”) more code, if possible.
Instrumenting more code ,[object Object],[object Object]
Pex understand managed .NET code only Pex does not understand native code. Problem if branching over values obtained from the environment Pex may not automatically detect all such cases. Testability File System? if (!File.Exists(f)) throw ...
Hidden Complexity Pex analyzes everyexecuted .NET instruction Some used libraries may be surprisingly expensive to analyze XML parsing repeatedly converting data between different representations void Sum(string[] A) { var sum = “0”;   foreach(var a in A)     sum = (int.Parse(a) + int.Parse(sum)).ToString();   if(sum == “123”) throw new Exception();  }                     Don’t do this.
Exploration Boundaries Configurable bounds include: TimeOut MaxBranches MaxCalls MaxConditions Number of conditions that depend on test inputs MaxRuns ConstraintSolverTimeOut ConstraintSolverMemoryLimit
Multi-threaded code Unlike test inputs, thread-interleavings can normally not be controlled Thus, Pex can only explore single-threaded code Related approach to explore thread-schedules (but not input parameters) by controlling thread-scheduler: CHESShttp://research.microsoft.com/CHESS
Lack of  Test Oracle Write assertions and Pex will try to break them Without assertions, Pex can only find violations of runtime contracts causing NullReferenceException, IndexOutOfRangeException, etc. Assertions leveraged in product and test code Pex can leverage Code Contracts (discussed later)
Exercise Limitations Goal: Understand limitations. Apply Pex to if (File.Exists(fileName))     throw new Exception(“found it”); if (DateTime.Parse(s).Year == 2009) throw new Exception(“found it”);
Wrapping up
What you learnedso far The Definition of Test Unitaire Unit Test Isolation through Moles Unit Tests Isolation through Stubs Stated-based Unit Tests with Behaved Types Write Pex parameterized unit tests
Thank you http://research.microsoft.com/pex
Stubs And Moles Dot Net Hub

Más contenido relacionado

Destacado

Pdf tp4 mesure_antennes
Pdf tp4 mesure_antennesPdf tp4 mesure_antennes
Pdf tp4 mesure_antennesrachid Dakir
 
Anuj 10mar2016
Anuj 10mar2016Anuj 10mar2016
Anuj 10mar2016Anuj012
 
Corrigé td2
Corrigé td2Corrigé td2
Corrigé td2blogger
 
Les transmissions et les supports
Les transmissions et les supportsLes transmissions et les supports
Les transmissions et les supportsFouad Root
 
Propagation en Hautes Fréquences
Propagation en Hautes FréquencesPropagation en Hautes Fréquences
Propagation en Hautes FréquencesLionel Repellin
 
finite element method for waveguide
finite element method for waveguidefinite element method for waveguide
finite element method for waveguideAnuj012
 
Cours 3 — les techniques de transfert
Cours 3 — les techniques de transfertCours 3 — les techniques de transfert
Cours 3 — les techniques de transfertFarice Romaric Sanon
 
Amplificateurs optiques (soa, raman, edfa)
Amplificateurs optiques (soa, raman, edfa)Amplificateurs optiques (soa, raman, edfa)
Amplificateurs optiques (soa, raman, edfa)Assia Mounir
 
Camouflage des antennes mobiles
Camouflage des antennes mobilesCamouflage des antennes mobiles
Camouflage des antennes mobilesConnexion Mobile
 
Conception antenne radio assistée par ordinateur
Conception antenne radio assistée par ordinateurConception antenne radio assistée par ordinateur
Conception antenne radio assistée par ordinateurPassion Radio Amateur
 
Arab tarek 2
Arab tarek 2Arab tarek 2
Arab tarek 2iamnbrone
 
Principes de balun et unun de 1,8 à 50 Mhz
Principes de balun et unun de 1,8 à 50 MhzPrincipes de balun et unun de 1,8 à 50 Mhz
Principes de balun et unun de 1,8 à 50 Mhzwebmasterref68
 
(Médias de communications)
(Médias de communications)(Médias de communications)
(Médias de communications)Anouar Abtoy
 
Formation Bus de Terrain _Partie 1a _ Un peu de la theorie
Formation Bus de Terrain _Partie 1a _ Un peu de la theorieFormation Bus de Terrain _Partie 1a _ Un peu de la theorie
Formation Bus de Terrain _Partie 1a _ Un peu de la theorieWojciech GOMOLKA
 

Destacado (20)

Pdf tp4 mesure_antennes
Pdf tp4 mesure_antennesPdf tp4 mesure_antennes
Pdf tp4 mesure_antennes
 
Anuj 10mar2016
Anuj 10mar2016Anuj 10mar2016
Anuj 10mar2016
 
Td2 rtel-atm-1011
Td2 rtel-atm-1011Td2 rtel-atm-1011
Td2 rtel-atm-1011
 
Corrigé td2
Corrigé td2Corrigé td2
Corrigé td2
 
Les transmissions et les supports
Les transmissions et les supportsLes transmissions et les supports
Les transmissions et les supports
 
Propagation en Hautes Fréquences
Propagation en Hautes FréquencesPropagation en Hautes Fréquences
Propagation en Hautes Fréquences
 
Analyseur d'antennes
Analyseur d'antennesAnalyseur d'antennes
Analyseur d'antennes
 
finite element method for waveguide
finite element method for waveguidefinite element method for waveguide
finite element method for waveguide
 
Cours 3 — les techniques de transfert
Cours 3 — les techniques de transfertCours 3 — les techniques de transfert
Cours 3 — les techniques de transfert
 
Amplificateurs optiques (soa, raman, edfa)
Amplificateurs optiques (soa, raman, edfa)Amplificateurs optiques (soa, raman, edfa)
Amplificateurs optiques (soa, raman, edfa)
 
Camouflage des antennes mobiles
Camouflage des antennes mobilesCamouflage des antennes mobiles
Camouflage des antennes mobiles
 
Conception antenne radio assistée par ordinateur
Conception antenne radio assistée par ordinateurConception antenne radio assistée par ordinateur
Conception antenne radio assistée par ordinateur
 
Arab tarek 2
Arab tarek 2Arab tarek 2
Arab tarek 2
 
7480 solutions
7480 solutions7480 solutions
7480 solutions
 
Principes de balun et unun de 1,8 à 50 Mhz
Principes de balun et unun de 1,8 à 50 MhzPrincipes de balun et unun de 1,8 à 50 Mhz
Principes de balun et unun de 1,8 à 50 Mhz
 
Codage
CodageCodage
Codage
 
(Médias de communications)
(Médias de communications)(Médias de communications)
(Médias de communications)
 
Td1 gsm
Td1 gsmTd1 gsm
Td1 gsm
 
Techniques de transmission
Techniques de transmissionTechniques de transmission
Techniques de transmission
 
Formation Bus de Terrain _Partie 1a _ Un peu de la theorie
Formation Bus de Terrain _Partie 1a _ Un peu de la theorieFormation Bus de Terrain _Partie 1a _ Un peu de la theorie
Formation Bus de Terrain _Partie 1a _ Un peu de la theorie
 

Similar a Stubs And Moles Dot Net Hub

Tester les applications Zend Framework
Tester les applications Zend FrameworkTester les applications Zend Framework
Tester les applications Zend FrameworkMickael Perraud
 
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...Cyrille Grandval
 
POO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdfPOO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdfLarbaSAWADOGO2
 
TDD avec ou sans mock
TDD avec ou sans mockTDD avec ou sans mock
TDD avec ou sans mockYannick Ameur
 
testUnitaire (1).pptx
testUnitaire (1).pptxtestUnitaire (1).pptx
testUnitaire (1).pptxManalAg
 
Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Jean-Michel Doudoux
 
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Loic Yon
 
XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...
XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...
XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...Publicis Sapient Engineering
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowMathias Kluba
 
Formation Extreme Programming, Tests unitaires, travail collaboratif
Formation Extreme Programming, Tests unitaires, travail collaboratifFormation Extreme Programming, Tests unitaires, travail collaboratif
Formation Extreme Programming, Tests unitaires, travail collaboratifkemenaran
 
Interface collectionsinter
Interface collectionsinterInterface collectionsinter
Interface collectionsinterRYMAA
 
Comment écrire du code testable ?
Comment écrire du code testable ?Comment écrire du code testable ?
Comment écrire du code testable ?Fou Cha
 
Cocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitairesCocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitairesCocoaHeads France
 
Java 5, un blian
Java 5, un blianJava 5, un blian
Java 5, un bliantareq
 
Java 5, un bilan
Java 5,  un bilanJava 5,  un bilan
Java 5, un bilanteejug
 

Similar a Stubs And Moles Dot Net Hub (20)

Tester les applications Zend Framework
Tester les applications Zend FrameworkTester les applications Zend Framework
Tester les applications Zend Framework
 
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
 
POO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdfPOO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdf
 
TDD avec ou sans mock
TDD avec ou sans mockTDD avec ou sans mock
TDD avec ou sans mock
 
testUnitaire (1).pptx
testUnitaire (1).pptxtestUnitaire (1).pptx
testUnitaire (1).pptx
 
Et4 4 testinformel
Et4 4 testinformelEt4 4 testinformel
Et4 4 testinformel
 
C++ 11/14
C++ 11/14C++ 11/14
C++ 11/14
 
Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8
 
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
 
XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...
XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...
XebiCon'17 : Mutation testing, ou évaluer l’efficacité de vos tests ! - Sar...
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - Specflow
 
Anatomie du test
Anatomie du testAnatomie du test
Anatomie du test
 
Formation Extreme Programming, Tests unitaires, travail collaboratif
Formation Extreme Programming, Tests unitaires, travail collaboratifFormation Extreme Programming, Tests unitaires, travail collaboratif
Formation Extreme Programming, Tests unitaires, travail collaboratif
 
Interface collectionsinter
Interface collectionsinterInterface collectionsinter
Interface collectionsinter
 
fortran 2.pdf
fortran 2.pdffortran 2.pdf
fortran 2.pdf
 
Comment écrire du code testable ?
Comment écrire du code testable ?Comment écrire du code testable ?
Comment écrire du code testable ?
 
Cocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitairesCocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitaires
 
Java 5, un blian
Java 5, un blianJava 5, un blian
Java 5, un blian
 
Java 5, un bilan
Java 5,  un bilanJava 5,  un bilan
Java 5, un bilan
 
Cours tp2
Cours tp2Cours tp2
Cours tp2
 

Stubs And Moles Dot Net Hub

  • 1. Moles, Stubs et PexTest UnitairesIsolés et Paramétrisés Jonathan “Peli” de Halleux Microsoft Research
  • 2. Objectifs de cette sessionA la fin de cette session, je saurai Ecrire des tests unitaires UtiliserMoles et Stubs pour isoler les tests Ecrire des test unitairesparamétriséavec Pex Ecrire des tests baséssur des transitions d’états
  • 4. A test unitaireest un programmecontenant des assertions qui testeuneunité de code Test Unitaire void PushNonEmpty() { var stack = new Stack(); stack.Push(3); Assert.IsFalse(stack.Empty); }
  • 5. Quiz Les thèmes des questions du quiz… Couverture de code Assertions Isolation La définition de tests unitaires
  • 6. Le Code à Tester string ReadFooValue() { string[] lines = File.ReadAllLines(@"t:yapp.ini"); foreach(var line in lines){ intindex = line.IndexOf('='); string name = line.Substring(index); if (name == "Foo") { string value = line.Substring(index); return value; } } return null; }
  • 7. Quiz: Couverture Combien de couverture de blocs a-t-on besoin? 50% 80% 100% La couverture de blocs n’est pas suffisante
  • 8. Quiz: Couverture Combien de couverture de blocs a-t-on besoin? 50% 80% 100% La couverture de blocs n’est pas suffisante
  • 9. Quiz: Couverture Combien de tests pour 100% de couverture de blocs? 1 2 3 10 1000
  • 10. Quiz: Couverture Combien de tests pour 100% de couverture de blocs? 1 2 3 10 1000
  • 11. Quiz: Couverture [TestMethod] void ExistingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“Foo=b”}); Reader.ReadFooValue();} Quelautre test pour 100% cov.?
  • 12. Quiz: Couverture [TestMethod] void ExistingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“Foo=b”}); Reader.ReadFooValue();} Quelautre test pour 100% cov.? [TestMethod] void MissingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“a=b”}); Reader.ReadFooValue();}
  • 13. Quiz: Assertions Pourquoiécrire des Assertions? Documentation S’assurerque le code est correct Faire plaisir au chef Prévenir de futursfautes Validater des entrées utilisateur Capturer les fautestôtdansl’exécution
  • 14. Quiz: Assertions Pourquoiécrire des Assertions? Documentation S’assurerque le code est correct Faire plaisir au chef Prévenir de futursfautes Validater des entrées utilisateur Capturer les fautestôtdansl’exécution
  • 15. Quiz: Assertions if (name == "Foo") { var value = line.Substring(index); Debug.Assert(???); return value; } Quelssont de bonsexemplesd’assertions? Debug.Assert(true); Debug.Assert(value != null); Debug.Assert(value.Length == line.Length – (index + 1)); No assertions
  • 16. Quiz: Assertions if (name == "Foo") { var value = line.Substring(index); Debug.Assert(???); return value; } Quelssont de bonsexemplesd’assertions? Debug.Assert(true); Debug.Assert(value != null); Debug.Assert(value.Length == line.Length – (index + 1)); No assertions
  • 17. Quiz: Assertions Quelssont de bonsexemplesd’assertions? Assert.IsTrue(value == “b”); Assert.IsTrue(value == null); Assert.IsTrue(String.IsNullOrEmpty(value)) Assert.IsTrue(false); No assertions [TestMethod] void MissingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“a=b”}); string value = Reader.ReadFooValue(); Assert.IsTrue(????);}
  • 18. Quiz: Assertions Quelssont de bonsexemplesd’assertions? Assert.IsTrue(value == “b”); Assert.IsTrue(value == null); Assert.IsTrue(String.IsNullOrEmpty(value)) Assert.IsTrue(false); No assertions [TestMethod] void MissingFoo() { File.WriteAllLines(@"t:yapp.ini",new string[]{“a=b”}); string value = Reader.ReadFooValue(); Assert.IsTrue(????);}
  • 19. Quiz: Couverture +Assertions Comment avoirconfiancedans le code? Haute couverture, peuxd’assertions Bassecouverture, beaucoup d’assertions Haute couverture, peuxd’assertions Bassecouverture, beaucoup d’assertions “Je l’aiécrit”
  • 20. Quiz: Couverture +Assertions Comment avoirconfiancedans le code? Haute couverture, peuxd’assertions Bassecouverture, beaucoup d’assertions Haute couverture, beaucoup d’assertions Bassecouverture, peuxd’assertions “Je l’aiécrit”
  • 21. Quiz: Couverture +Assertions Considéronsuneexécution de tests automatisée Comment iplementerune assertion,e.g. Debug.Assert? { /* ignore */ } Log(c); if(!c) MessageBox.Show(“Assert!”); if(!c) throw new AssertionException(); Kill process
  • 22. Quiz: Couverture +Assertions Considéronsuneexécution de tests automatisée Comment iplementerune assertion,e.g. Debug.Assert? { /* ignore */ } Log(c); if(!c) MessageBox.Show(“Assert!”); if(!c) throw new AssertionException(); Kill process
  • 23. Quiz: Couverture +Assertions Considéronsuneexécution de tests automatisée Comment iplementerune assertion,e.g. Debug.Assert? { /* ignore */ } Log(c); if(!c) MessageBox.Show(“Assert!”); if(!c) throw new AssertionException(); Kill process 1 assertion = 1 branch
  • 24. The Code à Tester string ReadFooValue() { string[] lines = File.ReadAllLines(@"t:yapp.ini"); foreach(var line in lines){ intindex = line.IndexOf('='); string name = line.Substring(index); if (name == "Foo") { string value = line.Substring(index); return value; } } return null; }
  • 25. Quiz: Isolation string ReadFooValue() { string[] lines = File.ReadAllLines(@"t:yapp.ini"); ... } Quellessont les dépendancesexternes? Réseau Disque local Températureambiante
  • 26. Quiz: Isolation string ReadFooValue() { string[] lines = File.ReadAllLines(@"t:yapp.ini"); ... } Quellessont les dépendancesexternes? Réseau Disquedur Températureambiante
  • 27. Quiz: Isolation Quelest le problème du disquedur? Le Mappingexiste déjà Les tests ne peuventêtreexécuté en parralèle Le disqueestplein Droitd’accès Pas de problèmes
  • 28. Quiz: Isolation Quelest le problème du disquedur? Le Mappingexiste déjà Les tests ne peuventêtreexécuté en parralèle Le disqueestplein Droitd’accès Pas de problèmes
  • 29. Quiz: Isolation Comment gérer le problème? Toujoursexécuterdans le même environment Refactoring: utiliser des Streams Refactoring: introduireIFileSystem Refactoring: passer lines comme argument Change l’implémentation de File.ReadAllLines
  • 30. Quiz: Isolation Abstractiondevraitêtre la première option Comment gérer le problème? Toujoursexécuterdans le même environment Refactoring: utiliser des Streams Refactoring: introduireIFileSystem Refactoring: passer lines comme argument Change l’implémentation de File.ReadAllLines
  • 31. Quiz: Isolation Comment gérer le problème? Toujoursexécuterdans le même environment Refactoring: utiliser des Streams Refactoring: introduireIFileSystem Refactoring: passer lines comme argument Change l’implémentation de File.ReadAllLines Dernier ressort
  • 32. Quiz: Isolation Comment changer File.ReadAllLines? Surcharger la procédure Recompiler le CLR Instrumentation du code Demander poliment
  • 33. Quiz: Isolation Comment changer File.ReadAllLines? Surcharger la procédure Recompiler le CLR Instrumentation du code Demander poliment
  • 34. Quiz: Test Unitaire Propriétés de test unitaires? Connection au réseau Exécutelongtemps En mémoire Lit le disquedur Exécuterapidement Reproducible Exécute 10 mèthodes Exécute 100 mèthodes Exécute 10000 mèthodes Requiertune base de données SQL
  • 35. Quiz: Test Unitaire Propriétés de test unitaires? Connection au réseau Exécutelongtemps En mémoire Lit le disquedur Exécuterapidement Reproducible Exécute 10 mèthodes Exécute 100 mèthodes Exécute 10000 mèthodes Requiertune base de données SQL
  • 36. Quiz: La Définition d’un Test Unitaire Qu’est-cequ’un Test Unitaire? Un test unitaireest un programme qui exécute (lentement/rapidement) le code à tester, (avec/sans) dépendences à l’environement, (avec/sans) assertions. Qu’est-cequ’unebatterie de tests unitaires? Un ensemble de test unitaires qui atteint un (haut/bas) taux de couverture de code
  • 37. Quiz: La Définition d’un Test Unitaire Qu’est-cequ’un Test Unitaire? Un test unitaireest un programme qui exécuterapidement le code à tester, sansdépendences à l’environement, avec assertions. Qu’est-cequ’unebatterie de tests unitaires? Un ensemble de test unitaires qui atteint un hauttaux de couverture de code
  • 39. Le code à tester ne devrait pas dépendre de l’environement: Comment changerFile.ReadAllLines? Surchargeruneméthodestatique Changer le CLR (et le recompiler) Ecrirel’application en javascript Instrumentation de code Le casse tête du testeur var lines = File.ReadAllLines(@"t:yapp.ini");
  • 40. Le code à tester ne devrait pas dépendre de l’environement: Comment changerFile.ReadAllLines? Surchargeruneméthodestatique Changer le CLR (et le recompiler) Ecrirel’application en javascript Instrumentation de code Le casse tête du testeur var lines = File.ReadAllLines(@"t:yapp.ini");
  • 41. Et si on savait changer File.ReadAllLinesfacilementdans un contexte de test? Faisons un voeux var lines = File.ReadAllLines(@"t:yapp.ini"); File.ReadAllLines = delegate(string fileName) { return new string[]{“a=b”}; }
  • 42. Avec Moles, on peux le faire:redirigertoutes les futures exécutions de ReadAllLinesvers un délégué qui renvoie{“a=b”}: Molerdes méthodes var lines = File.ReadAllLines(@"t:yapp.ini"); MFile.ReadAllLinesString = delegate(string fileName) { return new string[]{“a=b”}; }
  • 43. Avec Moles, on peux le faire:redirigertoutes les futures exécutions de ReadAllLinesvers un délégué qui renvoie{“a=b”}: Molerdes méthodes var lines = File.ReadAllLines(@"t:yapp.ini"); string[] ReadAllLines(string fileName); MFile.ReadAllLinesString = delegate(string fileName) { return new string[]{“a=b”}; } Func<string,string[]> ReadAllLines{ set; }
  • 44. Quiz: Func<T> Associez les délégués et méthodes Func<string> Action Action<string> Func<bool,string> Func<string, bool> Action<int> Action<List<T>, int> boolFile.Exists(string) Console.WriteLine(string) void Flush() String.Empty {get;} List<T>.Capacity {set;}
  • 45. Quiz: Func<T> Associez les délégués et méthodes Func<string> Action Action<string> Func<bool,string> Func<string, bool> Action<int> boolFile.Exists(string) Console.WriteLine(string) void Flush() String.Empty {get;} List<T>.Capacity {set;}
  • 46. C# 3.0 Lambdas MFile.ReadAllLinesString = delegate(string fileName) { return new string[]{“a=b”}; }
  • 47. C# 3.0 Lambdas MFile.ReadAllLinesString = (fileName) => { return new string[]{“a=b”}; }
  • 48. C# 3.0 Lambdas MFile.ReadAllLinesString = (fileName) => new string[]{“a=b”};
  • 49. C# 3.0 Lambdas MFile.ReadAllLinesString = fileName => new string[]{“a=b”};
  • 50. Quiz: Lambdas Associez les lambdas et méthodes () => “” () => {} s => {} (s) => “” (s) => false boolFile.Exists(string) Console.WriteLine(string) void Flush(); String.Empty {get;} string ToString();
  • 51. Quiz: Lambdas Associez les lambdas et méthodes () => “” () => {} s => {} (s) => “” (s) => false boolFile.Exists(string) Console.WriteLine(string) void Flush(); String.Empty {get;} string ToString();
  • 52. Pour chaqueclasseuneclasse mole Unepropriété par méthode Conventions de noms Structure d’un Mole class File { static string[] FileReadAllLines(string f); } class MFile { Func<string, string[]> FileReadAllLinesString { set; } }
  • 53. Quiz: Moles Convention de noms: ‘M’ + nom de classe Nom de méthode+ noms des classes des paramètres Accesseur de propriétés: Get Quelest le mole de boolFile.Exists(string)? SFile.ExistsString MFile.Exists MFile.ExistsStringBool MFile.ExistsString
  • 54. Quiz: Moles Convention de noms: ‘M’ + nom de classe Nom de méthode+ noms des classes des paramètres Accesseur de propriétés: Get Quelest le mole de boolFile.Exists(string)? SFile.ExistsString MFile.Exists MFile.ExistsStringBool MFile.ExistsString
  • 55. Injection de détoursdans le corps des méthodes avec un profiler DétoursCourt circuit de méthodes
  • 56. Injection de détoursdans le corps des méthodes avec un profiler DétoursCourt circuit de méthodes structDateTime{ static DateTime Now { return InternalNow(); } }
  • 57. Injection de détoursdans le corps des méthodes avec un profiler DétoursCourt circuit de méthodes structDateTime{ static DateTime Now { return InternalNow(); } } Func<DateTime> f = GetDetour(...); if(f != null) return f();
  • 58. Demo
  • 59. Molesen action “Remplacerquelconqueméthode .NET avec un délégué” L’instrumentationrequiertune configuration spéciale: [HostType(“Moles”)] avec MSTest MFile.ReadAllLinesString= (f) => new string[0];
  • 60. Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles Identifier les dépendencesexternes Replacer chaque API externe avec un délégué
  • 63. The Code à Tester string ReadFooValue() { string[] lines = File.ReadAllLines(@"t:yapp.ini"); foreach(var line in lines){ intindex = line.IndexOf('='); string name = line.Substring(index); if (name == "Foo") { string value = line.Substring(index); return value; } } return null; }
  • 64. Dependency Injection interface IFileSystem { string[] ReadAllLines(string fileName);} string ReadFooValue(IFileSystemfs) { string[] lines = fs.ReadAllLines(@"t:yapp.ini"); ... }
  • 65. Structure d’un Stub interface IFileSystem { string[] ReadAllLines(string fileName);} class SIFileSystem : IFileSystem, IStub { public Func<string,string[]> ReadAllLinesString; string[] IFileSystem.ReadAllLines(string name){ return this.ReadAllLinesString(name); } }
  • 66. Stub en action class SIFileSystem : IFileSystem, IStub { public Func<string,string[]> ReadAllLinesString; string[] IFileSystem.ReadAllLines(string name){ return this.ReadAllLinesString(name); } } var lines = { “foo=a”, “b=c”}; varfs = new SIFileSystem{ReadAllLinesString = f => lines }; ReadFooValue(fs);
  • 67. Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles L’isolation de tests unitaires avec Stubs
  • 68. Stubs vsMoles Moles pour le code des autres “pas le choix” Stubs pour votre code Refactoring + interfaces + Stubs
  • 70. The recette d’un Test Unitaire 3 ingrédientsétentiels: Données Séquence de méthodes Assertions void PushIsNotEmpty() { int item = 3; var stack = new Stack(); stack.Push(item); Assert.IsTrue(stack.IsEmpty); }
  • 71. Quiz: stack.Push (???) stack.Push(???); Quelledonnéeutiliser? 0 1 int.MaxValue, int.MinValue -1 1000 Peuimporte Il faux d’abord lire le code
  • 72. Quiz: stack.Push (???) stack.Push(???); Quelledonnéeutiliser? 0 1 int.MaxValue, int.MinValue -1 1000 Peuimporte Il faux d’abord lire le code
  • 73. Test UnitaireParamétrisé = Test Unitaire avec Parametres Separation de concepts Spécification Données pour avoir de la couverture de code Test UnitaireParamétrisé void PushIsNotEmpty(Stack stack, int item) { stack.Push(item); Assert.IsFalse(stack.IsEmpty); }
  • 74. Test UnitaireParamétrisé void PushIsNotEmpty(Stack stack, int item) { stack.Push(item); Assert.IsFalse(stack.IsEmpty); } Test UnitaireParamétrisé = Test Unitaire avec Parametres Separation de concepts Spécification Données pour avoir de la couverture de code pour tout stack, pour tout item, … ajouter un element et le stack n’est pas vide
  • 75. Génération de donnéesavec l’exécutiondynamiquesymbolique
  • 76. Goal: Soit un programmeparamétrisé, générerautomaticement un ensemble de donnéesqui, à l’exécution, vontatteindre un maximum de cheminsd’exécution Quelle technique pourrait-on utiliser? 76 Le challengede la génération de données
  • 77. ExécutiondynamiquesymboliqueExample Choiser le prochain chemin Exécuter&Observer Résoudre void CoverMe(int[] a) { if (a == null) return; if (a.Length > 0) if (a[0] == 1234567890) throw new Exception("bug"); } Observed constraints a==null a!=null && !(a.Length>0) a!=null && a.Length>0 && a[0]!=1234567890 a!=null && a.Length>0 && a[0]==1234567890 Data null {} {0} {123…} Constraints to solve a!=null a!=null && a.Length>0 a!=null && a.Length>0 && a[0]==1234567890 a==null F T a.Length>0 T F Done: There is no path left. a[0]==123… T F
  • 78. ExécutiondynamiquesymboliqueExample Choose next path Quelstests Pex générera-t-il? Execute&Monitor Solve void CoverMe2( int[] a, int index) { if (a[index] == 1 + a[index + 1]) throw new Exception("bug"); } Observed constraints Data Constraints to solve F T T F T F
  • 79. Quiz: Exécutiondynamiquesymbolique Quels tests Pex générera-t-il? (null, 0), ({0,1}, 0) (null, 0), ({0,1}, 0), ({0,1}, 1) ({}, 1), ({0,0,0,0}, 3) (null, 0), ({}, 0), ({0}, 0), ({0}, 1), ({1}, 0), ({0,0},0), ({0,1}, 0) void CoverMe2(int[] a, int index) { if (a[index] == 1 + a[index + 1]) throw new Exception("bug"); }
  • 80. Demo
  • 81. Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles L’isolation de tests unitaires avec Stubs Test unitairesparamétrisés avec Pex
  • 82. Behaved TypesTests à base de transition d’état
  • 83. Behaved file system interface IFileSystem { string[] ReadAllLines(string fileName);} class BIFileSystem : SIFileSystem { BehavedDictionary<string, string[]> files; public BIFileSystem() { this.files= new BehavedDictionary<string, string[]>(this,”Files”); this.ReadAllLinesString= fn => { string[] lines; if (!this.files.TryGetValue(fn, out lines)) throw new FileNotFoundException(fn); return (string[])lines.Clone(); }; } }
  • 84. Behaved file system interface IFileSystem { string[] ReadAllLines(string fileName);} On approxime le systême de fichiers par un dictionnaire fileName->lignes  
  • 85. Behaved file system interface IFileSystem { string[] ReadAllLines(string fileName);} class BIFileSystem : SIFileSystem { BehavedDictionary<string, string[]> files; public BIFileSystem() { this.files= new BehavedDictionary<string, string[]>(this,”Files”); this.ReadAllLinesString= fn => { string[] lines; if (!this.files.TryGetValue(fn, out lines)) throw new FileNotFoundException(fn); return (string[])lines.Clone(); }; } } Undefined state
  • 86. Démo
  • 87. What you learnedso far The Definition of Test Unitaire Unit Test Isolation through Moles Unit Tests Isolation through Stubs Stated-based Unit Tests with Behaved Types
  • 89. Jusqu’ici on a appris La définition de tests unitaires L’isolation de tests unitaires avec Moles L’isolation de tests unitaires avec Stubs Test unitairesparamétrisés avec Pex Test à base de transition d’état avec Behaved Types
  • 91. PatternNormalized Roundtrip For an API f(x), f-1(f(f-1(x)) = f-1(x) for all x void ParseToString(string x) { varnormalized = int.Parse(x); var intermediate = normalized.ToString(); varroundtripped = int.Parse(intermediate); // assert quiz 1. Assert(x == intermediate); 2. Assert(intermediate == roundtripped); 3. Assert(normalized == roundtripped); 4. Assert(x == roundtripped); }
  • 92. PatternState Relation Observe a state change void ContainedAfterAdd(string value) { var list = new List<string>(); list.Add(value); // assert quiz 1. Assert(value != null); 2. Assert(list.Contains(value)); 3. Assert(list.IndexOf(value) < 0); 4. Assert(list[0] == value); }
  • 93. PatternSame Observable Behavior Given two methods f(x) and g(x), and a method b(y) that observes the result or the exception behavior of a method, assert that f(x) and g(x) have same observable behavior under b, i.e. b(f(x)) = b(g(x)) for all x. public void ConcatsBehaveTheSame( string left, string right) { PexAssert.AreBehaviorsEqual( () => StringFormatter.ConcatV1(left, right), () => StringFormatter.ConcatV2(left, right)); }
  • 94. PatternAllowed Exception Allowed exception -> negative test case [PexAllowedException(typeof(ArgumentException))] void Test(object item) { varfoo = new Foo(item) // validates item // generated test (C#)[ExpectedException(typeof(ArgumentException))]void Test01() { Test(null); // argument check }
  • 95. PatternReachability Indicate which portions of a PUT should be reachable. [PexAssertReachEventually] public void Constructor(object input) { new Foo(input); PexAssert.ReachEventually(); }
  • 96. PatternRegression Tests Generated test asserts any observed value Return value, out parameters, PexGoal When code evolves, breaking changes in observable will be discovered intAddTest(int a, int b) { return a + b; } void AddTest01() { varresult = AddTest(0, 0); Assert.AreEqual(0, result); }
  • 97. More Patterns Read patterns paper:patterns.pdf http://research.microsoft.com/Pex/patterns.pdf
  • 99. The yellow event bar notifies about important events, including certain limitations Event Bar Click on issue kind for more information
  • 100. Events View You should act on these events: Refactor your code, or tell Pex to ignore it in the future, let Pex analyze (“instrument”) more code, if possible.
  • 101.
  • 102. Pex understand managed .NET code only Pex does not understand native code. Problem if branching over values obtained from the environment Pex may not automatically detect all such cases. Testability File System? if (!File.Exists(f)) throw ...
  • 103. Hidden Complexity Pex analyzes everyexecuted .NET instruction Some used libraries may be surprisingly expensive to analyze XML parsing repeatedly converting data between different representations void Sum(string[] A) { var sum = “0”; foreach(var a in A) sum = (int.Parse(a) + int.Parse(sum)).ToString(); if(sum == “123”) throw new Exception(); } Don’t do this.
  • 104. Exploration Boundaries Configurable bounds include: TimeOut MaxBranches MaxCalls MaxConditions Number of conditions that depend on test inputs MaxRuns ConstraintSolverTimeOut ConstraintSolverMemoryLimit
  • 105. Multi-threaded code Unlike test inputs, thread-interleavings can normally not be controlled Thus, Pex can only explore single-threaded code Related approach to explore thread-schedules (but not input parameters) by controlling thread-scheduler: CHESShttp://research.microsoft.com/CHESS
  • 106. Lack of Test Oracle Write assertions and Pex will try to break them Without assertions, Pex can only find violations of runtime contracts causing NullReferenceException, IndexOutOfRangeException, etc. Assertions leveraged in product and test code Pex can leverage Code Contracts (discussed later)
  • 107. Exercise Limitations Goal: Understand limitations. Apply Pex to if (File.Exists(fileName)) throw new Exception(“found it”); if (DateTime.Parse(s).Year == 2009) throw new Exception(“found it”);
  • 109. What you learnedso far The Definition of Test Unitaire Unit Test Isolation through Moles Unit Tests Isolation through Stubs Stated-based Unit Tests with Behaved Types Write Pex parameterized unit tests