Skip to content

Run the API and JSF tests from Maven Tests, with server-side coverage - #12783

Open
ashmanda-cs wants to merge 80 commits into
IQSS:developfrom
uncch-rdmc:12782-normalize-testing-harness
Open

ashmanda-cs wants to merge 80 commits into
IQSS:developfrom
uncch-rdmc:12782-normalize-testing-harness

Conversation

@ashmanda-cs

@ashmanda-cs ashmanda-cs commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

How it was before

  • The API tests and the JSF tests ran in two separate workflows, and each built the same containers.
  • The JSF suite ran Chromium, Firefox and WebKit one after another on a single runner, and a failure in Chromium stopped the other browsers.
  • The JSF suite was written in TypeScript, so running it needed Node.js.
  • Neither suite reported code coverage.
  • When a test failed, only the logs remained. The images it ran against were thrown away.

What this PR introduces

  • One workflow, "Dataverse Tests", which Maven Tests runs after its unit tests. It builds the base and app images once, from the classes Maven Tests compiled, and hands them to separate jobs, each with its own fresh Dataverse:
    • "Dataverse API Tests"
    • "Dataverse JSF Tests" in Chromium, then Firefox and WebKit in parallel
  • The JSF tests run the Java version of the suite (gdcc/dataverse-jsf-tests, java branch: Playwright for Java and JUnit 5) with Maven, so they no longer need Node.js.
  • Test results on the pull request: "API Test Results" for the API tests, and one "JSF Test Results" for all three browsers.
  • Server-side code coverage. The base image now ships the JaCoCo agent, and a new JAVA_AGENTS setting attaches it, or any other Java agent. The test jobs record which server code they exercise. Maven Tests merges that with the unit and integration test coverage, using the existing JaCoCo executions in pom.xml, and sends it to Coveralls and SonarCloud.
  • The base image is always built from the pull request instead of pulled from Docker Hub, so changes to it are tested.
  • Reproducible failures. Each run's images are kept for a week, with a note of the exact commit, and the testing guide explains how to start them locally.
  • CodeQL analyzes one language at a time instead of all four at once.
  • The old "Container Integration Tests" and "Dataverse JSF Frontend Tests" workflows are removed.

How it helps

  • The containers are built once per run instead of twice.
  • The browsers no longer wait for each other, and one browser's failure no longer hides the others.
  • Each suite has its own job, logs and results, and failing tests show up by name on the pull request.
  • The JSF tests run with Java and Maven, like the rest of Dataverse, so Java developers can run and change them without Node.js.
  • Coveralls and SonarCloud show how much of the server the API and JSF tests exercise, next to the unit tests.
  • A failing test can be investigated locally on the exact images CI used.
  • Fewer jobs compete for the runners all IQSS repositories share.

Business value

  • More dependable pull request checks, so contributions can be reviewed and merged with confidence.
  • Coverage that reflects what the API and UI tests actually exercise, to show where tests are missing.
  • Less time spent re-running and diagnosing CI failures.
  • UI tests in the same language and tooling as the application, so more of the team can maintain them.
  • Less pressure on CI capacity shared across IQSS projects.

Which issue(s) this PR closes:

Special notes for your reviewer:

  • Changes to Maven Tests (maven_unit_test.yml):
    • It calls Dataverse Tests after its unit tests, the same way it calls container_app_push.yml.
    • Its trigger paths now also cover what the API and JSF tests depend on, including container-base and dataverse-spi.
    • The coverage job waits for Dataverse Tests before merging and submitting, and SonarCloud analyzes the merged report.
  • Changes to the base image:
    • It ships the JaCoCo agent in a new AGENTS_DIR.
    • startInForeground.sh attaches the agents listed in JAVA_AGENTS.
    • docker-compose-dev.yml passes JAVA_AGENTS through. It is empty by default, so nothing changes unless it is set.
  • Changes from the first review:
    • renamed workflow and file
    • separate API and JSF jobs
    • the repo's setup-maven action
    • BASE_URL instead of hard-coded URLs
    • narrower trigger paths
    • JaCoCo in the base image
    • coverage through the existing JaCoCo executions
    • the base image always built
    • CodeQL one language at a time
    • the JSF suite in Java, run with Maven (instead of a Maven module wrapping the Node suite)
    • test results summaries for the API and JSF tests
  • The JSF suite comes from the java branch of gdcc/dataverse-jsf-tests (Port the suite to Java (Playwright for Java + JUnit 5) gdcc/dataverse-jsf-tests#14). Moving it into this repository is left for a follow-up.

Suggestions on how to test this:

  1. In the checks of this pull request, open Maven Tests: it should show the Dataverse Tests jobs (Build Containers, Dataverse API Tests and the three Dataverse JSF Tests jobs) after the unit tests.
  2. Check the "API Test Results" and "JSF Test Results" summaries on this pull request. The JSF one lists each test once, with a run per browser.
  3. Check that the Coverage Report Submission job merges the jacoco-api.exec and jacoco-jsf-*.exec files with the unit and integration data.
  4. Optional: follow "Reproducing a CI Failure Locally" in the testing guide with this pull request's run.

Does this PR introduce a user interface change? If mockups are available, please link/include them here:

No. It only changes CI, the base image and the developer setup.

Is there a release notes update needed for this change?:

Yes, for developers: doc/release-notes/12782-normalize-testing-harness.md.

Additional documentation:

  • Testing guide: the new workflow, the Java JSF suite, code coverage and reproducing failures locally.
  • Release checklist: the checks to watch.
  • Base image guide: JAVA_AGENTS and AGENTS_DIR.

Loads the container images and exploded WAR handed off by a build job,
starts the stack and applies the test configuration. The steps are the
same as in the existing container test workflows.
Takes the artifact name as input so multiple jobs in one workflow run
can upload logs without name collisions.
Builds the containers once and uploads the saved images together with
target/dataverse, which docker-compose-dev.yml bind-mounts into the app
container.
Each browser gets its own runner and fresh stack. Playwright projects
chain the browsers, so --no-deps isolates one browser, with
authentication run as a separate invocation first.
Superseded by container_tests.yml. Kept as .disabled for easy rollback.
Superseded by container_tests.yml. Kept as .disabled for easy rollback.
…2782

Runs the old workflow side by side with container_tests.yml on the same
commit for a timing comparison. Revert this commit afterwards.
Runs the old workflow side by side with container_tests.yml on the same
commit for a timing comparison. Revert this commit afterwards.
The side-by-side timing comparison is done. This reverts commit 4f40418.
…S#12782

The side-by-side timing comparison is done. This reverts commit 966d887.
The workflow runs Dataverse's test suites inside containers; it doesn't
test the containers themselves. The concurrency group follows the name.
Lets developers download the exact images a failed run tested against
and start them locally.
On pull requests the built code is the merge commit, not the PR head,
so the artifact now says exactly which commit to check out when
reproducing a failure locally.
@ashmanda-cs
ashmanda-cs force-pushed the 12782-normalize-testing-harness branch from 01298b5 to f898373 Compare October 3, 2026 18:36
@ashmanda-cs
ashmanda-cs marked this pull request as ready for review October 3, 2026 19:17
Copilot AI balanced review requested due to automatic review settings October 3, 2026 19:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…QSS#12782

Besides target/site, the integration-test job now hands over the
jacoco-*.exec files in target/coverage-reports/, so the coverage job can
merge them again with the server-side coverage of Dataverse Tests.
Maven Tests now runs the API and JSF tests after its unit tests, as a
reusable workflow (like push-app-img), reusing the unit-test job's
compiled classes. That puts all test suites in one workflow run, so
their coverage can be merged. On pushes it only runs for develop, as
Dataverse Tests did before.
…rts IQSS#12782

The coverage job waits for Dataverse Tests as well, puts its
jacoco-*.exec files next to the unit and integration data in
target/coverage-reports/, and reruns the existing jacoco-merge-unit-and-it
and jacoco-report executions before submitting to Coveralls. SonarCloud
analyzes that merged report. When Dataverse Tests is skipped (branch
pushes), the merge covers the unit and integration tests as before.
Dataverse Tests now only runs when Maven Tests calls it (or by hand), so
pull requests don't run it twice. Maven Tests' paths gain the ones
Dataverse Tests had (conf, src, modules except backports and src/maven,
docker-compose-dev.yml, tests, scripts, and the workflows and actions),
which also brings container-base and dataverse-spi back in: the API and
JSF tests run on images built from them. The path list is shared
between push and pull_request with a YAML anchor.
Maven Tests' coverage job now merges the API and JSF tests' coverage
with the unit and integration data using the existing JaCoCo
executions, and submits it to Coveralls and SonarCloud. The separate
jacococli merge, per-suite reports and summary table are no longer
needed.
…ged coverage IQSS#12782

Remove the Dataverse Tests status badge (a called workflow has no runs
of its own; the Maven Tests badge now covers all suites) and relabel the
Coveralls badge as test coverage. The testing guide, release checklist
and release note say Maven Tests runs the API and JSF tests after its
unit tests, from the same compiled classes, and that their server-side
coverage goes to Coveralls and SonarCloud.
The dependency plugin copies the JaCoCo runtime agent, at the version
the JaCoCo Maven plugin uses, into the image's new AGENTS_DIR
(/opt/payara/agents). It isn't attached by default; the next commit adds
a way to attach agents at runtime.
startInForeground.sh adds a -javaagent option to JVM_ARGS for each
space-separated entry in JAVA_AGENTS, next to the existing ENABLE_DUMPS
handling. An entry is a jar, optionally followed by =options; relative
jar paths are resolved against AGENTS_DIR. The list is split with read,
so agent options containing * (like JaCoCo's includes) are not expanded
as file globs. Empty by default, so nothing changes unless it is set.
docker-compose-dev.yml hands JAVA_AGENTS to dev_dataverse and publishes
port 6300 for a JaCoCo agent in tcpserver mode. Like the other compose
variables it defaults to empty both as a Maven property in the ct
profile (mvn -Pct docker:start) and in .env (docker compose), so no
agent is attached unless it is set.
start-dataverse-stack gets a java-agents input that it passes to the
compose file as the JAVA_AGENTS property. The test jobs set it to the
agent shipped in the base image, defined once next to BASE_URL, instead
of downloading the agent and editing docker-compose-dev.yml on the
runner.
The JaCoCo agent now ships in the base image and is attached through
JAVA_AGENTS, so downloading it and patching docker-compose-dev.yml on
the runner is no longer needed.
Set max-parallel: 1 on the language matrix, so a push takes one runner
instead of four from the organization's shared concurrency limit. Each
language is still its own independent job (fail-fast: false), in the
listed order. The run takes about 8 minutes instead of 5, still well
under the API and JSF tests.
@ashmanda-cs ashmanda-cs changed the title Build containers once and run JSF browsers and integration tests in parallel Run the API and JSF tests from Maven Tests, with server-side coverage Oct 15, 2026
…QSS#12782

docker-compose-dev.yml now builds gdcc/keycloak from conf/keycloak
instead of pulling a published image. The build job built it, but only
saved the app and configbaker images, so the test jobs tried to pull
gdcc/keycloak from Docker Hub and the stack failed to start. Save every
gdcc/* image the build produced, so images added to the compose file
later travel along too.
The dump and upload steps ran with always(), so when the stack failed to
start they failed too (connection refused on port 6300), adding a second
red step next to the real cause. Run them only if the stack step
succeeded and the run wasn't cancelled; they still run after test
failures, so coverage from failing runs is kept.

@ashmanda-cs ashmanda-cs left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

run-jsf-tests now checks out gdcc/dataverse-jsf-tests at the java
branch (a ref input, so it can be pinned) and runs the Java port of the
suite: install the browser's system libraries with Playwright's Java
CLI, then mvn verify for that browser only. Node.js, npm ci and the
separate authentication step are gone; Java and Maven come from the
job's setup-maven. The JUnit reports and the per-test traces, videos
and screenshots are uploaded as jsf-test-results-<browser>.
SKIP_PREFLIGHT and DOTENV_CONFIG_QUIET were only read by the Node suite.
The Java suite reads the remaining variables (BASE_URL, LOGIN_ADAPTER,
DV_USERNAME, DV_PASSWORD, DV_FULL_NAME, ROOT_DATAVERSE,
LOCALLY_FAIR_ENABLED).
IQSS#12782

The JSF tests now run the Java port of gdcc/dataverse-jsf-tests (java
branch) with Maven. Say so, how CI runs it per browser, and that running
it locally needs Java and Maven but no Node.js.
The Java JSF suite writes JUnit reports, so each browser job now
publishes them with the same action as the API job, as a check and PR
comment named "JSF Test Results (<browser>)". A failing JSF test shows
up by name on the pull request instead of only as a failed job. The JSF
jobs get checks: write and pull-requests: write for this; Maven Tests
already grants them to the call.
IQSS#12782

Also drop the claim that the suites finish at about the same time: the
JSF chain (Chromium, then Firefox and WebKit) takes longer than the API
tests.
Instead of a check and PR comment per browser, a JSF Test Results job
runs after the Chromium, Firefox and WebKit jobs, downloads their JUnit
reports and publishes them together. Each test counts once, with a run
per browser; report_individual_runs reports a failure in a single
browser on its own, pointing at that browser's report. Only this job
needs write access to checks and pull requests, so the JSF jobs go back
to read-only.
The JSF jobs failed only in the suite's own failsafe verify step, which
read all three browsers' summaries in a single-browser run. That is
fixed in gdcc/dataverse-jsf-tests#15 (java branch), which the workflow
checks out at run time.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Size: 10 A percentage of a sprint. 7 hours.

Projects

Status: Ready for Review ⏩

Development

Successfully merging this pull request may close these issues.

Feature Request: Normalize the testing harness

4 participants