Jimmy Bogard, wrote an article: “Getting value out of your unit tests”, where he gives three rules:
- “Test names should describe the what and the why, from the user’s perspective” – the idea is that a developer should be able to read the name and understand what the intended behavior is.
- “Tests are code too, give them some love” – production code isn't the only place that you should do your refactoring. Readable tests are easier to maintain and easier for next person to understand. “I hate, hate long, complex tests. If a test has 30 lines of setup, please put that behind a creation method. A long test just irritates and leaves the developer cross-eyed. If I don’t have long methods in production code, why would I allow this in our test code?”
- “Don’t settle on one fixture pattern/organizational style” – Sometimes the standard pattern of one class, one test fixture doesn’t work.
Lior Friedman added: “Rule #0 - Test external behavior and not internal structure.” Or, test the expectations for a class not its current structure.
Ravichandran Jv added his own rules:
- One Assert per test (where possible).
- If there are any "if else" inside a test, move the branches to individual test methods.
- Methods under test, if they, too, have if else branches, the method should be refactored.
- Name of the method should be the kind of test. For instance, TestMakeReservation is different from TestMakeNoReservation().
Charlie Poole, author of NUnit, rewords one Assert per to test to one “Logical Assert” – saying “Sometimes, due to a lack of expressiveness in the testing api, you need to write multiple physical asserts to achieve the desired result. Much of the development in the NUnit framework api has been out of an attempt to get a single assert to do more work.”
Bryan Cook produces a considerable list of his own:
- DO: Name Fixtures consistently
- DO: Mimic namespaces of Target Code
- DO: Name Setup/TearDown methods consistently
- CONSIDER: Separating your Tests from your Production Code
- DO: Name Tests after Functionality
- CONSIDER: Use "Cannot" Prefix for Expected Exceptions
Bryan has over a dozen more suggestions.
Finally a couple of people suggested Gerard Meszaros’s book: “xUnit Test Patterns: Refactoring Test Code”
Previously on InfoQ: Recommended TDD Tutorials, Designing for Testability, Unit Testing Tips from Googleand Making TDD Stick: Problems and Solutions for Adopters
Community comments
Re: Guidelines for Better Unit Tests
by Christoph Kutzinski,
Re: Guidelines for Better Unit Tests
by Mark Levison,
Typo?
by Kerry Buckley,
Re: Typo?
by Mark Levison,
Long Bean (Pojo) UnitTesting
by Faisal Basra,
Re: Long Bean (Pojo) UnitTesting
by jean-simon Larochelle,
Re: Long Bean (Pojo) UnitTesting
by James Richardson,
I would add rule -1
by jean-simon Larochelle,
Another book (for dotnet shops..)
by HJ Meulekamp,
Re: Another book (for dotnet shops..)
by Mark Levison,
Test code IS production code
by Piers Thompson,
Re: Test code IS production code
by Mark Levison,
Re: Test code IS production code
by Leonid Maslov,
Interesting video on unit testing
by Franco Martinig,
Re: Guidelines for Better Unit Tests
by Christoph Kutzinski,
Your message is awaiting moderation. Thank you for participating in the discussion.
> CONSIDER: Separating your Tests from your Production Code
No, don't consider it - do it!
Don't let ANY test code slip into your production environment!
Re: Guidelines for Better Unit Tests
by Mark Levison,
Your message is awaiting moderation. Thank you for participating in the discussion.
Agreed - but I can't change other people's words. I think the key point is your tests are code think carefully about them and treat them nicely.
Typo?
by Kerry Buckley,
Your message is awaiting moderation. Thank you for participating in the discussion.
Surely "...is not the only place..."?
Long Bean (Pojo) UnitTesting
by Faisal Basra,
Your message is awaiting moderation. Thank you for participating in the discussion.
What if, I have a very long object, basically we have an enterprise application, We have a very big object named Proposal, that contains several nested child objects, then how I can test it integrated with all child populated. We have Spring with Hibernate configured.
Looking expert advice.
Re: Typo?
by Mark Levison,
Your message is awaiting moderation. Thank you for participating in the discussion.
Thanks typo. Sorry for the mistake.
Re: Long Bean (Pojo) UnitTesting
by jean-simon Larochelle,
Your message is awaiting moderation. Thank you for participating in the discussion.
You should start by extracting the nested class to separate package visibility class. If the nested class are not static you will probably have to add a parameter to the constructor where you will use 'this' as a parameter. I find myself avoiding nested class more and more because in the end they make class bigger and more difficult to test. If you extract those you might even be able to use 'mocks' if you add interfaces to them.
We use the DbUnit extension to test database stuffs. Search the Web for tips on testing Hibernate based code.
I would add rule -1
by jean-simon Larochelle,
Your message is awaiting moderation. Thank you for participating in the discussion.
Any tests is better than none.
Re: Long Bean (Pojo) UnitTesting
by James Richardson,
Your message is awaiting moderation. Thank you for participating in the discussion.
do you mean a RunnerBean?
Another book (for dotnet shops..)
by HJ Meulekamp,
Your message is awaiting moderation. Thank you for participating in the discussion.
I'm currently reading the art of unittesting
www.artofunittesting.com/
I think it is a great practical programmers book, reviewers on amazon seem to agree with me..
Test code IS production code
by Piers Thompson,
Your message is awaiting moderation. Thank you for participating in the discussion.
“Tests are code too, give them some love”
I prefer "Test code IS production code".
Good developers have a refined sense of what isn't appropriate in production code (long methods, meaningless identifiers, cut'n'paste, complex 'if' statements, code formatting etc etc etc) which doesn't always get applied to the test code - "it's only test code - bad practices don't really matter as long as it works".
This is symptomatic of having working on projects without a large automated test suite that needs to be maintained along with the code. If you have such a suite then maintaining it is as significant a consumer of development effort as maintaining the non-test code. Therefore you must pay attention to the maintenance costs of your test code - and that means applying all the usual good practices to the test code as well as the non-test code.
Remember - "Test code IS production code".
P.
Re: Another book (for dotnet shops..)
by Mark Levison,
Your message is awaiting moderation. Thank you for participating in the discussion.
I've had a chance to read this book, but like you have heard good things about it.
Re: Test code IS production code
by Mark Levison,
Your message is awaiting moderation. Thank you for participating in the discussion.
"Test code IS production code" - I like it. An even better statement.
Interesting video on unit testing
by Franco Martinig,
Your message is awaiting moderation. Thank you for participating in the discussion.
Kevin Henney made an excellent presentation on this topic at Oredev 2008. You can watch the video on www.testingtv.com/2009/08/18/know-your-units/
Re: Test code IS production code
by Leonid Maslov,
Your message is awaiting moderation. Thank you for participating in the discussion.
I really like Your statement, I would like to think of it myself :))
Trying to tell the same in my article. In my opinion tests are the most fragile part of application production code , the one you would like to be as much readable and clear it could be, the simplest it could be and s on... Actually all the qualities You would like to have to your business/mission critical code :)))