03 - Testing and CI
1. Why
Sinew's tests run in commonTest wherever possible, and on each platform where behavior differs: secure storage, crypto, biometrics, the network checker, engine errors. CI has to run all of them, enforce the dependency graph and the ABI, and prove that production builds carry no devtools.
2. Shape
| Job | Runner | Runs |
|---|---|---|
jvm-android | ubuntu | ./gradlew check for android (host tests) and jvm: unit tests, checkKotlinAbi, checkSinewGraph, Detekt, Kover (80% floor) |
android-device | ubuntu + emulator (Gradle Managed Devices) | instrumented tests: Keystore, Tink keyset loss, biometrics with an emulator fingerprint, the network checker |
ios | macos | ./gradlew iosSimulatorArm64Test, plus the Keychain, CryptoKit and biometric tests on a simulator, plus an xcodebuild of the sample |
web | ubuntu | ./gradlew wasmJsBrowserTest in headless Chrome |
devtools-gating | ubuntu + macos | builds the production variants and fails if any non-no-op com.srctool.sinew.devtools class is present, and checks that the merged real ABI dumps equal the no-op dump (APK via apkanalyzer, the iOS framework via nm, desktop and web bundles by class and symbol listing) |
publish | macos, on tags | see Publishing |
| Rule | Why |
|---|---|
| Test first by default. A test written after the code must be seen failing once. Bug fixes are always test-first. | The base testing rules |
| 80% line coverage per module, measured by Kover on the JVM run | The floor from the base note |
| Every job uses the Gradle build cache and the configuration cache | Four targets make the build slow otherwise |
| The web job is required, unlike Camouflage's | Sinew's web code is mostly plain Kotlin/Wasm. The Compose modules (-l10n, -viewmodel, -camouflage, -devtools-ui) are tested on web too, but their web screenshots aren't tested |
3. API
Gradle tasks CI calls: check, checkKotlinAbi, checkSinewGraph, koverVerify, iosSimulatorArm64Test, wasmJsBrowserTest, checkDevToolsGating (a custom task wrapping the artifact checks), publishAndReleaseToMavenCentral.
4. Build steps
- The
jvm-androidjob at S0, with everything that runs on the JVM. iosandwebjobs at S0, on placeholder tests.android-deviceat S4, when secure storage and biometrics exist.devtools-gatingat S7.
Done when
- All jobs are green on
main, and the gating job fails on a branch that adds the real devtools to the production variant.
5. Edge cases
| Case | Decided behavior |
|---|---|
| A flaky emulator biometric test | It's retried once by the job. Twice flaky in a week means it's fixed or quarantined, never ignored. |
| Coverage drops below 80% on a module | koverVerify fails the job. |
Decided by default (revisit during implementation)
- The web job is required for Sinew. Unlike Camouflage, Sinew's web code doesn't depend on Compose web's Beta status.