Skip to content

feat: aggregate and gate process test coverage, fix the cancellation gateway - #111

Merged
emaarco merged 1 commit into
mainfrom
emaarco/process-coverage-reports-scope
Nov 7, 2026
Merged

emaarco merged 1 commit into
mainfrom
emaarco/process-coverage-reports-scope

Conversation

@emaarco

@emaarco emaarco commented Nov 7, 2026

Copy link
Copy Markdown
Member

Why

#110 writes one process test coverage report per test class, but there was no overview across classes and nothing failed when a path went untested. Turning on a 100 % minimum surfaced two gaps that held in every example: the 7-day signature reminder was never tested, and in cancel-bike-order the condition of the gateway "Cancellation possible?" sat on the "No" flow, so a cancellable order went through "Clarify return with supplier" and "Book costs" (ADR-0014 of the Temporal example already noted that the model reads as inverted).

What

  • Combined report (CIB seven): the four CIB seven examples apply the extension's report aggregator. Gradle loads it from the buildscript classpath, because no plugin marker is published, and runs aggregateProcessTestCoverage after test. Maven runs the aggregate goal in the test phase. The result is all/report.html in the report folder.
  • Coverage gate, 100 % per process test class (CIB seven, Fluxnova):
    • The minimum is set in one place, as the extension's system property on the test task or in Surefire: org.cibseven.community.process_test_coverage.ASSERT_AT_LEAST, or process_test_coverage.ASSERT_AT_LEAST for Fluxnova.
    • The Spring examples get a test-only ProcessTestCoverageContextCustomizerFactory, registered in META-INF/spring.factories. It builds the coverage properties with the extension's builder only for classes ending in ProcessTest. Other classes that run the process, such as BikeUnavailableTransactionTest, are still reported but not gated. The extension's own inclusion patterns cannot be used for this, because an excluded class that starts a process fails with "Coverage state must be initialized".
    • cibseven-remote uses the JUnit 5 extension, whose builder reads the property itself.
    • Running single test methods covers less, so the minimum can be lowered for that run with -PprocessTestCoverageMinimum=0 (Gradle) or -Dprocess-test-coverage.minimum=0 (Maven).
    • There is no gate for Camunda 8, Operaton and Temporal. Camunda Process Test has no minimum option, Operaton has no working coverage tool (see feat: generate process test coverage reports in the BPMN examples #110) and Temporal has no model.
  • Cancellation gateway fix (all 12 examples):
    • The "No" flow now carries ${!cancellationPossible} (Camunda 8: =not(cancellationPossible)). The models were edited with bpmn-cli, so each diff is one line, and the generated process APIs were regenerated.
    • The Temporal workflow and ADR-0014 follow the same rule: possible reverses the order right away, not possible waits for the return clarification and books the costs.
  • Demo dealer: an order of the custom build BIKE-CUSTOM cannot be cancelled. Every other order still can. The rule is encoded in the order id prefix ORDER-CUSTOM-, so the adapter keeps no state.
  • Process tests:
    • The abort test now covers the "not possible" path and checks that costs are booked once.
    • The abort after an accepted alternative covers the "possible" path, with no clarify-return task and no costs.
    • A new test covers the signature reminder: one reminder, then the deadline rejects the application.
  • Bruno:
    • 03-abort and the demo data 07-withdrawn-return-open order BIKE-CUSTOM, so they keep the clarify-return path.
    • The new scenario 11-abort-order-cancelled shows the direct cancellation.
    • In Temporal, 03-abort also checks that the application is still WITHDRAWN after a few seconds.
  • fullstack-cibseven-embedded:
    • "Custom Build" is seeded into the bike catalogue, and the Playwright abort spec orders it, so the UI still reaches the clarify-return path.
    • The withdrawal note (withdrawRequestedNote, en/de) now says the Tasklist step is only needed when the dealer cannot cancel.
  • Docs: each example's AGENTS.md describes the combined report and the gate, the review-process agents list BIKE-CUSTOM as intended, and drift.yml records why the Fluxnova factory and the Temporal check differ.

Verification

  • Clean full builds after the last change, all passing: ./gradlew clean build / ./mvnw -B clean verify in cibseven-embedded, cibseven-process-engine-api and cibseven-remote (both variants), fullstack-cibseven-embedded and fluxnova-embedded (both variants). Each BikeLeasingProcessTest reaches 100 %. The CIB seven report folders contain all/report.html.
  • Gate checked: without the new reminder test, BikeLeasingProcessTest fails with "matches if the coverage ratio is at least 1.0" in cibseven-embedded (93 %), cibseven-remote (94.6 %) and fluxnova-embedded (94.4 %), in both variants. BikeUnavailableTransactionTest (46 %) passes ungated.
  • Single-method runs: a run of one BikeLeasingProcessTest method fails the gate, and passes with -PprocessTestCoverageMinimum=0. ./mvnw test -Dtest=…#… -Dprocess-test-coverage.minimum=0 passes and writes all/.
  • Other examples: ./gradlew build / ./mvnw -B verify passed in operaton-embedded, operaton-process-engine-api, operaton-remote, temporal-native and the three Zeebe examples. These builds ran before the last whitespace and Bruno-only edits in those examples. The Zeebe builds ran one at a time, because Camunda Process Test containers time out under podman load.
  • Repository checks: npm run drift, npm run generate:check, scripts/check-owner.sh, npm test and npm --prefix examples/fullstack-cibseven-embedded/frontend run verify all pass. bpmn-cli validate reports every edited model valid, with no warnings.
  • Not run: the Bruno collections and the Playwright e2e suite, which need a running stack.

Out of scope / Follow-ups

  • The UI copy of withdrawRequestedNote (en/de) and the visible "Custom Build" bike in the fullstack catalogue are user-facing; please confirm the wording and the choice.
  • The extension's Gradle aggregator task is not compatible with the configuration cache (it holds a Project); the cache is off in these builds.
  • The aggregators read every report.json under the report folder, so reports of renamed or deleted test classes stay in all/ until clean.
  • The flipped branch in the Temporal workflow is not guarded with Workflow.getVersion; the dev server keeps no state, and on a real cluster a parked cancel workflow would simply complete without booking costs.
  • An upstream issue for the CIB seven extension: excluding a test class that starts a process crashes instead of skipping it.

Refs https://github.com/Miragon/cibseven-developer-training/issues/249

…gateway

- Combine the per-class coverage reports in the CIB seven examples (report aggregator, Gradle and Maven).
- Fail every *ProcessTest class below 100 % process coverage in the CIB seven and Fluxnova examples; the minimum is the extension's system property, applied to process test classes only.
- Fix cancel-bike-order in all examples: a cancellable order is reversed directly, only a non-cancellable one is clarified and its costs booked. The demo dealer refuses cancellation for BIKE-CUSTOM.
- Cover the signature reminder and both cancellation branches in the process tests; Bruno, demo data, fullstack UI and docs follow.

Refs Miragon/cibseven-developer-training#249
@emaarco
emaarco merged commit 3385713 into main Nov 7, 2026
61 checks passed
@emaarco
emaarco deleted the emaarco/process-coverage-reports-scope branch November 7, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant