Merge pull request #34 from fknives/issue#4-recycler-view-test

Issue#4 Add scrolling to recyclerview so elements can be verified safely
This commit is contained in:
Gergely Hegedis 2022-01-05 15:06:57 +02:00 committed by GitHub
commit b35467fcba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 36 deletions

View file

@ -137,6 +137,7 @@ dependencies {
testImplementation "androidx.test.ext:junit:$testing_androidx_junit_version" testImplementation "androidx.test.ext:junit:$testing_androidx_junit_version"
testImplementation "androidx.test.espresso:espresso-core:$testing_espresso_version" testImplementation "androidx.test.espresso:espresso-core:$testing_espresso_version"
testImplementation "androidx.test.espresso:espresso-intents:$testing_espresso_version" testImplementation "androidx.test.espresso:espresso-intents:$testing_espresso_version"
testImplementation "androidx.test.espresso:espresso-contrib:$testing_espresso_version"
testImplementation project(':mockserver') testImplementation project(':mockserver')
testImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version" testImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version" testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version"
@ -151,6 +152,7 @@ dependencies {
androidTestImplementation "androidx.test.ext:junit:$testing_androidx_junit_version" androidTestImplementation "androidx.test.ext:junit:$testing_androidx_junit_version"
androidTestImplementation "androidx.test.espresso:espresso-core:$testing_espresso_version" androidTestImplementation "androidx.test.espresso:espresso-core:$testing_espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-intents:$testing_espresso_version" androidTestImplementation "androidx.test.espresso:espresso-intents:$testing_espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$testing_espresso_version"
androidTestImplementation project(':mockserver') androidTestImplementation project(':mockserver')
androidTestImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version" androidTestImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version"
androidTestRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version" androidTestRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version"
@ -161,10 +163,3 @@ dependencies {
implementation "io.reactivex.rxjava3:rxjava:3.1.2" implementation "io.reactivex.rxjava3:rxjava:3.1.2"
} }
///Users/gergelyhegedus/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.5.31/ff5d99aecd328872494e8921b72bf6e3af97af3e/kotlin-stdlib-jdk8-1.5.31.jar (version 1.5)
///Users/gergelyhegedus/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.5.31/77e0f2568912e45d26c31fd417a332458508acdf/kotlin-stdlib-jdk7-1.5.31.jar (version 1.5)
///Users/gergelyhegedus/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.6.0/a40b8b22529b733892edf4b73468ce598bb17f04/kotlin-stdlib-1.6.0.jar (version 1.6)
///Users/gergelyhegedus/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.6.0/7857e365f925cfa060f941c1357cda1f8790502c/kotlin-stdlib-common-1.6.0.jar (version 1.6)
//w: Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath
//dagger.lint.DaggerIssueRegistry in /Users/gergelyhegedus/.gradle/caches/transforms-3/7d8d9a87fed97b25e3e147795231ede4/transformed/jetified-dagger-lint-aar-2.40/jars/lint.jar does not specify a vendor; see IssueRegistry#vendor

View file

@ -1,9 +1,11 @@
package org.fnives.test.showcase.ui.home package org.fnives.test.showcase.ui.home
import android.app.Instrumentation import android.app.Instrumentation
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
@ -48,12 +50,15 @@ class HomeRobot : Robot {
Espresso.onView(withId(R.id.logout_cta)).perform(click()) Espresso.onView(withId(R.id.logout_cta)).perform(click())
} }
fun assertContainsItem(item: FavouriteContent) = apply { fun assertContainsItem(index: Int, item: FavouriteContent) = apply {
val isFavouriteResourceId = if (item.isFavourite) { val isFavouriteResourceId = if (item.isFavourite) {
R.drawable.favorite_24 R.drawable.favorite_24
} else { } else {
R.drawable.favorite_border_24 R.drawable.favorite_border_24
} }
Espresso.onView(withId(R.id.recycler))
.perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(index))
Espresso.onView( Espresso.onView(
allOf( allOf(
withChild(allOf(withText(item.content.title), withId(R.id.title))), withChild(allOf(withText(item.content.title), withId(R.id.title))),
@ -64,7 +69,10 @@ class HomeRobot : Robot {
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
} }
fun clickOnContentItem(item: Content) = apply { fun clickOnContentItem(index: Int, item: Content) = apply {
Espresso.onView(withId(R.id.recycler))
.perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(index))
Espresso.onView( Espresso.onView(
allOf( allOf(
withId(R.id.favourite_cta), withId(R.id.favourite_cta),

View file

@ -105,8 +105,8 @@ class MainActivityTest {
activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) activityScenario = ActivityScenario.launch(HiltMainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
ContentData.contentSuccess.forEach { ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(FavouriteContent(it, false)) homeRobot.assertContainsItem(index, FavouriteContent(content, false))
} }
homeRobot.assertDidNotNavigateToAuth() homeRobot.assertDidNotNavigateToAuth()
} }
@ -119,11 +119,11 @@ class MainActivityTest {
activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) activityScenario = ActivityScenario.launch(HiltMainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true) val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true)
homeRobot.assertContainsItem(expectedItem) homeRobot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth() .assertDidNotNavigateToAuth()
} }
@ -135,7 +135,7 @@ class MainActivityTest {
activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) activityScenario = ActivityScenario.launch(HiltMainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true) val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true)
@ -144,7 +144,7 @@ class MainActivityTest {
activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) activityScenario = ActivityScenario.launch(HiltMainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.assertContainsItem(expectedItem) homeRobot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth() .assertDidNotNavigateToAuth()
} }
@ -156,13 +156,13 @@ class MainActivityTest {
activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) activityScenario = ActivityScenario.launch(HiltMainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), false) val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), false)
homeRobot.assertContainsItem(expectedItem) homeRobot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth() .assertDidNotNavigateToAuth()
} }
@ -194,8 +194,8 @@ class MainActivityTest {
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loopMainThreadFor(2000L) loopMainThreadFor(2000L)
ContentData.contentSuccess.forEach { ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(FavouriteContent(it, false)) homeRobot.assertContainsItem(index, FavouriteContent(content, false))
} }
homeRobot.assertDidNotNavigateToAuth() homeRobot.assertDidNotNavigateToAuth()
} }
@ -236,8 +236,8 @@ class MainActivityTest {
activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) activityScenario = ActivityScenario.launch(HiltMainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
ContentData.contentSuccess.forEach { ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(FavouriteContent(it, false)) homeRobot.assertContainsItem(index, FavouriteContent(content, false))
} }
homeRobot.assertDidNotNavigateToAuth() homeRobot.assertDidNotNavigateToAuth()
} }

View file

@ -97,8 +97,8 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
ContentData.contentSuccess.forEach { ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(FavouriteContent(it, false)) homeRobot.assertContainsItem(index, FavouriteContent(content, false))
} }
homeRobot.assertDidNotNavigateToAuth() homeRobot.assertDidNotNavigateToAuth()
} }
@ -111,11 +111,11 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true) val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true)
homeRobot.assertContainsItem(expectedItem) homeRobot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth() .assertDidNotNavigateToAuth()
} }
@ -127,7 +127,7 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true) val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true)
@ -136,7 +136,7 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.assertContainsItem(expectedItem) homeRobot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth() .assertDidNotNavigateToAuth()
} }
@ -148,13 +148,13 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(ContentData.contentSuccess.first()) homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), false) val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), false)
homeRobot.assertContainsItem(expectedItem) homeRobot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth() .assertDidNotNavigateToAuth()
} }
@ -186,8 +186,8 @@ class MainActivityTest : KoinTest {
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loopMainThreadFor(2000L) loopMainThreadFor(2000L)
ContentData.contentSuccess.forEach { ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(FavouriteContent(it, false)) homeRobot.assertContainsItem(index, FavouriteContent(content, false))
} }
homeRobot.assertDidNotNavigateToAuth() homeRobot.assertDidNotNavigateToAuth()
} }
@ -228,8 +228,8 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
ContentData.contentSuccess.forEach { ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(FavouriteContent(it, false)) homeRobot.assertContainsItem(index, FavouriteContent(content, false))
} }
homeRobot.assertDidNotNavigateToAuth() homeRobot.assertDidNotNavigateToAuth()
} }

View file

@ -45,6 +45,11 @@ task unitTests(dependsOn: ["app:testKoinDebugUnitTest", "app:testHiltDebugUnitTe
description = 'Run all unit tests' description = 'Run all unit tests'
} }
task robolectricTests(dependsOn: ["app:testKoinDebugUnitTest", "app:testHiltDebugUnitTest"]){
group = 'Tests'
description = 'Run all robolectric tests'
}
task androidTests(dependsOn: ["app:connectedKoinDebugAndroidTest", "app:connectedHiltDebugAndroidTest"]){ task androidTests(dependsOn: ["app:connectedKoinDebugAndroidTest", "app:connectedHiltDebugAndroidTest"]){
group = 'Tests' group = 'Tests'
description = 'Run all Android tests' description = 'Run all Android tests'

View file

@ -17,7 +17,9 @@ object ContentData {
val contentSuccess: List<Content> = listOf( val contentSuccess: List<Content> = listOf(
Content(ContentId("1"), "title_1", "says_1", ImageUrl("img_1")), Content(ContentId("1"), "title_1", "says_1", ImageUrl("img_1")),
Content(ContentId("2"), "title_2", "says_2", ImageUrl("img_2")), Content(ContentId("2"), "title_2", "says_2", ImageUrl("img_2")),
Content(ContentId("3"), "title_3", "says_3", ImageUrl("img_3")) Content(ContentId("3"), "title_3", "says_3", ImageUrl("img_3")),
Content(ContentId("4"), "title_4", "says_4", ImageUrl("img_4")),
Content(ContentId("5"), "title_5", "says_5", ImageUrl("img_5"))
) )
/** /**

View file

@ -16,5 +16,17 @@
"title": "title_3", "title": "title_3",
"says": "says_3", "says": "says_3",
"image": "img_3" "image": "img_3"
},
{
"id": "4",
"title": "title_4",
"says": "says_4",
"image": "img_4"
},
{
"id": "5",
"title": "title_5",
"says": "says_5",
"image": "img_5"
} }
] ]