Test-Driven Development An Introduction Mattias Ståhlberg mattias.stahlberg@enea.com
Debugging sucks. Testing rocks.
Contents 1. What is unit testing? 2. What is test-driven development? 3. Example 4. Writing Testable Code 5. Continuous Integration 6. Recommended reading 7. Conclusions
What is a Unit Test? A unit is a class or a set of related functions Smallest part that makes sense to test Tests that the unit does what the programmer intended Tests the unit s public interface Written contract that the production code must satisfy Requires an automatic unit testing framework
Java Example with JUnit @Test public void shouldcalculateaveragespeed() { Track track = new Track(); track.addpoint(0, 0, 0); track.addpoint(0, 1, 1); track.addpoint(1, 1, 2); track.addpoint(1, 0, 3); track.addpoint(0, 0, 4); assertequals(1, track.averagespeed()); } @Test(expected=ArithmeticException.class) public void averagespeedshouldthrowexceptiononzerodistance() { Track track = new Track(); track.averagespeed(); }
Advantages of Unit-Tested Code Gives courage to modify and improve (refactor) the code Knowledge that the code works Problems solved early in the development phase Documents the code Little or no need for debugging Reduced need for costly manual testing Saves time and money
Properties of Good Unit Tests Descriptive name Readable Focused Isolated Automatic Repeatable Fast
Contents 1. What is unit testing? 2. What is test-driven development? 3. Test coverage 4. Visualizing test results 5. Excuses for not testing 6. How to succeed 7. Common pitfalls 8. Recommended reading 9. Conclusion
What is Test-Driven Development? Test-driven is more about design than about testing A design method that renders clean, well-tested code Short iterations where unit tests, either for improvements or new functionality, are written first
What is Test-Driven Development? (contd.) Can also be applied to other types of tests (e.g. acceptance tests) Does not imply no formal testing Kent Beck: Never write a single line of code unless you have a failing automated test Eliminate duplication
Development Cycle 1. Create a new automatic test case 2. Run all tests and watch the new one fail 3. Write production code to make the test pass 4. Run all tests and watch them pass 5. Refactor the code, e.g. eliminate duplicated code 6. Start over Refactor
Advantages of Test-Driven Development Interfaces are tried before they exist more mature interfaces More and better tests improved quality Design and code evolved in small steps less risk, less integration problems Less risk to develop functionality that might be needed Less risk to skip testing when time is short Addictive, stimulating, and great fun Regular and frequent positive feedback
Test-Driven Bug Fixing 1. Create an automatic test that indicates the existence of the bug 2. Locate the bug 3. Fix the bug Ensures that the automatic tests will detect the problem if it should arise again
Contents 1. What is unit testing? 2. What is test-driven development? 3. Example 4. Writing Testable Code 5. Continuous Integration 6. Recommended reading 7. Conclusions
Live Demonstration TDD using Eclipse and JUnit http://www.eclipse.org http://www.junit.org/
Contents 1. What is unit testing? 2. What is test-driven development? 3. Example 4. Writing Testable Code 5. Continuous Integration 6. Recommended reading 7. Conclusions
Writing testable code Use dependency injection Inject interfaces Favor object composition over class inheritance Impossible to chose different class hierarchy at testtime but easy to chose different object composition Favor polymorphism over conditional statements Leads to smaller and more focused classes, which are easier to test
Writing testable code (contd.) Avoid global state and singletons Cannot be replaced at test-time If you really have to have a singleton: Wrap it in a simple adapter Avoid non-private static method calls Cannot be replaced at test-time Can be wrapped in a simple adapter Strive for small and focused classes with clear responsibilities Test first!
Google's guide to testable code http://misko.hevery.com/code-reviewers-guide/ Flaw #1: Constructor does Real Work Flaw #2: Digging into Collaborators Flaw #3: Brittle Global State & Singletons Flaw #4: Class Does Too Much
Contents 1. What is unit testing? 2. What is test-driven development? 3. Example 4. Writing Testable Code 5. Continuous Integration 6. Recommended reading 7. Conclusions
Definition of Continuous Integration A fully automated and reproducible build, including testing, that runs many times a day Martin Fowler (September 2000) A software engineering practice in which isolated changes are immediately tested and reported on when they are added to a larger code base. http://whatis.com (July 2008)
Continuous Integration Benefits Allows each developer to integrate daily thus reducing integration problems Provides rapid feedback on the health of the software If a defect is introduced into the code base, it can be identified and corrected as soon as possible Enables project visibility at all levels
Visualizing Test Results
Try it out! Download Hudson from www.hudson-ci.org $> java jar hudson.war
Contents 1. What is unit testing? 2. What is test-driven development? 3. Example 4. Writing Testable Code 5. Continuous Integration 6. Recommended reading 7. Conclusions
Recommended Reading Kent Beck: Test-Driven Development By Example Andy Hunt, Dave Thomas: Pragmatic Unit Testing in Java with Junit Martin Fowler: Refactoring: Improving the Design of Existing Code http://www.refactoring.com/ http://xunitpatterns.com/ (also as printed book) http://googletesting.blogspot.com/ Testing on the toilet http://misko.hevery.com/code-reviewers-guide/
Contents 1. What is unit testing? 2. What is test-driven development? 3. Example 4. Writing Testable Code 5. Continuous Integration 6. Recommended reading 7. Conclusions
Unit testing Gives courage to refactor and improve Eliminates problems early Requires discipline Saves time and money
Test-driven development Is a design method Gives better unit tests Renders clean code that works Is great fun
Continuous Integration Brings visibility and rapid feedback to the project