Dashboard > JJGuidelines > Home > Appendix B - Guidelines Rules > B.6. Testing rules
JJGuidelines Log In | Sign Up   View a printable version of the current page.
B.6. Testing rules
Added by Alexander Bollaert, last edited by Alexander Bollaert on Jan 15, 2007  (view change)

Testing rules

Overview

Table B.6. Testing rules

Rules
TEST_001: Provide A Unit Test For Each Utility Class, Library Or Base Layer
TEST_002: Name Test Methods Properly
TEST_003: Provide Mock Objects For A Unit Which Collaborates With Other Objects
TEST_004: Only Test What Can Possibly Break
TEST_005: Automate Running Unit Tests In The Build Process
TEST_006: Do Not Write Business Logic In Mock Objects
TEST_007: Run Scenario Tests As Part Of The Delivery Procedure Of A Product
TEST_008: Keep Mock Objects Independent From Each Other
TEST_009: Do Not Rely On The Order Of Tests Within A Testcase
TEST_010: Avoid Visual Inspection In Unit Tests
TEST_011: Avoid Code Duplication In Unit Tests
TEST_012: Call setUp() and tearDown() Methods Of A Testcase's Superclass
TEST_013: Isolate Test Data From Test Code
TEST_014: Do Not Load Data From Hardcoded Locations
TEST_015: Make Tests Locale Independent
TEST_016: Keep Unit Tests Small And Fast

TEST_001: Provide A Unit Test For Each Utility Class, Library Or Base Layer

Each utility class, library or base layer should be covered by a unit test

TEST_002: Name Test Methods Properly

Name the test method of a testcase properly. The name should not only start with "test", it should also be an accurate description of what the test does.

WRONG

public class CalcTest extends TestCase {
    public void test1() {
        // ...
    }

    public void test2() {
        // ...
    }
}

RIGHT

public class CalcTest extends TestCase {
    public void testDivisionByZero() {
        // ...
    }

    public void testAdditionCommutativity() {
        // ...
    }
}

TEST_003: Provide Mock Objects For A Unit Which Collaborates With Other Objects

Provide mock objects when the unit collaborates with other objects.

TEST_004: Only Test What Can Possibly Break

Only test what can possibly break. Do not test trivial code like most accessors and mutators (get/set methods).

TEST_005: Automate Running Unit Tests In The Build Process

Automate running unit tests in the build process.

TEST_006: Do Not Write Business Logic In Mock Objects

Don't write business logic in mock objects.

TEST_007: Run Scenario Tests As Part Of The Delivery Procedure Of A Product

Running scenario tests should be a part of the delivery procedure of the product. Preferably run the automated scenario tests at least every night. Make sure all scenario tests work before delivering production code.

TEST_008: Keep Mock Objects Independent From Each Other

Keep your mock objects independent from each other. When moch objects start to call other mock objects, this is a sign that your mock objects try to be real objects (which they shouldn't).

TEST_009: Do Not Rely On The Order Of Tests Within A Testcase

Do not assume that the tests will be performed in the order they appear in your code. When JUnit uses the Java reflection API to dynamically build the testsuite, it offers no guarantees about the order of the tests.

WRONG

public class ExampleTest extends TestCase {
    public ExampleTest(String testName) {
        super(testName);
    }

    public void testThisFirst() { // ...
    }

    public void testThisSecondly() { // ...

    }
}

RIGHT

Tests should be independent from each other. In the rare case that ordering tests actually makes sense (e.g. for performance reasons), use the static suite() method to order your tests :

public static Test suite() {
        suite.addTest(new ExampleTest("testThisFirst"));
        suite.addTest(new ExampleTest("testThisSecondly"));
        return suite;
    }

TEST_010: Avoid Visual Inspection In Unit Tests

Avoid visual inspection in a unit test. Instead use the assert methods to compare the results with expected values.

WRONG

public void testMessage() { // ...
	System.out.println("Message body : " + message.getBody());
	System.out.println("Message size : " + message.getSize());
	// ...
}

RIGHT

public void testMessage() { 
	// ... 
	assertNotNull(message.getBody()); 
	assertEquals(1000, message.getSize()); 
	// ... 
}

TEST_011: Avoid Code Duplication In Unit Tests

Avoid code duplication in unit tests. A possible solution to this is factoring out the duplicate code and maybe even moving it to a common superclass.

WORSE

public class EuroAmountTest extends TestCase {
    public void testEquals() {
        // identical initialization code
        EuroAmount fiveEuroFiftyCents = new EuroAmount(5, 50);
        EuroAmount threeEuroEightyCents = new EuroAmount(3, 80);
        Assert.assertTrue(!fiveEuroFiftyCents.equals(null));
        Assert.assertEquals(fiveEuroFiftyCents, fiveEuroFiftyCents);
        Assert.assertEquals(threeEuroEightyCents, new EuroAmount(3, 80));
        Assert.assertTrue(!fiveEuroFiftyCents.equals(threeEuroEightyCents));
    }

    public void testAddition() {
        // identical initialization code
        EuroAmount fiveEuroFiftyCents = new EuroAmount(5, 50);
        EuroAmount threeEuroEightyCents = new EuroAmount(3, 80);
        EuroAmount expected = new EuroAmount(9, 30);
        EuroAmount result = fiveEuroFiftyCents.add(threeEuroEightyCents);
        Assert.assertTrue(expected.equals(result));
    }
}

BETTER

public class EuroAmountTest extends TestCase {
    private EuroAmount fiveEuroFiftyCents;

    private EuroAmount threeEuroEightyCents;

    // identical initialization code is no longer duplicated
    protected void setUp() {
        fiveEuroFiftyCents = new EuroAmount(5, 50);
        threeEuroEightyCents = new EuroAmount(3, 80);
    }

    public void testEquals() {
        Assert.assertTrue(!fiveEuroFiftyCents.equals(null));
        Assert.assertEquals(fiveEuroFiftyCents, fiveEuroFiftyCents);
        Assert.assertEquals(threeEuroEightyCents, new EuroAmount(3, 80));
        Assert.assertTrue(!fiveEuroFiftyCents.equals(threeEuroEightyCents));
    }

    public void testAddition() {
        EuroAmount expected = new EuroAmount(9, 30);
        EuroAmount result = fiveEuroFiftyCents.add(threeEuroEightyCents);
        Assert.assertTrue(expected.equals(result));
    }
}

TEST_012: Call setUp() and tearDown() Methods Of A Testcase's Superclass

When you subclass for your testcase

WRONG

public class ExampleTest extends AbstractExampleTest {
    public void testFeatureX() {
        // ...
    }

    public void setUp() {
        // set up fixture specific for ExampleTestCase
        // ...
    }

    public void tearDown() {
        // tear down fixture specific for ExampleTestCase
        // ...
    }
}

RIGHT

public class ExampleTest extends AbstractExampleTest {
    public void testFeatureX() {
        // ...
    }

    public void setUp() {
        super.setUp();
        // allow super class to set up it's fixture
        // set up fixture specific for ExampleTestCase
        // ...
    }

    public void tearDown() {
        // tear down fixture specific for ExampleTestCase
        // ...
        super.tearDown();
        // allow super class to tear down it's fixture
    }
}

TEST_013: Isolate Test Data From Test Code

Isolate your test data from your test code. Separating test data allows you to change the test data without changing the test code.

TEST_014: Do Not Load Data From Hardcoded Locations

Do not read data from hardcode locations on the filesystem. Reading from hardcoded absolute filepaths makes the tests less portable.
Instead, put your data files on your test classpath and read the data using the static methods getResource() or getResourceAsStream() of Class. This will make the test data as portable as the test code.

TEST_015: Make Tests Locale Independent

Make sure your tests are locale independent. Running a test on a system with different locale settings should not break your tests.

TEST_016: Keep Unit Tests Small And Fast

Unit tests should be fast and small since you need to run them very often.

Site powered by a free Open Source Project / Non-profit License (more) of Confluence - the Enterprise wiki.
Learn more or evaluate Confluence for your organisation.
Hosted by JavaLobby
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.5 Build:#520 Jun 27, 2006) - Bug/feature request - Contact Administrators