Your SlideShare is downloading. ×
Atmosphere 2014: JUnit: beyond the basics - Adam Dudczak
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Atmosphere 2014: JUnit: beyond the basics - Adam Dudczak

374
views

Published on

Yes... I've heard about Spock ;-) and most likely dozens of other testing frameworks which were created after JUnit started to exist. JUnit is old, it's sometimes a bit grumpy, nevertheless it is stil …

Yes... I've heard about Spock ;-) and most likely dozens of other testing frameworks which were created after JUnit started to exist. JUnit is old, it's sometimes a bit grumpy, nevertheless it is stil very concise and lightweight library. It is enough to spend 10 minutes with JUnit documentation to understand the basic elements of test, how to write an assertion and how to launch your first test. In a day to day job there are several other JUnit features which might be very handy, there are also a few curosities worth to mention. In this presentation I will try to cover most of them including: parameterized tests, theories (org.junit.experimental.theories), rules (@Rule) and common matchers. As was already said JUnit is not a newbie in a testing framework world, over the years several additional libraries were added, I will show you a few interesting once, including randomized testing, benchmarking and REST interactions testing.

This presentation was developed with the support of Poznań JUG, Tricity JUG and Szczecin JUG who were hosting this lecture in the past. Discussion which we had during and after the meetings was a great aid and influenced heavily current content of this presentation.

Adam Dudczak - Adam Dudczak (@maneo), software engineer in Allegro group, working with Java (and JUnit) since 2004. Currently member of Allegro search team working on a better search experience in Allegro.pl. One of the leaders of Poznań JUG (www.jug.poznan.pl) and co-organizer of GeeCON conference (geecon.org). Father and husband, occasionally blogs at dudczak.info/dry.


0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
374
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. JUNIT Beyond the basics /AdamDudczak @maneo Atmosphere2014,Warszawa,19-20.05.2014
  • 2. WHO AM I? Software Engineer in Allegro group Workingwith Java(and JUnit) since 2004 One of the leaders of Co-organizer of conference Poznań JUG GeeCON
  • 3. WHY JUNIT? source:wikipedia
  • 4. THERE IS NO SPOCK... source:http://bit.ly/R0r8Ox
  • 5. WHY NOT? source:http://bit.ly/1jNoT8f
  • 6. ERRORRATE CLASS publicclassErrorRate{ doubleerrorRate; publicErrorRate(longnoOfItems,longnoOfErrors){ errorRate=calculateErrorRate(noOfItems,noOfErrors); } doublecalculateErrorRate(longnoOfItems,longnoOfErrors){ ... } publicStringgetErrorRateAsString(){ returnString.format("%2.02f",errorRate); } }
  • 7. SIMPLE ERRORRATE TEST publicclassErrorRateTest{ @Test publicvoidshouldCalculateErrorRate(){ //given ErrorRateerrorRate=newErrorRate(100,10); //when Stringresult=errorRate.getErrorRateAsString(); //then assertThat(result,is("0.01")); } }
  • 8. SIMPLE ERRORRATE TEST Object[][]testParameters=newObject[][]{ newObject[]{100,1,"0.01"}, newObject[]{0,0,"0.00"}, }; @Test publicvoidshouldCalculateErrorRate1(){ for(inti=0;i>testParameters.length;i++){ ErrorRateerrorRate =newErrorRate((Integer)testParameters[i][0], (Integer)testParameters[i][1]); Stringresult=errorRate.getErrorRateAsString(); assertThat(result,is((String)testParameters[i][2])); } }
  • 9. LET'S BRAKE SOMETHING... Object[][]testParameters=newObject[][]{ newObject[]{ 100,1,"0.02"}, newObject []{0,0,"0.02"}, }; Firsterror stops test Allcases are seen as one test
  • 10. JUNIT PARAMETRIZED @RunWith(Parameterized.class) publicclassErrorRateTest{ @Parameters publicstaticCollection<Object[]>data(){ returnArrays.asList(newObject[][]{ newObject[]{100,1,"0.01"}, newObject[]{0,0,"0.00"},}); } ...
  • 11. JUNIT PARAMETRIZED (2) ... longtotalNumberOfItems; longtotalNumberOfRejected; doublefinalErrorRate; publicErrorRateTest(longtotalNumberOfItems, longtotalNumberOfRejected, doublefinalErrorRate){ this.totalNumberOfItems=totalNumberOfItems; this.totalNumberOfRejected=totalNumberOfRejected; this.finalErrorRate=finalErrorRate; } ...
  • 12. JUNIT PARAMETRIZED (3) ... @Test publicvoidshouldCalculateErrorRate(){ //given ErrorRateerrorRate=newErrorRate(totalNumberOfItems, totalNumberOfRejected); //when Stringresult=errorRate.getErrorRateAsString(); //then assertThat(result,is(finalErrorRate)); } ...
  • 13. LET'S BRAKE SOMETHING... Two independenttests Alotof boilerplate code! Onlyone occurance of @Parameters per class
  • 14. JUNIT-PARAMS Parameterised tests thatdon'tsuck Created byPaweł Lipiński Alotof veryinterestingideas. https://code.google.com/p/junitparams/ <dependency> <groupId>pl.pragmatists</groupId> <artifactId>JUnitParams</artifactId> <version>1.0.2</version> <scope>test</scope> </dependency>
  • 15. JUNIT-PARAMS - SHOWCASE @RunWith(JUnitParamsRunner.class) publicclassSamples_of_Usage_Test{ @Test @Parameters({"AAA,1","BBB,2"}) publicvoidparams_in_annotation(Stringp1,Integerp2){} @Test @Parameters publicvoidparams_in_default_method(Stringp1,Integerp2){} privateObjectparametersForParams_in_default_method() { return$($("AAA",1),$("BBB",2)); }
  • 16. JUNIT-PARAMS - SHOWCASE @Test @Parameters(method="named2,named3") publicvoidparams_in_multiple_methods(Stringp1,Integerp2){} privateObjectnamed2(){return$($("AAA",1));} privateObjectnamed3(){return$($("BBB",2));} @Test @Parameters(source =ParametersProvidersTest.OneIntegerProvider.class) publicvoidparameters_from_external_class(intinteger){}
  • 17. JUNIT-PARAMS - SHOWCASE @Test @FileParameters("src/test/resources/test.csv") publicvoidload_params_from_csv(intage,Stringname){} @Test @FileParameters(value="src/test/resources/test.csv", mapper=PersonMapper.class) publicvoidload_params_from_any_file(PersonTest.Personperson){} @Test @FileParameters("classpath:test.csv") publicvoidload_params_from_classpath(intage,Stringname){}
  • 18. JUNIT-PARAMS More examples can be found at iSamples_of_Usage_Test.java PersonTest.java Similar to approach in TestNG Testcode is clear and concise -YEAH!!
  • 19. ORG.JUNIT.EXPERIMENTAL.THEORIES Theoryis, in factaparameterized test This approach is more focused on requirements than on particular testcases Similar to ScalaCheck (Scala) /QuickCheck (Erlang)
  • 20. ORG.JUNIT.EXPERIMENTAL.THEORIES Theorydescribes features of class/method and verifies them usinggiven setof inputdata Theoryis executed as one test If assertion fails for anysetof inputdatawhole theoryfails Example in ErrorRate_05_Theory_Test.java
  • 21. RANDOMIZED UNIT TESTING "Monkeytesting"-more randomness in your tests http://labs.carrotsearch.com/randomizedtesting.html
  • 22. RANDOMIZED UNIT TESTING @Test publicvoidrandomizedTesting(){ //Herewepicktwopositiveintegers. //Notesuperclassutilitymethods. inta=randomIntBetween(0,Integer.MAX_VALUE); intb=randomIntBetween(0,Integer.MAX_VALUE); intresult=Adder.add(a,b); assertTrue(result+"<("+a+"or"+b+")?", result>=a&&result>=b); }
  • 23. SOMETHING WENT WRONG! @Seed("2300CE9BBBCFF4C8:573D00C2ABB4AD89")
  • 24. @THREADLEAKING* Randomized UnitTestinglibraryhelps to check/control threads activity @ThreadLeaking*annotations verfies if threads are leaking from your tests/suite Check outErrorRate_06_Randomized_Test.java
  • 25. @RULE source:http://bit.ly/1jNpE13
  • 26. @RULE Resuable @Before/@After... and more Example in JunitRulesShowcaseTest JUnithas severalbuilt-in @Rules, ex.: ExternalResource, ExpectedException, TestName...
  • 27. @RULE publicstaticclassHasTempFolder{ @Rule publicTemporaryFolderfolder=newTemporaryFolder(); @Test publicvoidtestUsingTempFolder()throwsIOException{ FilecreatedFile=folder.newFile("myfile.txt"); FilecreatedFolder=folder.newFolder("subfolder"); //... } } @Rule cannotbe applied to static fields -use @ClassRule
  • 28. @RULE IN BETAMAX importco.freeside.betamax.Betamax; importco.freeside.betamax.Recorder; importorg.junit.*; publicclassMyTest{ @RulepublicRecorderrecorder=newRecorder(); @Betamax(tape="mytape") @Test publicvoidtestMethodThatAccessesExternalWebService(){ } }
  • 29. @RULE WITH SPRING AND WIREMOCK @Rule publicWireMockRulewireMockRule=newWireMockRule(8089); //Checkouthttp://wiremock.org/ @Rule publicTestRulecontextRule=newSpringContextRule( newString[]{"testContext.xml"},this); @Autowired publicStringbar; @Test publicvoidtestBar()throwsException{ .... }
  • 30. JUNIT BENCHMARKS AND TIMEOUT publicclassMyTest{ @Rule publicTestRulebenchmarkRun=newBenchmarkRule(); @Rule publicTestTimeouttimeoutRule=newTestTimeout(30); @Test publicvoidtwentyMillis()throwsException{ Thread.sleep(20); } } MyTest.twentyMillis:[measured10outof15rounds] round:0.02[+-0.00],round.gc:0.00[+-0.00],GC.calls:0, GC.time:0.00,time.total:0.32, time.warmup:0.12,time.bench:0.20
  • 31. JUNIT BENCHMARKS Chartand persistentresults history http://labs.carrotsearch.com/junit-benchmarks.html
  • 32. BETTER EXCEPTION HANDLING Example byRafał Borowiec ( )blog.codeleak.pl/ publicclassExpectedExceptionsTest{ @Rule publicExpectedExceptionthrown=ExpectedException.none(); @Test publicvoidverifiesTypeAndMessage(){ thrown.expect(RuntimeException.class); thrown.expectMessage("Runtimeexceptionoccurred"); thrownewRuntimeException("Runtimeexceptionoccurred"); } }
  • 33. "NEW" ASSERTIONS source:http://bit.ly/1taOW0H
  • 34. "NEW" ASSERTIONS assertThatand built-in Hamcrestmatchers Readable assertions and better error handling assertThat("thisstring",is("thisstring")); assertThat(theBiscuit,is(equalTo(myBiscuit))); assertThat("thisstring",containsString("is"));
  • 35. ALTERNATIVE APPROACH - FEST/ASSERTJ Alternative (butin factamainstream) wayof building assertions gives access to hundreds of assertionsAssertJ assertThat(frodo.getName()).isEqualTo("Frodo"); assertThat(frodo).isNotEqualTo(sauron) .isIn(fellowshipOfTheRing); assertThat(sauron).isNotIn(fellowshipOfTheRing);
  • 36. ORGANIZE TESTS IN @SUITE @RunWith(Suite.class) @SuiteClasses({ ErrorRate_01_SimpleTest.class, ErrorRate_03_Parametrized_Test.class }) publicclassSuiteInitializationExample{ @ClassRule publicstaticExternalResourceresource=newExternalResource(){ @Override protectedvoidbefore()throwsThrowable{ System.out.println("StartingtheheavyweightServer"); }; @Override protectedvoidafter(){ System.out.println("StoppingtheheavyweightServer"); }; }; }
  • 37. CATEGORIES/SUITES AND BUILD TOOLS Suite is abitAnt-ish -use Categories Categories are supported byboth andMaven Gradle <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <groups>com.ex.FastTests,com.ex.RegressionTests</groups> </configuration> </plugin> </plugins> </build>
  • 38. USE CATEGORIES ON THE @SUITE LEVEL publicclassHeavyIntegrationTest{ @Test @Category(HeavyWeight.class) publicvoidshouldCalculateErrorRate(){ assumeTrue(isHeavyWeightServerRunning()); //heavestuffwithheavyWeightserverhere } ...
  • 39. USE CATEGORIES ON THE @SUITE LEVEL @RunWith(Categories.class) @IncludeCategory(HeavyWeight.class) @SuiteClasses({ ErrorRate_01_SimpleTest.class, HeavyIntegrationTest.class }) publicclassSuiteWithCategories{ //categorymarkerinterface publicinterfaceHeavyWeight{} ...
  • 40. CODE SAMPLES Allexamples can be found at: https://bitbucket.org/maneo/junit-presentation/
  • 41. THAT'S ALL FOLKS Thank you for your attention. adam (at) dudczak.info /@maneo