Testing
Scipio ERP runs its tests inside a running framework, not outside it. The test runner boots the container stack, so a test case reaches the real delegator and the real dispatcher. A service test therefore proves the service, its entity model and its ECA rules together.
Run the tests#
gradlew.bat runTestThat builds every subproject, boots the test container and runs every suite of every component. Three properties narrow it:
| Property | Meaning |
|---|---|
-PtestComponent=<name> | Only the suites of one component, for example manufacturing. |
-PtestSuite=<name> | Only one suite, by its suite-name. |
-PtestCase=<name> | Only one case. |
gradlew.bat runTest -PtestComponent=manufacturing
gradlew.bat runTest -PtestComponent=accounting -PtestCase=testInvoiceTotalgradlew run is not the server. The root project has no task named run,
so Gradle abbreviates it to runTest: Tomcat binds 8443, every suite runs and
the process exits. It looks like a server that dies a minute after start. The
server task is start:
| Task | What it does |
|---|---|
start | Starts the server. |
startDebug | Starts the server with the debug port on 5005. |
stop | Stops the server. |
runTest | Runs the test suites and exits. |
loadSeed | Loads the seed data. |
loadDemo | Loads the demo data. |
The test database#
The test container uses the test delegator. In a development install that
delegator shares the Derby database of the default delegator, so the data a
test reads must already be there. Load it first, or a test that inserts a row
fails on a foreign key to a status item or an enumeration it cannot find:
gradlew.bat loadSeed -PloadComponent=manufacturing
gradlew.bat loadDemo -PloadComponent=manufacturing-PloadComponent limits the load to one component. Without it both tasks load
everything.
Write a test#
A test case extends org.ofbiz.service.testtools.OFBizTestCase and lives in
the component source under a test package:
package com.ilscipio.scipio.manufacturing.test;
public class MrpRunTest extends OFBizTestCase {
public MrpRunTest(String name) {
super(name);
}
public void testMrpRunCreatesProposals() throws Exception {
GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin")
.where("userLoginId", "system").queryOne();
Map<String, Object> result = dispatcher.runSync("executeMrp",
UtilMisc.toMap("mrpName", "test", "userLogin", userLogin));
assertFalse(ServiceUtil.isError(result));
}
}dispatcher comes from OFBizTestCase, and delegator from
EntityTestCase above it. There is no user login helper: query the
UserLogin you need, as the example does.
Register the class in a suite file under the component’s testdef directory:
<test-suite suite-name="productionruntests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/test-suite.xsd">
<test-case case-name="mrp-run-tests">
<junit-test-suite class-name="com.ilscipio.scipio.manufacturing.test.MrpRunTest"/>
</test-case>
</test-suite>A case can also load data instead of running a class. Put the fixture first in the file, and the cases below it read it:
<test-case case-name="manufacturing-tests-data-load">
<entity-xml action="load" entity-xml-url="component://manufacturing/testdef/data/ManufacturingTestsData.xml"/>
</test-case>Declare the suite file in the component descriptor:
<test-suite loader="main" location="testdef/productionruntests.xml"/>Read the result#
The runner writes one XML file per suite to
runtime/logs/test-results/<suite>.xml. Read the counts there, but read the
failures themselves in runtime/logs/ofbiz.log: look for the lines that carry
TestRunContainer and -->. The case names in the XML file can be shifted
against the failure they report, so the log is the reliable source.
A failure inside a service shows the service error message, not a stack trace, because the test calls the service the way the application does.