Objectives: Test Options JUnit Testing Framework TestRunners Test Cases and Test Suites Test Fixtures JUnit
What is Unit Testing? Writing tests for small, discretely-defined portions of code Run and Analyze the Tests Make it part of Development Process Run on a Regular Basis Result is better confidence in the quality of Code
Why Unit Test? Increase Robustness of your Code Reduce the time and cost of delivering a system Measure your progress of development Early discovery of regressions Identify unintended side effects Focus your development effort
What is JUnit? Open source framework for unit testing written by Erich Gamma and Kent Beck. Assertions for testing expected results Test fixtures for sharing common test data Test suites for easily organizing and running tests Based on Annotations Textual test runner org.junit.runner.JUnitCore
JUnit Goals Provide a framework that encourages developers to write tests Overcome the “lack of time” argument Use familiar tools Create tests that retain their value over time Test should be reusable by others Leverage existing tests to create new ones Test Fixtures
Writing Testing Code Debugger Statements Runtime Expressions Print Statements Test Scripts Tests as Objects Familiar to Developers Established Methodology
Writing a Test Case Steps for running a Test Case using JUnit Define a class to contain test methods Annotate test methods To check a value, call assertTrue() and pass a boolean that is true if the test succeeds
Simple Test Case import java.util.*; import org.junit.Test; import static org.junit.Assert.*; public class MathTest public void addition() { double result= 3 + 2; assertTrue(result == 5.0); }
Alternative Ways to Execute the Test Test Suite import org.junit.runner.*; import org.junit.runners.*; import public class AllTests {... // this class can be empty }
TestCase Lifecycle Methods marked Invoked prior to each test Methods marked Invoked after each test For each test method in a TestCase class, the JUnit framework performs these basic steps: Create a new instance of the TestCase class method(s) of the TestCase Invoke the test method method(s) of the TestCase Release the reference to the TestCase instance, which then becomes garbage
Class Scoped set-up and tear-down static methods marked Run exactly once before all the test methods in the class run static methods marked Run exactly once after all the test methods in the class run For expensive initializations and clean-ups Database connections Network connections Instead of re-creating before each and every test, create it only once and tear it down once Test cases can run much faster
Fixtures Used to establish baseline testing environment Can be shared by many different tests and test cases. To create a fixture: Create a TestCase class Add an instance variable for each part of the fixture method to initialize the variables method to release any permanent resources you allocated in initialization
Fixture Example import java.util.*; import org.junit.*; import static org.junit.Assert.*; public class MathTest { protected double fVal1; protected double public void setUp() { fVal1 = 2.0; fVal2 = 3.0; public void addition() { double result= fVal1 + fVal2; assertTrue(result == 5.0); } }
Test Code Contained within test cases Test methods must be public, must take no arguments, and must return void. Typically named testXXX public void testEmptyCollection(){} public void testOneItemCollection(){}
Determining Success or Failure Part of testing is to run and analyze the test to determine success or failure Assert Methods throw AssertionError assertEquals() assertTrue() assertNotNull() Several overloaded versions in org.junit.Assert Uncaught exceptions are captured by test runner
Testing Exceptions Use annotation to declare expected exceptions If exception is not thrown (or a different exception is thrown), the test will public void divideByZero() { int n = 2/0; }
Ignored Tests Use annotation to declare ignored tests For excessively complex or slow tests not currently public void testInternet() { // screenscrape all web pages }
Timed Tests Use annotation to declare timeout parameter If test takes longer than the specified number of milliseconds to run, the test public void retrieveData() { // database access }
Test Design Create Repeatable Tests Run Unit Test after code modification Guard against regressions “code a little, test a little” Write tests as you develop Write tests to help you debug Constantly check your tests against your code
What to test Critical Areas of your code Parts that are most likely to break get/set methods? Forwarding methods? JSP with no business logic? Refactored Code Code that changes the value of an object or creates some kind of side effect.
Test Suite Runs more than one test at the same time Programmatic container for TestCase classes Runs test cases as a logical group Can contain other TestSuites
Creating a Test Suite import org.junit.runner.*; import org.junit.runners.*; import AnotherTest.class}) public class AllTests public static public static void… }
Test Runner - JUnitCore Executes tests Text output Period (.) indicates passed test .E indicates failed test .I indicates ignored test JUnitCore will run any number of test classes java –classpath.;junit-4.4.jar org.junit.runner.JUnitCore TestA TestB TestC
Test Runner Output Text Output
Summary Test Options JUnit Testing Framework TestRunners Test Cases and Test Suites Test Fixtures