Run Example Test
Runs one example/tutorial integration test from the distribution module in
2 seconds, bypassing the hardcoded failsafe suite that would otherwise run the
entire example suite (6 min, some tests need internet).
When to use
- The user wants to run / verify / check a specific example or tutorial test,
e.g.
ChainExampleTest,JwtVerificationExampleTest, a*ExampleTestundercom.predic8.membrane.examples.*, or a*TutorialTestundercom.predic8.membrane.tutorials.*.
The distribution must be built first
The base classes (DistributionExtractingTestcase) unzip
distribution/target/membrane-api-gateway-*.zip and start membrane from the
unzipped distribution — not from the source tree. So the tests only ever see
what was last built. Before running them the distribution must be built at the
repo root with:
mvn clean install -DskipTests
The script does this for you (see below). -DskipTests still compiles tests but
skips running them, which also dodges the German-locale annot test failure on
this machine.
How to run
Invoke the helper script with the test class (simple name, fully-qualified name, or path all work):
.claude/skills/run-example-test/run-example-test.sh ChainExampleTest # fast, ~2s
.claude/skills/run-example-test/run-example-test.sh -b ChainExampleTest # rebuild dist first, then run
With no argument it runs the full example IT suite via failsafe (slow, some tests need internet) — and always rebuilds the distribution first, because the suite runs from the built distribution.
The script:
- Distribution build. For the full suite it always runs
mvn clean install -DskipTestsat the root. For a single test it builds the.ziponly if it is missing, or if you pass-b. - Resolves the class name to its FQN by finding the
.javaunderdistribution/src/test/java. - Incrementally recompiles distribution test classes (offline) so edits to the test class are picked up.
- Runs just that class via a tiny JUnit Platform launcher (
RunOne.java), with the working directory set todistribution/(the tests resolve./target).
Exit code is non-zero if the test fails or no tests were found.
When to pass -b (single test): the test recompile in step 3 only covers the
test class itself. Anything that lives inside the distribution .zip — the
example's config/YAML/scripts, or any upstream module like core — is not
reflected until the distribution is rebuilt. Pass -b (or delete the zip) after
editing those.
Locale
The tests run under the English locale, so output is deterministic on a
German JVM (this machine defaults to de/DE). On macOS the JVM ignores
LANG/LC_ALL, so the script uses -Duser.language=en -Duser.country=US
instead, applied to all three JVMs involved:
- the JUnit launcher / failsafe fork — passed directly (
-DargLinefor failsafe); - the child membrane process the tests start via
membrane.sh— via exportedJAVA_OPTS(start_router.shforwards it tojava, andProcess2copies the environment into the child).
(A test that overrides getEnvs() with its own JAVA_OPTS, e.g.
LoggingJsonExampleTest, replaces it and won't get the locale — a rare edge case.)
Why a launcher instead of -Dit.test
distribution/pom.xml hardcodes <test>**/ExampleTests.java</test> for failsafe,
and ExampleTests is a JUnit Platform @Suite. The suite engine ignores
failsafe's class filter, so -Dit.test=Foo runs the whole suite anyway. The
launcher selects a single class directly and skips the suite.
Gotchas
- Changed
core(or another upstream module), not just the test? Step 3 only recompilesdistributiontest classes. Rebuild first withmvn clean install -DskipTestsfrom the repo root so the.zipreflects your change, or delete the zip and let the script rebuild it. - A few suite tests are environmentally flaky / need internet (e.g. anything
hitting
api.predic8.de). Prefer the offline tests undercom.predic8.membrane.examples.withoutinternetwhen demonstrating. - Cached artifacts (
target/cp.txt,target/run-one/) live undertarget/and are recreated automatically;mvn cleanwipes them harmlessly.