1 / 30

Unit Testing

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)

ruby
Download Presentation

Unit Testing

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Unit Testing

  2. Topics • Motivation • JUnit framework • Basic JUnit tests – static methods • @Before and @BeforeClass – instance methods • Ensure exceptions thrown • Test floating point values

  3. Test-Driven Development (TDD) • Add a test (or tests) for an new unit of functionality (unit === method) • Run prior tests, see new test fail • may write stubs so code compiles • Implement new functionality • Run tests, see them succeed • Refactor – clean code rocks! • Repeat

  4. JUnit Motivation • Goal: relieve human from task of comparing expected and actual values public class Utilities { public static intcalcPerimeter(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)); } }

  5. JUnit 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

  6. Packages in Java • A package is a way to bundle classes by functionality Customers don’t really want to see all your test code!

  7. Create 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 unique • http://www.efsavage.com/blog/posts/java_package_conventions/

  8. More 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)

  9. TDD 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)

  10. The 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?

  11. Adding 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

  12. Eclipse and JUnit 2. Select JUnit Test Case 1. Select JUnit Test Case Pick a meaningful name We’ll use JUnit 4 click

  13. Eclipse and JUnit continued Dialog for class to test: You must type in package Then you’ll see possible classes

  14. Eclipse prompts for library

  15. Build Path • If 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 Path • Select Add Libraries Select JUnit 4

  16. JUnit 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.*;

  17. Some windchill tests package tests; import junit.framework.Assert; import org.junit.*; import Windchill.MyTempConverter; public class TestWindchillCalcs { @Test public void testWindchill() { long expected = -11; long actual = MyTempConverter.windChill(5, 0); Assert.assertEquals(expected, actual); expected = 3; actual = MyTempConverter.windChill(10, 15); Assert.assertEquals(expected, actual); } }

  18. The 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)); • } • }

  19. Run as JUnit Test

  20. JUnit Execution All is well! Error! Look at failure trace for explanation

  21. Can also test for expected exceptions package Windchill; public class BadInputException extends RuntimeException { public BadInputException() {} public BadInputException(String msg){ super(msg); } } Exception class @Test (expected = BadInputException.class) public void testWindchillLowSpeed() throws BadInputException { long actual = MyTempConverter.windChill(4, 10); } JUnit test 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); }

  22. Testing 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

  23. Example 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 }

  24. Test it – see @Before message public 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); Assert.assertEquals(5, location.getX()); Assert.assertEquals(10, location.getY()); } @Test public void testMove2() { location.move(5, 10); Assert.assertEquals(5, location.getX()); Assert.assertEquals(10, location.getY()); location.move(5, 10); Assert.assertEquals(10, location.getX()); Assert.assertEquals(20, location.getY()); } }

  25. Example 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; } }

  26. The @BeforeClass test import 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

  27. Testing 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; } }

  28. The 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); Assert.assertEquals(expected, actual, EPSILON); expected = 0.3556; actual = MyConverter.englishToMeters(1, 2); Assert.assertEquals(expected, actual, EPSILON); }

  29. What tests could you write for… • A chess game • A linked list library • String library • UPC code

  30. Advanced Topic • The static import construct allows unqualified access to static members • So when should you use static import? Very sparingly! import static org.junit.Assert.assertEquals; @Test public void testMove3() { location.move(5, 10); assertEquals(5, location.getX()); assertEquals(10, location.getY()); }

More Related