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

Fix #3315: Set up UIAutomator with Bazel #3505

Merged
merged 44 commits into from
Aug 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b720222
Introducing UiAutomator
FareesHussain Jul 15, 2021
f90cbfc
Using 23 api level
FareesHussain Jul 15, 2021
930abe0
some local tweaks
FareesHussain Jul 16, 2021
bb6f5bb
Updated implementation based on adb commands
FareesHussain Jul 20, 2021
46a1b56
Merge branch 'develop' of https://github.com/oppia/oppia-android into…
FareesHussain Jul 20, 2021
44f4003
Nit fixes
FareesHussain Jul 20, 2021
72620a2
Nit fixes
FareesHussain Jul 20, 2021
7a384c3
Merge branch 'setup-uiautomator' of https://github.com/FareesHussain/…
FareesHussain Jul 22, 2021
8a641d7
Requested changes
FareesHussain Jul 22, 2021
c58b6f6
fix class name
FareesHussain Jul 22, 2021
09c419e
update dependencies
FareesHussain Jul 22, 2021
004e3a1
Nit fixes
FareesHussain Jul 24, 2021
7a1221d
Requested changes
FareesHussain Jul 30, 2021
0aec4a5
Merge branch 'develop' of https://github.com/oppia/oppia-android into…
FareesHussain Jul 30, 2021
6e09966
updated maven_install
FareesHussain Jul 30, 2021
4486882
Nit fix
FareesHussain Jul 30, 2021
f64d32c
Add CODEOWNERS
FareesHussain Jul 30, 2021
dc66ba2
Added KDoc
FareesHussain Jul 30, 2021
c233b71
NIT
FareesHussain Jul 30, 2021
2044979
Added comments
FareesHussain Jul 30, 2021
7ac1ac5
Added oppia_instrumentation_test.bzl
FareesHussain Jul 31, 2021
3bb5348
added exempted_file_path
FareesHussain Jul 31, 2021
e5a6128
Helper utility shifted to testing module
FareesHussain Aug 4, 2021
425ebfa
NIT
FareesHussain Aug 4, 2021
067537f
NIT
FareesHussain Aug 4, 2021
b9233c6
deleted the previous utility
FareesHussain Aug 4, 2021
37b10e2
ignoring instrumentation in ComputeAffectedTests.kt
FareesHussain Aug 5, 2021
3c1e79f
NIT
FareesHussain Aug 5, 2021
44363c1
NIT
FareesHussain Aug 5, 2021
e95d29f
NIT
FareesHussain Aug 6, 2021
c608f7c
changed startsWith("instrumentation/")
FareesHussain Aug 6, 2021
66f6b51
filtered bazel targets
FareesHussain Aug 6, 2021
6514ba9
NIT
FareesHussain Aug 6, 2021
e81706b
NIT
FareesHussain Aug 6, 2021
a4266e4
filtering the instrumentation from the total affected targets
FareesHussain Aug 6, 2021
6f2836c
NIT
FareesHussain Aug 6, 2021
3660243
changed directory to javatests
FareesHussain Aug 10, 2021
d4aa4d4
NIT
FareesHussain Aug 10, 2021
41ea23f
NIT
FareesHussain Aug 10, 2021
b15451b
fixed scripts
FareesHussain Aug 11, 2021
73c650e
NIT
FareesHussain Aug 11, 2021
0d50914
updated the ComputedAffectedTests
FareesHussain Aug 13, 2021
e2db957
ignoring player directory
FareesHussain Aug 13, 2021
9ffd04e
Merge branch 'develop' of https://github.com/oppia/oppia-android into…
FareesHussain Aug 16, 2021
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
8 changes: 8 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ NOTICE @BenHenning
# Global model ownership.
/model/ @vinitamurthi @BenHenning


#####################################################################################
# instrumentation #
#####################################################################################

# End-to-end test utilities and modules.
/instrumentation/src/java/**/*.kt @anandwana001 @BenHenning

#####################################################################################
# global overrides #
#####################################################################################
Expand Down
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ package_group(
"//app/...",
"//data/...",
"//domain/...",
"//instrumentation/...",
"//testing/...",
"//utility/...",
],
Expand Down
15 changes: 15 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,21 @@ http_archive(

load("@rules_jvm_external//:defs.bzl", "maven_install")

ATS_TAG = "1edfdab3134a7f01b37afabd3eebfd2c5bb05151"
BenHenning marked this conversation as resolved.
Show resolved Hide resolved

ATS_SHA256 = "dcd1ff76aef1a26329d77863972780c8fe1fc8ff625747342239f0489c2837ec"

http_archive(
name = "android_test_support",
sha256 = ATS_SHA256,
strip_prefix = "android-test-%s" % ATS_TAG,
urls = ["https://github.com/android/android-test/archive/%s.tar.gz" % ATS_TAG],
)

load("@android_test_support//:repo.bzl", "android_test_repositories")

android_test_repositories()

# Note to developers: new dependencies should be added to //third_party:versions.bzl, not here.
maven_install(
artifacts = DAGGER_ARTIFACTS + get_maven_dependencies(),
Expand Down
30 changes: 30 additions & 0 deletions instrumentation/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
This library contains all android_binary and android_instrumentation_test targets to each
test suite in instrumentation module as a oppia_instrumentation_test wrapper.
Note that:
- All the oppia_instrumentation_test targets are named similar to the respective class name
of the test suite.
"""

exports_files(["src/javatests/AndroidManifest.xml"])

# Used for end-to-end tests
android_binary(
name = "oppia_test",
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
testonly = True,
custom_package = "org.oppia.android",
enable_data_binding = True,
manifest = "//app:src/main/AndroidManifest.xml",
manifest_values = {
"applicationId": "org.oppia.android",
"minSdkVersion": "19",
"targetSdkVersion": "29",
"versionCode": "0",
"versionName": "0.1-test",
},
multidex = "native",
visibility = ["//:oppia_testing_visibility"],
deps = [
"//app",
],
)
40 changes: 40 additions & 0 deletions instrumentation/oppia_instrumentation_test.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
Instrumentation macros to define up end-to-end tests.
"""

load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_android_library")

def oppia_instrumentation_test(
name,
srcs,
deps):
"""
Creates library, binary, and instrumentation test for each test suite.

Args:
name: str. The class name of the test suite.
srcs: list of str. List of test files corresponding to this test suite.
deps: list of str. The list of dependencies needed to build and run the test.
"""
kt_android_library(
name = "%s_lib" % name,
testonly = True,
srcs = srcs,
deps = deps,
)

native.android_binary(
name = "%sBinary" % name,
testonly = True,
custom_package = "org.oppia.android",
instruments = "//instrumentation:oppia_test",
manifest = "//instrumentation:src/javatests/AndroidManifest.xml",
deps = [":%s_lib" % name],
)

# TODO(#3617): Target isn't supported yet.
native.android_instrumentation_test(
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
name = name,
target_device = "@android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86_qemu2",
test_app = ":%sBinary" % name,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
This library contains the utilities used in end-to-end testing.
"""

load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_android_library")

kt_android_library(
name = "e2e_test_helper",
testonly = True,
srcs = [
"EndToEndTestHelper.kt",
],
visibility = ["//:oppia_testing_visibility"],
deps = [
"//third_party:androidx_test_ext_junit",
"//third_party:androidx_test_uiautomator_uiautomator",
"//third_party:com_google_truth_truth",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.oppia.android.instrumentation.testing

import android.content.Context
import android.content.Intent
import androidx.test.core.app.ApplicationProvider
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import com.google.common.truth.Truth.assertThat

/** This object contains common operations used for end-to-end tests. */
object EndToEndTestHelper {

private val OPPIA_PACKAGE = "org.oppia.android"
private val LAUNCH_TIMEOUT_SECONDS = 30000L
private val TRANSITION_TIMEOUT_SECONDS = 5000L

/** Starts Oppia from the home screen. */
fun UiDevice.startOppiaFromScratch() {
// Start from the home screen
pressHome()

// Wait for launcher
val launcherPackage = launcherPackageName
assertThat(launcherPackage).isNotNull()
wait(Until.hasObject(By.pkg(launcherPackage).depth(1)), LAUNCH_TIMEOUT_SECONDS)

// Launch the blueprint app
val context = ApplicationProvider.getApplicationContext<Context>()
val intent = context.packageManager
.getLaunchIntentForPackage(OPPIA_PACKAGE)
intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) // Clear out any previous instances
context.startActivity(intent)

// Wait for the app to appear
wait(Until.hasObject(By.pkg(OPPIA_PACKAGE)), LAUNCH_TIMEOUT_SECONDS)
}

/** Waits for the view with given resourceId to appear. */
fun UiDevice.waitForRes(resourceId: String, timeout: Long = TRANSITION_TIMEOUT_SECONDS) {
wait(Until.hasObject(By.res(resourceId)), timeout)
}

/** Waits for the view with given text to appear. */
fun UiDevice.waitForText(text: String) {
wait(Until.hasObject(By.text(text)), TRANSITION_TIMEOUT_SECONDS)
}

/** Return the UiObject with the given text. */
fun UiDevice.findObjectByText(text: String): UiObject2? {
waitForText(text)
return findObject(By.text(text))
}

/** Returns the UiObject for the given resourceId. */
fun UiDevice.findObjectByRes(resourceId: String): UiObject2? {
waitForRes(resourceId)
return findObject(By.res("$OPPIA_PACKAGE:id/$resourceId"))
}

/** Performs a scroll until the view with the give text is visible. */
fun scrollRecyclerViewTextIntoView(text: String, isVertical: Boolean = true) {
val recyclerView = UiScrollable(UiSelector().scrollable(true))
if (isVertical) {
recyclerView.setAsVerticalList()
} else {
recyclerView.setAsHorizontalList()
}
recyclerView.scrollTextIntoView(text)
}
}
11 changes: 11 additions & 0 deletions instrumentation/src/javatests/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xmxl version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.oppia.android.app.instrumentation">
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="29" />
<instrumentation
android:targetPackage="org.oppia.android"
android:name="androidx.test.runner.AndroidJUnitRunner" />
<application android:label="OppiaTest" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
This library contains the test suite source files of the player package.
"""

load("//instrumentation:oppia_instrumentation_test.bzl", "oppia_instrumentation_test")

oppia_instrumentation_test(
name = "ExplorationPlayerTest",
srcs = [
"ExplorationPlayerTest.kt",
],
deps = [
"//instrumentation/src/java/org/oppia/android/instrumentation/testing:e2e_test_helper",
"//third_party:androidx_test_ext_junit",
"//third_party:androidx_test_runner",
"//third_party:androidx_test_uiautomator_uiautomator",
"//third_party:com_google_truth_truth",
"//third_party:junit_junit",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.oppia.android.instrumentation.player

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.oppia.android.instrumentation.testing.EndToEndTestHelper.findObjectByRes
import org.oppia.android.instrumentation.testing.EndToEndTestHelper.findObjectByText
import org.oppia.android.instrumentation.testing.EndToEndTestHelper.scrollRecyclerViewTextIntoView
import org.oppia.android.instrumentation.testing.EndToEndTestHelper.startOppiaFromScratch
import org.oppia.android.instrumentation.testing.EndToEndTestHelper.waitForRes

/** Tests for Explorations. */
class ExplorationPlayerTest {
private lateinit var device: UiDevice

@Before
fun setUp() {
// Initialize UiDevice instance
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.startOppiaFromScratch()
}

@Test
fun testExploration_prototypeExploration_toolbarTitle_isDisplayedSuccessfully() {
navigateToPrototypeExploration()
assertThat(device.findObjectByRes("exploration_toolbar_title")).isNotNull()
}

/** Navigates and opens the Prototype Exploration using the admin profile. */
private fun navigateToPrototypeExploration() {
device.findObjectByRes("skip_text_view")?.click()
device.findObjectByRes("get_started_button")?.click()
device.waitForRes("profile_select_text")
device.findObjectByText("Admin")?.click()
scrollRecyclerViewTextIntoView("First Test Topic")
device.findObjectByText("First Test Topic")?.click()
device.findObjectByText("LESSONS")?.click()
device.findObjectByText("First Story")?.click()
scrollRecyclerViewTextIntoView("Chapter 1: Prototype Exploration")
device.findObjectByText("Chapter 1: Prototype Exploration")?.click()
}
}
1 change: 1 addition & 0 deletions scripts/assets/test_file_exemptions.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ exempted_file_path: "domain/src/main/java/org/oppia/android/domain/util/FloatExt
exempted_file_path: "domain/src/main/java/org/oppia/android/domain/util/FractionExtensions.kt"
exempted_file_path: "domain/src/main/java/org/oppia/android/domain/util/JsonAssetRetriever.kt"
exempted_file_path: "domain/src/test/java/org/oppia/android/domain/classify/InteractionObjectTestBuilder.kt"
exempted_file_path: "instrumentation/src/java/org/oppia/android/instrumentation/testing/EndToEndTestHelper.kt"
exempted_file_path: "scripts/src/java/org/oppia/android/scripts/common/CommandExecutor.kt"
exempted_file_path: "scripts/src/java/org/oppia/android/scripts/common/CommandResult.kt"
exempted_file_path: "scripts/src/java/org/oppia/android/scripts/license/LicenseFetcher.kt"
Expand Down
2 changes: 1 addition & 1 deletion scripts/buildifier_lint_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ else
buildifier_file_path="$github_actions_path/oppia-android-tools/buildifier"
fi

$buildifier_file_path --lint=warn --mode=check --warnings=-native-android,+out-of-order-load,+unsorted-dict-items -r app data domain model testing utility third_party tools scripts BUILD.bazel WORKSPACE oppia_android_test.bzl
$buildifier_file_path --lint=warn --mode=check --warnings=-native-android,+out-of-order-load,+unsorted-dict-items -r app data domain instrumentation model testing utility third_party tools scripts BUILD.bazel WORKSPACE oppia_android_test.bzl

status=$?

Expand Down
4 changes: 2 additions & 2 deletions scripts/ktlint_lint_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ else
jar_file_path="$github_actions_path/oppia-android-tools/ktlint"
fi

java -jar $jar_file_path --android app/src/**/*.kt data/src/**/*.kt domain/src/**/*.kt testing/src/**/*.kt utility/src/**/*.kt scripts/src/**/*.kt
java -jar $jar_file_path --android app/src/**/*.kt data/src/**/*.kt domain/src/**/*.kt testing/src/**/*.kt utility/src/**/*.kt scripts/src/**/*.kt instrumentation/src/**/*.kt

status=$?

Expand All @@ -25,7 +25,7 @@ else
echo "********************************"
echo "Ktlint issue found."
echo "Please fix the above issues.
You can also use the java -jar $jar_file_path -F --android domain/src/**/*.kt utility/src/**/*.kt data/src/**/*.kt app/src/**/*.kt testing/src/**/*.kt scripts/src/**/*.kt
You can also use the java -jar $jar_file_path -F --android domain/src/**/*.kt utility/src/**/*.kt data/src/**/*.kt app/src/**/*.kt testing/src/**/*.kt scripts/src/**/*.kt instrumentation/src/**/*.kt
command to fix the most common issues."
echo "Please note, there might be a possibility where the above command will not fix the issue.
In that case, you will have to fix it yourself."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,23 @@ private fun computeAffectedTargetsForDevelopBranch(bazelClient: BazelClient, out

val allTestTargets = bazelClient.retrieveAllTestTargets()
println()

// Filtering out the targets to be ignored.
val nonInstrumentationAffectedTestTargets = allTestTargets.filter { targetPath ->
!targetPath
.startsWith(
"//instrumentation/src/javatests/org/oppia/android/instrumentation/player",
ignoreCase = true
)
}

println(
"Affected test targets:" +
"\n${allTestTargets.joinToString(separator = "\n") { "- $it" }}"
"\n${nonInstrumentationAffectedTestTargets.joinToString(separator = "\n") { "- $it" }}"
)
outputFile.printWriter().use { writer -> allTestTargets.forEach { writer.println(it) } }
outputFile.printWriter().use { writer ->
nonInstrumentationAffectedTestTargets.forEach { writer.println(it) }
}
}

private fun computeAffectedTargetsForNonDevelopBranch(
Expand Down Expand Up @@ -103,10 +115,22 @@ private fun computeAffectedTargetsForNonDevelopBranch(
println("Affected test targets due to transitive build deps: $transitiveTestTargets")

val allAffectedTestTargets = (affectedTestTargets + transitiveTestTargets).toSet()

// Filtering out the targets to be ignored.
anandwana001 marked this conversation as resolved.
Show resolved Hide resolved
val nonInstrumentationAffectedTestTargets = allAffectedTestTargets.filter { targetPath ->
!targetPath
.startsWith(
"//instrumentation/src/javatests/org/oppia/android/instrumentation/player",
ignoreCase = true
)
}

println()
println(
"Affected test targets:" +
"\n${allAffectedTestTargets.joinToString(separator = "\n") { "- $it" }}"
"\n${nonInstrumentationAffectedTestTargets.joinToString(separator = "\n") { "- $it" }}"
)
outputFile.printWriter().use { writer -> allAffectedTestTargets.forEach { writer.println(it) } }
outputFile.printWriter().use { writer ->
nonInstrumentationAffectedTestTargets.forEach { writer.println(it) }
}
}
Loading