-
-
Notifications
You must be signed in to change notification settings - Fork 3
5 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.
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.
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);
}
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.
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.
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.