4 KiB
4 KiB
Building, running, and debugging instrumentation tests
Both APKs matter
Instrumentation tests need TWO APKs:
:app:assembleGoogleMocked→app-google-mocked.apk— production code under test:app:assembleGoogleMockedAndroidTest→app-google-mocked-androidTest.apk— the test code
If you change production code and rebuild only the test APK, the installed main APK stays old and your fix doesn't take effect. Symptom: "the fix doesn't help" — except it does, you just ran the unfixed build.
# Build both
./gradlew :app:assembleGoogleMocked :app:assembleGoogleMockedAndroidTest
# Install each
adb install -r -t <path-to-app-google-mocked.apk>
adb install -r -t <path-to-app-google-mocked-androidTest.apk>
Run a single test (manual)
adb shell pm clear com.tangem.wallet.mocked
curl -X POST http://localhost:8081/__admin/scenarios/reset
adb shell am instrument -w \
-e class "com.tangem.tests.tangempay.TangemPayTest#freezeUnfreezeCard_TogglesCardState" \
com.tangem.wallet.mocked.test/com.tangem.common.HiltTestRunner
Classify the result — Allure noise vs. real failure
After pm clear, /data/user/0/<pkg>/files/original_screenshots doesn't exist →
AllureResultsHack.testRunFinished throws NoSuchFileException → reported as
Tests run: 1, Failures: 1 with a stack trace starting at AllureResultsHack. This is a post-run
hook failure, NOT a test logic failure.
Distinguish:
- First stack frame is
AllureResultsHack.testRunFinished→ infra hook noise; ignore it. - Kaspresso step logs show all
SUCCEEDfor steps 1..N → the test passed. - A REAL failure shows
java.lang.AssertionErrorinside the test's own classes (e.g.at com.tangem.tests.X.foo$lambda…). When auto-classifying CLI output, key off the presence ofjava.lang.AssertionErrorvs. onlyoriginal_screenshots.
@Ignore on instrumentation tests
- Pattern:
@Ignore("https://tangem.atlassian.net/browse/AND-XXXXX")above@Test. - When ignored,
am instrument -e class …reportsOK (0 tests)withTests run: 0(NOTSkipped: 1). Auto-detection should match the zero-test count.
WireMock cheatsheet
Local override is detected; otherwise hits remote. Default local port: 8081.
# Set a scenario state — PUT, not POST
curl -X PUT http://localhost:8081/__admin/scenarios/<name>/state \
-H "Content-Type: application/json" -d '{"state":"<state>"}'
# Reset all scenarios
curl -X POST http://localhost:8081/__admin/scenarios/reset
# Inspect
curl http://localhost:8081/__admin/mappings | jq
curl http://localhost:8081/__admin/scenarios | jq '.scenarios[] | {name, state}'
- Mocks repo: default to the sibling directory
../tangem-api-mocks/(i.e. next totangem-app-android). If that path doesn't exist, ask the user where the mocks repo is rather than guessing. - The repo is branch-per-suite — dozens of feature branches (e.g.
send-via-swap-p1,account-creation,swap-express-mocks,android-tangem-pay-mocks). There is no universal default branch; check out the one the suite under test expects. If it's unclear which branch holds the mappings for your flow, ask the user. Mappings live undermocks/mappings/, response bodies undermocks/__files/. - State transitions are atomic per
requiredScenarioState. If a scenario defines anAfterDepositmapping for/customer/balancebut not/customer/me, a request to/customer/meafter switching toAfterDepositfalls through. Check both endpoints when an "after" assertion fails.
Misc
./gradlew unitTestaggregates all debug/googleDebug + JVM-module tests — faster than per-module tasks for verifying a broad change (but it's for unit tests, not instrumentation).- Detekt config lives in the
tangem-android-toolsgit submodule — look there before assuming a local.detekt.yml. - Path discipline: stay in
/Users/maxibello/dev/tangem-app-android;cdinto the mocks repo only when needed and prefer absolute paths (the shell session resets cwd).