Sei sulla pagina 1di 27

Unit and Functional Testing with

JUnit and Related Tools


Greg Barnes
University of Washington
gsbarnes@washington.edu
Introduction
Testing
JUnit, etc.
Best practices from the testing community
My best practices
Types of Testing
Unit testing: Does a single object work?
Integration testing: Do multiple objects work together?
Functional testing: Does my application work?
Performance testing: Does my application work well?
Acceptance testing: Does the customer like my
application?
Why Test?
No-brainers: Functional, Acceptance, Performance testing
Why Unit Test?
Coverage, especially of strange conditions
Facilitates teamwork, lessens 'ownership'
Confidence in your own work
Enable refactoring
Self-documentation of API
Improve design
How to use tests
A common testing cycle:
Write some new code OR Fix a bug OR Refactor
some code
Run tests to ensure the now-changed code works
Check the new code in
Basic testing principles
For things that can be tested automatically, tests
should be:
easy to write
easy to run
objective (easy to see if they pass or fail)
repeatable (deterministic)
JUnit
Open source framework for testing Java code
Attempts to make writing unit tests easy
Structure:
TestSuites
TestCase [Java class]
Test [Java method]
Fixtures: common setup/teardown code
Most often you write TestCases, Tests, and Fixtures
Example
import junit.framework.TestCase;
public class TestString extends TestCase {
public void testEndsWith() {
assertTrue(abcabc.endsWith(abc));
}
public void testEndsWithEmptyString() {
assertTrue(Doesn't end with empty string!,
abcabc.endsWith());
}
}
Some best practices
TestCases (Java classes)
Usually test a single Java class
Name starts or ends with Test
Tests (Java methods)
test a single method
testXxx tests method xxx
multiple tests of method xxx are named testXxxYyy,
where Yyy describes a particular condition, e.g.,
testEndsWithEmpty
Label your assertions
One test per test method
More details
fixtures: setUp, tearDown
assertFalse, assertEquals, assertNotEquals,
assertNull, etc., etc.
JUnit 4/Java 5 some incremental improvements
Running JUnit tests
Many ways:
Command line
IDE (Eclipse plug-in, etc.)
Ant
Maven
Various ways of viewing output (text, XML ->
Web page, ...)
More best practices
Run your tests using a tool: IDE, Ant, Maven
Tests should be independent
Same package, different directory
src test
org org
jasig jasig
SomeClass.java TestSomeClass.java
OtherClass.java TestOtherClass.java
Related tools
xUnit - e.g., CUnit for C
WebTest, HttpUnit web applications
DBUnit database-driven code
Cactus J2EE components
Code coverage tools Do my tests cover all
possible lines of code?
Continuous testing tools Run tests on a
schedule, or whenever code is checked in
Functional testing
For web applications: WebTest, HttpUnit, Cactus,
JMeter...
HttpUnit and Cactus tests are like JUnit
WebTest uses XML to specify tests
JMeter has a GUI (and writes XML)
All require a special environment to run tests
Functional tests usually are slower than unit tests
Functional tests usually are run separately from unit tests
Best practices from the testing
community
If its hard to write a test, the code your testing
should probably be changed.
To test a private method, make it protected
(or package-protected)
Best Practices from the testing
community II
Test anything that can reasonably break

Best practices from the testing
community III
Always verify that tests fail when they should
Particularly important if youre fixing a bug
Test-Driven Development
Always write a failing test before writing any new
code
Refactor

Best Practices from the testing
community IV
Test one object at a time
Stubs, mock objects
Mock Objects
Allow you to test a class that relies on other, non-
trivial objects, particularly objects that are
difficult to instantiate or slow
Mock versions of many popular classes (e.g.,
HttpRequest)available, as well as packages
that create Mocks automatically
Example

Want to test DB.getUser(User, Callback), but it's
hard to create a Callback object.

public void testGetUser() {
Callback mc = new MockCallback();
assertNotNull(DB.getUser(new User(), mc)
}
More on Mocks
Mocks can keep track of how they were used, so
you can check in with them afterwards to make
sure the class you're testing performed the
operations you expected

Example
Check that DB.getUser(User, Callback)
actually does what it's supposed to do with the
Callback object

MockCallback mc = new MockCallback();
mc.expects([something]);
mc.expects([something else]);
assertNotNull(DB.getUser(new User(), mc);
mc.verify();
My best practices
Write tests that work and are easy to use.
Dont reject tests if they work and are easy to use.
Create a test whenever fixing a bug. Make sure it
fails before fixing the code.
Create a test when adding a new feature, or
tricky code.
Write clean test code.
Best practices you can break
If it helps you write and run tests more often:
Ignore test-driven design
Dont obsess about testing `anything that could
possibly fail
Test more than one object at once
But
Learn about mock objects
Learn about other tools
Conclusions
Testing is good
Don't put barriers in the way of writing and
running tests
Learn about the testing toolbox, and be prepared
to use the tools as appropriate
References
http://www.junit.org
http://httpunit.sourceforge.net
JUnit in Action Vincent Massol
Java Development with Ant Erik
Hatcher, Steve Loughran
Sample project rules relating to tests
If a change you make creates a bug, and the tests
dont pass, its your fault.
Dont check in code unless the tests pass.
If a change you make creates a bug (in other
code), and the tests pass, its the fault of whoever
wrote the other code.
Write more tests.

Potrebbero piacerti anche