Add a recipe for custom build types and product flavors - #313
Conversation
Document how the Gradle plugin infers install tasks and package IDs, why flavored and custom build type projects fail with "Unable to find instrumentation info", and the four settings to configure together. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AgUU49S4wSWd7vhJS7kEmU
AndroidTestifyBot
left a comment
There was a problem hiding this comment.
Changes requested
Accurate page — the inference table matches GradleProjectExtensions exactly, and the testifySettings sample output reproduces the real println block's field order and alignment. Two changes.
1. Lead with moduleName for nested modules
The nested-module section recommends running install tasks by hand. There's a better fix: the lookup is findByPath(":${settings.moduleName}:${settings.installAndroidTestTask}"), and moduleName is user-settable — so
testify {
moduleName "feature:login"
}makes the path resolve to :feature:login:installDebugAndroidTest and restores the automatic dependency. It also feeds the testifyModule resValue and the ./gradlew $moduleName:screenshotPull hints in error messages, which come out correct with the full path too.
Please make that the primary recommendation, with manual install tasks as the fallback.
2. Hedge the instrumentation error string
INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info… is a platform message, not a Testify one, and it's what readers will paste into a search box. Please prefix it with "an error like this", the same treatment #321 gives its Hilt error.
Verified correct
installTask/installAndroidTestTaskinference, including "first alphabetically" —tasks.namesis aSortedSet.- That the inferred package IDs exclude product-flavor suffixes —
applicationTargetPackageIdonly readsdefaultConfig.applicationIdand the debug build type. testifySettingsprintingapplicationPackageIdastargetPackageId.-Pverbose=true, and thatscreenshotTest/screenshotRecorddependsOnthe install tasks.- Issue #238 is real, open, and exactly about this
findByPathfailure. The "skips installing without an error" claim is right —getInstallDebugAndroidTestTask(project)?.let { }swallows the null.
flavorDimensions = ["backend"] is the current AGP form and reads fine against an AGP 9 baseline — no change suggested unless you target an older minimum.
Reviewed by Claude on behalf of @DanielJette.
AndroidTestifyBot
left a comment
There was a problem hiding this comment.
Approved
Both requested changes are in, and the moduleName section went further than I asked.
moduleName now leads, with the mechanism explained
The plugin looks for the install tasks at
:<moduleName>:<task name>, andmoduleNamedefaults to the module's own name, without its parent directories.
Verified: TestifySettings.create does extension.moduleName ?: project.name, and Gradle's project.name for :feature:login is login. So the inferred path really is :login:installGoogleMockDebugAndroidTest, which doesn't exist — and getInstallDebugAndroidTestTask(project)?.let { } swallows the null, hence the silent skip. Setting moduleName "feature:login" makes findByPath resolve. Manual installs are correctly demoted to a fallback.
The Groovy/Kotlin spelling is right in both tabs: moduleName has no is prefix, so both DSLs use the same name.
The error string is now attributed, not just hedged
The message comes from Android rather than Testify, and you'll see an error like this:
Better than what I asked for — telling readers the message isn't Testify's is more useful than a bare "an error like this".
New claim, verified
Testify runs the tests with
adb shell am instrumentusingtestPackageId, and reads screenshots from the device usingapplicationPackageId.
Correct on both halves: ScreenshotTestTask builds .argument("$testPackageId/$testRunner"), while ScreenshotPullTask and DeviceUtilities use runAs(targetPackageId) and interpolate targetPackageId into the SD card path. The follow-on — that a wrong applicationPackageId still lets tests run but sends screenshotPull/screenshotClear to the wrong app — follows directly and is right.
Re-verified from the previous round
Inference table, "first alphabetically" (tasks.names is a SortedSet), flavor suffixes correctly excluded from the inferred IDs, testifySettings printing targetPackageId, -Pverbose=true, and issue #238.
Docs build verified locally: exit 0, zero warnings, individually and combined.
Reviewed by Claude on behalf of @DanielJette.
What does this change accomplish?
Build types and product flavors have no docs page, and
flavorhas returned no results in docs search in 2023, 2024 and 2025. Two users in #131 worked out the configuration themselves and asked for it to be documented.Fixes #131
Relates to #238
How have you achieved it?
recipes/23-build-types-and-flavors.md.GradleProjectExtensions.kt: the firstinstall…Debug/install…DebugAndroidTesttask alphabetically, andapplicationIdplus the debug build type suffix (flavor suffixes are ignored).installTask,installAndroidTestTask,applicationPackageIdandtestPackageIdtogether.:<moduleName>:<task>.testPackageId) and which only affectscreenshotPull/screenshotClear(applicationPackageId).testifySettingsand-Pverbose=true.moduleNameto the full module path so the plugin finds the install tasks, with running the install tasks by hand as a fallback.Scope of Impact and Testing instructions
Documentation only; no library or plugin changes, so no CHANGELOG entry. Built locally with
yarn buildfromdocs/. No broken links. Behaviour checked againstTestifyExtension.kt,GradleProjectExtensions.ktandScreenshotTestTask.kt.Each commit includes
[skip ci]so CI doesn't run for this docs-only change.Notice
Warning
This change must keep
mainin a shippable state; it may be shipped without further notice.🤖 Generated with Claude Code
https://claude.ai/code/session_01AgUU49S4wSWd7vhJS7kEmU