This document describes writing and running JUnit tests for Fedora. For a general introduction to unit testing or JUnit itself, consult http://www.junit.org/.
Test code is located in a separate source tree from production
code. The JUnit classes are located under src/test/junit
.
We can characterize the types of tests we will write as a spectrum bounded by two extremes:
Object tests are tests of objects in isolation. An object is instantiated, a method invoked, and the result is verified. End-to- end tests, on the other hand, test an entire application, from the outside. The Fedora Test Plan tends towards tests on this end of the spectrum.
Generally, all the tests you write will be derived from the base
TestCase, fedora.test.FedoraTestCase
. This base class
implements FedoraTestConstants
, which defines a number of
useful test-related constants.
End-to-end (or integration) tests for Fedora typically require
a running instance of the Fedora Server.
Tests that require a running instance of the Fedora Server should
extend FedoraServerTestCase
(which itself extends
FedoraTestCase
). The setUp and tearDown methods of
FedoraServerTestCase
start and stop a Fedora Server,
so be sure to call super() if you override setUp or tearDown.
The following TestCase class will:
testExample1
testExample2
package fedora.test.integration; public class TestExampleA extends FedoraServerTestCase { public void testExample1() throws Exception { assertEquals("1", "1"); } public void testExample2() throws Exception { String xml = "<galaxy><planet name='Earth'/></galaxy>"; assertXpathExists("//planet[@name='Earth']", xml); } public static void main(String[] args) { junit.textui.TestRunner.run(TestAPIM.class); } }
Note that in the preceding example, a Fedora Server is
started and stopped for each test case (i.e. once for
testExample1
and again for
testExample2)
. For many tests, this is neither
required nor desirable as starting an instance of Fedora is
relatively expensive (i.e. slow). Sharing a single Fedora Server
between tests may be accomplished with an instance of
FedoraServerTestSetup
.
The general pattern is as follows:
suite()
method in your
TestCase
.TestSetup
at the end
of the suite()
method.package fedora.test.integration; import org.custommonkey.xmlunit.SimpleXpathEngine; public class TestExampleB extends FedoraServerTestCase { public static Test suite() { TestSuite suite = new TestSuite("Unit test for APIM"); suite.addTestSuite(TestExampleB.class); return new FedoraServerTestSetup(suite); } public void setUp() throws Exception { TestIngestDemoObjects.ingestDemoObjects(); SimpleXpathEngine.registerNamespace("dc", "http://purl.org/dc/elements/1.1/"); } public void tearDown() throws Exception { SimpleXpathEngine.clearNamespaces(); TestIngestDemoObjects.purgeDemoObjects(); } public void testExample() throws Exception { assertEquals("1", "1"); } public void testExample2() throws Exception { String xml = "<galaxy><planet name='Earth'/></galaxy>"; assertXpathExists("//planet[@name='Earth']", xml); } public static void main(String[] args) { junit.textui.TestRunner.run(TestExampleB.class); } }
The following extends the preceding pattern, allowing for a setup and teardown that occurs once for an entire test run (i.e. starting and stopping the Fedora Server), another setup and teardown that occurs once for a given suite (e.g. ingesting and purging demo objects), and yet another that occurs for each test case.
package fedora.test.integration; import org.custommonkey.xmlunit.SimpleXpathEngine; public class TestExampleC extends FedoraServerTestCase { public static Test suite() { TestSuite suite = new TestSuite("Unit test for APIM"); suite.addTestSuite(TestExampleC.class); TestSetup wrapper = new TestSetup(suite) { public void setUp() { TestIngestDemoObjects.ingestDemoObjects(); } public void tearDown() { TestIngestDemoObjects.purgeDemoObjects(); } }; return new FedoraServerTestSetup(wrapper); } public void setUp() throws Exception { System.out.println("once per test case setUp()"); } public void tearDown() throws Exception { System.out.println("once per test case tearDown()"); } public void testExample() throws Exception { assertEquals("1", "1"); } public void testExample2() throws Exception { String xml = "<galaxy><planet name='Earth'/></galaxy>"; assertXpathExists("//planet[@name='Earth']", xml); } public static void main(String[] args) { junit.textui.TestRunner.run(TestExampleC.class); } }
fedora.test.integration.AllTests
is the
grandfather of all Fedora integration tests. This is currently
the test that is called by the Ant junit target. All tests
that should be run as part of the test plan should be called by
this test suite. Note that AllTests can call other test suites,
so it's not necessary to individually list all the TestCases at
this level.
Testing multiple configurations of the Fedora Server is handled
through a combination of Properties
files and
fedora.test.integration.TestFedoraConfigurations
.
Properties files located in src/fcfg/server that are prefixed with
"junit" are applied against the base fedora.fcfg and then run.
# junit-mckoi.properties module.fedora.server.storage.DOManager.storagePool = localMcKoiPool module.fedora.server.search.FieldSearch.connectionPool = localMcKoiPool module.fedora.server.storage.ConnectionPoolManager.poolNames = localMcKoiPool module.fedora.server.storage.ConnectionPoolManager.defaultPoolName = localMcKoiPool
Running the Fedora server tests require that you have the
environment variable FEDORA_HOME
correctly defined. For
testing, FEDORA_HOME
should point to the
dist
directory Ant creates when the server
target is invoked.
In addition, the database you intend to run against should already be up and running.
Note that FedoraServerTestCase will delete the various filesystem directories for the object, datastream, temp and resource index upon completion. It will also drop the tables in the Fedora database.
Note: Ant 1.6 suffers from a JUnit affliction described at http://ant.apache.org/faq.html#delegating-classloader. Ensuring junit.jar is in ANT_HOME/lib should do the trick.
As of Fedora 2.1, it's necessary to run fedora-setup
and to start and stop the server before running the tests so that
the required configuration files are in play.
$ ant server $ fedora-setup $ fedora-start $ fedora-stop $ ant junit
You should have the following source directories configured: