Unit Testing

32
Unit Testing Unit Testing

description

Unit Testing. Topics. Motivation JUnit framework Basic JUnit tests – static methods @Before and @BeforeClass – instance methods Ensure exceptions thrown Test floating point values. Test-Driven Development (TDD). Add a test (or tests) for an new unit of functionality (unit === method) - PowerPoint PPT Presentation

Transcript of Unit Testing

Page 1: Unit Testing

Unit TestingUnit Testing

Page 2: Unit Testing

TopicsTopics

• Motivation• JUnit framework• Basic JUnit tests – static methods• Ensure exceptions thrown• @Before and @BeforeClass –

instance methods• Test floating point values

Page 3: Unit Testing

JUnit MotivationJUnit Motivation• Goal: relieve human from task of comparing

expected and actual values

public class Utilities {public static int calcPerimeter(int length, int width)

{ return 2 * (length + width); }

public static void main(String [] args) { // Ensure output is 16 System.out.println(Utilities.calcPerimeter(2,6)); }

}

Page 4: Unit Testing

Test-Driven Development (TDD)Test-Driven Development (TDD)

1. Add a test (or tests) for an new unit of functionality (unit === method)

2. Run prior tests, see new test fail– may write stubs so code compiles

3. Implement new functionality4. Run tests, see them succeed5. Refactor – clean code rocks!6. Repeat

Page 5: Unit Testing

Tests FirstTests First

• Some “easy” examples– How would you test a function to

calculate the area of a triangle?– How would you test a function to

calculate the circumference of a circle?– How would you test a function that

calculates wind chill?

Page 6: Unit Testing

JUnit FrameworkJUnit Framework• Test Case. Method that runs one or more

tests. • Test Suite. Collection of tests run at the

same time. Includes one or more test cases/methods.

• Test Runner. Utility used to run a test suite. – In Eclipse, shows a graphical presentation. – May also be a command-line version (Ruby).

• JUnit framework available from http://junit.org

Page 7: Unit Testing

Packages in JavaPackages in Java

• A package is a way to bundle classes by functionality

Customers don’t really want to see all your test code!

Page 8: Unit Testing

Create a PackageCreate a Package

In Eclipse:• Create a Java project, click on src• Select new package icon• Enter an appropriate name• For this example, create a package

named windchill*• Select the package, create a new

class named MyTempConverter

* for distribution, you’d want to ensure uniquehttp://www.efsavage.com/blog/posts/java_package_conventions/

Page 9: Unit Testing

More on PackagesMore on Packages

• The package statement must be the first line in the file, e.g.:package windchill;

public class MyTempConverter {

}

• Each package has its own directory (in the file structure)

Page 10: Unit Testing

TDD Example: WindchillTDD Example: Windchill

See the formula and chart:http://www.nws.noaa.gov/om/windchill/index.shtml

Windchill formula:• 35.74 + 0.6215T - 35.75V (**0.16) + 0.4275TV(**0.16)

Page 11: Unit Testing

The TempConverter classThe TempConverter class

• First we create the “failing” methods – so that our tests will at least compile

package windchill;

public class MyTempConverter {

public static long windChill(int speed, int temperature){ return -1;}

}

Why does it make sense for this method to be static?

Page 12: Unit Testing

Adding the testsAdding the tests

• Create a package for your tests• Add your test classes to the package

– Select the test package– Create a new class of type JUnit Test

Case

Page 13: Unit Testing

Eclipse and JUnitEclipse and JUnit

1. Select JUnit Test Case 2. Select JUnit Test Case

We’ll use JUnit 4Pick a meaningful name

click

Page 14: Unit Testing

Eclipse and JUnit continuedEclipse and JUnit continued

Dialog for class to test:You must type in packageThen you’ll see possible classes

Page 15: Unit Testing

Eclipse prompts for libraryEclipse prompts for library

Page 16: Unit Testing

Build PathBuild PathIf Eclipse creates a JUnit test for you, you’ll be prompted to add library.To add a library later:

Right-click on project name (in package explorer)Select Build PathSelect Add Libraries

Select JUnit 4

Page 17: Unit Testing

JUnit v4JUnit v4

• New Java Feature: annotations• Places a “marker” in code that is

interpreted by another tool• For JUnit, marker/annotation is @Test• No need to extend TestCase (JUnit3)• Must import org.junit.*;

Page 18: Unit Testing

Some windchill testsSome windchill testspackage tests;

import junit.framework.Assert;

import static org.junit.Assert.*;

import Windchill.MyTempConverter;

public class TestWindchillCalcs {

@Test

public void testWindchill()

{

long expected = -11;

long actual = MyTempConverter.windChill(5, 0);

assertEquals(expected, actual);

// local variables not needed

assertEquals(3, MyTempConverter.windChill(10, 15));}

}

Page 19: Unit Testing

The TempConverter classThe TempConverter class

• Now add code so that the tests pass

package Windchill;

public class MyTempConverter {

public static long windChill(int speed, int temperature){ double newTemp = 35.74 + 0.6215*temperature - 35.75 * Math.pow(speed, 0.16) + 0.4275 * temperature * Math.pow(speed,0.16); return Math.round(newTemp);}

public static void main(String[] args) { System.out.println(MyTempConverter.windChill(10, 30));

}

}

Page 20: Unit Testing

Run as JUnit TestRun as JUnit Test

Page 21: Unit Testing

JUnit ExecutionJUnit Execution

All is well!

Error! Look at failure trace for explanation

Page 22: Unit Testing

Can also test for expected exceptionsCan also test for expected exceptionspackage Windchill;

public class BadInputException extends RuntimeException {public BadInputException() {}

public BadInputException(String msg){ super(msg); }}

@Test (expected = BadInputException.class)public void testWindchillLowSpeed() throws BadInputException{ long actual = MyTempConverter.windChill(4, 10);}

public static long windChill(int speed, int temperature){if (speed < 5) throw new BadInputException("Windchill not valid if speed < 5");double newTemp = 35.74 + 0.6215*temperature - 35.75 * Math.pow(speed, 0.16) + 0.4275 * temperature * Math.pow(speed,0.16);return Math.round(newTemp);}

Exception class

JUnit test

Page 23: Unit Testing

Discuss with a partnerDiscuss with a partner

• When would we need the throws clause on the test?

• What happens if the (expected) phrase is removed?

Page 24: Unit Testing

Testing instance methodsTesting instance methods• When testing a class that has instance methods

(most often), the test will need to create an instance

• @BeforeClass and @AfterClass annotated methods will be run exactly once during your test run - at the very beginning and end of the test as a whole, before anything else is run. In fact, they're run before the test class is even constructed, which is why they must be declared static.

• The @Before and @After methods will be run before and after every test case, so will probably be run multiple times during a test run

Page 25: Unit Testing

Example to illlustrate @BeforeExample to illlustrate @Before

package game;

public class Location {

private int x, y;

public void move(int dx, int dy)

{

x += dx;

y += dy;

}

// Also has constructors and getters

}

Page 26: Unit Testing

Test it – see @Before messageTest it – see @Before messagepublic class TestLocation {

private Location location;

@Before

public void setUp(){

System.out.println("In @Before"); location = new Location();

}

@Test

public void testMove() {

location.move(5, 10);

assertEquals(5, location.getX());

assertEquals(10, location.getY());

}

@Test

public void testMove2() {

location.move(5, 10);

assertEquals(5, location.getX());

assertEquals(10, location.getY());

location.move(5, 10);

assertEquals(10, location.getX());

assertEquals(20, location.getY());

}

}

Page 27: Unit Testing

Example of @BeforeClassExample of @BeforeClass• Assume the board set up is complex, and

you don’t need to reset between tests.

package game;

public class Board { private String gameStatus;

public void init() { gameStatus = "Long game set up is done!"; } public String getGameStatus() { return gameStatus; }

}

Page 28: Unit Testing

The @BeforeClass testThe @BeforeClass testimport game.Board;

public class TestBoard {

static Board board;

@BeforeClass

public static void setUpBeforeClass() throws Exception {

System.out.println("In @BeforeClass");

board = new Board();

board.init();

}

@Test

public void test1() {

assertEquals(board.getGameStatus(), "Long game set up is done!");

}

@Test

public void test2() {

assertEquals(board.getGameStatus(), "Long game set up is done!");

}

}

}

@BeforeClass not run for each test instance – just the entire test suite – so variables must be static

This is an advanced detail – will not be covered on tests, BUT may be helpful in your projects

Page 29: Unit Testing

Testing floating pointsTesting floating points• Remember that floating point values should not be

compared exactly. public class MyConverter {

public static double INCHES_TO_METERS = 0.0254;

public static double englishToMeters(int feet, int

inches)

{

return 0;

//int totalInches = feet * 12 + inches;

//return totalInches * INCHES_TO_METERS;

}

}

Page 30: Unit Testing

The testThe test• Use a tolerance

public class TestConversions {

public static double EPSILON = .0001;

@Test

public void testFeetToMeters()

{

double expected = 0.0508;

double actual = MyConverter.englishToMeters(0, 2);

assertEquals(expected, actual, EPSILON);

expected = 0.3556;

actual = MyConverter.englishToMeters(1, 2);

assertEquals(expected, actual, EPSILON);

}

Page 31: Unit Testing

What tests could you write for…What tests could you write for…

• A chess game• A linked list library• String library• UPC code

Page 32: Unit Testing

Advanced TopicAdvanced Topic• The static import construct allows unqualified access to static members

import static org.junit.Assert.assertEquals;

@Test

public void testMove3() {

location.move(5, 10);

assertEquals(5, location.getX());

assertEquals(10, location.getY());

}