Why Magento E2E suites need a parallel strategy
A Magento store is more than its product detail page. Useful end-to-end tests follow customers through search, configurable products, account sessions, carts, checkout and shipping. They also exercise Admin changes and integrations that affect what the storefront does next. As those journeys accumulate, a single browser runner becomes a bottleneck.
MageLens grew out of a Magento project with more than 600 E2E tests. Its technical guide to parallel coverage describes a generalized version of a real project's Cypress CI setup: two guest smoke shards for fast feedback, and eight isolated suites for a broader coverage run. This article explains that design and the safeguards that make its combined report meaningful.
The aim is to shorten the wait for evidence without weakening the evidence itself. A useful report must still identify the code that ran, retain eligible code that never ran, and distinguish passing tests from incomplete execution.
Scope matters. MageLens's
./bin/run-coverageruns the full configured suite in one workspace. Distributed scheduling and cross-run merging are application-specific CI work. MageLens does not expose a distributed--shardoption or a general cross-run merge command. The patterns below require collectors, manifests and validation adapted to your application.
Separate smoke feedback from full coverage
Use a small, deliberate smoke suite to answer the first question after a change: can the most important guest journeys still complete? Use the full suite to examine the broader application and produce coverage. The two workflows serve different decisions.
| Workflow | Selection in the source example | What the result tells you |
|---|---|---|
| Guest smoke | Two shards: guest catalog and other guest scenarios; coverage off | Whether the selected smoke journeys passed |
| Full E2E coverage | Eight suites spanning the broader application | Which eligible PHP, JavaScript and template operations executed during that full run |
The smoke workflow targets pull requests into development branches. The full workflow targets pull requests into the release branch. Adapt those triggers to your team's branching model; the principle is to make the purpose of each result explicit.
A two-way split must avoid running the same files twice. In the source example, the second selection includes the guest directory but excludes the catalog files already assigned to the first shard:
strategy:
fail-fast: false
matrix:
include:
- shard: catalog
spec: cypress/e2e/guest/catalog/**/*.cy.js
- shard: other
spec: cypress/e2e/guest/**/*.cy.js
exclude: cypress/e2e/guest/catalog/**/*.cy.js
This is a selection fragment, not a complete workflow. The CI job must pass spec to Cypress's --spec option and apply exclude through excludeSpecPattern where present. It also needs the application's build, services and browser setup. Check application readiness before starting Cypress, and keep that readiness probe separate from the smoke tests themselves.
Smoke success says nothing about tests outside that selection. The full workflow includes guest scenarios again, producing a self-contained result rather than depending on observations from an earlier smoke run.
Build once, then isolate eight suites
Prepare one Magento build for the tested commit, including locked dependencies, generated files, browser dependencies and instrumented assets. Restore that same build in each shard and in the reporting job. Consistent sources and instrumentation are as important as the time saved by avoiding repeated builds.
The example divides its full suite into guest, state changes, slow flows, signed-in journeys, catalog, integrations, Admin and quotes, and shipping. These are generalized application groups, not a claim that MageLens ships tests for every store's business processes.
Each matrix entry sends only its assigned spec paths to Cypress. Because the CI matrix schedules the jobs, this approach does not require Cypress Cloud scheduling. Keep a complete, non-overlapping inventory as new specs are added or existing files move.
Isolation includes state, not just CPU. Give each shard its own services and a database restored from the CI snapshot. Otherwise one suite's cart operations, configuration changes or fixture cleanup can break another suite. Shared external resources need their own strategy: separate search indexes, unique fixture identities, or serialized access to a mutable sandbox. Separate databases do not isolate a shared remote service.
Set fail-fast: false so other shards can finish and preserve evidence when one fails. This changes how much evidence you retain, not whether the overall run passed. Keep dependent operations together and isolate tests that deliberately change application state.
When several environments run on one host, assign different Docker project names, domains and ports. Do not run concurrent coverage commands in one MageLens workspace: preparation replaces previous outputs and a workflow lock protects that shared state.
Estimate speed without promising a benchmark
Consider 1,000 tests averaging 12 seconds each. That is about 200 minutes of browser execution on one runner. Eight perfectly balanced shards would reduce each shard's test execution to about 25 minutes, before setup and reporting. These are illustrative arithmetic, not measured MageLens timings or a promised eightfold speedup.
Single runner: build + setup + all tests + report
Parallel run: shared build + slowest shard (setup + tests) + merge/report
The slowest shard sets the pace. Balance using observed durations rather than file counts alone, and account for the extra runner capacity and repeated setup. A test waiting on an external system can outweigh many fast catalog assertions.
Preserve raw evidence from every shard
A report merger needs raw execution records, matching manifests and actual test outcomes. HTML reports are useful to people, but they cannot reconstruct the union of everything the suite exercised.
Keep each shard's artifact in its own directory. A practical arrangement is:
coverage-input/
coverage-raw-guest/
metadata.json
test-results.json
php/native/
js/
templates/manifest.json
templates/hits/
coverage-raw-catalog/
...
...
Record the suite name, selected specs, tested commit and runner outcome. Also record the workflow execution and attempt so a retry cannot accidentally reuse an earlier artifact. Compare the received artifacts with an explicit expected suite list: seven results are incomplete when eight suites were scheduled.
Upload evidence even after a failing test job. A GitHub Actions artifact step can use if: always() and if-no-files-found: error. The reporting job can run after the whole test matrix, provided the shared build succeeded. Such a job should collect diagnostics from failures while preserving the failed or incomplete overall status.
Avoid flattening downloaded artifacts. Different shards often use the same filenames, so one out.json or current.json can overwrite another. If JavaScript maps are staged together, give their filenames unique shard prefixes. Filename changes prevent collisions; they do not fix source paths inside a coverage map.
Start with a fresh artifact directory for each execution. Reusing dependencies or a compatible zero-hit manifest can be useful. Reusing old execution hits contaminates the result. Warm-up and readiness checks belong before the measured test execution, with fresh counters for collection.
Merge covered locations, not percentages
Coverage across shards is a union over one shared source inventory. It is not an average of shard percentages and it is not the sum of those percentages.
Imagine a file with 100 executable lines. One shard visits lines 1–40 and another visits lines 31–70. Each reports 40% on its own. Their union covers 70 distinct lines, so combined coverage is 70%. The overlap must be counted once when deciding whether a line is covered.
| Measurement | Valid merge basis | Meaning after merging |
|---|---|---|
| PHP | Compatible native PCOV records and the same executable-line manifest | A PHP line is covered when an accepted record shows it executed |
| Whole-file JavaScript | Matching Istanbul statement, function and branch maps | Counters describe the same instrumented source locations |
| Templates | A matching manifest plus compatible execution and DOM records | Executed constructs and DOM presence remain distinct observations |
Preserve eligible files that no shard loaded. Without a zero-hit baseline, the denominator can shrink to the files encountered by the tests and make coverage look better than it is. In MageLens, application modules and configured local theme scope are measured; vendor packages require explicit inclusion and unrelated inactive themes remain excluded. See the coverage guide for the exact scope and exclusions.
JavaScript: validate Istanbul maps before reporting
Stage validated Istanbul maps with unique filenames, together with a zero-hit baseline for the same build. Then merge once and render from that merged output using the project's locked reporting dependency:
mkdir -p coverage-merge/merged
./node_modules/.bin/nyc merge \
coverage-merge/js-input coverage-merge/merged/coverage.json
./node_modules/.bin/nyc report \
--temp-dir coverage-merge/merged \
--report-dir coverage/js \
--reporter html --reporter json-summary --reporter lcovonly
These commands assume the CI wrapper has already validated the records and supplied the matching source tree and include/exclude configuration. Begin with an empty merged directory and keep it outside the input directory, so a later merge cannot ingest its own previous output.
Verify source hashes and the statement, function and branch maps. Use identical application paths in the containers, or normalize paths to a common source root with validation. Include each execution contribution once; never combine a shard aggregate with snapshots already represented by that aggregate. nyc merges maps, while your wrapper must enforce commit identity, suite completeness and test outcomes.
PHP: retain deployment and run identity
The source example uses a project-specific helper to validate PCOV records against a common deployment fingerprint and identical executable-line manifests. It checks the expected suite count, rejects incompatible records and requires hit-only records to reference the accepted manifest. Validated records receive unique names before the PHP reporter produces HTML and Clover output against the matching source.
PHP inside .phtml still belongs in PHP coverage. Retain uncovered executable lines; emitted HTML and JavaScript are not PHP lines merely because they occur in a PHP template file.
MageLens's local PHP reporter validates a single collection run, including its run ID and backend identity. Copying directories from separate ./bin/run-coverage invocations, or rewriting run IDs until they appear compatible, is not a valid distributed merge. A cross-shard adapter must explicitly validate compatibility and preserve the provenance of each contribution.
Templates: keep execution separate from DOM presence
Compare every shard's template manifest with the restored build before merging. A mismatch must stop reporting rather than assign hits to different source locations. Compatible .mtc records can be staged under one hits directory for the installed template reporter:
./bin/runner node_modules/.bin/magento-template-coverage report \
--manifest coverage/template-manifest.json \
--hits coverage/raw/templates \
--output coverage/templates
That command assumes prior validation by the CI wrapper. It produces the template report only; it does not establish that the full test suite passed or finalize MageLens's combined report.
Template coverage includes supported bindings, expressions and inline scripts. DOM presence remains a separate metric: seeing a button does not prove its click handler executed. Retain warnings about unsupported syntax or PHP-generated script fragments. Where those warnings apply, the percentage describes only the constructs the tool can measure.
Publish a result only when its status is honest
Failure evidence is valuable. A shard that stops halfway may still tell you which code executed before the failure. Publish those observations as incomplete diagnostics, without converting a rendered report into a passing full-suite result.
Before presenting the run as successful, require:
- Every expected shard exactly once, with its intended selection and actual test results.
- One intended commit and workflow execution, with compatible source and instrumentation inventories.
- All expected tests executed and passed. Failed, skipped, pending, cancelled or missing tests cannot be counted as success.
- Successful source-integrity checks and valid merges for all three collectors, preserving zero-hit baselines and measurement warnings.
MageLens's combined report and success badges already require passing tests and valid current-run records. Preserve that standard in a distributed pipeline. If the branch moves while reporting runs, keep the report attached to the commit that was actually tested.
Give AI-assisted development an evidence loop
An AI coding assistant can propose a plausible Magento change faster than a person can verify its consequences. E2E tests and coverage provide concrete feedback for that review. The workflow remains useful whether a human or an assistant wrote the patch.
Start with an observable acceptance condition: for example, a customer's selected shipping method persists through a checkout step. Run the relevant scenario, then inspect the PHP, JavaScript and template records to see whether the implementation you changed was reached. If a modified handler remains unexecuted, add a scenario that drives that interaction and an assertion that verifies its result.
This is deterministic evidence about a specific run: explicit test outcomes, a known source revision and recorded execution. It is not a guarantee that the application is correct, that all user journeys are covered, or that an E2E environment cannot be flaky. Assertions establish the expected behavior; coverage shows where execution went. Both are needed for an informed review.
Give the assistant the tested commit, failing assertion, relevant file and source location, scope, and any measurement warning. After the fix, rerun the full configured suite and inspect fresh reports. Avoid treating an old screenshot or a higher percentage as proof of the new change. MageLens's coding-agent guide documents the supported workflow and integrity rules.
Start with one trustworthy run
First establish the standard local lifecycle: configure the application, run ./bin/run-coverage, and inspect coverage/index.html. Use real business journeys and meaningful assertions. Once the suite's feedback time becomes a problem, carry that same collection discipline into isolated CI shards and a validated merge.
The benefit of parallel Magento E2E testing is faster access to the evidence your team already needs. The value of the combined report depends on preserving its meaning from the first browser action to the last published badge.
Return to the MageLens overview, follow the installation guide, or read the original parallel E2E coverage documentation for the full workflow fragments and implementation boundaries.