Skip to content
This repository has been archived by the owner on Feb 16, 2020. It is now read-only.

5 testing

Markus Perndorfer edited this page Dec 5, 2018 · 1 revision

Testing

Tag
5-testing

The big issue is the very high cycle time from build to a finished test run, and also the runtime of (integration) tests themselves.

Here are some tips and tricks to mitigate this.

Minimal Test Data Set

First, make sure to define a minimal, common data set for the junit tenant. This usually includes things like:

  • Languages
  • Currencies
  • Product / Content Catalog(s) + Demo Product Data
  • Basestore(s)
  • Test / Demo Accounts
  • ...

This data set should contain everything you need to run any integration test.

To get this data imported when you run ant yunitinit, you can use an event listener on AfterInitializationEndEvent as a workaround, because usual mechanism of @SystemSetup classes is not triggered when initializing the junit tenant.

With the minimal test data set, you now only need to modify / add data specific for your test case, as opposed to bootstrapping everything.

Run unit tests without starting the platform

Use the @UnitTest annotation + Mockito for quick tests.

To execute them, either use the IntelliJ hybris plugin or, if you want to trigger them via ant, use the -Dtestclasses.suppress.junit.tenant=true flag to disable the platform startup

ant unittests -Dtestclasses.suppress.junit.tenant=true

If you only want to trigger tests from a specific extension, you can either cd into the extension folder or use the various filter options like -Dtestclasses.extensions=... or -Dtestclasses.packages=....

For more details how you can control which tests are executed check Testing in SAP Hybris Commerce

Pitfall
Platform starts even if suppressed

As soon as any code involved in the tests fiddles around with de.hybris.platform.core.Registry, the platform will start automatically. So don't do it.

In earlier versions, using de.hybris.platform.util.Config also started the platform.

So as a rule of thumb, don't use any of the static platform util classes if you want to avoid an unexpected startup. Directly using Registry or any other of the static util classes is usually a code smell anyway...

To prevent any startup without breaking the startup if you actually need it (for example, because you want to execute full test suite, not only unit tests), you have to hack the platform a bit in a @BeforeClass method:

@BeforeClass
public static void forceSuppressStartup() throws Exception {
    Field shutdownInProgress = RedeployUtilities.class.getDeclaredField("shutdownInProgress");
    shutdownInProgress.setAccessible(true);
    shutdownInProgress.set(null, true);
}

Use ServicelayerTransactionalTest for Integration Tests

Extending your integration test class from de.hybris.platform.servicelayer.ServicelayerTransactionalTest enables:

  • injecting Spring beans via @Resource annotation

  • Every @Test method is run inside a database transaction

    • tests can be re-run easily
    • tests are properly isolated
    • you don't destroy your minimal test data set
  • Convenience methods like importData to import impex files

SAP Commerce 6.7 also introduced platform support for the Spock Framework, see Testing in SAP Hybris Commerce Using Spock for details.

If you write your integration tests in Spock, use de.hybris.platform.servicelayer.ServicelayerTransactionalSpockSpecification as base class to get the same benefits.

Modify (test) classes while the platform is running

The best solution for hot swapping / reloading is JRebel, but that is rather expensive.

A free solution to avoid the overhead of restarting the platform while you write your tests is DCEVM. Check DCEVM Free JRebel Alternative for the setup and details.

With DCEVM in place, you can launch the server and use the testweb extension to execute your tests while you modify and compile the tests in your IDE.

Check The Hybris Testweb Front End for more details / documentation on how to launch tests on a running server.

Here are the scenarios that DCEVM enables:

  • add a test method to an existing test class

  • remove a test method from an existing test class

  • add a new test class

    For this to work correctly, you have to run ant build inside the extension once after you have added the new test class. Otherwise, the new class is not detected by the testing framework

Pitfall
New @Resource fields not injected when modifying an existing class

It seems that the fields of the class definition are cached somewhere even when using DCEVM, and therefore new fields are not injected correctly. As a workaround, use getApplicationContext().getBean(...) in a @Before method to initialize the new field.

//new field introduced while the server was running
@Resource
FlexibleSearchService flexibleSearchService;

@Before
void setup() {
    //workaround until the next server restart
    flexibleSearchService = getApplicationContext().getBean("flexibleSearchService", FlexibleSearchService.class);
}

Make sure you remove the workaround before the next restart of the server!

Pitfall
Class reloading for Spock tests

Unfortunately, Groovy doesn't seem to play nice with DCEVM, so hot swapping Spock tests doesn't work reliably.

Avoid solrserver start

If your particular test case doesn't require solr, you can disable the start by adding...

solrserver.instances.default.autostart=false

...to your local.properties.

This should shave of a few precious seconds from the test execution time.