Você está na página 1de 12

JUnit Tutorial

Summary

This article demonstrates a quick and easy way


to write and run JUnit test cases and test
suites. We'll start by reviewing the key benefits
of using JUnit and then write some example
tests to demonstrate its simplicity and
effectiveness.

Table of Contents

This article contains the following sections:

• Introduction
• Why Use JUnit?
• Design of JUnit
• Step 1: Install JUnit
• Step 2: Write a Test Case
• Step 3: Write a Test Suite
• Step 4: Run the Tests
• Step 5: Organize the Tests
• Testing Idioms
• Training and Mentoring
• Resources

Why Use JUnit?


JUnit actually helps you write code faster while increasing code
quality. Once you start using JUnit you'll begin to notice a
powerful synergy emerging between coding and testing,
ultimately leading to a development style of only writing new
code when a test is failing.

Here are just a few reasons to use JUnit:

• JUnit tests allow you to write code faster while


increasing quality.
When you write tests using JUnit, you'll spend less time
debugging, and you'll have confidence that changes to
your code actually work. This confidence allows you to
get more aggressive about refactoring code and adding
new features.

Without tests, it's easy to become paranoid (suspicious|


fearful| obsessed) about refactoring or adding new
features because you don't know what might break as a
result. With a comprehensive test suite, you can quickly
run the tests after changing the code and gain
confidence that your changes didn't break anything. If a
bug is detected while running tests, the source code is
fresh in your mind, so the bug is easily found. Tests
written in JUnit help you write code at an extreme pace
and spot defects quickly.

• JUnit is elegantly simple.

Writing tests should be simple - that's the point! If


writing tests is too complex or takes too much time,
there's no incentive to start writing tests in the first
place. With JUnit, you can quickly write tests that
exercise your code and incrementally add tests as the
software grows.

Once you've written some tests, you want to run them


quickly and frequently without disrupting the creative
design and development process. With JUnit, running
tests is as easy and fast as running a compiler on your
code. In fact, you should run your tests every time you
run the compiler. The compiler tests the syntax of the
code and the tests validate the integrity of the code.

• JUnit tests check their own results and provide


immediate feedback.

Testing is no fun if you have to manually compare the


expected and actual result of tests, and it slows you
down. JUnit tests can be run automatically and they
check their own results. When you run tests, you get
simple and immediate visual feedback as to whether the
tests passed or failed. There's no need to manually comb
through a report of test results.
• JUnit tests can be composed into a hierarchy of
test suites.

JUnit tests can be organized into test suites containing


test cases and even other test suites. The composite
behavior of JUnit tests allows you to assemble collections
of tests and automatically regression test the entire test
suite in one fell swoop. You can also run the tests for any
layer within the test suite hierarchy.

• Writing JUnit tests is inexpensive.

Using the JUnit testing framework, you can write tests


cheaply and enjoy the convenience offered by the testing
framework. Writing a test is as simple as writing a
method that exercises the code to be tested and defining
the expected result. The framework provides the context
for running the test automatically and as part of a
collection of other tests. This small investment in testing
will continue to pay you back in time and quality.

• JUnit tests increase the stability of software.

The fewer tests you write, the less stable your code
becomes. Tests validate the stability of the software and
instill confidence that changes haven't caused a ripple-
effect through the software. The tests form the glue of
the structural integrity of the software.

• JUnit tests are developer tests.

JUnit tests are highly localized tests written to improve a


developer's productivity and code quality. Unlike
functional tests, which treat the system as a black box
and ensure that the software works as a whole, unit
tests are written to test the fundamental building blocks
of the system from the inside out.

Developer's write and own the JUnit tests. When a


development iteration is complete, the tests are
promoted as part and parcel of the delivered product as
a way of communicating, "Here's my deliverable and the
tests which validate it."
• JUnit tests are written in Java.

Testing Java software using Java tests forms a seamless


bond between the test and the code under test. The
tests become an extension to the overall software and
code can be refactored from the tests into the software
under test. The Java compiler helps the testing process
by performing static syntax checking of the unit tests
and ensuring that the software interface contracts are
being obeyed.

• JUnit is free!

Design of JUnit
JUnit is designed around two key design patterns: the
Command pattern [Command Pattern: An object encapsulates
everything needed to execute a method in another object.]
and the Composite pattern[Composite Pattern: Assemble
groups of objects with the same signature.].
A TestCase is a command object. Any class that contains test
methods should subclass the TestCase class. A TestCase can
define any number of public testXXX() methods. When you want
to check the expected and actual test results, you invoke a
variation of the assert() method.
TestCase subclasses that contain multiple testXXX() methods can
use the setUp() and tearDown() methods to initialize and release
any common objects under test, referred to as the test fixture.
Each test runs in the context of its own fixture, calling setUp()
before and tearDown() after each test method to ensure there
can be no side effects among test runs.
TestCase instances can be composed into TestSuite hierarchies
that automatically invoke all the testXXX() methods defined in
each TestCase instance. A TestSuite is a composite of other tests,
either TestCase instances or other TestSuite instances. The
composite behavior exhibited by the TestSuite allows you to
assemble test suites of test suites of tests, to an arbitrary
depth, and run all the tests automatically and uniformly to
yield a single pass or fail status.

Step 1: Install JUnit

1. First, download
[http://sourceforge.net/project/showfiles.php?group_id=
15278] the latest version of JUnit, referred to below as
junit.zip.
2. Then install JUnit on your platform of choice:

Windows

To install JUnit on Windows, follow these steps:

1. Unzip the junit.zip distribution file to a directory


referred to as %JUNIT_HOME%.
2. Add JUnit to the classpath:

set CLASSPATH=%JUNIT_HOME%\junit.jar

Unix (bash)
To install JUnit on Unix, follow these steps:

3. Unzip the junit.zip distribution file to a directory


referred to as $JUNIT_HOME.
4. Add JUnit to the classpath:

export CLASSPATH=$JUNIT_HOME/junit.jar

3. Test the installation by using either the textual or


graphical test runner to run the sample tests distributed
with JUnit.

Note: The sample tests are not contained in the junit.jar,


but in the installation directory directly. Therefore, make
sure that the JUnit installation directory is in the
CLASSPATH.

Add %JUNIT_HOME% or D:\work\junit3.8 to class path to test the


intallation

To use the textual test runner, type:

java junit.textui.TestRunner junit.samples.AllTests

To use the graphical test runner, type:


java junit.swingui.TestRunner junit.samples.AllTests

All the tests should pass with an "OK" (textual runner) or


a green bar (graphical runner). If the tests don't pass,
verify that junit.jar is in the CLASSPATH.

Step 2: Write a Test Case


First, we'll write a test case to exercise a single software
component. We'll focus on writing tests that exercise the
component behavior that has the highest potential for
breakage, thereby maximizing our return on testing
investment.
To write a test case, follow these steps:

1. Define a subclass of TestCase.


2. Override the setUp() method to initialize object(s) under
test.
3. Optionally override the tearDown() method to release
object(s) under test.
4. Define one or more public testXXX() methods that exercise
the object(s) under test and assert expected results.

The following is an example test case:


Example JUnit Test Case
import junit.framework.TestCase;

public class ShoppingCartTest extends


TestCase {

private ShoppingCart cart;


private Product book1;

/**
* Sets up the test fixture.
*
* Called before every test case method.
*/
protected void setUp() {

cart = new ShoppingCart();

book1 = new Product("Pragmatic Unit


Testing", 29.95);

cart.addItem(book1);
}
/**
* Tears down the test fixture.
*
* Called after every test case method.
*/
protected void tearDown() {
// release objects under test here, if
necessary
}

/**
* Tests emptying the cart.
*/
public void testEmpty() {

cart.empty();

assertEquals(0, cart.getItemCount());
}

/**
* Tests adding an item to the cart.
*/
public void testAddItem() {

Product book2 = new Product("Pragmatic


Project Automation", 29.95);
cart.addItem(book2);

double expectedBalance =
book1.getPrice() + book2.getPrice();

assertEquals(expectedBalance,
cart.getBalance(), 0.0);

assertEquals(2, cart.getItemCount());
}

/**
* Tests removing an item from the cart.
*
* @throws ProductNotFoundException If the
product was not in the cart.
*/
public void testRemoveItem() throws
ProductNotFoundException {

cart.removeItem(book1);

assertEquals(0, cart.getItemCount());
}

/**
* Tests removing an unknown item from the
cart.
*
* This test is successful if the
* ProductNotFoundException is raised.
*/
public void testRemoveItemNotInCart() {

try {

Product book3 = new


Product("Pragmatic Version Control", 29.95);
cart.removeItem(book3);

fail("Should raise a
ProductNotFoundException");

} catch(ProductNotFoundException
expected) {
// successful test
}
}
}

NOTE: Sequence of methods for every testXXX method

1. setUp()

2. testXXX

3. tearDown()

Step 3: Write a Test Suite


Next, we'll write a test suite that includes several test cases.
The test suite will allow us to run all of its test cases in one fell
swoop.
To write a test suite, follow these steps:

1. Write a Java class that defines a static suite() factory


method that creates a TestSuite containing all the tests.
2. Optionally define a main() method that runs the TestSuite in
batch mode.

The following is an example test suite:


Example JUnit Test Suite
import junit.framework.Test;
import junit.framework.TestSuite;

public class EcommerceTestSuite {

public static Test suite() {

TestSuite suite = new TestSuite();

//
// The ShoppingCartTest we created
above.
//
suite.addTestSuite(ShoppingCartTest.class
);

//
// Another example test suite of tests.
//
suite.addTest(CreditCardTestSuite.suite());

//
// Add more tests here
//

return suite;
}

/**
* Runs the test suite using the textual
runner.
*/
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
}

Step 4: Run the Tests


Now that we've written a test suite containing a collection of
test cases and other test suites, we can run either the test
suite or any of its test cases individually. Running a TestSuite will
automatically run all of its subordinate TestCase instances and
TestSuite instances. Running a TestCase will automatically invoke
all of its public testXXX() methods.
JUnit provides both a textual and a graphical user interface.
Both user interfaces indicate how many tests were run, any
errors or failures, and a simple completion status. The
simplicity of the user interfaces is the key to running tests
quickly. You should be able to run your tests and know the test
status with a glance, much like you do with a compiler.
To run our test case using the textual user interface, use:
java junit.textui.TestRunner ShoppingCartTest

The textual user interface displays "OK" if all the tests passed
and failure messages if any of the tests failed.
To run the test case using the graphical user interface, use:

java junit.swingui.TestRunner ShoppingCartTest

The graphical user interface displays a Swing window with a


green progress bar if all the tests passed or a red progress bar
if any of the tests failed.
The EcommerceTestSuite can be run similarly:

java junit.swingui.TestRunner EcommerceTestSuite

Step 5: Organize the Tests


The last step is to decide where the tests will live within our
development environment.
Here's the recommended way to organize tests:

1. Create test cases in the same package as the code under


test. For example, the com.mydotcom.ecommerce package
would contain all the application-level classes as well as
the test cases for those components.
2. To avoid combining application and testing code in your
source directories, create a mirrored directory structure
aligned with the package structure that contains the test
code.
3. For each Java package in your application, define a
TestSuite class that contains all the tests for validating the
code in the package.
4. Define similar TestSuite classes that create higher-level
and lower-level test suites in the other packages (and
sub-packages) of the application.
5. Make sure your build process includes the compilation of
all tests. This helps to ensure that your tests are always
up-to-date with the latest code and keeps the tests
fresh.

By creating a TestSuite in each Java package, at various levels


of packaging, you can run a TestSuite at any level of abstraction.
For example, you can define a com.mydotcom.AllTests that runs all
the tests in the system and a
com.mydotcom.ecommerce.EcommerceTestSuitethat runs only those
tests validating the e-commerce components.
The testing hierarchy can extend to an arbitrary depth.
Depending on the level of abstraction you're developing at in
the system, you can run an appropriate test. Just pick a layer
in the system and test it!
Here's an example test hierarchy:
Example JUnit Test Hierarchy
AllTests (Top-level Test Suite)
SmokeTestSuite (Structural Integrity Tests)
EcommerceTestSuite
ShoppingCartTestCase
CreditCardTestSuite
AuthorizationTestCase
CaptureTestCase
VoidTestCase
UtilityTestSuite
MoneyTestCase
DatabaseTestSuite
ConnectionTestCase
TransactionTestCase
LoadTestSuite (Performance and Scalability
Tests)
DatabaseTestSuite
ConnectionPoolTestCase
ThreadPoolTestCase

Testing Idioms
Keep the following things in mind when writing JUnit tests:

• The software does well those things that the tests check.
• Test a little, code a little, test a little, code a little...
• Make sure all tests always run at 100%.
• Run all the tests in the system at least once per day (or
night).
• Write tests for the areas of code with the highest
probability of breakage.
• Write tests that have the highest possible return on your
testing investment.
• If you find yourself debugging using System.out.println(),
write a test to automatically check the result instead.
• When a bug is reported, write a test to expose the bug.
• The next time someone asks you for help debugging,
help them write a test.

Write unit tests before writing the code and only write new
code when a test is failing.
Resources

• Source Code - Complete source code for the


ShoppingCartTest example
• JUnit - The official JUnit website
• JUnit FAQ - Frequently asked questions and answers
• A Dozen Ways to Get the Testing Bug by Mike Clark
(java.net, 2004)
• Pragmatic Unit Testing by Andy Hunt and Dave Thomas
(The Pragmatic Programmers, 2003)
• JUnitPerf - JUnit test decorators for continuous
performance testing

Você também pode gostar