test.py
test.py is the build and test helper script for Apache Juneau. It runs the Maven build, the Java tests, a
performance guard, the tooling's own Python tests and the browser tests, each as a row on
juneau-terminal, which also keeps the logs and the run history.
push.py runs it as its test step.
What It Does
A full run (the default) takes these steps in order, and stops at the first one that fails:
| Row | What it runs |
|---|---|
| Compile | mvn clean install -T1C -DskipTests. |
| Java tests | mvn test -T1C -Drat.skip=true, one block per module. |
| Perf | The performance guard. |
| Python tests | scripts/tests, the tooling's own pytest suite, through python3 -m pytest when pytest is importable, else uv run --native-tls --with pytest --with pyyaml. With neither, it prints a notice and skips. Nothing is installed. |
| Browser tests | The *_BrowserTest classes in juneau-console-views, juneau-petstore-core and juneau-terminal-region, under -Pjs-tests. See Browser tests. |
| Traces | The stack-trace guard over what the rows above printed. |
--build-only runs Compile alone. --test-only runs everything after Compile.
Usage
Full Build and Test (Default)
python3 scripts/test.py
# or
python3 scripts/test.py --full
# or
python3 scripts/test.py -f
Build Only (Skip Tests)
python3 scripts/test.py --build-only
# or
python3 scripts/test.py -b
Test Only (No Build)
python3 scripts/test.py --test-only
# or
python3 scripts/test.py -t
Board Console
python3 scripts/test.py --console board
Draws one row per step instead of streaming Maven's output, and writes the raw output to a full log whose tail -f
command the header prints. See Console view.
Exclude Container-Backed Tests
python3 scripts/test.py --no-container
Adds -DexcludedGroups=container to the test run, leaving out tests tagged @Tag("container") (the Spring Boot,
Jetty and Tomcat container tests), for a faster local loop when you only need core coverage.
Browser Tests
python3 scripts/test.py --js-tests # always run them
python3 scripts/test.py --no-js-tests # never run them
The browser tests are excluded from the main test pass and run in their own step, as CI's js-tests,
js-tests-petstore and js-tests-terminal jobs do. With neither flag, they run when a .js, .cjs, .css or
.ftl file under a src/ tree differs from origin/master (committed, uncommitted or untracked), and otherwise the
row shows as skipped. If Node or npm is missing, an automatic run is skipped with a notice, but --js-tests fails.
The first run downloads Playwright and Chromium (it needs the network); later runs reuse target/js.
Performance Guard
After the Java tests pass, the Perf row compares the wall-clock time of mvn test with the suite entry in the
project-root perf-baseline.txt, and each module's time from Maven's Reactor Summary with its entry under
[modules]. The suite breaches above its baseline plus JUNEAU_CI_PERF_THRESHOLD (default 0.20, so 20%). A module
breaches only when it is over that and also more than JUNEAU_CI_PERF_MIN_SECONDS (default 3) seconds over its
baseline. A module with no entry is reported and never fails. The report goes to target/perf-guard.txt.
Breaches are warnings unless you pass --enforce-perf:
python3 scripts/test.py --enforce-perf
Stack-Trace Guard
After the other rows pass, the Traces row scans what they printed for stack traces and fails on any whose header line
(for example java.lang.IllegalStateException: boom) is not matched by an entry in scripts/trace-allowlist.txt. Each
entry is a regular expression followed by # and the reason it is allowed; an entry with no reason, an invalid
expression or a repeated expression fails the row. The report of every trace, allowed or not, goes to
target/trace-guard.txt.
The scan reads the run's full log, which exists with --console board or --console none. With the default
--console full there is none, so the row is skipped with a warning. --warn-traces reports traces as a warning
instead of failing; an allowlist error still fails.
python3 scripts/test.py --console board --warn-traces
Rebaselining
python3 scripts/test.py --rebaseline
Rewrites the suite line and the [modules] section of perf-baseline.txt from this repository's run history
(~/.cache/juneau-terminal/history, see Run history and estimates),
prints what changed, and exits without building. Each value is the median of the last --window passing runs
(default 20) of the same command shape, rounded up to a tenth of a second, after dropping runs over three times the
median. A module whose runs spread by more than 50% takes the 75th percentile instead. Keys with fewer than
--min-runs runs (default 5) keep their value, and a module with no history is removed. The rest of the file is
kept as it is.
One-Shot JFR Profiling
python3 scripts/test.py --profile juneau-core/juneau-marshall
Runs mvn test -pl <module> with a Java Flight Recorder recording and writes it to
target/profile-results/<module>-<timestamp>.jfr. It replaces the test argLine, so the JaCoCo agent doesn't skew
the profile. It runs instead of the build and tests.
Command-Line Options
| Option | Effect |
|---|---|
--full, -f | Clean build, then the tests. The default. |
--build-only, -b | Only the build. Can't be combined with --test-only. |
--test-only, -t | Only the tests (Java, Perf, Python and Browser), with no build. |
--no-container | Excludes @Tag("container") tests. |
--js-tests | Also runs the browser tests. Fails if Node or npm is missing. |
--no-js-tests | Never runs the browser tests. Can't be combined with --js-tests. |
--enforce-perf | Fails the run on a performance-guard breach. |
--warn-traces | Reports stack traces in the test output as a warning instead of failing the Traces row. |
--rebaseline | Rewrites perf-baseline.txt from the run history, then exits. |
--window <n> | With --rebaseline: the number of recent runs per key (default 20). |
--min-runs <n> | With --rebaseline: skips keys with fewer runs than this (default 5). |
--console full|board|none | The console view. Default full, which streams Maven's output live; also JUNEAU_TERMINAL_CONSOLE, and the flag wins. |
--detail summary|actionable|modules|all | How many sub-rows a finished row keeps. Default actionable; also JUNEAU_TERMINAL_DETAIL. |
--full-log <path> | Also appends every byte Maven prints to this file. |
--board-log <path> | Also appends the board one-line-per-event stream to this file. |
--profile <module> | Runs a one-shot JFR profile of the module's tests. |
--verbose, -v | Accepted for compatibility and has no effect: Maven's output always streams live. |
--timing-log <path> | Ignored, with a warning: timings are in the run history now. It will be removed in a later release. |
--help, -h | Shows the help message. |
Environment
| Variable | Effect |
|---|---|
JUNEAU_MVN_WRAPPER | A prefix for every mvn command, such as a lock script that serializes concurrent runs on one checkout. |
JUNEAU_CI_PERF_THRESHOLD | The performance guard's tolerance (default 0.20). |
JUNEAU_CI_PERF_MIN_SECONDS | The seconds a module must also exceed its baseline by (default 3). |
JUNEAU_PUSH_NO_SOUND=1 | Silences the bell at the end of a run. Under push.py, only push.py rings it. |
Exit Codes
0- Success.1- An unknown option, a conflicting pair of options, or a failed performance guard (with--enforce-perf), Python test run or browser test run.2- An invalid--detailvalue.130- Cancelled with Ctrl-C or SIGTERM.- Otherwise, Maven's own exit code when the build or Java tests fail.
Requirements
- Python 3, and the
juneau-terminalsources in the checkout (juneau-terminal/src/main/python/), which the script loads directly. - Maven on the
PATH. - Node and npm for the browser tests, and pytest or
uvfor the Python tests.