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#

text
gradlew.bat runTest

That builds every subproject, boots the test container and runs every suite of every component. Three properties narrow it:

PropertyMeaning
-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.
text
gradlew.bat runTest -PtestComponent=manufacturing
gradlew.bat runTest -PtestComponent=accounting -PtestCase=testInvoiceTotal

gradlew 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:

TaskWhat it does
startStarts the server.
startDebugStarts the server with the debug port on 5005.
stopStops the server.
runTestRuns the test suites and exits.
loadSeedLoads the seed data.
loadDemoLoads 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:

text
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:

java
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:

xml
<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:

xml
<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:

xml
<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.

Ask the people who wrote it.

Support, development and training from the team that builds Scipio ERP.