Skip to content

Continuous integration

db-test’s own CI runs its integration suite against all three engines. This is the job, as it is in the repository. Adapt it for your project.

.github/workflows/ci.yml
integration:
runs-on: ubuntu-latest
# The integration suite starts a container per engine. Running the three engines as
# separate jobs keeps one engine's failure from hiding the others' results.
strategy:
fail-fast: false
matrix:
engine: [MsSql, PostgreSql, MySql]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
with:
dotnet-version: |
8.0.x
10.0.x
- name: Restore
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
# One leg per supported runtime, in one job so the database image is pulled once.
# DBTEST_TIMING turns on the per-test timing file, which is uploaded below.
- name: Integration tests (net8.0)
env:
DBTEST_TIMING: "1"
run: >-
dotnet test tests/DbTest.Integration.Tests
--configuration Release
--no-build
--framework net8.0
--filter "FullyQualifiedName~${{ matrix.engine }}HarnessTests"
- name: Integration tests (net10.0)
env:
DBTEST_TIMING: "1"
run: >-
dotnet test tests/DbTest.Integration.Tests
--configuration Release
--no-build
--framework net10.0
--filter "FullyQualifiedName~${{ matrix.engine }}HarnessTests"
- name: Upload timings
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: timings-${{ matrix.engine }}
path: tests/DbTest.Integration.Tests/bin/Release/*/dbtest-timing.tsv
if-no-files-found: ignore

One job per engine. The suite starts a container per engine. Running the engines as separate matrix legs, with fail-fast: false, keeps one engine’s failure from hiding the others’ results.

Docker comes from the runner. The job has no Docker setup step: it relies on the Docker daemon on the ubuntu-latest runner, which Testcontainers talks to.

Select a leg by class name. The matrix value is part of the test class name, and --filter "FullyQualifiedName~${{ matrix.engine }}HarnessTests" runs only that engine’s classes: MsSqlHarnessTests, PostgreSqlHarnessTests or MySqlHarnessTests. Name your per-engine classes in a pattern like that to filter the same way.

One step per runtime. The packages ship net8.0 and net10.0 assets. The job tests both with --framework, in one job so the database image is pulled once, and installs both runtimes with actions/setup-dotnet.

Timings as an artifact. DBTEST_TIMING: "1" turns on the per-test timing file. The last step uploads it for each engine, with if: always() so a failing run still reports its timings.