Title: JUnit intro
1JUnit intro
2What are Programmer Tests?
- Programmer Testing is the testing performed by a
developer with the goal of verifying the correct
functioning of his/her own code - Programmer Tests are automated unit tests that
exercise program units such as classes and
methods , not the complete features or
requirements supported by the software as a whole - Important distinction if its not automated,
its not really programmer testing thats
exploratory testing.
3Safety Net
- Having a good test coverage with an automated
unit test harness - prevents a system from becoming legacy(), and
- enables effective refactoring, because it also
prevents regression - Metaphor Mold
- Michael Feathers defines legacy code as code
without tests
4Michael Feathers (2004)
- I don't care how good you think your design is.
If I can't walk in and write a test for an
arbitrary method of yours in five minutes its not
as good as you think it is, and whether you know
it or not, you're paying a price for it - You think your design is good? Pick a class, any
class, and try to instantiate it in a test
harness. - Can you make this class work outside the
application? - Can you get it to the point where you can tinker
with it, in real time, build it alone in less
than a second, and add tests to find out what it
really does in certain situations.
5Available tools for Java
- JUnit (www.junit.org)
- The de facto Java unit testing framework
- Extremely simple, suitable for unit/component
testing - Plenty of extensions for J2EE, for example
- TestNG (testng.org)
- Very close to JUnit but not quite
- Can configure test groups/suites in a more
flexible way (it is usable for some integration
testing)
6JUnit Concepts
- Test suite Executable row of several Test cases
- Test case Java class containing test methods
- Test fixture the initial state of a Test Case,
consisting of the member variables initialized
through a method annotated with _at_Before. E.g. - _at_Before
- public void setUp()
- Test method a no-argument method of a TestCase
class annotated with _at_Test (represents a single
logical test) For example - _at_Test
- public void someMethod()
-
- Only things to do in _at_Test testA()... methods
is business logic assertions. - Test fixture contains everything else needed to
run the tests (it is initialized in "_at_Before
setUp()...").
7TestCase lifecycle
- _at_Before public void setUp() ...
- gets called once before each test method is
executed - _at_After public void tearDown() ...
- gets called once after each test method has been
executed regardless of whether the test passed
or failed (or threw some other exception). - Each test method gets called exactly once in some
order (test methods should be isolated, so the
order does not matter). - The same instance of a TestCase may or may not be
used for executing the tests dont depend on
the constructor, use setUp() for setup!
8Suite Example
- import org.junit.
- import org.junit.runner.RunWith
- import org.junit.runners.Suite
- _at_RunWith(Suite.class)
- _at_Suite.SuiteClasses(value TestCase1.class,
TestCase2.class) - public class SomeSuite
- // any code
- // may contain TestCase1, TestCase2
- // as inner classes, if their fixtures have
much - // in common
-
9Simple Annotations in a TestCase
- import org.junit.
- public class TestCase1
- _at_Before protected void setUp() super.setUp()
- _at_After protected void tearDown()
super.tearDown() - _at_Test public void methodOne() ...
- _at_Test(expected RuntimeException.class)
- public void testSomeException() ...
- _at_Ignore(value "Test method not ready")
- _at_Test
- public void ignoredTestCase() ...
10Simple TestCase (3)
- import org.junit.
- public class TestCalculator
- private Calculator calculator
- protected void setUp()
- super.setUp()
- calculator new Calculator()
-
- _at_Test
- public void addingPositiveIntegers()
- int expected 5
- int actual calculator.add(2, 3)
- assertEquals("2 3 should be 5", expected,
actual) -
11Test anything that could fail
- import org.junit.
- public class TestCalculator
- private Calculator calculator
- _at_Before protected void setUp()
- _at_After
- protected void tearDown()
- _at_Test public void addingPositiveIntegers()
- _at_Test public void addingNegativeIntegers()
- _at_Test public void addingZeroes()
- _at_Test public void addingPositiveToNegative()
How many method calls are executed?
12Test Granularity
- Each unit test should check one specific piece of
functionality. Do not combine multiple, unrelated
tests into a single testXXX( ) method. - If the first assertEquals( ) in some method
fails, the remainder is not executed. You won't
know if the other (unrelated) asserts are
functional. - One method may contain several asserts, if they
are related, i.e. if the failure of one assert
would cause failures in other asserts anyway.
13Exercise 1Write a TestCase
- Task Write a JUnit TestCase for the Template
class, place it under - sem02-demo/src/main/java/exercise1/TemplateTest.ja
va - Theres a bug in Template class. Try to find it!
14Simple TestSuite
- import org.junit.
- import org.junit.runner.RunWith
- import org.junit.runners.Suite
- _at_RunWith(Suite.class)
- _at_Suite.SuiteClasses(value CalculatorIntegerTest
.class, CalculatorFloatingPointTest.class,
CalculatorLogarithmsTest.class ) - public class CalculatorTestSuite
- // Can leave empty
15Exercise 2Write a TestSuite
- Task
- Write a JUnit TestSuite exercise2.AllTests that
collects all the TestCase classes from
sem02_demo/src/test/java/exercise2.
16What if I need to do something expensive in
setUp()?
- If you need to perform some kind of one-time
setup before running the test methods of a
TestCase (and cant/wont replace the expensive
stuff with a mock implementation), use
_at_BeforeClass annotation - public class Example
- _at_BeforeClass public static void onlyOnce()
- _at_Before public void beforeEachTest()
- _at_Test public void one() ...
- _at_Test public void two() ...
17Example of _at_BeforeClass
- public class InterestCalculatorTestWithTestSetup
- private static double interestRate,
loanAmount - private static int loanDuration
- public static Test suite()
- TestSuite suite new TestSuite(InterestCa
lculatorTestWithTestSetup.class) - TestSetup wrapper new TestSetup(suite)
- public void setUp() throws
IOException - ResourceBundle bundle
ResourceBundler.getBundle( - InterestCalculatorTestWith
TestSetup.class.getName()) - inrerestRate Double.parseDouble(
bundle.getString(interest.rate)) - loanAmount Double.parseDouble(bu
ndle.getString(loan.amount)) - loanDuration Interest.parseInt(b
undle.getString(loan.duration)) -
-
- return wrapper
-
- public void testInterestCalculation()
18Assertions
- We already saw one assertion in action, the
assertEquals() method - There are a bunch others take a look at the
Javadocs for org.junit.Assert - The most often used assertions assertEquals(),
assertNull(), assertSame(), assertTrue() and
their opposites are enough for most situations
and the rest you can easily write on your own. - Assert.fail() is used, if control should not
reach that line in the test - this makes the test
method to fail.
19Testing Expected Exceptions
- _at_Test
- public void method1()
- try
- Template t new Template( "My f\\oo
template" ) - fail("Should NOT allow unterminated
variables in " t) -
- catch (IllegalArgumentException expected)
-
- _at_Test(expectedIllegalArgumentException.class)
- public void method2()
- new Template( "This is my f\\oo template"
)
First approach is longer, but allows more precise
control, where exactly the test method fails.
20What happens when an assertion fails?
- The failed assertions create a org.junit.runner.no
tification.Failure when they fail. - JUnit tags the test as failure for later
reference. - If a test throws any other exception (e.g.
NullPointerException), JUnit again catches these
but tags the test as error instead of
failure.