Test Driven Development With Eclipse


Test Driven Development With Eclipse

Elliotte Rusty Harold

Tuesday, August 30, 2005

elharo@metalab.unc.edu

http://www.cafeaulait.org/


Test Driven Development

  1. Write a test for a feature

  2. Code the simplest thing that can possibly work

  3. Run the test

  4. Test passed ? goto 1 : goto 2


Test Driven Development


Out of the Box


Demo: Complex Arithmetic


Create the Project


Your first test method


Writing the Complex class


Run the test

  1. Select ComplexTest.java in the Package Explorer

  2. Context Menu/Run/JUnit Test

  3. The test fails!

You want your tests to fail the first time you run them. That's how you know they're testing what you want them to test.


Debug until the test passes

Simplest thing that could possibly work:

    public Complex add(Complex z2) {
        return new Complex(2, 2);
    }
    
    public long getRealPart() {
        return 2;
    }

    public long getImaginaryPart() {
        return 2;
    }

Write another test


Repaired code

    private int real;
    private int imaginary;

    public Complex(int real, int imaginary) {
        this.real = real;
        this.imaginary = imaginary;
    }

    public Complex add(Complex z) {
        return new Complex(this.real+z.real, this.imaginary + z.imaginary);
    }

    public long getRealPart() {
        return this.real;
    }

    public long getImaginaryPart() {
        return this.imaginary;
    }

Any other obvious bugs?


Adding a feature


Unit Testing


Reinitialization Example


Consequences


static data is not reinitialized

One of these tests will fail:

    private static Complex w = new Complex(1, 1);
    
    public void testAddNumberToItselfStatic() {
        
        w = w.add(w);
        assertEquals(2.0, w.getRealPart(), 0.000001);
        assertEquals(2.0, w.getImaginaryPart(), 0.000001);
        
    }
    
    
    public void testAddNumberToItselfTwiceStatic() {
        
        w = w.add(w).add(w);
        assertEquals(3.0, w.getRealPart(), 0.000001);
        assertEquals(3.0, w.getImaginaryPart(), 0.000001);
        
    }

Fixtures


Freeing resources after each test


Assertion Messages


Floating point assertions

As always with floating point arithmetic, you want to avoid direct equality comparisons.


Integer assertions

Straight-forward because integer comparisons are straight-forward:


Object comparisons: asserting object equality


Object comparisons: asserting object identity


Asserting Truth


Asserting Falsity


Asserting Nullness

e.g. testing for memory leak:

    public void testMemoryLeak() throws InterruptedException {
        Complex z1 = new Complex(-2, 0);
        WeakReference ref = new WeakReference(z1);
        z1 = null;
        System.gc();
        System.gc();
        System.gc();
        Thread.sleep(1000);
        assertNull(ref.get());
    }

Asserting Non-Nullness

    public void testToString() {
        Complex z1 = new Complex(-2, 0);
        assertNotNull(z1.toString());
    }

Deliberately failing a test


Tests that throw Exceptions


Testing exceptional conditions

    public void testParseComplexThrowsNumberFormatException() {
         
        try {
            Complex z = Complex.parseComplex("Foo");
            fail("Parsed Foo as complex number");
        }
        catch (NumberFormatException success) {
            assertTrue(success.getMessage().indexOf("Foo") >= 0);
        }
        
    }

Test Suites


Test Suites

Multiple test classes can be combined in a test suite class:

public class FunctionTests {
    
    public static Test suite() {
        
        TestSuite result = new TestSuite();
        result.addTest(new TestSuite(TranslateFunctionTest.class));
        result.addTest(new TestSuite(SubstringTest.class));
        result.addTest(new TestSuite(SubstringBeforeTest.class));
        result.addTest(new TestSuite(SubstringAfterTest.class));
        result.addTest(new TestSuite(LangTest.class));
        result.addTest(new TestSuite(LastTest.class));
        result.addTest(new TestSuite(ConcatTest.class));
        result.addTest(new TestSuite(ContainsTest.class));
        result.addTest(new TestSuite(StringLengthTest.class));
        result.addTest(new TestSuite(StartsWithTest.class));
        result.addTest(new TestSuite(CountTest.class));
        result.addTest(new TestSuite(LocalNameTest.class));
        result.addTest(new TestSuite(NameTest.class));
        result.addTest(new TestSuite(NamespaceURITest.class));
        result.addTest(new TestSuite(SumTest.class));
        result.addTest(new TestSuite(NumberTest.class));
        result.addTest(new TestSuite(RoundTest.class));
        result.addTest(new TestSuite(StringTest.class));
        result.addTest(new TestSuite(BooleanTest.class));
        result.addTest(new TestSuite(CeilingTest.class));
        result.addTest(new TestSuite(FloorTest.class));
        result.addTest(new TestSuite(IdTest.class));
        result.addTest(new TestSuite(TrueTest.class));
        result.addTest(new TestSuite(FalseTest.class));
        result.addTest(new TestSuite(NotTest.class));
        result.addTest(new TestSuite(NormalizeSpaceTest.class));
        return result;
        
    }
    
}

Test Suites Can Be Combined Into Larger Suites

public class JaxenTests {

    public static Test suite() {
        
        TestSuite result = new TestSuite();
        result.addTest(SAXPathTests.suite());
        result.addTest(FunctionTests.suite());
        result.addTest(CoreTests.suite());
        result.addTest(DOMTests.suite());
        result.addTest(JDOMTests.suite());
        result.addTest(DOM4JTests.suite());
        result.addTest(XOMTests.suite());
        result.addTest(JavaBeanTests.suite());
        result.addTest(PatternTests.suite());
        result.addTest(BaseTests.suite());
        result.addTest(HelpersTests.suite());
        result.addTest(ExprTests.suite());
        result.addTest(UtilTests.suite());
        return result;
        
    }
    
}

What to Test


What Not to Test


To Learn More


Index | Cafe con Leche

Copyright 2005 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified August 26, 2005