JUnit Test Fixture Pattern 15 January 2019 OSU CSE 1 The Problem - - PowerPoint PPT Presentation

junit test fixture pattern
SMART_READER_LITE
LIVE PREVIEW

JUnit Test Fixture Pattern 15 January 2019 OSU CSE 1 The Problem - - PowerPoint PPT Presentation

JUnit Test Fixture Pattern 15 January 2019 OSU CSE 1 The Problem In principle, a test fixture for a kernel class should be usable with any kernel class (UUT, or unit under test) that purports to implement the same interface


slide-1
SLIDE 1

JUnit Test Fixture Pattern

15 January 2019 OSU CSE 1

slide-2
SLIDE 2

The Problem

  • In principle, a test fixture for a kernel class

should be usable with any kernel class (UUT, or “unit under test”) that purports to implement the same interface

  • However, you actually must modify the test

fixture when you change the UUT, because each test case has to call the UUT’s constructor—whose name is that of the UUT!

15 January 2019 OSU CSE 2

slide-3
SLIDE 3

Example

@Test public final void testPushEmpty() { Stack<String> s = new Stack1L<>(); Stack<String> sExpected = new Stack1L<>(); s.push("red"); sExpected.push("red"); assertEquals(sExpected, s); }

15 January 2019 OSU CSE 3

slide-4
SLIDE 4

Example

@Test public final void testPushEmpty() { Stack<String> s = new Stack1L<>(); Stack<String> sExpected = new Stack1L<>(); s.push("red"); sExpected.push("red"); assertEquals(sExpected, s); }

15 January 2019 OSU CSE 4

This kind of call of the constructor for the UUT needs to be changed (throughout the test fixture) if you want to change the UUT.

slide-5
SLIDE 5

Single-Point Control Over Change

  • Question: How do we achieve the goal of

single-point control over change in this situation?

15 January 2019 OSU CSE 5

slide-6
SLIDE 6
  • Question: How do we achieve the goal of

single-point control over change in this situation?

  • Answer: “Re-route” all UUT constructor

calls to another method, which then calls the UUT constructor, so only the body of that one method needs to be changed to accommodate a different UUT

15 January 2019 OSU CSE 6

Single-Point Control Over Change

slide-7
SLIDE 7

The Code for a Test Case

@Test public final void testPushEmpty() { Stack<String> s = this.constructorTest(); Stack<String> sExpected = new Stack1L<>(); s.push("red"); sExpected.push("red"); assertEquals(sExpected, s); }

15 January 2019 OSU CSE 7

Instead of calling the UUT’s constructor directly here, you call a method (perhaps named constructorTest), which then calls the UUT’s constructor.

slide-8
SLIDE 8

Code for constructorTest

Stack<String> constructorTest() { return new Stack1L<String>(); }

15 January 2019 OSU CSE 8

slide-9
SLIDE 9

The Code for a Test Case

@Test public final void testPushEmpty() { Stack<String> s = this.constructorTest(); Stack<String> sExpected = this.constructorRef(); s.push("red"); sExpected.push("red"); assertEquals(sExpected, s); }

15 January 2019 OSU CSE 9

Instead of calling the UUT’s constructor directly here, you call a method (perhaps named constructorRef) ...

slide-10
SLIDE 10

The Code for a Test Case

@Test public final void testPushEmpty() { Stack<String> s = this.constructorTest(); Stack<String> sExpected = this.constructorRef(); s.push("red"); sExpected.push("red"); assertEquals(sExpected, s); }

15 January 2019 OSU CSE 10

... which then calls the constructor from either the UUT or a reference implementation

  • f the same interface.
slide-11
SLIDE 11

Code for constructorRef

  • If there is no reference implementation:

Stack<String> constructorRef() { return new Stack1L<String>(); }

  • If, say, Stack3 is available as a reference

implementation:

Stack<String> constructorRef() { return new Stack3<String>(); }

15 January 2019 OSU CSE 11

slide-12
SLIDE 12

Isolating This Change Point

15 January 2019 OSU CSE 12

extends Stack1LTest

test cases

constructorTest constructorRef StackTest

slide-13
SLIDE 13

The Code of StackTest

public abstract class StackTest { protected abstract Stack<String> constructorTest(); protected abstract Stack<String> constructorRef(); ... }

15 January 2019 OSU CSE 13

slide-14
SLIDE 14

The Code of StackTest

public abstract class StackTest { protected abstract Stack<String> constructorTest(); protected abstract Stack<String> constructorRef(); ... }

15 January 2019 OSU CSE 14

StackTest is an abstract class now.

slide-15
SLIDE 15

The Code of StackTest

public abstract class StackTest { protected abstract Stack<String> constructorTest(); protected abstract Stack<String> constructorRef(); ... }

15 January 2019 OSU CSE 15

protected means that this method may be called or overridden in a subclass (which is our intent for Stack1LTest), but may not even be called from any other class declared outside this package.

slide-16
SLIDE 16

The Code of StackTest

public abstract class StackTest { protected abstract Stack<String> constructorTest(); protected abstract Stack<String> constructorRef(); ... }

15 January 2019 OSU CSE 16

abstract means that this method (called an abstract method) must be overridden in some subclass (which is our intent for Stack1LTest).

slide-17
SLIDE 17

The Code of Stack1LTest

public class Stack1LTest extends StackTest { @Override protected final Stack<String> constructorTest() { ... } @Override protected final Stack<String> constructorRef() { ... } }

15 January 2019 OSU CSE 17

slide-18
SLIDE 18

The Code of Stack1LTest

public class Stack1LTest extends StackTest { @Override protected final Stack<String> constructorTest() { ... } @Override protected final Stack<String> constructorRef() { ... } }

15 January 2019 OSU CSE 18

Incidentally, final here means that this method may not be

  • verridden in any subclass of

Stack1LTest.

slide-19
SLIDE 19

The Code of Stack1LTest

public class Stack1LTest extends StackTest { @Override protected final Stack<String> constructorTest() { ... } @Override protected final Stack<String> constructorRef() { ... } }

15 January 2019 OSU CSE 19

What code goes here?

slide-20
SLIDE 20

Another Problem

  • In a typical test case, it takes many lines of

code just to construct the values on which to run a test!

  • For instance, suppose you want to test a

method with this Stack<String> value as input:

<"a", "stack", "with", "stuff">

15 January 2019 OSU CSE 20

slide-21
SLIDE 21

Another Problem

  • In a typical test case, it takes many lines of

code just to construct the values on which to run a test!

  • For instance, suppose you want to test a

method with this Stack<String> value as input:

<"a", "stack", "with", "stuff">

15 January 2019 OSU CSE 21

What code must you write to give a variable this value?

slide-22
SLIDE 22

A Convenience Method

  • Consider this method in StackTest:

/** * Creates and returns a Stack<String> * with the given entries. * @ensures * createFromArgsTest = [entries in args] */ private Stack<String> createFromArgsTest( String... args) {/* body */}

15 January 2019 OSU CSE 22

slide-23
SLIDE 23

A Convenience Method

  • Consider this method in StackTest:

/** * Creates and returns a Stack<String> * with the given entries. * @ensures * createFromArgsTest = [entries in args] */ private Stack<String> createFromArgsTest( String... args) {/* body */}

15 January 2019 OSU CSE 23

This special Java varargs notation (yes, three dots, or ellipsis, is part of the Java code here!) allows you to call this method with zero or more arguments of type String.

slide-24
SLIDE 24

A Convenience Method

  • Consider this method in StackTest:

/** * Creates and returns a Stack<String> * with the given entries. * @ensures * createFromArgsTest = [entries in args] */ private Stack<String> createFromArgsTest( String... args) {/* body */}

15 January 2019 OSU CSE 24

The method body is written as if args were an array of Strings

  • f length equal to the number of

arguments in the call; and args is guaranteed not to be null.

slide-25
SLIDE 25

A Convenience Method

  • Consider this method in StackTest:

/** * Creates and returns a Stack<String> * with the given entries. * @ensures * createFromArgsTest = [entries in args] */ private Stack<String> createFromArgsRef( String... args) {/* body */}

15 January 2019 OSU CSE 25

In addition to createFromArgsTest you will also want createFromArgsRef.