Testing FOP
FOP trunk, as of r1178747, has upgraded the unit test framework to JUnit 4. With this, there are a few changes made to how developers write unit tests. Here is a brief synopsis of some of the new features in JUnit 4:
Unit tests no longer extend junit.framework.TestCase. This is very important to remember, because JUnit4 is backward compatible and as such, if a test does extend the TestCase class, the JUnit3 runner will be invoked. This also means that assertEquals() and other assert methods aren't members of the test class. To address this, static imports are provided, for example, import static org.junit.Assert.assertEquals.
Test method names no longer need to be prefixed with "test". JUnit4 uses annotations to describe tests, as such the @org.junit.Test annotation should be applied to methods that are intended to be run as tests. Conversely, @org.junit.Ignore can be applied to tests that should be ignored. If the ignore annotation is used, the developer should put a comment suggesting why this test is being ignored.
The public void setUp() method signature no longer has a significant role in initializing the test class member variables before tests. Instead, an @Before annotation can be used on a method of any name (though it must still have the public void method signature). Conversely, there is an @After annotation, to use to replace the tearDown() method. Additionally, JUnit4 gives several new features such as the @BeforeClass and @AfterClass that, when bound to methods with a public static void signature are invoked only once, before the first time the test class is initialized and after all the test methods are invoked in the class, respectively. This feature is especially useful for resource hungry tasks that only need to be run once to initialize the test class.
The junit.framework.TestSuite is no longer used for creating a suite of tests. Instead a test suite should have the follwing annotations:
@org.junit.runner.RunWith(org.junit.runners.Suite.class)
@org.junit.runners.Suite.SuiteClasses({ < list class names that should be run > })
However, FOP now uses a regular expression (**/*TestCase.java) for adding test classes to a list of tests to run. This does not mean that test cases should not be added to a test suite! Other developers still use the test suites to run a subset of tests and as such it is important to ensure your test case is added the the appropriate test suite.
As a consequence of the previous point Abstract test class names should not be suffixed with "TestCase" as this will throw an exception in the JUnit class loader.
A test can be parameterized using @RunWith(Parameterized.class) annotation on the class, with a corresponding @Parameters annotation on the method that gets the parameters (which must have a signature of public static Collection<T[]> where T is the parameter type). The parameters are then injected into the constructor of the test, such that T[0] is the first constructor parameter etc. This is how the Layout Engine tests have been implemented. There is an unfortunate consequence that currently Junit4 does not provide a way of name parameterized tests, hopefully this will be addressed in future versions of JUnit.
Mocking Framework
As of r1204457 mockito has been added to the testing library class path. The link provided has plenty of information and a brief tutorial to help developers starting to use mocking in their tests.
Code Coverage
As of r1203749 FOP uses Jacoco for code-coverage analysis. There are several things that must be done before Jacoco can be run, firstly the developer needs to download Jacoco and specify the directory of the JAR to give build.xml access to it. This is preferably done by adding the $jacocoant.jar property to build-local.properties which will be consumed by jacoco.xml. Then, the ant -f jacoco.xml clean coverage-report command can be used to invoke code coverage analysis. The results are output in HTML format to the build/report_jacoco/ directory.