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

[Android] Add UI tests. #3780

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions android/BOINC/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ android {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled true
vectorDrawables.useSupportLibrary = true

testInstrumentationRunner = 'androidx.test.runner.AndroidJUnitRunner'
}

buildTypes {
Expand Down Expand Up @@ -167,6 +169,10 @@ dependencies {
testImplementation 'org.robolectric:robolectric:4.3.1'
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$junit5_version"

androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test:rules:1.3.0'
}
repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package edu.berkeley.boinc

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.hamcrest.Matchers.allOf
import org.hamcrest.core.IsInstanceOf
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

// Disable BOINC notifications (or just the main channel on Oreo and higher) before running this test, as
// the client notification can cover the hamburger button during test execution and cause the test to fail.
@LargeTest
@RunWith(AndroidJUnit4::class)
class BOINCActivityTest {
@Rule
@JvmField
var mActivityScenarioRule = ActivityScenarioRule(BOINCActivity::class.java)

@Test
fun boincActivityTest() {
val textView = onView(
allOf(withText(R.string.tab_tasks),
withParent(allOf(withId(R.id.action_bar),
withParent(withId(R.id.action_bar_container)))),
isDisplayed()))
textView.check(matches(withText(R.string.tab_tasks)))

val appCompatImageButton = onView(
allOf(withContentDescription("BOINC"),
childAtPosition(
allOf(withId(R.id.action_bar),
childAtPosition(
withId(R.id.action_bar_container),
0)),
1),
isDisplayed()))
appCompatImageButton.perform(click())

val viewInteraction = onView(allOf(withText(R.string.tab_notices), isDisplayed()))
viewInteraction.perform(click())

val textView2 = onView(
allOf(withText(R.string.tab_notices),
withParent(allOf(withId(R.id.action_bar),
withParent(withId(R.id.action_bar_container)))),
isDisplayed()))
textView2.check(matches(withText(R.string.tab_notices)))

appCompatImageButton.perform(click())

val viewInteraction2 = onView(allOf(withText(R.string.tab_projects), isDisplayed()))
viewInteraction2.perform(click())

val textView3 = onView(
allOf(withText(R.string.tab_projects),
withParent(allOf(withId(R.id.action_bar),
withParent(withId(R.id.action_bar_container)))),
isDisplayed()))
textView3.check(matches(withText(R.string.tab_projects)))

appCompatImageButton.perform(click())

val viewInteraction3 = onView(allOf(withText(R.string.tab_preferences), isDisplayed()))
viewInteraction3.perform(click())

val textView4 = onView(
allOf(withText(R.string.tab_preferences),
withParent(allOf(withId(R.id.action_bar),
withParent(withId(R.id.action_bar_container)))),
isDisplayed()))
textView4.check(matches(withText(R.string.tab_preferences)))

appCompatImageButton.perform(click())

val viewInteraction4 = onView(allOf(withText(R.string.menu_about), isDisplayed()))
viewInteraction4.perform(click())

val textView5 = onView(
allOf(withId(R.id.title), withText(R.string.menu_about),
withParent(withParent(withId(android.R.id.content))),
isDisplayed()))
textView5.check(matches(withText(R.string.menu_about)))

val appCompatButton = onView(
allOf(withId(R.id.returnB), withText(R.string.about_button),
childAtPosition(
childAtPosition(
withId(android.R.id.content),
0),
6),
isDisplayed()))
appCompatButton.perform(click())

appCompatImageButton.perform(click())

val viewInteraction5 = onView(allOf(withText(R.string.menu_eventlog), isDisplayed()))
viewInteraction5.perform(click())

val textView6 = onView(
allOf(withText(R.string.menu_eventlog),
withParent(allOf(withId(R.id.action_bar),
withParent(withId(R.id.action_bar_container)))),
isDisplayed()))
textView6.check(matches(withText(R.string.menu_eventlog)))

val textView7 = onView(
allOf(withText(R.string.eventlog_client_header),
withParent(allOf(withContentDescription(R.string.eventlog_client_header),
withParent(IsInstanceOf.instanceOf(android.widget.LinearLayout::class.java)))),
isDisplayed()))
textView7.check(matches(withText(R.string.eventlog_client_header)))

val textView8 = onView(
allOf(withText(R.string.eventlog_gui_header),
withParent(allOf(withContentDescription(R.string.eventlog_gui_header),
withParent(IsInstanceOf.instanceOf(android.widget.LinearLayout::class.java)))),
isDisplayed()))
textView8.check(matches(withText(R.string.eventlog_gui_header)))

val appCompatImageButton2 = onView(
allOf(withContentDescription("Navigate up"),
childAtPosition(
allOf(withId(R.id.action_bar),
childAtPosition(
withId(R.id.action_bar_container),
0)),
1),
isDisplayed()))
appCompatImageButton2.perform(click())

val textView9 = onView(
allOf(withText(R.string.tab_tasks),
withParent(allOf(withId(R.id.action_bar),
withParent(withId(R.id.action_bar_container)))),
isDisplayed()))
textView9.check(matches(withText(R.string.tab_tasks)))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package edu.berkeley.boinc

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.hamcrest.Matchers.allOf
import org.hamcrest.core.IsInstanceOf
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@LargeTest
@RunWith(AndroidJUnit4::class)
class SplashActivityToEventLogTest {
@Rule
@JvmField
var mActivityScenarioRule = ActivityScenarioRule(SplashActivity::class.java)

@Test
fun splashActivityToEventLogTest() {
val imageView = onView(
allOf(withId(R.id.logo), withContentDescription("Starting…"),
childAtPosition(
childAtPosition(
withId(android.R.id.content),
0),
0),
isDisplayed()))
imageView.perform(longClick())

val textView = onView(
allOf(withId(R.id.refresh), withContentDescription("Refresh"),
childAtPosition(
childAtPosition(
withId(R.id.action_bar),
2),
0),
isDisplayed()))
textView.check(matches(isDisplayed()))

val textView2 = onView(
allOf(withId(R.id.email_to), withContentDescription("Send as Email"),
childAtPosition(
childAtPosition(
withId(R.id.action_bar),
2),
1),
isDisplayed()))
textView2.check(matches(isDisplayed()))

val textView3 = onView(
allOf(withId(R.id.copy), withContentDescription("Copy to Clipboard"),
childAtPosition(
childAtPosition(
withId(R.id.action_bar),
2),
2),
isDisplayed()))
textView3.check(matches(isDisplayed()))

val textView4 = onView(
allOf(withText("CLIENT MESSAGES"),
childAtPosition(
childAtPosition(
IsInstanceOf.instanceOf(androidx.appcompat.widget.LinearLayoutCompat::class.java),
0),
0),
isDisplayed()))
textView4.check(matches(withText("CLIENT MESSAGES")))

val textView5 = onView(
allOf(withText("GUI MESSAGES"),
childAtPosition(
childAtPosition(
IsInstanceOf.instanceOf(androidx.appcompat.widget.LinearLayoutCompat::class.java),
1),
0),
isDisplayed()))
textView5.check(matches(withText("GUI MESSAGES")))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package edu.berkeley.boinc

import android.view.View
import android.view.ViewGroup
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher

fun childAtPosition(parentMatcher: Matcher<View>, position: Int): Matcher<View> {
return object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("Child at position $position in parent ")
parentMatcher.describeTo(description)
}

public override fun matchesSafely(view: View): Boolean {
val parent = view.parent
return parent is ViewGroup && parentMatcher.matches(parent)
&& view == parent.getChildAt(position)
}
}
}