java junit tutorial - budapest university of technology ... · bme department of control...

11
BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial Author: Péter Budai, BME IIT, 2011. The description of the annotations of JUnit can be found here: http://junit.sourceforge.net/javadoc/ The most frequently asked questions about JUnit are answered here (especially sections 4, 5 and 7): http://junit.sourceforge.net/doc/faq/faq.htm The following JUnit Tutorial shows and example for parameterized testing: http://www.mkyong.com/tutorials/junit-tutorials/ 1 Installing the JUnit plugin Eclipse has built in support for JUnit, but code coverage testing requires the EclEmma plugin. The eclipse.zip archive found on the website of the subject already contains this plugin. In case we don’t run Eclipse under Windows we have to install this plugin manually. To do this, select the menu item Help/Install New Software... and specify the following: After installing the plugin, restart Eclipse.

Upload: dinhnhan

Post on 21-Apr-2018

245 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

1

Java JUnit Tutorial

Author: Péter Budai, BME IIT, 2011.

The description of the annotations of JUnit can be found here:

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

The most frequently asked questions about JUnit are answered here (especially sections 4, 5

and 7):

http://junit.sourceforge.net/doc/faq/faq.htm

The following JUnit Tutorial shows and example for parameterized testing:

http://www.mkyong.com/tutorials/junit-tutorials/

1 Installing the JUnit plugin

Eclipse has built in support for JUnit, but code coverage testing requires the EclEmma plugin. The

eclipse.zip archive found on the website of the subject already contains this plugin.

In case we don’t run Eclipse under Windows we have to install this plugin manually. To do this, select

the menu item Help/Install New Software... and specify the following:

After installing the plugin, restart Eclipse.

Page 2: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

2

Important note: the EclEmma plugin works only with JRE/JDK 6, the new JDK 7 is not yet

supported! If JDK 7 is installed on the computer, make sure to set the generation of JDK 6

compatible class files in the project properties. (Right click on the project, select Properties, and in

the opening window under Java Compiler set the JDK Compliance.)

2 Creating a simple calculator class

Create a simple calculator class in Java which can multiply and divide double numbers. The most

simple features of JUnit will be demonstrated on this class.

Create a new Java project named JUnitTest:

Page 3: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

3

Create a new class named Calculator under the package junittest:

Finally realize the functions inside the Calculator class. Create a multiply and a divide method. Make

sure to avoid division by zero. If the divisor is zero, throw an IllegalArgumentException:

package junittest;

public class Calculator {

public double multiply(double a, double b) {

return a * b;

}

public double divide(double a, double b)

throws IllegalArgumentException {

if(b == 0) {

throw new IllegalArgumentException();

}

return a / b;

}

}

Page 4: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

4

3 Testing the Calculator class with JUnit 4

JUnit is an open source Java library which has become the most popular too for unit testing Java

programs. The JUnit framework contains classes which make testing units of the source code easier

and repeatable.

The JUnit framework is supported by most development environments, including Eclipse. In order to

be able to use this framework, its library must be added to the project. Right click on the project and

select the Properties menu item. In the opening window navigate to Java Build Path, Libraries and

click Add Library... Select JUnit and make sure to select version 4! The following window may help

you to find this option:

After selecting the right version, the project should look like as follows:

Page 5: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

5

The test classes should be handled separately from the application logic since they should not be

added to the resulting .jar file. Therefore we should create a new source directory inside our Eclipse

project for the test classes. Right click on the project and select New > Source Folder. The directory

name should be test as shown in the following picture:

The test classes can also be organized into packages just like our normal classes. The convention is to

place the unit test classes in the same packages as the tested classes. Such way the test classes can

access package visible members of the tested classes.

Create a new JUnit Test Case under the test folder. Its name should be CalculatorTest under the

package junittest:

If there is no JUnit Test Case item, a simple Java class in the same package will suffice.

Page 6: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

6

The JUnit test cases are represented by Java methods annotated by @Test and its companions

grouped into classes. These test cases will be executed by the framework and it will also summarize

the results. A test class can contain multiple test methods. Inside the test methods the static

assertXXX() functions of the class org.junit.Assert can be used to compare the real and the expected

results. These functions will automatically characterize the test cases as failed if the real and the

expected results differ. JUnit also makes it possible to specify that the expected behavior is an

exception. The exact way to do this can be read in the FAQ.

Let’s prepare out test cases. In this example we will only test a single pair of numbers, however, in a

real life scenario multiple pairs of numbers may be better. We will also check whether our class will

throw the expected exception in case the divisor is zero. The following is our test class:

package junittest;

import org.junit.Assert;

import org.junit.Test;

public class CalculatorTest {

@Test

public void testMultiply() {

Calculator calc = new Calculator();

double result = calc.multiply(5.0, 8.0);

Assert.assertEquals(40.0, result, 0);

}

@Test

public void testDivide() throws Exception {

Calculator calc = new Calculator();

double result = calc.divide(20.0, 4.0);

Assert.assertEquals(5.0, result, 0);

}

@Test(expected=IllegalArgumentException.class)

public void testDivideByZero() throws Exception {

Calculator calc = new Calculator();

calc.divide(10.0, 0.0);

}

}

Page 7: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

7

When our test class is ready, select it in the Package Explorer, right click on it (or on the name of the

project) and choose the Run As/JUnit Test menu item. Eclipse will execute the test cases and will

show the results in the following window:

4 Using test fixtures

The JUnit frameworks runs the test methods independently from each other. The behavior of one

test method does not affect the behavior of another one. This is achieved by creating a new instance

of the test class for each test method call.

Testing more complex component may require setting up an object with a specific initial state. These

setup steps logically do not belong to the test. In addition, if multiple test methods use the same

initial state, these steps would have to be repeated for each method. Therefore, JUnit provides

means to create test initialization (annotated by @Before) and test finalization (annotated by

@After) methods. These initialization and finalization methods will be called before and after each

test method, respectively. This way a test environment called test fixture can be provided for the

tests.

Modify our test class so that the calculator object needs not to be created manually at the beginning

of each test. Place the instantiation into an initialization method. There is not much gain by this in

our example, but it is sufficient for demonstration purposes.

package junittest;

import org.junit.Assert;

import org.junit.Before;

import org.junit.Test;

public class CalculatorTest {

Calculator calc;

@Before

public void setUp() {

calc = new Calculator();

}

Page 8: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

8

@Test

public void testMultiply() {

double result = calc.multiply(5.0, 8.0);

Assert.assertEquals(40.0, result, 0);

}

@Test

public void testDivide() throws Exception {

double result = calc.divide(20.0, 4.0);

Assert.assertEquals(5.0, result, 0);

}

@Test(expected=IllegalArgumentException.class)

public void testDivideByZero() throws Exception {

calc.divide(10.0, 0.0);

}

}

Note that the calculator object must be visible for all test methods, therefore, it has to be stored in

an attribute. If we have done everything correctly, all the tests must pass.

5 Code coverage with the EclEmma plugin

Emma is an open source Java library that can provide information about the execution of a Java

program: it can mark which statements have been executed during the run of the program or even

during JUnit tests. There is also an Eclipse plugin called EclEmma that integrates this tool with Eclipse

even showing which parts of the code have been executed.

Using the EclEmma plugin is really easy. Right click on the name of the project in the Package

Explorer and select Coverage As > JUnit Test. After running the tests a Coverage window will be

shown where the statistics can be viewed by files. Double clicking on a file name the source code will

be opened and the source lines will be colored if they have been executed, e.g.:

Page 9: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

9

6 Parameterized testing with JUnit

When testing different algorithms it is usually desirable to test specific operations for different

inputs to make sure the program works even for extreme values. In this case we would have to write

a different test method for each input combination which can be very tedious for large parameter

domains. Luckily, JUnit offers a solution for this through parameterized tests.

A parameterized test must have a static method annotated by the @Parameters annotation and this

static method must return with the input combinations. The test methods in the test class will be

executed for each input combination. The test object will receive the input combination in its

constructor. All of this is illustrated in JUnit Tutorial (see above).

The static method returns with a collection of Object arrays (Collection<Object[]> or List<Object[]>,

etc.). The number of elements in the collection determines how many times the tests should be

executed. An Object array contains a single input combination. It can even contain the expected

results.

The number of items (.length) in an Object[] must be equal to the number of parameters of the

constructor of the test class, since these items will be passed to the constructor when the JUnit

framework instantiates the class.

For example, if the constructor of the test class has three parameters, and there are four input

combinations, then the static method must return with a collection of four Object arrays each with a

length of three.

In practice we usually store the input parameters of the constructor in attributes in the test class so

that we can access them later in the test methods.

Parameterized tests are special, since they cannot be executed by the default JUnit engine.

Therefore our test class must be annotated by the @RunWith annotation, in which the

parameterized execution engineorg.junit.runners.Parameterized has to be specified.

Now modify our test class so that it performs the multiplication and division test for five different

operand combination:

package junittest;

import java.util.ArrayList;

import java.util.List;

import org.junit.Assert;

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.junit.runners.Parameterized;

import org.junit.runners.Parameterized.Parameters;

Page 10: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

10

@RunWith(Parameterized.class)

public class CalculatorTest {

double a;

double b;

Calculator calc;

public CalculatorTest(double a, double b) {

this.a = a;

this.b = b;

}

@Before

public void setUp() {

calc = new Calculator();

}

@Test

public void testMultiply() {

double result = calc.multiply(a, b);

Assert.assertEquals(a * b, result, 0);

}

@Test

public void testDivide() throws Exception {

double result = calc.divide(a, b);

Assert.assertEquals(a / b, result, 0);

}

@Test(expected=IllegalArgumentException.class)

public void testDivideByZero() throws Exception {

calc.divide(a, 0.0);

}

@Parameters

public static List<Object[]> parameters() {

List<Object[]> params = new ArrayList<Object[]>();

params.add(new Object[] {0.0, 0.0});

params.add(new Object[] {10.0, 0.0});

params.add(new Object[] {10.0, 3.0});

params.add(new Object[] {20.0, 4.0});

params.add(new Object[] {40.0, 5.0});

return params;

}

}

Page 11: Java JUnit Tutorial - Budapest University of Technology ... · BME Department of Control Engineering and Information Technology Software laboratory 3. 2011. 1 Java JUnit Tutorial

BME Department of Control Engineering and Information Technology Software laboratory 3. 2011.

11

If we execute our tests we will notice that not every test will pass:

The first two input combinations contain zero dividers where the testDivide method received an

unexpected IllegalArgumentException. This is clearly not the fault of the Calculator class. The

problem is with the testDivide method, it should know about the exception.