[#278] Fix Firebase Test Lab configuration
This commit is contained in:
parent
5b8aaaaed9
commit
fb5fc153a5
|
@ -121,7 +121,7 @@ jobs:
|
|||
run: |
|
||||
mkdir ${ARTIFACTS_DIR_PATH}
|
||||
|
||||
zip -r ${REPORTS_ZIP_PATH} . -i build/reports/ktlint/*
|
||||
zip -r ${REPORTS_ZIP_PATH} . -i build/reports/ktlint/\*
|
||||
- name: Upload Artifacts
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
|
@ -151,6 +151,7 @@ jobs:
|
|||
run: |
|
||||
./gradlew :app:lintZcashmainnetRelease
|
||||
- name: Collect Artifacts
|
||||
if: ${{ always() }}
|
||||
timeout-minutes: 1
|
||||
env:
|
||||
ARTIFACTS_DIR_PATH: ${{ format('{0}/artifacts', env.home) }}
|
||||
|
@ -159,6 +160,7 @@ jobs:
|
|||
mkdir ${ARTIFACTS_DIR_PATH}
|
||||
zip -r ${LINT_ZIP_PATH} . -i *build/reports/*
|
||||
- name: Upload Artifacts
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
|
@ -184,6 +186,7 @@ jobs:
|
|||
# Note that we explicitly check just the Kotlin modules, to avoid compiling the Android modules here
|
||||
./gradlew :preference-api-lib:check
|
||||
- name: Collect Artifacts
|
||||
if: ${{ always() }}
|
||||
timeout-minutes: 1
|
||||
env:
|
||||
ARTIFACTS_DIR_PATH: ${{ format('{0}/artifacts', env.home) }}
|
||||
|
@ -192,6 +195,7 @@ jobs:
|
|||
mkdir ${ARTIFACTS_DIR_PATH}
|
||||
zip -r ${RESULTS_ZIP_PATH} . -i *build/reports/*
|
||||
- name: Upload Artifacts
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
|
@ -232,10 +236,12 @@ jobs:
|
|||
# This first environment variable is used by Flank, since the temporary token is missing the project name
|
||||
GOOGLE_CLOUD_PROJECT: ${{ secrets.FIREBASE_TEST_LAB_PROJECT }}
|
||||
ORG_GRADLE_PROJECT_ZCASH_FIREBASE_TEST_LAB_API_KEY_PATH: ${{ steps.auth_test_lab.outputs.credentials_file_path }}
|
||||
# Because Fulladle doesn't allow Test Orchestrator to be enabled/disabled for a specific submodule, it must be enabled for all modules
|
||||
ORG_GRADLE_PROJECT_IS_USE_TEST_ORCHESTRATOR: true
|
||||
run: |
|
||||
# NEED Firebase Test Lab API key
|
||||
# ./gradlew runFlank --parallel
|
||||
./gradlew runFlank --parallel
|
||||
- name: Collect Artifacts
|
||||
if: ${{ always() }}
|
||||
timeout-minutes: 1
|
||||
env:
|
||||
ARTIFACTS_DIR_PATH: ${{ format('{0}/artifacts', env.home) }}
|
||||
|
@ -243,8 +249,9 @@ jobs:
|
|||
run: |
|
||||
mkdir ${ARTIFACTS_DIR_PATH}
|
||||
|
||||
zip -r ${TEST_RESULTS_ZIP_PATH} . -i *build/outputs/androidTest-results/*
|
||||
zip -r ${TEST_RESULTS_ZIP_PATH} . -i build/fladle/\* \*/build/outputs/androidTest-results/\*
|
||||
- name: Upload Artifacts
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
|
|
|
@ -4,6 +4,7 @@ plugins {
|
|||
id("kotlin-parcelize")
|
||||
id("zcash.android-build-conventions")
|
||||
id("com.github.triplet.play")
|
||||
id("com.osacky.fladle")
|
||||
}
|
||||
|
||||
val packageName = "co.electriccoin.zcash"
|
||||
|
@ -146,6 +147,7 @@ dependencies {
|
|||
androidTestImplementation(libs.androidx.uiAutomator)
|
||||
androidTestImplementation(libs.bundles.androidx.test)
|
||||
androidTestImplementation(projects.sdkExtLib)
|
||||
androidTestImplementation(projects.spackleLib)
|
||||
|
||||
if (isOrchestratorEnabled) {
|
||||
androidTestUtil(libs.androidx.test.orchestrator) {
|
||||
|
@ -222,3 +224,48 @@ tasks.whenTaskAdded {
|
|||
finalizedBy(fetchScreenshotsTask)
|
||||
}
|
||||
}
|
||||
|
||||
// Firebase Test Lab has min and max values that might differ from our project's
|
||||
// These are determined by `gcloud firebase test android models list`
|
||||
@Suppress("MagicNumber", "PropertyName", "VariableNaming")
|
||||
val FIREBASE_TEST_LAB_MIN_API = 23
|
||||
|
||||
@Suppress("MagicNumber", "PropertyName", "VariableNaming")
|
||||
val FIREBASE_TEST_LAB_MAX_API = 30
|
||||
|
||||
val firebaseTestLabKeyPath = project.properties["ZCASH_FIREBASE_TEST_LAB_API_KEY_PATH"].toString()
|
||||
if (firebaseTestLabKeyPath.isNotBlank()) {
|
||||
val minSdkVersion = run {
|
||||
val buildMinSdk =
|
||||
project.properties["ANDROID_MIN_SDK_VERSION"].toString().toInt()
|
||||
buildMinSdk.coerceAtLeast(FIREBASE_TEST_LAB_MIN_API).toString()
|
||||
}
|
||||
val targetSdkVersion = run {
|
||||
val buildTargetSdk =
|
||||
project.properties["ANDROID_TARGET_SDK_VERSION"].toString().toInt()
|
||||
buildTargetSdk.coerceAtMost(FIREBASE_TEST_LAB_MAX_API).toString()
|
||||
}
|
||||
|
||||
fladle {
|
||||
serviceAccountCredentials.set(File(firebaseTestLabKeyPath))
|
||||
|
||||
configs {
|
||||
create("sanityConfig") {
|
||||
clearPropertiesForSanityRobo()
|
||||
|
||||
debugApk.set(
|
||||
project.provider {
|
||||
"${buildDir}/outputs/apk/zcashmainnet/release/app-zcashmainnet-release.apk"
|
||||
}
|
||||
)
|
||||
|
||||
testTimeout.set("5m")
|
||||
|
||||
devices.addAll(
|
||||
mapOf("model" to "Nexus6", "version" to minSdkVersion),
|
||||
mapOf("model" to "Pixel2", "version" to targetSdkVersion)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@ import androidx.compose.ui.test.onNodeWithTag
|
|||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
|
@ -26,6 +28,7 @@ import cash.z.ecc.sdk.fixture.WalletAddressFixture
|
|||
import cash.z.ecc.sdk.model.MonetarySeparators
|
||||
import co.electriccoin.zcash.app.test.EccScreenCaptureProcessor
|
||||
import co.electriccoin.zcash.app.test.getStringResource
|
||||
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
|
||||
import co.electriccoin.zcash.ui.MainActivity
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.screen.backup.BackupTag
|
||||
|
@ -39,6 +42,8 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.junit.rules.RuleChain
|
||||
|
||||
// TODO [#285]: Screenshot tests fail on older devices due to issue granting external storage permission
|
||||
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
|
||||
class ScreenshotTest {
|
||||
|
||||
companion object {
|
||||
|
@ -80,6 +85,11 @@ class ScreenshotTest {
|
|||
@Test
|
||||
@SmallTest
|
||||
fun take_screenshots_for_restore_wallet() {
|
||||
// TODO [#286]: Screenshot tests fail on Firebase Test Lab
|
||||
if (FirebaseTestLabUtil.isFirebaseTestLab(ApplicationProvider.getApplicationContext())) {
|
||||
return
|
||||
}
|
||||
|
||||
composeTestRule.waitUntil { composeTestRule.activity.walletViewModel.secretState.value is SecretState.None }
|
||||
|
||||
composeTestRule.onNodeWithText(getStringResource(R.string.onboarding_1_header)).also {
|
||||
|
@ -124,6 +134,11 @@ class ScreenshotTest {
|
|||
@Test
|
||||
@SmallTest
|
||||
fun take_screenshots_for_new_wallet_and_rest_of_app() {
|
||||
// TODO [#286]: Screenshot tests fail on Firebase Test Lab
|
||||
if (FirebaseTestLabUtil.isFirebaseTestLab(ApplicationProvider.getApplicationContext())) {
|
||||
return
|
||||
}
|
||||
|
||||
onboardingScreenshots(composeTestRule)
|
||||
backupScreenshots(composeTestRule)
|
||||
homeScreenshots(composeTestRule)
|
||||
|
|
|
@ -69,13 +69,21 @@ if (firebaseTestLabKeyPath.isNotBlank()) {
|
|||
}
|
||||
fladle {
|
||||
serviceAccountCredentials.set(File(firebaseTestLabKeyPath))
|
||||
// TODO [#282]: Replace this with NexusLowRes once tests pass on larger screen sizes
|
||||
devices.addAll(
|
||||
mapOf("model" to "NexusLowRes", "version" to minSdkVersion),
|
||||
mapOf("model" to "NexusLowRes", "version" to targetSdkVersion)
|
||||
mapOf("model" to "Nexus6", "version" to minSdkVersion),
|
||||
mapOf("model" to "Pixel2", "version" to targetSdkVersion)
|
||||
)
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
flakyTestAttempts.set(2)
|
||||
|
||||
if (project.properties["IS_USE_TEST_ORCHESTRATOR"].toString().toBoolean()) {
|
||||
useOrchestrator.set(true)
|
||||
environmentVariables.set(mapOf("clearPackageData" to "true"))
|
||||
} else {
|
||||
useOrchestrator.set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@ plugins {
|
|||
id("zcash.android-build-conventions")
|
||||
}
|
||||
|
||||
// Force orchestrator to be used for this module, because we need the preference files
|
||||
// to be purged between tests
|
||||
val isOrchestratorEnabled = true
|
||||
|
||||
android {
|
||||
// TODO [#6]: Figure out how to move this into the build-conventions
|
||||
kotlinOptions {
|
||||
|
@ -13,14 +17,15 @@ android {
|
|||
freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
||||
|
||||
// Force orchestrator to be used for this module, because we need the preference files
|
||||
// to be purged between tests
|
||||
defaultConfig {
|
||||
testInstrumentationRunnerArguments["clearPackageData"] = "true"
|
||||
}
|
||||
|
||||
testOptions {
|
||||
execution = "ANDROIDX_TEST_ORCHESTRATOR"
|
||||
if (isOrchestratorEnabled) {
|
||||
defaultConfig {
|
||||
testInstrumentationRunnerArguments["clearPackageData"] = "true"
|
||||
}
|
||||
|
||||
testOptions {
|
||||
execution = "ANDROIDX_TEST_ORCHESTRATOR"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,9 +39,11 @@ dependencies {
|
|||
androidTestImplementation(libs.bundles.androidx.test)
|
||||
androidTestImplementation(libs.kotlinx.coroutines.test)
|
||||
|
||||
androidTestUtil(libs.androidx.test.orchestrator) {
|
||||
artifact {
|
||||
type = "apk"
|
||||
if (isOrchestratorEnabled) {
|
||||
androidTestUtil(libs.androidx.test.orchestrator) {
|
||||
artifact {
|
||||
type = "apk"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package co.electriccoin.zcash.spackle
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.Settings
|
||||
|
||||
/*
|
||||
* This is not under a test module, because there are some code paths that we might want to alter
|
||||
* during Google Play Prelaunch reports.
|
||||
*/
|
||||
object FirebaseTestLabUtil {
|
||||
private const val FIREBASE_TEST_LAB_SETTING = "firebase.test.lab" // $NON-NLS
|
||||
private const val SETTING_TRUE = "true" // $NON-NLS
|
||||
|
||||
private val isFirebaseTestLabCached = LazyWithArgument<Context, Boolean> {
|
||||
isFirebaseTestLabImpl(it)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the environment is Firebase Test Lab.
|
||||
*/
|
||||
fun isFirebaseTestLab(context: Context) = isFirebaseTestLabCached.getInstance(context)
|
||||
|
||||
private fun isFirebaseTestLabImpl(context: Context): Boolean {
|
||||
/*
|
||||
* Per the documentation at https://firebase.google.com/docs/test-lab/android-studio
|
||||
*/
|
||||
// Tested with the benchmark library, this is very fast. There shouldn't be a need to make
|
||||
// this a suspend function. That said, we'll still cache the result as a just-in-case
|
||||
// since IPC may be involved.
|
||||
return runCatching {
|
||||
SETTING_TRUE == Settings.System.getString(context.contentResolver, FIREBASE_TEST_LAB_SETTING)
|
||||
}.recover {
|
||||
// Fail-safe in case an error occurs
|
||||
// 99.9% of the time, it won't be Firebase Test Lab
|
||||
false
|
||||
}.getOrThrow()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue