Test Driven Development

Abstracting Clauses

Lecture Overview

Creating a simple Test

public class Die {
    private Integer numberOfFaces;
    private Integer currentFaceValue;

    public Die(Integer numberOfFaces) {
        this.numberOfFaces = numberOfFaces;
    }

    public void roll() {
        ThreadLocalRandom randomNumberGenerator = ThreadLocalRandom.current();
        Integer randomFaceValue = randomNumberGenerator.nextInt(1, numberOfFaces);
        this.currentFaceValue = randomFaceValue;
    }

    public Integer getCurrentFaceValue() {
        return currentFaceValue;
    }

    public Integer getNumberOfFaces() {
        return numberOfFaces;
    }
}

Simple-Test Pattern

Simple-Test Pattern

public class DieTest {
    @Test
    public void testConstructor() {
        // given
        Integer expectedFaceValue = null;
        Integer expectedNumberOfFaces = null;

        // when
        Die die = new Die(expectedNumberOfFaces);
        Integer actualFaceValue = die.getCurrentFaceValue();
        Integer actualNumberOfFaces = die.getNumberOfFaces();

        // then
        Assert.assertEquals(expectedFaceValue, actualFaceValue);
        Assert.assertEquals(expectedNumberOfFaces, actualNumberOfFaces);
    }
}

Simple-Test Pattern

public class DieTest {
    @Test
    public void testRoll() {
        // given
        Integer numberOfFaces = 2;
        Integer unexpected = null;
        Die die = new Die(numberOfFaces);

        // when
        die.roll();
        Integer actual = die.getCurrentFaceValue();
        Boolean conformsToUpperBound = actual <= numberOfFaces;
        Boolean conformsToLowerBound = actual > 0;
    
        // then
        Assert.assertNotEquals(unexpected, actual);
        Assert.assertTrue(conformsToUpperBound);
        Assert.assertTrue(conformsToLowerBound);
    }
}

Issues With this Pattern

Issues With this Pattern

Resolving Bloat

Resolving Class-Bloat

Resolving Package-Bloat

Beginning Abstraction

Abstracting a Test Method

public class ConstructorTest {
    // template method
    private void test(Integer expectedNumberOfFaces) {
        Integer expectedFaceValue = null;

        // when
        Die die = new Die(expectedNumberOfFaces);
        Integer actualFaceValue = die.getCurrentFaceValue();
        Integer actualNumberOfFaces = die.getNumberOfFaces();

        // then
        Assert.assertEquals(expectedFaceValue, actualFaceValue);
        Assert.assertEquals(expectedNumberOfFaces, actualNumberOfFaces);
    }

    @Test
    public void test0() { test(3); }

    @Test
    public void test1() { test(4); }

    @Test
    public void test2() { test(6); }
}

Abstracting a Test Method

public class RollTest {
    // template-method definition
    private void test(Integer numberOfFaces) {
        // given
        Integer unexpected = null;
        Die die = new Die(numberOfFaces);

        // when
        die.roll();
        Integer actual = die.getCurrentFaceValue();
        Boolean conformsToUpperBound = actual <= numberOfFaces;
        Boolean conformsToLowerBound = actual > 0;
    
        // then
        Assert.assertNotEquals(unexpected, actual);
        Assert.assertTrue(conformsToUpperBound);
        Assert.assertTrue(conformsToLowerBound);
    }

    @Test
    public void test0() { test(2); }

    @Test
    public void test1() { test(3); }

    @Test(expected=NullPointerException.class)
    public void test2() { test(null); }
}

Summary