JUnit

7
JUnit: general Java testing Overview A bit thanks to Jennifer Kohnke, the designer of the by now famous logo. JUnit is a regression testing framework written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java. JUnit is Open Source Software, released under the IBM Public License and hosted on SourceForge. The latest version is 3.6 (5/7/2001). This is essentially based on "JUnit Test Infected: Programmers Love Writing Tests" by Kent Beck and Erich Gamma. Testing is not closely integrated with development. This prevents you from measuring the progress of development- you can't tell when something starts working or when something stops working. Using JUnit you can cheaply and incrementally build a test suite that will help you measure your progress, spot unintended side effects, and focus your development efforts. JUnit was the start to a series of specialised Testing Frameworks like HTTPUnit or Cactus that extend JUnit. The Problem Every programmer knows they should write tests for their code. Few do. The universal response to "Why not?" is "I'm in too much of a hurry." This quickly becomes a vicious cycle- the more pressure you feel, the fewer tests you write. The fewer tests you write, the less productive you

Transcript of JUnit

Page 1: JUnit

JUnit: general Java testing

Overview

A bit thanks to Jennifer Kohnke, the designer of the by now famous logo.

JUnit is a regression testing framework written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java. JUnit is Open Source Software, released under the IBM Public License and hosted on SourceForge. The latest version is 3.6 (5/7/2001). This is essentially based on "JUnit Test Infected: Programmers Love Writing Tests" by Kent Beck and Erich Gamma.

Testing is not closely integrated with development. This prevents you from measuring the progress of development- you can't tell when something starts working or when something stops working. Using JUnit you can cheaply and incrementally build a test suite that will help you measure your progress, spot unintended side effects, and focus your development efforts.

JUnit was the start to a series of specialised Testing Frameworks like HTTPUnit or Cactus that extend JUnit.

The Problem

Every programmer knows they should write tests for their code. Few do. The universal response to "Why not?" is "I'm in too much of a hurry." This quickly becomes a vicious cycle- the more pressure you feel, the fewer tests you write. The fewer tests you write, the less productive you are and the less stable you code becomes. The less productive and accurate you are, the more pressure you feel.

Programmers burn out from just such cycles. Breaking out requires an outside influence. We found the outside influence we needed in a simple testing framework that lets us do a little testing that makes a big difference.

The best way to convince you of the value of writing your own tests would be to sit down with you and do a bit of development. Along the way, we would encounter new bugs, catch them with tests, fix them, have them come back, fix them again, and so on. You would see the value of the immediate feedback you get from writing and saving and rerunning your own unit tests.

Page 2: JUnit

We'll write a simple program and its tests, and show you the results of running the tests. This way you can get a feel for the process we use and advocate without having to pay for our presence.

Installation

Download JUnit and put the junit.jar in your classpath. That's it.

Example

What I show here is less than the tip of the ice-berg. I highly recommend reading "Test Infected" http://junit.sourceforge.net/doc/testinfected/testing.htm and if you have more time Martin Fowler's excellent book "Refactoring" (Addison Wesley).

Basically JUnit allows the "easy" testing of any class and it's methods. to test the Fibonacci class, we create a class called TestFibonacci which extends TestCase. Then in the methods setUP() and tearDown() we can deal with variables needed for the tests.. TestCase adds all methods that start with the name "test" to a test suite. Towards the end of each test one compares the expected result with the "actual" result using assert. The TestFibonacci Suite can be executed at once. Either in textmode, where a "." and "F" indicate successful and failed tests, or using a GUI. At the end the test suite whill show which tests passed and which ones failed and where.

> java TestFibonacciarmin@linux:> java TestFibonacci..FTime: 0.08

FAILURES!!!Test Results:Run: 2 Failures: 1 Errors: 0There was 1 failure:1) test2(TestFibonacci)junit.framework.AssertionFailedError at junit.framework.Assert.fail(Assert.java:143) at junit.framework.Assert.assert(Assert.java:19) at junit.framework.Assert.assert(Assert.java:26) at TestFibonacci.test2(TestFibonacci.java:23) at java.lang.reflect.Method.invoke(Native Method) at junit.framework.TestCase.runTest(TestCase.java:155) at junit.framework.TestCase.runBare(TestCase.java:129) at junit.framework.TestResult$1.protect(TestResult.java:100) at junit.framework.TestResult.runProtected(TestResult.java:117) at junit.framework.TestResult.run(TestResult.java:103) at junit.framework.TestCase.run(TestCase.java:120) at junit.framework.TestSuite.run(TestSuite.java:144) at junit.textui.TestRunner.doRun(TestRunner.java:61) at junit.textui.TestRunner.run(TestRunner.java:181) at TestFibonacci.main(TestFibonacci.java:27)

Page 3: JUnit

We look at a small Java snipplet to calculate Fibonacci numbers recursively. Fibonacci Numbers are defined as: f(0)=1; f(1)=1 und f(n)=f(n-1)+f(n-2). So f(2)=2; f(3)=3 und f(4)=5.

Our first implementation is buggy. The tests should show it.

class Fibonacci { int compute (int n) { if (n<2) return n;//bug; should be "1" else return compute(n-1)+compute(n-2); }}

The corresponding testing code.

import junit.framework.*;

public class TestFibonacci extends TestCase { Fibonacci f;

public TestFibonacci(String name) { super(name); }

public void setUp(){ f=new Fibonacci(); }

public static Test suite() { return new TestSuite(TestFibonacci.class); }

public void test1() { assert(f.compute(1)==1); }

public void test2() { assert(f.compute(4)==5); } //starte text interface und lass die tests laufen. public static void main(String args[]) { junit.textui.TestRunner.run(suite()); }

}

Page 4: JUnit

JUnit still shows mistakes.

A bit of thinking shows that the mistake is in the first return statement. The new version:

if (n<2) return 1;

Page 5: JUnit

All tests are OK.

Different Test Suites can be put together in one big Test Suite, which calls the individual tests of the entire project.

public class AllTests { public static Test suite ( ) { suite.addTest(TestFibonacci.suite()); suite.addTest(TestNewton.suite()); ... ... }}

Conclusion

There is a huge difference between tests that are all running correctly and tests that aren't. Part of being test infected is not being able to go home if your tests aren't 100%. If you run your suite ten or a hundred times an hour, though, you won't be able to create enough havoc to make you late for supper.

You will be able to refactor much more aggressively once you have the tests. You won't understand at first just how much you can do, though. Try to catch yourself saying, "Oh, I see, I should have designed this thus and so. I can't change it now. I don't want to break anything." When you say this, save a copy of your current code and give yourself a couple of hours to clean up. (This part works best you can get a buddy to look over your shoulder while you work.) Make your changes, all the while running your tests. You will be surprised at how much ground you can cover in a couple of hours if you aren't worrying every second about what you might be breaking.

If you get addicted to unit tests, you might want to look into "extreme programming" www.xprogramming.org.

We tend to write the tests first, and the code afterwards. There's the story about Kent Beck that he deletes his code if it doesn't pass the test first time and starts again from scratch.