Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce tests sharding #21101

Merged
merged 23 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
168a994
Add and configure `fladle` Gradle plugin
wzieba Jul 31, 2024
ceb5d82
Run instrumented tests via fladle
wzieba Jul 31, 2024
e96ee1a
Update `firebase.secrets.json` path
wzieba Jul 31, 2024
99d5c67
Fix path to secrets
wzieba Jul 31, 2024
9e6afa0
Fix setting up paths for debug and instrumentation apks
wzieba Aug 1, 2024
3e93f61
Fix copying test logs for test collector
wzieba Jul 31, 2024
14ba431
Set different paths for smart flank report file
wzieba Jul 31, 2024
d36b4a9
Make Buildkite annotation work
wzieba Aug 1, 2024
3d7c853
temp: break instrumentation tests
wzieba Aug 1, 2024
cd01ef0
Fix Ruby formatting in test.rb
wzieba Aug 1, 2024
a462b4d
Use double asterix wildcard to locate matrix ids
wzieba Aug 1, 2024
4882026
Use relative path to locate matrix ids
wzieba Aug 1, 2024
7c69f45
Fix invalid matrix_ids relative path
wzieba Aug 1, 2024
9616d52
Set correct relative path
wzieba Aug 1, 2024
cc83564
Fix path for instrumented-tests result file
wzieba Aug 1, 2024
c1ef744
Revert "temp: break instrumentation tests"
wzieba Aug 1, 2024
cc4cc3b
Ignore `e2eAllDayStatsLoad` in `wordpress` variant
wzieba Aug 1, 2024
10c9a74
Update order of `testTargets`
wzieba Aug 1, 2024
997e808
rescue on `StandardError` when instrumentation tests fail
wzieba Aug 2, 2024
e7d901b
Break down `jq` command and its arguments
wzieba Aug 2, 2024
4d7c0b7
Split `pathForVariant` into two methods
wzieba Aug 5, 2024
9c05ddd
Add a comment about ignoring specific tests on WordPress variant when…
wzieba Aug 5, 2024
40986a8
Merge branch 'trunk' into introduce_tests_sharding
wzieba Aug 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .buildkite/commands/run-instrumented-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if [[ "$TESTS_EXIT_STATUS" -ne 0 ]]; then
fi

echo "--- 🚦 Report Tests Status"
results_file=$(find "build/instrumented-tests" -type f -name "*.xml" -print -quit)
results_file="build/instrumented-tests/JUnitReport.xml"

if [[ $BUILDKITE_BRANCH == trunk ]] || [[ $BUILDKITE_BRANCH == release/* ]]; then
annotate_test_failures "$results_file" --slack "build-and-ship"
Expand All @@ -28,6 +28,6 @@ else
fi

echo "--- 🧪 Copying test logs for test collector"
mkdir buildkite-test-analytics && cp build/instrumented-tests/*/*/*.xml buildkite-test-analytics
mkdir buildkite-test-analytics && cp -r build/instrumented-tests/matrix_* buildkite-test-analytics

exit $TESTS_EXIT_STATUS
51 changes: 51 additions & 0 deletions WordPress/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,57 @@ plugins {
id "com.google.dagger.hilt.android"
id "org.jetbrains.kotlinx.kover"
id "com.google.devtools.ksp"
id "com.osacky.fladle"
}

fladle {
testTargets = [
"notPackage org.wordpress.android.ui.screenshots"
]
configs {
wordpress {
def app = "wordpress"
debugApk.set(appPathForVariant(app))
instrumentationApk.set(testPathForVariant(app))
smartFlankGcsPath.set(pathForSmartFlankGcsPath(app))
/* Ignoring (already ignored by JUnit#assume) specific tests on the WordPress app to
prevent Fladle/Flank from scenario of executing them on a single shard.
This avoidance helps prevent test failures due to overly aggressive sharding that
could incur unnecessary costs and tests run failure. */
testTargets.set(testTargets.get() + [
"notClass org.wordpress.android.e2e.StatsTests",
"notClass org.wordpress.android.e2e.StatsGranularTabsTest",
Comment on lines +34 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for test targets unavailable on the variant, do we need to define them here to be excluded?

asking because when looking at the tests, it looks like there's a check to see if it's jetpack app before continuing with test setup:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, they have to. If they're not, fladle/flank might create a shard with only tests from StatsTests or StatsGranularTabsTest. As they're ignored, the execution will be very fast (few seconds) and Firebase Test Lab will mark the test run as failed. It will do this to signal a problem, as too aggressive sharding might bring more unwanted costs. Some more details are available in here the comment description: cc4cc3b . Failed run like this can be found here https://buildkite.com/automattic/wordpress-android/builds/19467#01910e2f-5783-4f74-8897-2725f66ce343

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for the detailed explanation and linking that commit's comment description! What do you think about adding a comment on the test too? So we would know for a future test that's only available on one variant we should add it to the exclusion list too

Copy link
Contributor Author

@wzieba wzieba Aug 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing, added a comment! WDYT?

9c05ddd

])
}
jetpack {
def app = "jetpack"
debugApk.set(appPathForVariant(app))
instrumentationApk.set(testPathForVariant(app))
smartFlankGcsPath.set(pathForSmartFlankGcsPath(app))
}
}
serviceAccountCredentials = new File(System.getProperty("user.home"), ".configure/wordpress-android/secrets/firebase.secrets.json")
ParaskP7 marked this conversation as resolved.
Show resolved Hide resolved
devices = [
["model": "Pixel2.arm", "version": "30"]
]

localResultsDir = "$rootDir/build/instrumented-tests"

maxTestShards = 50
shardTime = 120
}

String appPathForVariant(String app) {
String path = "outputs/apk/${app}Vanilla/debug"
return new File(layout.buildDirectory.dir(path).get().asFile, '*.apk').absolutePath
}
String testPathForVariant(String app) {
String path = "outputs/apk/androidTest/${app}Vanilla/debug"
return new File(layout.buildDirectory.dir(path).get().asFile, '*.apk').absolutePath
}

static String pathForSmartFlankGcsPath(String app) {
return "gs://fladle/wordpress-android/${app}/smart-flank/JUnitReport.xml"
}

sentry {
Expand Down
37 changes: 5 additions & 32 deletions fastlane/lanes/test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

GOOGLE_FIREBASE_SECRETS_PATH = File.join(Dir.home, '.configure', 'wordpress-android', 'secrets', 'firebase.secrets.json')

platform :android do
#####################################################################################
# build_and_run_instrumented_test
Expand All @@ -19,40 +17,15 @@

gradle(tasks: ["WordPress:assemble#{app.to_s.capitalize}VanillaDebug", "WordPress:assemble#{app.to_s.capitalize}VanillaDebugAndroidTest"])

# Run the instrumented tests in Firebase Test Lab
firebase_login(
key_file: GOOGLE_FIREBASE_SECRETS_PATH
)

apk_dir = File.join(PROJECT_ROOT_FOLDER, 'WordPress', 'build', 'outputs', 'apk')

test_succeeded = android_firebase_test(
project_id: firebase_secret(name: 'project_id'),
key_file: GOOGLE_FIREBASE_SECRETS_PATH,
model: 'Pixel2.arm',
version: 30,
test_apk_path: File.join(apk_dir, 'androidTest', "#{app}Vanilla", 'debug', "org.wordpress.android-#{app}-vanilla-debug-androidTest.apk"),
apk_path: File.join(apk_dir, "#{app}Vanilla", 'debug', "org.wordpress.android-#{app}-vanilla-debug.apk"),
test_targets: 'notPackage org.wordpress.android.ui.screenshots',
results_output_dir: File.join(PROJECT_ROOT_FOLDER, 'build', 'instrumented-tests'),
crash_on_test_failure: false
)

annotation_ctx = "firebase-test-#{app}-vanilla-debug"
if test_succeeded
begin
gradle(task: "runFlank#{app.to_s.capitalize}")
sh("buildkite-agent annotation remove --context '#{annotation_ctx}' || true") if is_ci?
else
details_url = lane_context[SharedValues::FIREBASE_TEST_MORE_DETAILS_URL]
message = "Firebase Tests failed. Failure details can be seen [here in Firebase Console](#{details_url})"
rescue StandardError
details_url = sh('jq', '.[].webLink', '../build/instrumented-tests/matrix_ids.json', '-r')
wzieba marked this conversation as resolved.
Show resolved Hide resolved
message = "#{app} Firebase Tests failed. Failure details can be seen [here in Firebase Console](#{details_url})"
sh('buildkite-agent', 'annotate', message, '--style', 'error', '--context', annotation_ctx) if is_ci?
UI.test_failure!(message)
end
end
end

def firebase_secret(name:)
UI.user_error!('Unable to locale Firebase Secrets File – did you run `configure apply`?') unless File.file? GOOGLE_FIREBASE_SECRETS_PATH
key_file_secrets = JSON.parse(File.read(GOOGLE_FIREBASE_SECRETS_PATH))
UI.user_error!("Unable to find key `#{name}` in #{GOOGLE_FIREBASE_SECRETS_PATH}") if key_file_secrets[name].nil?
key_file_secrets[name]
end
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pluginManagement {
gradle.ext.measureBuildsVersion = '3.1.0'
gradle.ext.koverVersion = '0.7.5'
gradle.ext.dependencyAnalysisVersion = '1.28.0'
gradle.ext.fladleVersion = '0.17.5'

plugins {
id "org.jetbrains.kotlin.android" version gradle.ext.kotlinVersion
Expand All @@ -30,6 +31,7 @@ pluginManagement {
id "com.google.dagger.hilt.android" version gradle.ext.daggerVersion
id "com.google.devtools.ksp" version gradle.ext.kspVersion
id "com.autonomousapps.dependency-analysis" version gradle.ext.dependencyAnalysisVersion
id "com.osacky.fladle" version gradle.ext.fladleVersion
}
repositories {
maven {
Expand Down
Loading