mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-09-14 06:11:20 -04:00
143 lines
5.0 KiB
HTML
143 lines
5.0 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en" dir="ltr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Testing</title>
|
||
<link rel="stylesheet" href="../styles/docs.css">
|
||
</head>
|
||
<body data-page="testing" data-locale="en">
|
||
<pre class="markdown-content"># Testing
|
||
|
||
Testing strategy and practices for the Meshtastic KMP project.
|
||
|
||
## Test Categories
|
||
|
||
### KMP Unit Tests (`commonTest`)
|
||
|
||
Shared tests that run on all platforms:
|
||
|
||
```bash
|
||
./gradlew allTests
|
||
```
|
||
|
||
- Business logic tests
|
||
- Data model validation
|
||
- Search/ranking algorithm tests
|
||
- Route serialization tests
|
||
|
||
### Android Host Tests
|
||
|
||
Android-specific tests that run on JVM:
|
||
|
||
```bash
|
||
./gradlew test
|
||
```
|
||
|
||
- ViewModel tests
|
||
- Repository tests with Room fakes
|
||
- Android-specific integration tests
|
||
|
||
### Compose UI Tests
|
||
|
||
Compose Multiplatform UI test framework:
|
||
|
||
```kotlin
|
||
@Test
|
||
fun myScreenTest() = runComposeUiTest {
|
||
setContent { MyScreen() }
|
||
onNodeWithText("Expected").assertIsDisplayed()
|
||
}
|
||
```
|
||
|
||
Located in `commonTest` or `jvmTest` source sets.
|
||
|
||
### Screenshot Tests
|
||
|
||
Uses Android Gradle Plugin's native (layoutlib) screenshot testing framework, split across two modules:
|
||
|
||
- **`:screenshot-tests`** — the **visual-regression gate**. CI runs `validateDebugScreenshotTest` on it; reframing one of these baselines is a real diff to review. Holds atomic, dual-purpose components.
|
||
- **`:docs-screenshots`** — **generate-only**, *not* validated in CI. Holds doc-framed compositions whose framing is tuned for the docs site, so reframing a doc image never churns the regression gate.
|
||
|
||
```bash
|
||
./gradlew :screenshot-tests:updateDebugScreenshotTest # record regression goldens
|
||
./gradlew :screenshot-tests:validateDebugScreenshotTest # compare against goldens (CI gate)
|
||
./gradlew :docs-screenshots:updateDebugScreenshotTest # record doc-framed composition images
|
||
./gradlew :screenshot-tests:copyDocsScreenshots # copy doc images from BOTH modules into docs/assets
|
||
```
|
||
|
||
Rendering is host-deterministic here (layoutlib): a local `update` produces references byte-identical to CI, so locally-recorded goldens pass `validate`. See `docs/assets/screenshots/README.md` for which module a new screenshot belongs in.
|
||
|
||
### Baseline Profile / Startup Performance
|
||
|
||
The `:baselineprofile` module (#5735) generates a [Baseline Profile](https://developer.android.com/topic/performance/baselineprofiles/overview) for `:androidApp`, AOT-compiling the hot startup paths so ART doesn't pay the JIT cost on first launch. It targets the `google` flavor (the variant most users run).
|
||
|
||
The Macrobenchmark generator (`BaselineProfileGenerator`) and the before/after benchmark (`StartupBenchmark`) live in `baselineprofile/src/main/kotlin/org/meshtastic/baselineprofile/`. Both run on a device/emulator:
|
||
|
||
```bash
|
||
./gradlew :androidApp:generateGoogleReleaseBaselineProfile # Generate the profile (commit the output)
|
||
./gradlew :androidApp:benchmarkGoogleReleaseBaselineProfile # Quantify the cold-start win
|
||
```
|
||
|
||
The generated profile is merged into `androidApp/src/googleRelease/generated/baselineProfiles/` and packaged into release builds via `androidx.profileinstaller`.
|
||
|
||
> ℹ️ **Note:** The journey covers cold start only (launch → first frame), because CI has no paired radio. Post-connection screens (node list, map, message thread) are not yet AOT-compiled.
|
||
|
||
Extending the journey past cold start needs a fake transport or a connected radio wired into the harness.
|
||
|
||
## Test Organization
|
||
|
||
```
|
||
feature/my-feature/src/
|
||
├── commonTest/kotlin/org/meshtastic/feature/myfeature/
|
||
│ ├── MyBusinessLogicTest.kt
|
||
│ └── MyModelTest.kt
|
||
└── jvmTest/kotlin/org/meshtastic/feature/myfeature/
|
||
└── MyDesktopSpecificTest.kt
|
||
```
|
||
|
||
## Testing Guidelines
|
||
|
||
### DO
|
||
|
||
- Write tests in `commonTest` when possible (runs everywhere)
|
||
- Test business logic independently from UI
|
||
- Use fakes/stubs instead of mocks where practical
|
||
- Test edge cases: empty states, error states, boundary values
|
||
- Test deep link routing in `DeepLinkRouterTest`
|
||
- Keep tests fast — no network, no disk I/O in unit tests
|
||
|
||
### DON'T
|
||
|
||
- Don't test framework behavior (Compose internals, Room queries)
|
||
- Don't create tests that depend on other feature modules
|
||
- Don't use `Thread.sleep` — use coroutine test dispatchers
|
||
- Don't rely on test execution order
|
||
|
||
## Running Tests
|
||
|
||
```bash
|
||
# All KMP tests
|
||
./gradlew allTests
|
||
|
||
# Specific module
|
||
./gradlew :feature:docs:allTests
|
||
|
||
# Code quality
|
||
./gradlew spotlessCheck detekt
|
||
|
||
# Full verification
|
||
./gradlew spotlessCheck detekt kmpSmokeCompile test allTests
|
||
```
|
||
|
||
## CI Integration
|
||
|
||
Tests run automatically on:
|
||
- Pull request creation/update
|
||
- Push to `main`
|
||
- Pre-release validation
|
||
|
||
Every job in `reusable-check.yml` runs on `ubuntu-24.04` with JDK 25 and Gradle caching; only the desktop and Flatpak-source jobs use a matrix. The ARM (`ubuntu-24.04-arm`) and container-backed `ubuntu-slim` runners carry the lightweight utility workflows instead — see `.skills/testing-ci/SKILL.md` for the four-tier rule.
|
||
</pre>
|
||
</body>
|
||
</html> |