Skip to content

Commit

Permalink
Merge branch 'master' into #823-add-dump-shard-obfuscation-option
Browse files Browse the repository at this point in the history
# Conflicts:
#	release_notes.md
#	test_runner/docs/ascii/flank.jar_-android-run.adoc
#	test_runner/docs/ascii/flank.jar_-firebase-test-android-run.adoc
#	test_runner/docs/ascii/flank.jar_-firebase-test-ios-run.adoc
#	test_runner/docs/ascii/flank.jar_-ios-run.adoc
  • Loading branch information
Piotr Adamczyk committed Jun 17, 2020
2 parents f4f53c6 + 7f3f1eb commit 65c487f
Show file tree
Hide file tree
Showing 42 changed files with 562 additions and 125 deletions.
22 changes: 16 additions & 6 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,29 @@ assignees: ''
---

**Describe the bug**
A clear and concise description of what the bug is.
> A clear and concise description of what the bug is.


**To Reproduce**
Steps to reproduce the behavior:
> Steps to reproduce the behavior:
1. Run '...'
2. See error

**Expected behavior**
A clear and concise description of what you expected to happen.
> A clear and concise description of what you expected to happen.


**Details (please complete the following information):**
- Have you tested on the latest Flank snapshot?
- Post the output of ` flank --version`.
> Have you tested on the latest Flank snapshot?
>
> Post the output of ` flank --version`.


**Additional context**
Add any other context about the problem here.
> Add any other context about the problem here.

84 changes: 84 additions & 0 deletions docs/test_sharding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Test Sharding

# Orchestrator

[Android Test Orchestrator][orchestrator] removes shared state and isolates crashes. Orchestrator trades performance for stability. Tests run slower when orchestrator is enabled.

Orchestrator ensures each tests runs Each test runs in a new [Instrumentation][instrumentation] instance to ensure there's no shared state. It's recommended to use `clearPackageData` as well to remove file system state.

When a test crashes, only that tests instrumentation instance crashes which enables other tests in the suite to continue execution. Without orchestrator, a test crash will break the entire test suite.

```yaml
gcloud:
use-orchestrator: true
```
## Orchestrator + Firebase Test lab
Orchestrator is **enabled by default in Flank** and disabled by default in gcloud CLI.
[AndroidX Test 1.3.0 Beta02][androidx_test] or later is required to run parameterized tests with orchestrator. Both the runner and orchestrator must be updated.
Local execution will use the version of Orchestrator defined in your gradle file. Firebase Test Lab currently uses Orchestrator v1.2.0. Firebase must manually upgrade Orchestrator on their devices for customers to use the new version.
[orchestrator]: https://developer.android.com/training/testing/junit-runner#using-android-test-orchestrator
[instrumentation]: https://developer.android.com/reference/android/app/Instrumentation
[androidx_test]: https://github.com/android/android-test/releases/tag/androidx-test-1.3.0-beta02
# GCloud Sharding
The [gcloud CLI][gcloud_cli] supports two types of sharding, uniform sharding and manual sharding via test targets for shard.
[--num-uniform-shards][test_targets_for_shards] is translated to “-e numShard” “-e shardIndex” [AndroidJUnitRunner][ajur] arguments. This uses the native `adb am instrument` sharding feature which randomly shards all tests. When using uniform shards, it's possible to have shards with empty tests.

Firebase will mark shards as failed when execution consists of skipped/empty tests, as this is likely an indication the tests are not configured correctly. This firebase design choice is incompatable with num-uniform-shards as you will randomly get failures when shards are empty. Using num-uniform-shards is therefor not recommended.

[--test-targets-for-shard][test_targets_for_shards] allows manually specifying tests to be run.

On FTL `--test-targets` or `--test-targets-for-shard` are passed as arguments to `adb shell am instrument`.

> adb shell am instrument -r -w -e class com.example.test_app.ParameterizedTest#shouldHopefullyPass com.example.test_app.test/androidx.test.runner.AndroidJUnitRunner

[gcloud_cli]: https://cloud.google.com/sdk/gcloud/reference/alpha/firebase/test/android/run
[uniform_shards]: https://cloud.google.com/sdk/gcloud/reference/alpha/firebase/test/android/run#--num-uniform-shards
[test_targets_for_shards]: https://cloud.google.com/sdk/gcloud/reference/alpha/firebase/test/android/run#--test-targets-for-shard
[ajur]: https://developer.android.com/training/testing/junit-runner#sharding-tests


# Flank
The Flank supports two types of sharding, automatic sharding and uniform sharding.

Automatic sharding is enabled by default and can be disabled by `--disable-sharding=true`. Under the hood automatic sharding uses same API as gcloud's `--test-targets-for-shard` but in difference to gcloud it creates shards automatically.
`--dump-shards` can help with verifying if calculates shards are correct. Automated sharding can work with `--test-targets` option.

`--num-uniform-shards` provides same functionality as gcloud's option. Is not compatible with automatic sharding.


# Parameterized tests


Flank [v20.06.1](https://github.com/Flank/flank/releases/tag/v20.06.1) fix some compatibility issues with named parameterized tests, when running with sharding. \
[Table](https://github.com/Flank/flank_parametrized_tests/tree/master/test_apk) below bases on [report](https://github.com/Flank/flank_parametrized_tests/tree/master/test_apk/report) from running parameterized tests with different configurations.
Flank uses same API as gcloud so everything supported by gcloud should be also supported by flank.

| | orchestrator | disabled | disabled | 1.3.0-rc01 | 1.3.0-rc01 |
| --- | ---: | --- | --- | --- | --- |
| | sharding | disabled | enabled | disabled | enabled |
| local | @RunWith(Parameterized::class) | OK | OK | OK | OK |
| local | @RunWith(Parameterized::class) {named} | OK | OK | OK | OK |
| local | @RunWith(JUnitParamsRunner::class) | OK | OK | OK | OK |
| gcloud | @RunWith(Parameterized::class) | OK | OK | OK | OK |
| gcloud | @RunWith(Parameterized::class) {named} | OK | OK | OK | OK |
| gcloud | @RunWith(JUnitParamsRunner::class) | OK | OK | null | null |
| flank v20.06.0 | @RunWith(Parameterized::class) | OK | OK | OK | OK |
| flank v20.06.0 | @RunWith(Parameterized::class) {named} | OK | missing | OK | missing |
| flank v20.06.0 | @RunWith(JUnitParamsRunner::class) | OK | missing | null | missing |
| flank v20.06.1 | @RunWith(Parameterized::class) | OK | OK | OK | OK |
| flank v20.06.1 | @RunWith(Parameterized::class) {named} | OK | OK | OK | OK |
| flank v20.06.1 | @RunWith(JUnitParamsRunner::class) | OK | OK | null | null |



# JUnit5
Android instrumented tests has no official support for JUnit5. [There is third-party support](https://github.com/mannodermaus/android-junit5)
6 changes: 3 additions & 3 deletions junit_html_report/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions release_notes.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
## next (unreleased)

- [#853](https://github.com/Flank/flank/pull/853) Store @Ignore tests in the JUnit XML without sending ignored tests to FTL. ([piotradamczyk5](https://github.com/piotradamczyk5), [adamfilipow92](https://github.com/adamfilipow92))
- [#837](https://github.com/Flank/flank/pull/837) Added obfuscate option to dump shards. ([piotradamczyk5](https://github.com/piotradamczyk5))
-
-
-
-

## v20.06.1
- [#840](https://github.com/Flank/flank/pull/840) Fix parametrized tests. ([jan-gogo](https://github.com/jan-gogo), [adamfilipow92](https://github.com/adamfilipow92), [pawelpasterz](https://github.com/pawelpasterz), [piotradamczyk5](https://github.com/piotradamczyk5))

## v20.06.0

Expand Down
36 changes: 18 additions & 18 deletions test_app/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ android {
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments(clearPackageData: 'true')

}
Expand Down Expand Up @@ -51,33 +51,33 @@ android {

testOptions {
animationsDisabled = true
execution = "ANDROIDX_TEST_ORCHESTRATOR"
//execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.core:core-ktx:1.1.0-alpha03'
implementation 'androidx.appcompat:appcompat:1.3.0-alpha01'
implementation 'androidx.core:core-ktx:1.4.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

// Espresso.
// https://developer.android.com/jetpack/androidx/releases/test
androidTestUtil 'androidx.test:orchestrator:1.2.0'

androidTestImplementation("androidx.test:runner:1.3.0-alpha02")
androidTestImplementation("androidx.test.ext:junit:1.1.2-alpha02")
androidTestImplementation("androidx.test.ext:junit-ktx:1.1.2-alpha02")
androidTestImplementation("androidx.test.ext:truth:1.3.0-alpha02")
androidTestImplementation("androidx.test.espresso.idling:idling-concurrent:3.3.0-alpha02")
androidTestImplementation("androidx.test.espresso.idling:idling-net:3.3.0-alpha02")
androidTestImplementation("androidx.test.espresso:espresso-accessibility:3.3.0-alpha02")
androidTestImplementation("androidx.test:rules:1.3.0-alpha02")
androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0-alpha02")
androidTestImplementation("androidx.test.espresso:espresso-contrib:3.3.0-alpha02")
androidTestImplementation("androidx.test.espresso:espresso-idling-resource:3.3.0-alpha02")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.3.0-alpha02")
androidTestImplementation("androidx.test.espresso:espresso-web:3.3.0-alpha02")
androidTestImplementation 'pl.pragmatists:JUnitParams:1.1.1'
androidTestImplementation("androidx.test:runner:1.3.0-rc01")
androidTestImplementation("androidx.test.ext:junit:1.1.2-rc01")
androidTestImplementation("androidx.test.ext:junit-ktx:1.1.2-rc01")
androidTestImplementation("androidx.test.ext:truth:1.3.0-rc01")
androidTestImplementation("androidx.test.espresso.idling:idling-concurrent:3.3.0-rc01")
androidTestImplementation("androidx.test.espresso.idling:idling-net:3.3.0-rc01")
androidTestImplementation("androidx.test.espresso:espresso-accessibility:3.3.0-rc01")
androidTestImplementation("androidx.test:rules:1.3.0-rc01")
androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0-rc01")
androidTestImplementation("androidx.test.espresso:espresso-contrib:3.3.0-rc01")
androidTestImplementation("androidx.test.espresso:espresso-idling-resource:3.3.0-rc01")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.3.0-rc01")
androidTestImplementation("androidx.test.espresso:espresso-web:3.3.0-rc01")
}

if (coverageEnabled) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.test_app

import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith

Expand All @@ -18,4 +19,12 @@ class InstrumentedTest : BaseInstrumentedTest() {

@Test
fun test2() = testMethod()

@Test
@Ignore("For testing purpose: https://github.com/Flank/flank/issues/852")
fun ignoredTest1() = testMethod()

@Test
@Ignore("For testing purpose: https://github.com/Flank/flank/issues/852")
fun ignoredTest2() = testMethod()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.test_app

import junit.framework.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized

@RunWith(Parameterized::class)
class ParameterizedTest(private val paramOne: Int, private val paramTwo: String) {

companion object {
@JvmStatic
@Parameterized.Parameters
fun data() = listOf(
arrayOf(1, "1"),
arrayOf(666, "666"),
arrayOf(54321, "54321")
)
}

@Test
fun shouldHopefullyPass() {
assertTrue(paramOne == paramTwo.toInt())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.example.test_app.bar

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.test_app.BaseInstrumentedTest
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith

Expand All @@ -10,4 +11,8 @@ class BarInstrumentedTest : BaseInstrumentedTest() {

@Test
fun testBar() = testMethod()

@Test
@Ignore("For testing purpose: https://github.com/Flank/flank/issues/852")
fun ignoredTestBar() = testMethod()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.example.test_app.foo

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.test_app.BaseInstrumentedTest
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith

Expand All @@ -10,4 +11,8 @@ class FooInstrumentedTest : BaseInstrumentedTest() {

@Test
fun testFoo() = testMethod()

@Test
@Ignore("For testing purpose: https://github.com/Flank/flank/issues/852")
fun ignoredTestFoo() = testMethod()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.example.test_app.parametrized

import androidx.test.espresso.Espresso
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.rule.ActivityTestRule
import com.example.test_app.MainActivity
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized

@RunWith(Parameterized::class)
class EspressoParametrizedClassParameterizedNamed(
private val textButton: String,
private val expectedText: String
) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{index}: {0} {1}")
fun data() = listOf(
arrayOf("toast", "toast"),
arrayOf("alert", "alert"),
arrayOf("exception", "exception")
)
}

@Rule
@JvmField
var activityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)

@Test
fun clickRightButton() {
Espresso.onView(ViewMatchers.withText(textButton))
.check(ViewAssertions.matches(ViewMatchers.withText(expectedText)))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.example.test_app.parametrized

import androidx.test.espresso.Espresso
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.rule.ActivityTestRule
import com.example.test_app.MainActivity
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized

@RunWith(Parameterized::class)
class EspressoParametrizedClassTestParameterized(
private val textButton: String,
private val expectedText: String
) {
companion object {
@JvmStatic
@Parameterized.Parameters
fun data() = listOf(
arrayOf("toast", "toast"),
arrayOf("alert", "alert"),
arrayOf("exception", "exception")
)
}

@Rule
@JvmField
var activityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)

@Test
fun clickRightButton() {
Espresso.onView(ViewMatchers.withText(textButton))
.check(ViewAssertions.matches(ViewMatchers.withText(expectedText)))
}
}
Loading

0 comments on commit 65c487f

Please sign in to comment.