Introduction to Unit Testing SE 2 Tutorial
Herman Lee May 26, 2008
Based on tutorial slides prepared by Thiago Bartolomei SE 3 lecture slides prepared by Paulo Alencar
Testing Stages
Unit testing
Testing of individual components
Integration testing
Testing to expose problems arising from the combination of components
System testing
Testing the complete system prior to delivery
Acceptance testing
Testing by users to check that the system satisfies requirements. Sometimes called alpha testing
Approaches to Low Level Testing
Debugging/Output calls
Cannot be automated Time consuming Application and test code get tangled (output calls)
Unit testing
Set of test cases targeting a single module and organized in test suites Strongly encouraged by the agile community
More Reasons to do Unit Testing
Provide a working specification of the functional code Automation
Write test once, use many times Regression tests incorrect changes discovered immediately more confidence in the code
Test Driven Design (TDD)
TDD = Test First Development + Refactoring
Test First Development
The act of writing a unit test is more an act of design than of verification. It is also more an act of documentation than of verification. (Robert C. Martin) Idea is to write first the unit tests for a module, and then implement the module. Why?
Writing the test makes you understand better the functional code and thus design it better (from the client perspective) Test becomes a documentation artifact, that clearly states the intention of the module
Test Driven Design Steps
Write tests that fail Implement modules to make tests pass Run all tests to make sure nothing is broken Refactor to keep code clean Continue development
Unit Testing with JUnit
Unit testing framework from Kent Beck (XP) and Erich Gamma (Gang of Four) Tool to support one of XP best practices Integrated in the Eclipse IDE Followed by cppUnit, phpUnit, pyUnit, etc
Preparing Eclipse Project
Create a regular project Project properties
Build Path add JUnit as a library (already shipped with Eclipse) Build Path optionally add a folder for tests Compiler if JUnit version 4, use Java version 5
That's it!
Example 1 Test Case (JUnit 3)
1) Test class must subclass TestCase. Usually it is named by adding suffix Test to tested class name. 2) Test methods must have prefix test 3) assertTrue(), assertEquals(), etc, give test pass conditions. E.g. assertTrue(x==10); 4) Test fixture a common environment to run a set of similar tests. Use setUp() and tearDown() methods to create and destroy the environment
Example 2 Test Suite (JUnit 3)
1) Test cases are organized in suites by subclassing (or constructing) TestSuite 2) Add single tests (methods) to suite using the add method or let JUnit extract them from the whole test case class 3) Execute tests using a test runner (in command line, standalone application or integrated in Eclipse)
JUnit 4
Test Cases
No longer have to extend TestCase Test methods annotated with @org.junit.Test setUp/tearDown annotated with @Before/@After Assertions statically accessed from Assert
Test Suites
No longer extend TestSuite Annotated with RunWith and Suite
Example
Source: http://www.devx.com/Java/Article/31983/0/page/1
JUnit 3 vs. JUnit 4
Source: http://www.devx.com/Java/Article/31983/0/page/2
DEMO in Eclipse
Some problems you may encounter
How to test a class A that depends on class B, if B has not been implemented yet?
Use a fake class B, called a Mock class Remember that classes should depend on interfaces B should be an interface! Note how this forces you to think about and minimize the dependencies, in order to make testing easier!
Some problems you may encounter
How to test a class that is very big and participates in many scenarios?
Rethink why this class is so big (God Class = Bad Smell) Refactor it in several smaller classes with well defined functionality and test them individually.
Some problems you may encounter
Where do I put my tests?
Either in the same package as the tested class:
pack.TheClass, pack.TheClassTest
Or in a test package:
pack.TheClass, pack.test.TheClassTest
Also, in an Eclipse project, you can have different source folders with the same package:
src/pack.TheClass, test/pack.TheClassTest Advantage you have protected access to the class
Some problems you may encounter
How to test UI?
Test functionality by accessing directly the lower tier (maybe a Facade or MVC pattern?) Testing UI itself usually requires specific tool support - Ex. HTTPUnit to do webpages testing
References / Further Study
Test Driven Development (TDD)
Test Driven Development: By Example, by Kent Beck http://www.agiledata.org/essays/tdd.html
Agile Software Development, Refactoring, Test First Design
Agile Software Development: Principles, Patterns, and Practices, by Robert C. Martin Refactoring: Improving Design of Existing Code, by Martin Fowler http://www.xprogramming.com and .org
References / Further Study
Unit test design patterns
http://www.marcclifton.com/tabid/87/Default.aspx http://www-106.ibm.com/developerworks/library/jmocktest.html
JUnit
http://www.junit.org JUnit 3 vs 4
http://www.devx.com/Java/Article/31983