Dette er et utdrag fra Unit Testing Succinctly eBook, av Marc Clifton, gitt vennlig av Syncfusion.
En enhetstestmotor på et reflekterende språk (for eksempel et. NET-språk) har tre deler:
Denne artikkelen inneholder kodeeksempler på hvordan dette virker, å sette sammen en enkelhets testmotor. Hvis du ikke er interessert i undersøkelsen av enhetstestmotorer, er du velkommen til å hoppe over denne artikkelen.
Koden her antar at vi skriver en testmotor mot Visual Studio-enhetstestattributtene som er definert i Microsoft.VisualStudio.QualityTools.UnitTestFramework-samlingen. Andre enhetstestmotorer kan bruke andre attributter til samme formål.
Arkitektonisk bør enhetstestene dine enten være plassert i en separat enhet fra koden som testes, eller som minimum bør bare inkluderes i forsamlingen dersom den er sammensatt i "Feilsøkingsmodus". Fordelen ved å sette enhetstestene i en separat enhet er at du også kan prøve enhetens ikke-feilsøking, optimalisert produksjonsversjon av koden.
Når det er sagt, er det første trinnet å laste enheten:
statisk bool LoadAssembly (string assemblyFilename, out Assembly assy, utstrengsproblem) bool ok = true; problem = String.Empty; assy = null; prøv assy = Assembly.LoadFile (assemblyFilename); fangst (Unntak ex) issue = "Feil lasting av samling:" + ex.Message; ok = false; gå tilbake ok;
Vær oppmerksom på at profesjonelle enhetstestmotorer laster sammen enheter i et eget applikasjonsdomene slik at montering kan lastes ut eller lastes om uten å starte testmaskinen på nytt. Dette gjør det også mulig å rekompilere enhetstestmontering og avhengige enheter uten å først slå av testmaskinen først.
Det neste trinnet er å reflektere over forsamlingen for å identifisere klassene som er utpekt som en "test fixture" og innenfor disse klassene, for å identifisere testmetodene. Et grunnleggende sett med fire metoder støtter kravene til minimale enhetstestmotor, oppdagelsen av testarmaturer, testmetoder og unntakshåndteringsegenskaper:
////// Returnerer en liste over klasser i den angitte enheten som har et "TestClass" -attributt. /// statisk IEnumerableGetTestFixtures (Assembly Assy) return assy.GetTypes (). Hvor (t => t.GetCustomAttributes (typeof (TestClassAttribute), false) .Length == 1); /// /// Returnerer en liste over metoder i testfestet som er dekorert med "TestMethod" -attributtet. /// statisk IEnumerableGetTestMethods (Type testFixture) return testFixture.GetMethods (). Hvor (m => m.GetCustomAttributes (typeof (TestMethodAttribute), false) .Length == 1); /// /// Returnerer en liste over spesifikke attributter som kan dekorere metoden. /// statisk IEnumerableGetMethodAttributes (MethodInfo metode) return method.GetCustomAttributes (typeof (AttrType), false) .Cast (); /// /// Returnerer sant hvis metoden er dekorert med et "ExpectedException" -attributt mens unntakstype er det forventede unntaket. /// statisk bool IsExpectedException (MethodInfo metode, Exception expectedException) Type expectedExceptionType = expectedException.GetType (); returnere GetMethodAttributes(metode). Hvor (attr => attr.ExceptionType == expectedExceptionType) .Count ()! = 0;
Når denne informasjonen er utarbeidet, påkaller motoren testmetodene i en prøvefeltboks (vi vil ikke at enhetens testmotor selv krasjer):
statisk tomrum RunTests (Type testFixture, Actionresultat) IEnumerable testmetoder = GetTestMethods (testFixture); if (testMethods.Count () == 0) // Ikke gjør noe hvis det ikke finnes noen testmetoder. komme tilbake; object inst = Activator.CreateInstance (testFixture); foreach (MethodInfo mi i testmetoder) bool pass = false; prøv // Testmetoder har ikke parametere. mi.Invoke (inst, null); pass = true; fangst (Unntak ex) pass = IsExpectedException (mi, ex.InnerException); Endelig resultat (testFixture.Name + "." + mi.Name + ":" + (pass? "Pass": "Feil"));
Til slutt kan vi sette denne koden sammen i en enkel konsollapplikasjon som tar enhetstestsamlingen som parameter resulterer i en brukbar, men enkel motor:
bruker system; bruker System.Collections.Generic; bruker System.IO; bruker System.Linq; bruker System.Reflection; bruker System.Text; bruker Microsoft.VisualStudio.TestTools.UnitTesting; namespace SimpleUnitTestEngine class Program static void Main (streng [] args) string issue; hvis (! VerifyArgs (args, ut problem)) Console.WriteLine (problem); komme tilbake; Montering assy; hvis (! LoadAssembly (args [0], ut assy, ut problem)) Console.WriteLine (issue); komme tilbake; IEnumerabletestFixtures = GetTestFixtures (assy); foreach (Type testFixture i testFixtures) RunTests (testFixture, t => Console.WriteLine (t)); statisk bool VerifyArgs (streng [] args, utstrengsproblem) bool ok = true; problem = String.Empty; hvis (args.Length! = 1) issue = "Bruk: SimpleUnitTestEngine "; ok = false; else string assemblyFilename = args [0]; hvis (! File.Exists (assemblyFilename)) issue =" Filnavnet "" + args [0] + "'eksisterer ikke." = false; return ok; ... resten av koden ...
Resultatet av å kjøre denne enkle testmotoren vises i et konsollvindu, for eksempel:
Våre enkle testmotorkonsolresultater