Title: An introduction to pragmatic unit testing with JUnit
1An introduction to pragmatic unit testing with
JUnit
- Presented to Dr.Cunninghams ENGR660 Class
-
- Jian Weng
- January 16, 2014
- jweng_at_olemiss.edu
2Outline
- Resource references
- JUnit features goals for unit testing
- Overview of JUnit test framework
- - JUnit framework
- - IDE environment
- - JUnit support files
- - User interfaces for viewing test
results - - Basic Code examples
- Strategies for developing JUnit tests
- - Create new test case
- - Write JUnit test by Right-BICEP
guidelines - - Run JUnit tests
- Conclusions
- Advanced topics
3Resource references
- Get JUnit resources and documents from the
official home pages - http//www.junit.org/
- http//junit.sourceforge.net/
- Pragmatic unit testing, Anderew Hunt and David
Thomas - Test-Driven Development, Kent Beck
- Eclipse Distilled, David Carlson
- Eclipse and MyEclipse websites
- http//www.eclipse.org
- http//www.myeclipseide.com
- Write JUnit test in Jython website
- http//www.jython.org/
4Outline
- Resource references
- JUnit features goals for unit testing
- Overview of JUnit test framework
- - JUnit framework
- - IDE environment
- - JUnit support files
- - User interfaces for viewing test
results - - Basic Code examples
- Strategies for developing JUnit tests
- - Create new test case
- - Write JUnit test by Right-BICEP
guidelines - - Run JUnit tests
- Conclusions
- Advanced topics
5JUnit features goals for unit testing
- Two key conceptions
- What is unit testing?
- What are the objectives of unit testing?
6JUnit features goals for unit testing
- What is unit testing?
- A unit test is a piece of code that exercises a
small, specific area of functionality, e.g., a
particular method in a particular context. - A unit test seeks to demonstrate that the code
does what the developer expects. - If testing indicates that code works as expected,
we proceed to assemble and test the whole system.
7JUnit features goals for unit testing
- What are the objectives of unit testing?
- Coding with more confidence
- Finding bugs as early as possible
- Locating bugs as soon as possible
- Lessening the time spent on debugging
- Checking the consistency among requirements,
design patterns and implementation code
8JUnit features goals for unit testing
- JUnit features
- An instance of the xUnit architecture for unit
testing frameworks - A unit testing framework for Java programs
- A simple framework to write repeatable tests
- The test-first design methodology or test-driven
development thought
9JUnit features goals for unit testing
- JUnit Goals
- Keep the design simple right from the start
- Keep the design easy to change
- Help developers create automated tests
- Create tests that retain their value over time
- Simple to achieve regression testing
10Outline
- Resource references
- JUnit features goals for unit testing
- Overview of JUnit test framework
- - JUnit framework
- - IDE environment
- - JUnit support files
- - User interfaces for viewing test
results - - Basic Code examples
- Strategies for developing JUnit tests
- - Create new test case
- - Write JUnit test by Right-BICEP
guidelines - - Run JUnit tests
- Conclusions
- Advanced topics
11Overview of JUnit framework
- Composite structure of JUnit framework
A utility to run a suite of tests
Helper methods assist to determine a method
performing correctly or not
A collection of tests that are run at the
sane time
A collection of one or more related test methods
12Overview of JUnit framework
- JUnit framework is integrated into popular Java
environments (IDE) - as below
- - JDeveloper
- - Eclipse
- - Forte/Netbeans
- - IntelliJ
- - JBuilder
- - TogetherJ
- - VisualAge
13Overview of JUnit framework
- JUnit support files
- junit.jar
- - Put this file in CLASSPATH environmental
variable - src.jar
- - JUnit sources for reference
14Overview of JUnit framework
- User interfaces for
- viewing JUnit test results
- Text
- - Run the test cases and view the test
results in - JUnit IDE
- GUI
- - Execute the GUI TestRunner class manually
in - command-line window
15Overview of JUnit framework
- Code for basic JUnit test case ( SimpleTest.java)
- package junit.samples
- import junit.framework.
- public class SimpleTest extends TestCase
- protected int fValue1
- protected int fValue2
- protected void setUp()
- fValue1 2
- fValue2 3
-
- protected void tearDown()
-
16- public void testAdd()
- double result fValue1 fValue2
- // forced failure result 5
- assertTrue(result 6)
-
- public void testDivideByZero()
- int zero 0
- int result 8/zero
-
- public void testEquals()
- assertEquals(12, 12)
- assertEquals(12L, 12L)
- assertEquals(new Long(12), new Long(12))
- assertEquals("Size", 12, 13)
- assertEquals("Capacity", 12.0, 11.99, 0.0)
-
17- public static Test suite()
- TestSuite suite new TestSuite()
- suite.addTest(new SimpleTest("add")
- protected void runTest()
testAdd() - )
- suite.addTest(new SimpleTest("testDivideByZero")
- protected void runTest()
testDivideByZero() - )
- return suite
-
- public static void main (String args)
- junit.textui.TestRunner.run(suite())
-
18Outline
- Resource references
- JUnit features goals for unit testing
- Overview of JUnit test framework
- - JUnit framework
- - IDE environment
- - JUnit support files
- - User interfaces for viewing test
results - - Basic Code examples
- Strategies for developing JUnit tests
- - Create new test case
- - Write JUnit test by Right-BICEP
guidelines - - Run JUnit tests
- Conclusions
- Advanced topics
19Strategies for developing JUnit tests
20Strategies for developing JUnit tests
-
- Create a new JUnit test case
- Import junit.jar file into the current project
21Strategies for developing JUnit tests
22Strategies for developing JUnit tests
23Strategies for developing JUnit tests
- Create a new JUnit test case
- Import junit.jar file into the current project
- Create a new JUnit test case by wizard
- Derive the new test case from junit.framework.Test
Case. - Add setUp(), tearDown(), main(), or constructor
functions into JUnit test framework
24Strategies for developing JUnit tests
JUnit test cases will extend from the base class
Some methods can be added into the test framework
first
Import the methods under test to the JUnit test
framework
25Strategies for developing JUnit tests
- Create a new JUnit test case
- Import junit.jar file into the current project
- Create a new JUnit test case by wizard
- Derive the new test case from junit.framework.Test
Case. - Add setUp(), tearDown(), main(), or constructor
functions into JUnit test framework - Import methods under test into the JUnit test
framework
26Strategies for developing JUnit tests
Pick up the methods that need to be under test
27Strategies for developing JUnit tests
- Code generated from the wizard
- import junit.framework.TestCase
- public class MoneyTest extends TestCase
- public static void main(String args)
-
- protected void setUp() throws Exception
- super.setUp()
-
- protected void tearDown() throws Exception
- super.tearDown()
-
- /
- Test method for 'Money.hashCode()'
28Strategies for developing JUnit tests
- /
- Test method for 'Money.add(IMoney)'
- /
- public void testAdd()
-
- /
- Test method for 'Money.addMoney(Money)'
- /
- public void testAddMoney()
-
- /
- Test method for 'Money.amount()'
- /
- public void testAmount()
29Strategies for developing JUnit tests
- /
- Test method for 'Money.currency()'
- /
- public void testCurrency()
-
- /
- Test method for 'Money.equals(Object)'
- /
- public void testEqualsObject()
-
- /
- Test method for 'Money.multiply(int)'
- /
- public void testMultiply()
30Strategies for developing JUnit tests
- Right-BICEP Guidelines
- Right Are the results right?
- B Are all the boundary conditions CORRECT?
- I Can you check the inverse relationship?
- C Can you cross-check results using other
means? - E Can you force error conditions to happen?
- P Are performance characteristics within bounds?
31Strategies for developing JUnit tests
- RIGHT
- Depends on requirements
- Write the test code first by what the code is
expected to do - For instance, to test whether a value returned
from largest() function correct or not, we can
test large amounts of data read from a file.
32Strategies for developing JUnit tests
- Boundary check - CORRECT
- Conformance - Verify a value conforms to an
expected format - Order - Verify the set of values
ordered - Range - Verify a value within the
reasonable minimum - and maximum
values - Reference - Verify the code that reference
something - external that
isnt under direct control of the - code itself
- Existence - Verify whether a value exists
- Cardinality - Verify therere exactly
enough values - Time - Verify everything is
happening in order, - at the right
time, or in time.
33Strategies for developing JUnit tests
- Inverse Check
- Check a method by applying its logical inverse
- For instance, check a method that calculates a
square root by squaring the result and test that
it is tolerably close to the original number
34Strategies for developing JUnit tests
- Cross-check
- If there are more than one way to calculate the
quantity, the result can be cross-checked by a
different method - This technique is applicable to the testing
system when there is a proven, known way which is
too inflexible or too slow
35Strategies for developing JUnit tests
- Force error conditions
- Mock objects can be used to simulate errors from
the real-world such as network lines drop, system
load, and disks fill up.
36Strategies for developing JUnit tests
- Performance characteristics
- Assure the code meets performance targets
- Achieve the quick regression test of performance
characteristics - For instance, an URL filter works fine for a
small URL list, it is necessary to test if it
still works well for a large URL list
37Strategies for developing JUnit tests
- package junit.samples.money
- import junit.framework.TestCase
- public class MoneyTest extends TestCase
- protected void setUp()
- f12CHF new Money(12, "CHF")
- f14CHF new Money(14, "CHF")
-
- public void testMoneyEquals()
- assertTrue(!f12CHF.equals(null))
- Money equalMoney new Money(12, "CHF")
- assertEquals(f12CHF, f12CHF)
- assertEquals(f12CHF, equalMoney)
- assertEquals(f12CHF.hashCode(),
equalMoney.hashCode()) - assertTrue(!f12CHF.equals(f14CHF))
-
- public void testHashCode ()
38Strategies for developing JUnit tests
- public void testAddMoney()
- // 12 CHF 14 CHF 26 CHF
- Money expected new Money(26, "CHF")
- assertEquals(expected, f12CHF.add(f14CHF))
-
- public void testMultiply()
- // 14 CHF 2 28 CHF
- Money expected new Money(28, "CHF")
- assertEquals(expected, f14CHF.multiply(2))
-
- public void testSimpleNegate()
- // 14 CHF negate -14 CHF
- Money expected new Money(-14, "CHF")
- assertEquals(expected, f14CHF.negate())
-
- public void testSimpleSubtract()
- // 14 CHF - 12 CHF 2 CHF
- Money expected new Money(2, "CHF")
- assertEquals(expected, f14CHF.subtract(f12CHF))
39Strategies for developing JUnit tests
- Tricks on writing JUnit tests
- The package with class under test need to be
imported if it is not in the same package as the
test case - Test class must extend TestCase and each test
method must start with test - Test methods have no arguments
- Order of test method execution varies
- Use assertTrue() and assertEquals() to verify
code - Use setUp() tearDown() to prepare test fixture
- Create some test methods manually in the test
case
40Strategies for developing JUnit tests
The run JUnit test name can be changed
- Debug or run JUnit test cases in Eclipse
Test case class name
Identify the location of failed test step
41Strategies for developing JUnit tests
- Debug or run tests in command-line window
Identify the location of failed test steps
42Strategies for developing JUnit tests
- import junit.framework.
- /
- TestSuite that runs all the sample tests
-
- /
- public class MoneyTest
- public static void main (String args)
- junit.textui.TestRunner.run (suite())
-
- public static Test suite ( )
- TestSuite suite new TestSuite("JUnit Money
Test") - suite.addTest(SimpleTest.suite())
- suite.addTest(new TestSuite(MoneyTest.class))
- return suite
-
43Strategies for developing JUnit tests
- Tricks on running JUnit test cases
- JUnit runs all test methods in one test case
automatically in Eclipse view - To run a few methods of a test case, JUnit need
to have suite() method with particular test
methods added manually. - Three ways to run test methods in a test case
- - add a whole test case
- - add certain methods of a test case
- - add the suite method of a test case
- To run JUnit test case in command-line window,
main() function shall be added into the test
case, it use testRunner to run the cases through
text ui, swing ui, or awt ui
44Outline
- Resource references
- JUnit features goals for unit testing
- Overview of JUnit test framework
- - JUnit framework
- - IDE environment
- - JUnit support files
- - User interfaces for viewing test
results - - Basic Code examples
- Strategies for developing JUnit tests
- - Create new test case
- - Write JUnit test by Right-BICEP
guidelines - - Run JUnit tests
- Conclusions
- Advanced topics
45Conclusions
- Simple to create the JUnit test framework through
integrated Java environment, e.g., Eclipse - Support many different unit testing strategies
- Run tests flexibly with an entire suite of test
methods or any of its parts - Identify points of failure quickly by comparing
expected with actual values - View test results through JUnit user interfaces
46Outline
- Resource references
- JUnit features goals for unit testing
- Overview of JUnit test framework
- - JUnit framework
- - IDE environment
- - JUnit support files
- - User interfaces for viewing test
results - - Basic Code examples
- Strategies for developing JUnit tests
- - Create new test case
- - Write JUnit test by Right-BICEP
guidelines - - Run JUnit tests
- Conclusions
- Advanced topics
47Advanced topics
- Improve a class design by defining and verifying
the class invariant - - A class invariant is an assertion about
objects of a class - - For an object to be valid, this assertion
must be true - - For instance, we can add CheckInvariant
method to a stack - class to check the stack to be empty or
overflow, thus to avoid - bugs in the code.
48Advanced topics
- Test-driven development is a valuable technique
that is to write tests before writing the methods
to test. - - The point of TDD is to drive out the
functionality the software actually needs, rather
than what the programmer thinks it probably ought
to have.
49Advanced topics
- Test invalid parameters
- - It depends on the software functionality.
That is if its not the codes responsibility to
check for input data problem, its unnecessary to
do so but if it is, then the extra checking for
input data is required
50Advanced topics
- A mock object is simply a debug replacement for a
real-world object, it is kind of a testing
pattern and can be implemented in three key steps
as - - Use an interface to describe the object
- - Implement the interface production code
- - Implement the interface of a mock object for
testing
51Advanced topics
- JUnit tests can be written in Jython(Python for
java) - - Python is a preferable language for writing
tests because it can integrate very well with the
platform it runs on - - Python is quite straightforward because of
dynamic typing - - Jython tests and test results can be
integrated inside the same view by adding
Jython.jar file to the Eclipse project. That is
to install Jython plugins.
52