ci: Instrumentation tests coverage in ci.
All checks were successful
Check PR code / BuildAndTestAndCoverage (pull_request) Successful in 31m43s
All checks were successful
Check PR code / BuildAndTestAndCoverage (pull_request) Successful in 31m43s
This commit is contained in:
parent
1b2e9edc8c
commit
6626784e8b
@ -48,7 +48,7 @@ jobs:
|
||||
adb logcat -G 16M
|
||||
./gradlew JacocoDebugCodeCoverage || true
|
||||
./gradlew androidApp:fetchScreenshots
|
||||
adb logcat 'InputReader:S' 'chatty:S' 'audio_hw_generic:S' '*:I' -d > ./androidApp/build/reports/androidTests/connected/screenshots/logs.txt
|
||||
adb logcat 'InputReader:S' 'chatty:S' 'audio_hw_generic:S' 'LogApiCalls:D' '*:I' -d > ./androidApp/build/reports/androidTests/connected/screenshots/logs.txt
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
|
@ -93,5 +93,6 @@ class `1-LoginActivityTest` : WithANRException() {
|
||||
performLogin()
|
||||
onView(withText(R.string.gdpr_dialog_title)).check(matches(isDisplayed()))
|
||||
onView(withText("OK")).perform(click())
|
||||
checkHomeLoadingDone()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package bou.amine.apps.readerforselfossv2.android
|
||||
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
@ -14,7 +15,9 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import bou.amine.apps.readerforselfossv2.android.testing.CountingIdlingResourceSingleton
|
||||
import org.hamcrest.CoreMatchers.not
|
||||
import org.junit.Before
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -29,6 +32,14 @@ class `2-HomeActivityTest` : WithANRException() {
|
||||
@get:Rule
|
||||
val activityRule = ActivityScenarioRule(HomeActivity::class.java)
|
||||
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry
|
||||
.getInstance()
|
||||
.register(CountingIdlingResourceSingleton.countingIdlingResource)
|
||||
checkHomeLoadingDone()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMenu() {
|
||||
onView(withId(R.id.action_search)).check(matches(isDisplayed())).check(
|
||||
|
@ -2,6 +2,7 @@ package bou.amine.apps.readerforselfossv2.android
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
@ -10,6 +11,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import bou.amine.apps.readerforselfossv2.android.testing.CountingIdlingResourceSingleton
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.not
|
||||
import org.junit.Before
|
||||
@ -31,6 +33,9 @@ class `3-SettingsActivityTest` : WithANRException() {
|
||||
activityRule.scenario.onActivity { activity ->
|
||||
context = activity.window.context
|
||||
}
|
||||
IdlingRegistry
|
||||
.getInstance()
|
||||
.register(CountingIdlingResourceSingleton.countingIdlingResource)
|
||||
openMenu()
|
||||
onView(withText(R.string.title_activity_settings)).perform(click())
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package bou.amine.apps.readerforselfossv2.android
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.action.ViewActions.replaceText
|
||||
@ -19,6 +20,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import bou.amine.apps.readerforselfossv2.android.testing.CountingIdlingResourceSingleton
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.not
|
||||
import org.junit.Before
|
||||
@ -38,6 +40,9 @@ class `4-SettingsActivityGeneralTest` : WithANRException() {
|
||||
|
||||
@Before
|
||||
fun init() {
|
||||
IdlingRegistry
|
||||
.getInstance()
|
||||
.register(CountingIdlingResourceSingleton.countingIdlingResource)
|
||||
openActionBarOverflowOrOptionsMenu(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ package bou.amine.apps.readerforselfossv2.android
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
@ -13,6 +14,7 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import bou.amine.apps.readerforselfossv2.android.settings.SettingsActivity
|
||||
import bou.amine.apps.readerforselfossv2.android.testing.CountingIdlingResourceSingleton
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.not
|
||||
import org.junit.After
|
||||
@ -35,6 +37,9 @@ class `5-SettingsActivityReaderTest` : WithANRException() {
|
||||
activityRule.scenario.onActivity { activity ->
|
||||
context = activity.window.context
|
||||
}
|
||||
IdlingRegistry
|
||||
.getInstance()
|
||||
.register(CountingIdlingResourceSingleton.countingIdlingResource)
|
||||
onView(withText(R.string.pref_header_viewer)).perform(click())
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package bou.amine.apps.readerforselfossv2.android
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
@ -15,6 +16,7 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import bou.amine.apps.readerforselfossv2.android.settings.SettingsActivity
|
||||
import bou.amine.apps.readerforselfossv2.android.testing.CountingIdlingResourceSingleton
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.not
|
||||
import org.junit.After
|
||||
@ -37,6 +39,9 @@ class `6-SettingsActivityOfflineTest` : WithANRException() {
|
||||
activityRule.scenario.onActivity { activity ->
|
||||
context = activity.window.context
|
||||
}
|
||||
IdlingRegistry
|
||||
.getInstance()
|
||||
.register(CountingIdlingResourceSingleton.countingIdlingResource)
|
||||
onView(withText(R.string.pref_header_offline)).perform(click())
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package bou.amine.apps.readerforselfossv2.android
|
||||
|
||||
import androidx.test.espresso.AmbiguousViewMatcherException
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.action.ViewActions.swipeDown
|
||||
@ -14,6 +15,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import bou.amine.apps.readerforselfossv2.android.testing.CountingIdlingResourceSingleton
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@ -32,6 +34,9 @@ class `7-SourcesActivityTest` : WithANRException() {
|
||||
|
||||
@Before
|
||||
fun init() {
|
||||
IdlingRegistry
|
||||
.getInstance()
|
||||
.register(CountingIdlingResourceSingleton.countingIdlingResource)
|
||||
sourceName = UUID.randomUUID().toString().substring(0, 15)
|
||||
|
||||
goToSources()
|
||||
|
@ -15,6 +15,7 @@ import androidx.test.espresso.action.ViewActions.typeTextIntoFocusedView
|
||||
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.base.DefaultFailureHandler
|
||||
import androidx.test.espresso.matcher.RootMatchers.isDialog
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isChecked
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isNotChecked
|
||||
@ -24,6 +25,7 @@ import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.UiSelector
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.not
|
||||
import org.hamcrest.Matchers.hasToString
|
||||
import org.junit.BeforeClass
|
||||
import java.io.BufferedOutputStream
|
||||
@ -139,6 +141,10 @@ fun testAddSourceWithUrl(
|
||||
onView(withText(sourceName)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
fun checkHomeLoadingDone() {
|
||||
onView(withId(R.id.swipeRefreshLayout)).inRoot(not(isDialog())).perform(waitUntilNotLoading(300000))
|
||||
}
|
||||
|
||||
@Suppress("detekt:UtilityClassWithPublicConstructor")
|
||||
open class WithANRException {
|
||||
companion object {
|
||||
|
@ -8,9 +8,14 @@ import android.widget.RelativeLayout
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
||||
import androidx.test.espresso.PerformException
|
||||
import androidx.test.espresso.Root
|
||||
import androidx.test.espresso.UiController
|
||||
import androidx.test.espresso.ViewAction
|
||||
import androidx.test.espresso.matcher.RootMatchers.isPlatformPopup
|
||||
import androidx.test.espresso.matcher.ViewMatchers.hasSibling
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withChild
|
||||
@ -19,11 +24,15 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withParent
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withResourceName
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.espresso.util.HumanReadables
|
||||
import androidx.test.espresso.util.TreeIterables
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.any
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers
|
||||
import org.hamcrest.TypeSafeMatcher
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
fun withError(
|
||||
@StringRes id: Int,
|
||||
@ -44,6 +53,47 @@ fun withError(
|
||||
}
|
||||
}
|
||||
|
||||
fun waitUntilNotLoading(millis: Long): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> = any(View::class.java)
|
||||
|
||||
override fun getDescription(): String = "wait for a specific view is not loading during $millis millis."
|
||||
|
||||
override fun perform(
|
||||
uiController: UiController,
|
||||
view: View?,
|
||||
) {
|
||||
uiController.loopMainThreadUntilIdle()
|
||||
val startTime = System.currentTimeMillis()
|
||||
val endTime = startTime + millis
|
||||
|
||||
do {
|
||||
// either the empty view is displayed
|
||||
for (child in TreeIterables.breadthFirstViewTraversal(view)) {
|
||||
// found view with required ID
|
||||
if (withId(R.id.emptyText).matches(child) && child.isVisible) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// or the refresh layout is refreshing
|
||||
if (view is SwipeRefreshLayout && !view.isRefreshing) {
|
||||
return
|
||||
}
|
||||
uiController.loopMainThreadForAtLeast(100)
|
||||
} while (System.currentTimeMillis() < endTime)
|
||||
|
||||
// timeout happens
|
||||
throw PerformException
|
||||
.Builder()
|
||||
.withActionDescription(this.description)
|
||||
.withViewDescription(HumanReadables.describe(view))
|
||||
.withCause(TimeoutException())
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isPopupWindow(): Matcher<Root> = isPlatformPopup()
|
||||
|
||||
fun withDrawable(
|
||||
|
Loading…
x
Reference in New Issue
Block a user