Skrivning af bedre enhedstests på kortere tid med Junit Parameters
De fleste mennesker forstår vigtigheden og fordelene ved enhedstests, og hvorfor du bør have dem i projekter, du arbejder på. De fleste mennesker bryder sig heller ikke om at skrive enhedstests i projekter, de arbejder på. TDD-folk er selvfølgelig på den anden side af spøgelset, men fra min erfaring er de en minoritet i it-branchen.
Når det kommer til mig, så er jeg sammen med de fleste :-). Jeg ved, hvorfor det er godt at have enhedstests, og hvordan det vil forbedre kvaliteten af kode og projekter. Jeg ved, hvorfor du skal investere i dem, men jeg er ikke super glad for at skrive enhedstests, det er ikke det, der holder mig vågen om natten. Jeg foretrækker meget mere at skabe cool software og løse komplekse problemer, og så skrive enhedstests. Derfor er jeg altid på udkig efter ting, der kan hjælpe mig med at få flere og bedre enhedstests, med mindre arbejde fra min side, da du i sidste ende burde have enhedstests i dine projekter.
En af de ting, der kan hjælpe dig med at skrive en bedre enhedstest med mindre tidsforbrug, er Junit Params.
Hvorfor skulle du bekymre dig om Junit Params?
Lad os forestille os, at vi har en simpel klasseperson, som har fornavn og efternavn. Forretningskrav er, at for- og efternavn ikke må være null eller tomme strenge.
Vi kan ende med en klasse, der ligner denne
010203040506070809101112131415161718192021 | public class Person { private final String firstName; private final String lastName; public Person(String first, String last) { if (first == null || first.trim().isEmpty() || last == null || last.trim().isEmpty() ) { throw new RuntimeException( "bad input" ); } this .firstName = first; this .lastName = last; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } } |
Næste trin er at sikre, at koden fungerer efter hensigten, og at vi har taget højde for alle hjørnesager.
Vi vil selvfølgelig gerne dække alle de muligheder ved hjælp af enhedstests, men hvis du tænker over det, vil vi have en masse gentaget kode, hvor vi tester fornavn for alle muligheder, og derefter efternavn, og så alle kombinationer og så videre, hvis vi ønsker at dække alle kantsager. Vi vil ende med meget mere kode i enhedstests og derefter kode i vores forretningslogik til denne simple klasse.
Lad os se, hvordan JUnit Params kan hjælpe os med dette.
Start opsætning
For at bruge Junit Params skal du blot tilføje afhængighed som for ethvert andet bibliotek
123456 | <dependency> <groupId>pl.pragmatists</groupId> <artifactId>JUnitParams</artifactId> <version> 1.1 . 1 </version> <scope>test</scope> </dependency> |
Herefter kan vi begynde at bruge JUnit Params i vores enhedstest
JUnit tests ved hjælp af JUnit Params
Lad os nu skrive få enhedstest ved at bruge JUnit Params.
Opret en simpel testklasse PersonTest og tilføj @RunWith(JUnitParamsRunner.class )
1234 | @RunWith (JUnitParamsRunner. class ) public class PersonTest { ....... } |
Nu kan vi skrive en simpel enhedstest for at validere vores klasse. Lad os først tjekke, om alt er i orden, hvis vi angiver null som fornavn
1234 | @Test (expected = RuntimeException. class ) public void fistNameNull() { Person p = new Person( null , "dummyLast" ); } |
Det gode ved JUnit Params er, at vi stadig kan skrive standard enhedstests og kombinere dem med JUnit Params.
For at udnytte JUnit-parametre på denne enhedstest skal jeg blot tilføje @Parameters med passende værdier, og så ville det se sådan ud
12345 | @Test (expected = RuntimeException. class ) @Parameters ({ "" , " " , " " , " " }) public void fistNameParamaters(String param) { Person p = new Person(param, "dummyLast" ); } |
med denne kode lavede jeg 4 enhedstests, som validerer min kode for værdierne "", ", " " og " ".
Dette viser allerede, hvor nyttige JUnit Params er, da du kun skriver en enhedstest, og den vil blive udført for alle forskellige muligheder for dine parametre.
Overførsel af parametre til flere inputparametre
Hvad sker der, hvis vi vil videregive parametre for både inputværdier, fornavn og efternavn. I så fald ville vi gøre noget som dette
12345678 | @Test (expected = RuntimeException. class ) @Parameters ({ " " , " " , // firstName, lastName " " , "" , " " , " " , " " , " " }) public void fistNameLastNameParamaters(String first, String last) { Person p = new Person(first, last); } |
da der er to inputparametre, vil de angivne værdier blive delt i par af to og brugt som input.
Som du kan se, er det meget nemt at angive input til flere parametre, selvom vi på denne måde skal levere alle kombinationer, som vi ønsker at teste.
Videregivelse af parametre til flere inputparametre på en brugervenlig måde
Hvis vi er ærlige, selvom testen ovenfor fungerer fint for flere inputparametre, er den ikke særlig brugervenlig. Lad os rette det i næste eksempel
12345 | @Test (expected = RuntimeException. class ) @Parameters ({ " | " , " |" , " | " , " | " }) public void fistNameLastNameParamaters2(String first, String last) { Person p = new Person(first, last); } |
nu er det meget mere klart, hvilken værdi der vil blive brugt til hvilken inputparameter i hver iteration.
Brug af ikke-strengværdier som inputparametre
Indtil videre var alle parametre Strings. Hvad hvis vores inputparameter ikke er en streng eller noget, der nemt kan konverteres fra/til streng, for eksempel null værdi.
I så fald kan vi bruge navngivet parameter
010203040506070809101112131415 | @Test (expected = RuntimeException. class ) @Parameters (named = "emptyStrings" ) public void namedParamaters(String first, String last) { Person p = new Person(first, last); } @NamedParameters ( "emptyStrings" ) private Object[] emptyStrings() { return new Object[]{ new Object[]{ null , "" }, new Object[]{ "" , null }, new Object[]{ " " , " " }, new Object[]{ " " , " " } }; } |
Reference
Kodeeksempler nævnt i dette indlæg kan findes på denne url
- https://github.com/vladimir-dejanovic/junit-params-blog-examples