33
Software Testing - Test Driven Development (TDD) with JUnit - Fernando Brito e Abreu DCTI / ISCTE-IUL QUASAR Research Group

2011/09/21 - JUnit

Embed Size (px)

Citation preview

Page 1: 2011/09/21 - JUnit

Software Testing - Test Driven Development

(TDD) with JUnit -

Fernando Brito e Abreu

DCTI / ISCTE-IUL QUASAR Research Group

Page 2: 2011/09/21 - JUnit

Software Engineering / Fernando Brito e Abreu 2 27-Sep-11

SWEBOK: the 10 Knowledge Areas

Software Requirements

Software Design

Software Construction

Software Testing

Software Maintenance

Software Configuration Management

Software Engineering Management

Software Engineering Process

Software Engineering Tools and Methods

Software Quality

Page 3: 2011/09/21 - JUnit

Working test first / TDD

Traditionally, code has been written using a

test-last philosophy, i.e. design, code, then test

Testing after the fact is often boring

Write code “test first” instead:

Write a simple test (one assertion)

Write enough code to make the test pass

Repeat the process, ‘filling’ out the code

Software Engineering / Fernando Brito e Abreu 3 27-Sep-11

Page 4: 2011/09/21 - JUnit

Unit testing, extreme style

Tests should be an integral part of the coding process

Whenever you implement a class, also make a companion test class

Tests are executable documentation

Tests allow other programmers see how to use code

Therefore they are part of the specification

Software Engineering / Fernando Brito e Abreu 4 27-Sep-11

Page 5: 2011/09/21 - JUnit

Best practices

Test everything that could possibly break

This is an XP maxim and it holds

A well-written test is hard to pass

If all your tests pass the first time, you are probably

not testing vigorously enough

All tests should pass before any update is made

to a collective code base

Software Engineering / Fernando Brito e Abreu 5 27-Sep-11

Page 6: 2011/09/21 - JUnit

Best practices

When a test case fails, track down the problem

by writing more tests, before going to the

debugger

The more tests you have, the better

Test invalid parameters to every method, rather

than just valid data

Robust software needs to recognize and handle

invalid data, and the tests that pass using incorrect

data are often the most informative Software Engineering / Fernando Brito e Abreu 6 27-Sep-11

Page 7: 2011/09/21 - JUnit

The xUnit testing frameworks story

Kent Beck published a unit test framework for the

Smalltalk language in 1999 named SmalltalkUnit (aka

SUnit)

Later, Erich Gamma ported SUnit to Java, creating JUnit

Many more xUnit implementations adapted to various

languages and platforms were made since

CppUnit (C++), NUnit (.Net), Dunit (Delphi), VBUnit (Visual

Basic), RUnit (R), PyUnit (Pyton), HtmlUnit, XMLUnit, …

Software Engineering / Fernando Brito e Abreu 7 27-Sep-11

Page 8: 2011/09/21 - JUnit

JUnit for Eclipse

Test class

This bar is only green

when all tests pass!

Software Engineering / Fernando Brito e Abreu 8 27-Sep-11

Test error messages and

tracing info appear here

for the selected test case

Page 9: 2011/09/21 - JUnit

Building a test suite

A test suite is the union of the test cases for all classes

in the system

A test suite should have:

One test class for each class in the system

Each test class should have at least one test method

(aka test case) for each method in the class under test

To be more precise, we should have a number of test cases

given by the McCabe complexity metric of the target method

Software Engineering / Fernando Brito e Abreu 9 27-Sep-11

Page 10: 2011/09/21 - JUnit

Test case stubs

JUnit test case stubs can be generated with Eclipse

Since only one test case stub is generated per method, you

should cut and paste those stubs if McCabe complexity metric

is greater than one

Method stubs look like this:

@Test

public final void testSomeMethod()

{

fail("Not yet implemented"); // TODO

}

Software Engineering / Fernando Brito e Abreu 10 27-Sep-11

Page 11: 2011/09/21 - JUnit

Test case stubs

Software Engineering / Fernando Brito e Abreu 11 27-Sep-11

Here we choose which

stubs we want to create

Page 12: 2011/09/21 - JUnit

Test suite organization

Test code must be separated from application

Give them each their own unique directory tree with

the same package naming structure

One tree using “src” as root

Another tree using “tests” as root

This lets tests live in the same package as the objects

they test, while still keeping them separate during a

build

Software Engineering / Fernando Brito e Abreu 12 27-Sep-11

Page 13: 2011/09/21 - JUnit

Test suite organization

If you select a file and do “Run As / Junit

Test” only the test cases in it are executed.

If you select a directory and do “Run As

/ Junit Test” all test classes contained in

it (recursively) are executed.

Software Engineering / Fernando Brito e Abreu 13 27-Sep-11

Page 14: 2011/09/21 - JUnit

Naming convention

Test classes

<test class name> ::= <class name>Test

e.g. ClientAccountTest, CurrencyTest, …

Test cases

<test case name> ::= test[<n>]<method name>.java

The <n> counter can be discarded when we have a single test (McCabe

complexity = 1)

e.g. client.testgetName(), myAccount.test1deposit(),

myAccount.test2deposit(), …

This convention is just an

example. The important thing is

using a consistent convention

to facilitate maintainability.

Software Engineering / Fernando Brito e Abreu 14 27-Sep-11

Page 15: 2011/09/21 - JUnit

JUnit mechanisms

Annotations

The mechanism by which JUnit determines organizes

and activates your test cases

Assertions

The mechanism by which JUnit determines the

success or failure of a test

An assert is a comparison between an expected

value and an actual value

Software Engineering / Fernando Brito e Abreu 15 27-Sep-11

Page 16: 2011/09/21 - JUnit

Annotations

@BeforeClass

@AfterClass

@Before

@After

@Test

@Ignore

@Timeout

Software Engineering / Fernando Brito e Abreu 16 27-Sep-11

Page 17: 2011/09/21 - JUnit

@BeforeClass

This annotation allows setting up methods that will run

before the full test suite contained in the class

This can be used to perform time intensive activities

Example: connect to a database

@BeforeClass

public void runBeforeFullSuite() {

// run once before all test cases

}

There is no restriction on the names of

the methods, but you should use

semantically meaningful identifiers

Software Engineering / Fernando Brito e Abreu 17 27-Sep-11

Page 18: 2011/09/21 - JUnit

@AfterClass

This annotation allows setting up methods that will run

after all tests contained in the class have finished

This can be used to perform clean-up activities

Example: disconnect from a database

@AfterClass

public void runAfterFullSuite() {

// run for one time after all test cases

}

Software Engineering / Fernando Brito e Abreu 18 27-Sep-11

Page 19: 2011/09/21 - JUnit

@Before

This annotation allows setting up all test cases, since the

corresponding method will run before each test case

A @Before method can prepare the test environment

e.g. read input data, initialize the class

@Before

public void runBeforeEveryTest() {

simpleMath = new SimpleMath();

}

Software Engineering / Fernando Brito e Abreu 19 27-Sep-11

Page 20: 2011/09/21 - JUnit

@After

This annotation allows tearing down test methods since

it will run after every test case

@After

public void runAfterEveryTest() {

simpleMath = null;

}

Software Engineering / Fernando Brito e Abreu 20 27-Sep-11

Page 21: 2011/09/21 - JUnit

@Test

Mark your test cases with @Test annotations

You don’t need to prefix your test cases with “test”,

although this is a good naming convention

@Test

public void testAddition() {

assertEquals(12, simpleMath.add(7, 5));

}

@Test

public void testSubtraction() {

assertEquals(9, simpleMath.subtract(12, 3));

}

Software Engineering / Fernando Brito e Abreu 21 27-Sep-11

Page 22: 2011/09/21 - JUnit

@Test

Another example:

@Test

public void listEquality() {

List<Integer> expected = new ArrayList<Integer>();

expected.add(5);

List<Integer> actual = new ArrayList<Integer>();

actual.add(5);

assertEquals(expected, actual);

}

Software Engineering / Fernando Brito e Abreu 22 27-Sep-11

Page 23: 2011/09/21 - JUnit

@Test(timeout = <delay>)

Define a timeout period in milliseconds with “timeout”

parameter

The test fails when the timeout period exceeds

@Test(timeout = 1000)

public void infinity() {

while (true)

;

}

Software Engineering / Fernando Brito e Abreu 23 27-Sep-11

Page 24: 2011/09/21 - JUnit

@Test(expected = <exception>.class)

Tests succeeds if the method throws the exception

Notice that the fail command is not executed

because the exception is raised and caught

by JUnit, that sees any further.

Software Engineering / Fernando Brito e Abreu 24 27-Sep-11

Page 25: 2011/09/21 - JUnit

@Ignore

Use this annotation for test cases you want to ignore

You can add a string parameter that defines the reason of

ignorance

This may be useful if the underlying code has been changed and

the test has not yet been adapted

@Ignore("Not Ready to Run")

@Test

public void multiplication() {

assertEquals(15, simpleMath.multiply(3, 5));

}

Software Engineering / Fernando Brito e Abreu 25 27-Sep-11

Page 26: 2011/09/21 - JUnit

Assertions

assertEquals

assertEquals for arrays

assertNull / assertNotNull

assertSame / assertNotSame

assertTrue / assertFalse

fail

Software Engineering / Fernando Brito e Abreu 26 27-Sep-11

Page 27: 2011/09/21 - JUnit

assertEquals This assertion states that:

expected.equals(actual) returns true, or

both objects are null

A message is printed if supplied, when a test fails

The equality test for a double or a float should specify

a maximum tolerance range (the delta), to cope with

floating point errors

There are overloaded versions of this method for all

Java’s primitive types

Software Engineering / Fernando Brito e Abreu 27 27-Sep-11

assertEquals(Object expected, Object actual) assertEquals(String message, Object expected, Object actual) assertEquals(Object expected, Object actual, delta) assertEquals(String message, Object expected, Object actual, delta)

Page 28: 2011/09/21 - JUnit

assertEquals for arrays

Two arrays are equal if they have the same length and

each element is equal to the corresponding element in

the other array; otherwise, they’re not.

public static void assertEquals(Object[] expected, Object[] actual);

public static void assertEquals(String message, Object[] expected, Object[]

actual);

Software Engineering / Fernando Brito e Abreu 28 27-Sep-11

Page 29: 2011/09/21 - JUnit

assertNull / assertNotNull This asserts that an object reference equals null,

printing a message otherwise (if supplied)

This asserts that an object reference is not null,

printing a message otherwise (if supplied)

assertNotNull(Object object),

assertNotNull(String message, Object)

assertNull(Object object),

assertNull(String message, Object object)

Software Engineering / Fernando Brito e Abreu 29 27-Sep-11

Page 30: 2011/09/21 - JUnit

assertSame / assertNotSame Asserts that the two objects are the same, printing a

message otherwise (if supplied)

This is a stricter condition than simple equality, as it

compares the object identities using expected == actual

Asserts that the two objects are not the same,

printing a message otherwise (if supplied)

assertSame(Object expected, Object actual)

assertSame(String message, Object expected, Object actual)

assertNotSame(Object expected, Object actual)

assertNotSame(String message, Object expected, Object actual)

Software Engineering / Fernando Brito e Abreu 30 27-Sep-11

Page 31: 2011/09/21 - JUnit

assertTrue / assertFalse Asserts that the condition is true, printing a message

otherwise (if supplied)

Asserts that the condition is false, printing a message

otherwise (if supplied)

assertTrue(boolean condition)

assertTrue(String message, boolean condition)

Software Engineering / Fernando Brito e Abreu 31 27-Sep-11

assertFalse(boolean condition)

assertFalse(String message, boolean condition)

Page 32: 2011/09/21 - JUnit

fail

This forces a failure. This is useful to close off paths

through the code that should not be reached

fail()

fail(String message)

Software Engineering / Fernando Brito e Abreu 32 27-Sep-11

Page 33: 2011/09/21 - JUnit

More Reading

http://www.junit.org/index.htm

http://open.ncsu.edu/se/tutorials/junit/

http://www.cs.umanitoba.ca/~eclipse/10-JUnit.pdf

http://supportweb.cs.bham.ac.uk/documentation/tutorial

s/docsystem/build/tutorials/junit/junit.pdf

http://junit.sourceforge.net/javadoc/junit/framework/

Software Engineering / Fernando Brito e Abreu 33 27-Sep-11