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

Topic Info Tablet Robolectric Tests [DON'T MERGE] #1480

Closed
wants to merge 8 commits into from

Conversation

MohamedMedhat1998
Copy link
Contributor

Notes

The current test-case fails because of some flickering effect that I noticed when I ran the app on my real device.
Here is the code

  @Test
  fun test() {
    launch(TopicInfoTestActivity::class.java).use {
      it.onActivity { activity ->
        val seeMoreTextView = getSeeMoreTextView(activity)
        val descriptionTextView = getTopicDescriptionTextView(activity)
        assertThat(seeMoreTextView?.text.toString()).isEqualTo("See More")
        assertThat(descriptionTextView?.maxLines).isEqualTo(5)
        seeMoreTextView?.performClick()
        assertThat(descriptionTextView?.maxLines).isEqualTo(12)
        assertThat(seeMoreTextView?.text.toString()).isEqualTo("See Less")
      }
    }
  }

Which means that the text start in expanded state instead of collapsed state.
When I inverted the order of the assertions, the test passed.

  @Test
  fun test() {
    launch(TopicInfoTestActivity::class.java).use {
      it.onActivity { activity ->
        val seeMoreTextView = getSeeMoreTextView(activity)
        val descriptionTextView = getTopicDescriptionTextView(activity)
        assertThat(seeMoreTextView?.text.toString()).isEqualTo("See Less")
        assertThat(descriptionTextView?.maxLines).isEqualTo(12)
        seeMoreTextView?.performClick()
        assertThat(descriptionTextView?.maxLines).isEqualTo(5)
        assertThat(seeMoreTextView?.text.toString()).isEqualTo("See More")
      }
    }
  }

So, is this a problem in the code itself?
If so, should I continue writing these tests tell the problem gets resolved, or there is something else that I can do?

Explanation

  • Implemented Robolectric-Test for "Topic-Info" Fragment

Checklist

  • The PR title starts with "Fix #bugnum: ", followed by a short, clear summary of the changes. (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • The PR explanation includes the words "Fixes #bugnum: ..." (or "Fixes part of #bugnum" if the PR only partially fixes an issue).
  • The PR follows the style guide.
  • The PR does not contain any unnecessary auto-generated code from Android Studio.
  • The PR is made from a branch that's not called "develop".
  • The PR is made from a branch that is up-to-date with "develop".
  • The PR's branch is based on "develop" and not on any other branch.
  • The PR is assigned to an appropriate reviewer in both the Assignees and the Reviewers sections.

@MohamedMedhat1998 MohamedMedhat1998 changed the base branch from develop to t-info-tablet-port-highfi July 17, 2020 13:16
TopicInfoFragment.newInstance(internalProfileId = 0, topicId = RATIOS_TOPIC_ID)
activity.supportFragmentManager.beginTransaction()
.add(R.id.topic_info_container, topicInfoFragment, TopicInfoFragment.TOPIC_INFO_FRAGMENT_TAG)
.commit()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use commitNow to ensure there's no delay in the UI showing up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@BenHenning BenHenning left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MohamedMedhat1998 can you include a video of the observed behavior to provide context on the issue you're observing? Also, what have you tried to do to fix this, & what are your thoughts on what's going wrong?

@BenHenning BenHenning removed their assignment Jul 18, 2020
Copy link
Contributor

@vinitamurthi vinitamurthi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that the initial set up has something to do with it being created in an expanded state?

android:id="@+id/topic_info_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".testing.TopicInfoTestActivity" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a new line at EOF

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@vinitamurthi vinitamurthi removed their assignment Jul 20, 2020
@vinitamurthi
Copy link
Contributor

vinitamurthi commented Jul 20, 2020

@BenHenning for some reason this PR is allowed to merge even without a review. Any idea why?

Edit: Nevermind, I just noticed this isn't being merged to develop!


fun handleOnCreate() {
activity.setContentView(R.layout.topic_info_test_activity)
val topicInfoFragment =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about putting a check here if a fragment already exist or not? WDYT
if (getTopicInfoFragment() == null)


private fun getTopicDescriptionTextView(activity: TopicInfoTestActivity): TextView? {
val topicInfoFragment =
activity.supportFragmentManager.findFragmentByTag(TopicInfoFragment.TOPIC_INFO_FRAGMENT_TAG)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about if we use the placeholder_id rather than TAG? This will remove using extra TAG part.

Intents.release()
}

private fun getTopicDescriptionTextView(activity: TopicInfoTestActivity): TextView? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about if we move these helper methods at the bottom of the file and bringing test cases at the top after @After method? This will make it looks good and if in future some more test cases a consistency will be there that all helper methods are at bottom and test cases in between.

@Test
fun test() {
launch(TopicInfoTestActivity::class.java).use {
it.onActivity { activity ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about if we use scenario -> rather than using it?

}

@Test
fun test() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the Ben comment if you could add some more about the current problem you are seeing for this.
Name of the test case can be more understandable just to understand what the test is all about.

@anandwana001 anandwana001 removed their assignment Jul 20, 2020
@MohamedMedhat1998
Copy link
Contributor Author

@MohamedMedhat1998 can you include a video of the observed behavior to provide context on the issue you're observing? Also, what have you tried to do to fix this, & what are your thoughts on what's going wrong?

@BenHenning
What I'm trying to do is testing the see_more TextView in this way:

  1. Start the activity/fragment and check the text inside the see_more TextView
  2. I expect that the text will be "See More", but it was actually "See Less" (according to the test result)
  3. I tried running the application on my real device to observe what happens, and noticed a flickering effect
    ezgif com-video-to-gif

So, the test case is failing.

Also, what have you tried to do to fix this, what are your thoughts on what's going wrong?

I haven't tried fixing that but I think the initial state of the fragment is set up incorrectly.

Is it possible that the initial set up has something to do with it being created in an expanded state?

That is what I'm thinking too.

@BenHenning
Copy link
Member

BenHenning commented Jul 22, 2020

Thanks @MohamedMedhat1998. This seems like the same issue as #1379 to me. The problem is likely that the topic page is in an initial loading state before becoming fully loaded. If this were Robolectric-specific, using TestCoroutineDispatchers would almost certainly fix the issue. Unfortunately, I haven't had time to figure out how to adapt these to an IdlingResource yet (it's not straightforward because Espresso isn't running with a fake clock, and it's not clear to me if it's valid to run background coroutines on a different clock than the wall clock being used by the main thread).

You could try to integrate TestCoroutineDispatchers and make this test first pass with Robolectric, then create a custom IdlingResource to see if it'll work on Espresso. I'm not sure exactly what the custom idling resource will look like yet.

@MohamedMedhat1998 MohamedMedhat1998 changed the base branch from t-info-tablet-port-highfi to develop July 25, 2020 11:36
@MohamedMedhat1998 MohamedMedhat1998 changed the base branch from develop to t-info-tablet-port-highfi July 25, 2020 11:36
@MohamedMedhat1998
Copy link
Contributor Author

Thanks @MohamedMedhat1998. This seems like the same issue as #1379 to me. The problem is likely that the topic page is in an initial loading state before becoming fully loaded. If this were Robolectric-specific, using TestCoroutineDispatchers would almost certainly fix the issue. Unfortunately, I haven't had time to figure out how to adapt these to an IdlingResource yet (it's not straightforward because Espresso isn't running with a fake clock, and it's not clear to me if it's valid to run background coroutines on a different clock than the wall clock being used by the main thread).

You could try to integrate TestCoroutineDispatchers and make this test first pass with Robolectric, then create a custom IdlingResource to see if it'll work on Espresso. I'm not sure exactly what the custom idling resource will look like yet.

@BenHenning @rt4914 I have tried using IdlingResources but the test failed for the same reason.
Also I have pushed a new commit that uses TestCoroutineDispatchers but the test case failed for the same reason.
I'm not sure if I'm using it correctly or not, here is the code below

@ExperimentalCoroutinesApi
  @InternalCoroutinesApi
  @Test
  fun secondTest() {
    launchTopicActivityIntent().use {
      testCoroutineDispatchers.advanceUntilIdle()
      onView(withId(R.id.topic_description_text_view))
        .check(
          matches(
            maxLines(
              /* lineCount= */ 5
            )
          )
        )
    }
  }

Error:

Expected: isTextInLines: 5 Got: 12

…olectric-tests

# Conflicts (Resolved):
#	app/src/main/java/org/oppia/app/activity/ActivityComponent.kt

-Added some test case
@BenHenning
Copy link
Member

@MohamedMedhat1998 when you used TestCoroutineDispatchers did you run the test with Robolectric? Given that this is an app module test, I'm not actually expecting it to work without #59 being resolved since we can't properly sync the two different application components being created in app module tests.

@MohamedMedhat1998
Copy link
Contributor Author

@MohamedMedhat1998 when you used TestCoroutineDispatchers did you run the test with Robolectric? Given that this is an app module test, I'm not actually expecting it to work without #59 being resolved since we can't properly sync the two different application components being created in app module tests.

@BenHenning yes, I was running it with robolectric.

Base automatically changed from t-info-tablet-port-highfi to develop July 28, 2020 07:06
@BenHenning
Copy link
Member

BenHenning commented Jul 29, 2020

@MohamedMedhat1998 in that case I suggest migrating the test suite or moving the tests in question to a local test suite like StateFragmentLocalTest & following the same Dagger setup we have there (where we're actually specifying the application class to use via a @Config parameter). A local test with Robolectric & coroutine dispatchers should have very high predictability for all parts of the UI, including the background async loading pieces.

References

@BenHenning BenHenning removed their assignment Jul 29, 2020
@MohamedMedhat1998
Copy link
Contributor Author

@MohamedMedhat1998 in that case I suggest migrating the test suite or moving the tests in question to a local test suite like StateFragmentLocalTest & following the same Dagger setup we have there (where we're actually specifying the application class to use via a @Config parameter). A local test with Robolectric & coroutine dispatchers should have very high predictability for all parts of the UI, including the background async loading pieces.

References

* https://github.com/oppia/oppia-android/blob/develop/app/src/test/java/org/oppia/app/player/state/StateFragmentLocalTest.kt#L1080

* https://github.com/oppia/oppia-android/blob/develop/app/src/test/java/org/oppia/app/player/state/StateFragmentLocalTest.kt#L98 (note that the paused looper mode is important here)

I think the main problem we are facing now is the line count in Robolectric tests.
I have posted this question on StackOverflow hoping that someone will have an answer

@rt4914
Copy link
Contributor

rt4914 commented Sep 3, 2020

@MohamedMedhat1998 Either update/finish this PR or if this is not needed then close this PR.

@rt4914 rt4914 removed their assignment Sep 3, 2020
@MohamedMedhat1998
Copy link
Contributor Author

closing this PR because it was created to demonstrate the issue with robolectric tests and lineCount of the TextView

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants