Wire Android uses a layered testing strategy covering unit tests, instrumented UI tests, and static analysis. This page describes how to run each type and how the test infrastructure is organised.
Gradle tasks
The following Gradle tasks are available from the project root:
| Task | Description |
|---|
./gradlew runUnitTests | Runs all unit tests |
./gradlew runAcceptanceTests | Runs all acceptance tests on a connected device |
./gradlew testCoverage | Generates a test code coverage report |
./gradlew staticCodeAnalysis | Runs static code analysis (Detekt) |
Unit tests
Unit tests run on the JVM and do not require a connected device or emulator.
Parameterized tests with JUnit 5
The project uses JUnit 5 parameterized tests to avoid writing multiple test cases for the same scenario with different inputs. Tests annotated with @ParameterizedTest receive their parameters as method arguments.
@ParameterizedTest
@MethodSource("provideInputs")
fun `given various inputs, when processed, then correct result`(input: String, expected: String) {
val result = process(input)
assertEquals(expected, result)
}
Refer to the JUnit 5 parameterized tests documentation for the full set of available argument sources.
Acceptance and UI tests
Acceptance tests are instrumented tests that run on a connected Android device or emulator.
./gradlew runAcceptanceTests
A connected device or running emulator is required to run acceptance tests.
UIAutomator framework
Wire Android migrated from Appium to UIAutomator for integrated UI testing. UIAutomator is part of the Android SDK and is more flexible than Espresso for cross-app testing scenarios.
UI tests live in a dedicated tests/ module with the following structure:
wire-android
├── app/
├── core/
├── features/
└── tests/
├── testsCore/ # Core UI test cases
└── testsSupport/ # Shared test utilities and helpers
This structure allows shared logic to be extracted into testsSupport and reused across test modules, enabling parallel execution across devices if needed.
Test annotations and filtering
UI tests use custom annotations that enable fine-grained filtering and structured reporting:
@TestCaseId("TC-8602")
@Category("criticalFlow")
@Tag(key = "feature", value = "calling")
fun `given a call, when answered, then connected`() { ... }
Filtering is handled by com.wire.android.tests.support.suite.TaggedFilter. Only tests matching the filter run; all others are excluded entirely and do not appear in reports.
Running specific test subsets
By test case ID
By category
By tag
./gradlew :tests:testsCore:connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.testCaseId=TC-8602
./gradlew :tests:testsCore:connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.category=criticalFlow
./gradlew :tests:testsCore:connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.tagKey=feature \
-Pandroid.testInstrumentationRunnerArguments.tagValue=calling
Both tagKey and tagValue must match for a test to be included.
Allure reports
The UI test suite integrates with Allure for rich HTML reporting. Allure results are written to the device at:
/sdcard/googletest/test_outputfiles/allure-results
To pull results from the device and generate a local report:
# Pull results from the device
adb exec-out sh -c 'cd /sdcard/googletest/test_outputfiles && tar cf - allure-results' > allure-results.tar
# Extract locally
rm -rf allure-results
mkdir allure-results
tar xf allure-results.tar -C allure-results
# Open the interactive HTML report
allure serve allure-results/allure-results
The report shows passed and failed tests, failure screenshots, and tag metadata. Only executed tests appear — filtered-out tests are not included.
Static code analysis
The project uses Detekt for Kotlin static analysis.
./gradlew staticCodeAnalysis
Detekt also runs as a pre-commit Git hook (see Contribution guidelines).
Code coverage
Coverage reports are uploaded to Codecov and displayed on pull requests.
Coverage thresholds
The project targets the following coverage levels (configured in codecov.yml):
| Scope | Target | Behaviour |
|---|
| Project | Auto (based on base branch) | Fails if coverage drops more than 2% |
| Patch (PR diff) | 80% | Informational only — does not fail the build |
Paths excluded from coverage
The following paths are excluded from coverage measurement:
buildSrc/
kalium/ (submodule)
- Test source sets (
**/test/**, **/androidTest/**)
- Generated screens (
**/*Screen*.kt)
- Mock, theme, common, navigation, and DI directories