TL;DR
* Software Quality Axes - Focus on test - Quality of a good test * Libraries to write maintainable tests - Junit, fest, mockito, openpojo, spring-mock - Build forge with jenkins and sonar * IDE features and plugins - Eclipse : shortcuts, static imports, eclipse template for junit4, eclipse save actions - Plug-ins : more unit, Eclemma codecoverage, infinitest, sonar ide * Coding style - Test as running specifications - Write testable code - Junit best practices * Conclusion
Software Quality Axes
Sonar is defining software quality through these 7 axes. I will mainly focus on unit tests and their code coverage, maintainability and make them fun to write.
As Java developers we are really lucky,
- there’s a plethora of libraries to write easily, maintainable tests and
- we have also a great IDE with a lot of plug-ins and built-in feature to maximize our productivity !
Quality of a good test from Kent Beck :
- isolated (unaffected by the presence, absence, or results of other tests)
- automated
- easy to write
- easy to read : expressive -> maintainable (fix or add new ones)
- easy to run
- unique : don’t overlap with others -> code coverage
I picked up some plugins and libraries to help on these areas.
Libraries to write maintainable tests
JUnit (easy to run)
JUnit3’s last release was in 2002. So it’s time to move to junit4 ! All the tooling around junit is available : ide, maven, jenkins, sonar,…
Don’t forget to use the ‘new’ features like
- parameterized testto run the same test with different dataset.
- MethodRuleto collect statistics or extra data on failure/error.
- ExpectedException
- @RunWith(Parallelized.class)
I know testNg do this better… but junit is so widespread in my development environment.
Fest Assert(easy to read)
Default junit assertion are not really expressive, custom errors messages are often required to make failure more understandable to the developer. Fest-Assert is a library that let you as a developer write assertion fluently like assertThat(frodo.getAge()).isEqualTo(33);
or assertThat(fellowshipOfTheRing).hasSize(9);
. More samples in this snippet. After reading this article you will understand why I prefer fest-assert over hamcrest. Note also that festAssert can be extended to support your model : find a sample for jodatime assertions
(easy to write)
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors. Mockito will help you testing nominal use cases but also extreme situation like unexpected/rare/hard to reproduce Exception (like db connection issues, corrupted database,…).
org.springframework.mock.web
(easy to write)
The org.springframework.mock.web
package contains a comprehensive set of Servlet API mock objects, targeted at usage with Spring’s Web MVC framework, which are useful for testing web contexts and controllers. These mock objects are generally more convenient to use than dynamic mock objects such as mockito.
Openpojo (easy to write)
Trivializing POJO testing and Identity.
It’s perhaps no a great idea to test getters/setters. The main point with this library is in fact to let you focus on the non trivial code by covering the trivial one. You will be surprised how easy it is when you use openpojo.You can also easily add your own testers for example verifying equals/hashCode
transitity, reflectivity, nullsafety,..
Build forge based on
(easy to run)
Getting fast feedback from your commit or the one from your coworker is what jenkins provides you.
Sonar will follow the evolution of your project taking a look at potential bugs, code duplications, uncovered code, fragile test, integration test,…
IDE features and plugins
Eclipse shortcuts (easy to write)
To be a productive programmer, don’t use the mouse 😉 Eclipse offers already a lot of shortcuts.My favorites : ctrl-shift-T
or ctrl-shift-R
for a goto type or resources
If you don’t know them well, some articles here and here and a great plugin to learn them.
Static imports (easy to write)
Open Preferences (Window -> Preferences) Browse to Java -> Editor -> Content Assist -> Favorites Click 'New Type...' enter org.junit.Assert.* enter org.mockito.Mockito.* enter org.mockito.Matchers.* enter org.fest.assertions.Assertions.*
If you type mock and then press Ctrl + Space
, the static method Mockito.mock
is proposed. The static import is added.
see it in action here
Eclipse template for junit4 (easy to write)
These templates once imported will help you to produces junit4 test method via content assist.
enter test
Ctrl + Space
and pick test4
your test method is generated just fill the name of the testcase
Eclipse save actions
Sonar is checking unused import, and the systematic use of braces. The good news is that you can configure eclipse to fix these 2 plagues automatically with save-actions
Under "Preferences": Java > Editor > Save Actions Check "Additional actions" Click "Configure…" Go to the "Code Style" tab Check "Use blocks in if/while/for/do statements" and configure to your preferences
plugin (easy to write and run)
MoreUnit assist you in writing more unit tests. With feature like easy navigation between code and unit test, skeleton generation,…
ctrl-j jump to test or code ctrl-r run associated test
If you don’t really follow the same naming convention as proposed by the plugin you can modify the preference ‘enable extended search for test methods:’
If needed there’s a similar plugin : fast code
Eclemma codecoverage plugin (unique and isolated)
Detecting uncovered code allows you to easily identify missing unit tests.
Eclemma brings code coverage analysis directly into the Eclipse workbench:
- Fast develop/test cycle:Launches from within the workbench like JUnit test runs can directly be analyzed for code coverage.
- Rich coverage analysis:Coverage results are immediately summarized and highlighted in the Java source code editors.
- Non-invasive: EclEmma does not require modifying your projects or performing any other setup.
(easy to run)
Infinitest is a never ending unit tests runner, displays assertions failure or errors as problem just like compilation errors ! To make infinitest your new best friend you need a fast test suites or filter out the slow ones.
Let’s see fest and infinitest in action : errors displayed in front of contains
and the fest message shows the actual content of the fellowshipOfTheRing
plugin
Setting up checkstyle, findbugs, pmd in all your developers workspaces, keeping all the plugins and rules up to date is quite hard. This last plugin will cover all the other axes. A good habit is to launch it when you think you are done… you will perhaps discover that you are not done yet 😉
The Sonar Eclipse Plugin provides a comprehensive integration of Sonar in Eclipse for Java projects. The objective of this integration is that developers do not leave their favorite IDE anymore to manage the quality of their source code. Most information displayed in the Sonar Web interface is now available in Eclipse. You can run local analysis based on the ruleset configured in your central sonar server.
Coding style
Writing tests is always easier if your code is designed to be testable and your test shows the intent of the test.
writing unit test as running specifications :
A good naming convention make it clear what you expect from the MailInboxSyncer
implementation.
Class MailInboxSyncerTest { @Test itShouldSyncMessagesFromPopSinceLastSync() {...} @Test itShouldCloseConnectionEvenWhenExceptionThrown() {...} @Test itShouldSyncMessagesOnlyWhenNotAlreadyInInbox() {...} @Test itShouldIgnoreMessagesOlderThenLastSync() {...} @Test itShouldIgnoreMessagesFailingFilter() {...} @Test itShouldDefaultToDefaultTimeWhenNeverSynced() {...} }
Write testable code
In general, don’t follow any rules from this article on How To Write Unmaintainable Code and Ensure a job for life ;-)
.
Global state is undesirable (statics, singleton,…) see testability-explorer and then injectability is good : dataSource=new org.apache.commons.dbcp.BasicDataSource()
vs setDataSource(Datasource datasource)
.
Code Design principles that could help having a code base more testable
Layered design Code against interfaces Put the code where it belongs Prefer composition over inheritance. Favor polymorphism over conditionals Avoid static methods and the Singleton pattern. Isolate dependencies. Inject dependencies
Code practices that don’t help
Mixing of concerns (business logic, caching, transaction,...) Mixing service objects with value objects Kilometric classes/methods A lot a dependency between your classes Do complicated creation work in objects Avoid interface usage, depends on concrete Static methods/fields Satefull singletons A lot of global attributes Make the scope of variable broader then required
Junit Best practices
donts
Don't write unit test without any assert Don't log… but assert Don't write complex condition logic : something you are not testing or something that is too complex that should be re-factored. Avoid hard-coding dataset Avoid over complex assert
do
Small and fast test No side effect A bug means a new unit test Externalize your dataset if possible (xml,csv,...) Avoid time dependency via jodatime
For spring integration test : @RunWith(SpringJUnit4ClassRunner.class) Assert result (not null, empty,…) Delta assertion : The pattern is like this: 1.measure 2.exercise 3.measure second times and 4.assert on deltas Guard Assertion : You assert some state before exercising the SUT. For ex an empty case for current dataset Create custom assertions if needed : When complex assertion are “copy-pasted” over the test code or when the assertion code “hides” the goals of the test you can “extract the code” in assertion method.
Conclusion
No excuse ! You have a now my personal toolbox to write more (maintainable) tests.
I’d like to thank all these developers contributing to a better quality, more productivity, gain in visibility via their tools and libraries !
Anything missing from this list ?
Do you have experience with bdd frameworks ?
Share your own testing pearls ?
#1 by mestachs on June 19, 2012 - 6:09 am
Things you should test ?
http://infiniteundo.com/post/25230828820/things-you-should-test
#2 by mestachs on June 24, 2012 - 7:56 am
http://blog.iterate.no/2012/06/20/programming-like-kent-beck/#3. Best Practices for [Unit] Testing
#3 by Anusree on June 29, 2012 - 5:52 am
This is a good list of eclipse plugins.Fast Code plugin is very good in unit test but this plugin can do much more to generate test
#4 by Joel Costigliola (@JoCosti) on June 30, 2012 - 3:19 pm
Just to let you know that Fest Assert 2.0 is available (milestone 6 to be precise, but is ready to use).
check this link : https://github.com/alexruiz/fest-assert-2.x/wiki
Regards,
Joel
#5 by mestachs on November 27, 2012 - 6:55 pm
in the same category : http://www.codeaffine.com/2012/11/26/working-efficiently-with-junit-in-eclipse-2/