Skip to content

Add integration tests to CI - #294

Open
mgaffigan wants to merge 4 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:feat/smoketest
Open

Add integration tests to CI#294
mgaffigan wants to merge 4 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:feat/smoketest

Conversation

@mgaffigan

@mgaffiganmgaffigan commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Modifies CI to primarily build within Docker. Uses that newfound Docker capability to run message-processing smoke tests against each supported runtime and database: alpine and Ubuntu (temurin21), with back-ends for derby, mysql, postgres, and sqlserver.

Adds file-based fixture tests. Each configuration in ci/configurations/ runs the applicable cases in ci/tests/. A fixture case deploys one or more exported channels, submits its message fixtures through the OIE client API, and asserts the resulting source and destination messages. Procedure to add a test:

  1. Create a test folder (ci/tests/110-hl7-no-op)
  2. Add any channels needed (ci/tests/110-hl7-no-op/channels/01-hl7-no-op/channel.xml) by exporting from a running instance
  3. Add messages (ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/source)
  4. Add assertions (ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/source_response, dest01, status/metadata, etc.)

Assertions are byte-for-byte, with ((ANY)) matching variable content such as generated IDs or timestamps. See ci/README.md for the full list of assertion files and how to add a new configuration. When a scenario needs logic that can't be expressed as input data and expected results, there is a JUnit 5 escape hatch under smoketest/src/test/java/... using the Harness/OieServer helpers.

Integration tests produce JUnit XML results at ci/test-results/<configuration>/.

Run every configuration locally:

ci/runtests.sh

For "inner loop troubleshooting" it is often worthwhile to run a single configuration:

ci/runtests.sh alpine-temurin21-mysql

Or iterate against an already-running server:

./gradlew :smoketest:test -Doie.baseUrl=https://localhost:8443

Responsive to #11 and #98

@github-actions

github-actionsBot commented Apr 12, 2026

Copy link
Copy Markdown

Test Results

121 files 121 suites 2m 37s ⏱️
677 tests 677 ✅ 0 💤 0 ❌
689 runs 689 ✅ 0 💤 0 ❌

Results for commit 5ea53df.

♻️ This comment has been updated with latest results.

@mgaffigan
mgaffiganforce-pushed the feat/smoketest branch 2 times, most recently from c81c101 to a07f581CompareApril 12, 2026 04:50
@mgaffigan
mgaffiganforce-pushed the feat/smoketest branch 2 times, most recently from 379f74b to b36b39bCompareJuly 24, 2026 17:01
@mgaffigan
mgaffigan requested a review from CopilotJuly 24, 2026 17:03

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR shifts CI toward Docker-based builds and adds a Dockerized integration-test runner that boots various docker-compose configurations and validates message processing using filesystem-discovered fixtures, publishing JUnit XML results as artifacts.

Changes:

  • Update GitHub Actions build pipeline to build/load Docker images, export build artifacts/test results from a Docker stage, and run matrix “docker smoke” integration tests per configuration.
  • Add a Python-based test runner container (ci/runner/) plus a PowerShell entrypoint for local execution (ci/runtests.ps1).
  • Introduce file-based integration test fixtures under ci/tests/ (RAW and HL7 no-op examples) and formalize the approach in ci/README.md.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/gen-dockerignore.pyAdds generator to derive .dockerignore from .gitignore plus Docker-specific excludes.
server/src/test/java/com/mirth/connect/server/launcher/Log4jMigrationsTest.javaMakes a migration test conditional when filesystem permission semantics don’t enforce non-writability.
DockerfileAdds a scratch stage to export build artifacts/test-results for CI packaging and upload.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/source_responseAdds expected source ACK fixture for HL7 test.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/sourceAdds HL7 ADT^A01 input message fixture.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/dest01_metadata.ymlAdds destination metadata assertions for HL7 test.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/channel.xmlAdds exported HL7 channel fixture with metadata column mappings.
ci/tests/101-raw-no-op/channels/01-raw-no-op/messages/01-hello-world/sourceAdds RAW message input fixture.
ci/tests/101-raw-no-op/channels/01-raw-no-op/messages/01-hello-world/dest01Adds RAW destination content assertion fixture.
ci/tests/101-raw-no-op/channels/01-raw-no-op/channel.xmlAdds exported RAW channel fixture with metadata column mappings.
ci/runtests.ps1Adds local test entrypoint that builds images and runs the runner container against configs.
ci/runner/run.pyAdds runner entrypoint wrapper for calling main().
ci/runner/messagetests.pyImplements message fixture discovery, message submission, polling, and assertions (with wildcard support).
ci/runner/main.pyImplements runner CLI: boot compose, login, discover/run tests, write JUnit XML, teardown.
ci/runner/junitxml.pyAdds minimal JUnit XML writer + helper to wrap steps as testcases.
ci/runner/DockerfileDefines runner image (docker CLI + Python + lxml + yaml).
ci/runner/compose.pyImplements docker compose up/down orchestration and per-run project naming.
ci/runner/channeltests.pyImplements channel fixture discovery/deploy/cleanup, and optional test hooks with timeouts.
ci/runner/api.pyImplements REST client for login, channel lifecycle, message submission/search, and XML parsing.
ci/README.mdDocuments the CI integration-test design, fixture format, and runner contract.
ci/configurations/ubuntu-temurin21-postgres.compose.ymlAdds Ubuntu+Postgres compose configuration with healthchecks.
ci/configurations/ubuntu-temurin21-derby.compose.ymlAdds Ubuntu+Derby compose configuration with healthchecks.
ci/configurations/alpine-temurin21-sqlserver.compose.ymlAdds Alpine+SQL Server compose configuration with db-init and healthchecks.
ci/configurations/alpine-temurin21-postgres.compose.ymlAdds Alpine+Postgres compose configuration with healthchecks.
ci/configurations/alpine-temurin21-mysql.compose.ymlAdds Alpine+MariaDB compose configuration with healthchecks.
ci/configurations/alpine-temurin21-derby.compose.ymlAdds Alpine+Derby compose configuration with healthchecks.
ci/.gitignoreIgnores runner outputs (test-results/, __pycache__/).
.github/workflows/upload_test_results.yamlExpands test result upload patterns to include docker smoke artifacts.
.github/workflows/build.yamlReworks CI to build/export via Docker, upload images, and run docker smoke matrix.
.dockerignoreReplaces hand-maintained ignore with generated content aligned to .gitignore semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadci/runner/api.py Outdated
Comment threadci/runner/messagetests.py Outdated
Comment threadci/runner/channeltests.py Outdated
Comment threadci/runtests.ps1 Outdated
@mgaffigan
mgaffigan marked this pull request as ready for review July 24, 2026 18:03
@mgaffiganmgaffigan mentioned this pull request Jul 25, 2026
@mgaffigan
mgaffiganforce-pushed the feat/smoketest branch 3 times, most recently from b59c7d6 to e6efb18CompareJuly 25, 2026 23:28
NicoPiel
NicoPiel previously approved these changes Jul 26, 2026

@jonbartelsjonbartels 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.

There is a build failure, looks like directory permissions https://github.com/OpenIntegrationEngine/engine/actions/runs/30450937701/job/90630023586?pr=294#step:9:1215

Fix this error and rebase. @ me when you do that and I'll re-review

Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
@mgaffigan

Copy link
Copy Markdown
ContributorAuthor

@jonbartels fixed

@jonbartels

Copy link
Copy Markdown
Contributor

The code looks good to me. I want to test and review this PR by grabbing the branch and writing my own, new test using the fixtures mechanism. I think I know a few cases for character encoding and strict parser settings that might be good.

Is there a mechanism that will let us test on Oracle? A casual search found https://github.com/gvenzl/oci-oracle-free. Again I can grab the branch and see about adding my own JVM/DB combo to see how it works.

Tentative approval pending some time to try the code out. TY Mitch!

@mgaffigan

Copy link
Copy Markdown
ContributorAuthor

Is there a mechanism that will let us test on Oracle? A casual search found https://github.com/gvenzl/oci-oracle-free. Again I can grab the branch and see about adding my own JVM/DB combo to see how it works.

I puttered around with ghcr.io/gvenzl/oracle-free:slim-faststart for a bit, but didn't get a working configuration. Oracle has weird client/server compatibility issues before/after v12. I'll see where I left that and push it somewhere.

Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
@mgaffigan

Copy link
Copy Markdown
ContributorAuthor

@jonbartels

Is there a mechanism that will let us test on Oracle? A casual search found https://github.com/gvenzl/oci-oracle-free. Again I can grab the branch and see about adding my own JVM/DB combo to see how it works.

Seems to work. Must have been unrelated. Maybe it was the download size that had me avoid it (~2GB).

@pacmano1

Copy link
Copy Markdown
Contributor

One thing worth considering: the configurations run serially. runtests.sh all loops the seven configs in the single build job under set -e, so the first failure aborts the rest and there's no parallelism. Since runtests.sh <config> already takes one configuration and the stacks are project-name isolated, a GH Actions matrix (one job per config, needs: build, images from the existing buildx cache) would give wall-time and full failure visibility for basically a build.yaml change.

Minor: a fixture whose configurations file lists only never-matching names is skipped in every config, and --fail-if-no-tests won't catch it — worth validating config names against ci/configurations/ eventually.

@mgaffigan

mgaffigan commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@pacmano1

One thing worth considering: the configurations run serially. runtests.sh all loops the seven configs in the single build job under set -e, so the first failure aborts the rest and there's no parallelism.

I did it this way originally, but since matricies run on different runners, the time it took to restore docker caches/github artifacts was significant. I decided to minimize transfer billing in trade for a few minutes of runtime to minimize costs. The matrix runner did complete faster in wall time, but billed more.

If we're not worried about github limits/billing, I can switch it back.

@pacmano1

Copy link
Copy Markdown
Contributor

No bill here. It's all free. I don't think we will him limts.

@@ -0,0 +1,40 @@
services:
db:
image: mariadb:11.8

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: MySQL and MariaDB might be wire-compatible, but it is still a bit confusing that the .yml is named mysql, but it's actually MariaDB being used. It might warrant a comment.

Sign up for freeto 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.

6 participants

@mgaffigan@jonbartels@pacmano1@madskonradsen@NicoPiel