Iterative through recyclerview's items and select one that matched the condition using Appium and Robot Framework

Viewed 206

I'm working on automated testing using Appium and Robot Framework. I have an issue dealing with an item in Recyclerview. The recyclerview's item is a custom view which is a combination of mutiple textviews. Let's assume that the recyclerview's item looks like this

======================

TextViewA | TextViewB | TextViewC |

======================

Where

  1. TextViewA's id is "tvA"
  2. TextViewB's id is "tvB"
  3. TextViewC's id is "tvC"

My goal is to write a robot to iterative through the items and click the Textview (any of three) if the item matched the following conditions:

  1. @text in TextviewA must be equal ${paramA}
  2. @text in TextviewB must be equal ${paramB}
  3. @text in TextviewC must be equal ${paramC}

I decided to do the following:

  1. Get all items in recyclerview as a list and loop through the items. How? - Impossible because the list is a RecyclerView
  2. If 1. is impossible, create a while loop (for loop where ${i} = 0 - 9999) and check that is item[${i}] exists. If the item exists, check whether the @text in TextViews matched the parameters. If the item does not exists, scroll up and check the item again
1 Answers

I am not familiar with appium or the robot framework, but if this is a visual test then I'm sure you can mock the inputs, right?

What I would expect a test to cover is that given a list with items A1, A2, A3, that there are three rows in a RecyclerView whose values are bound to A1, A2, and A3's contents.

You can't iterate all items of a RV like that, because the recycler view well.. recycles views, so it doesn't create all Views. It just uses a pool that gets reused as you scroll.

About your option 2

create a while loop (for loop where ${i} = 0 - 9999) and check that is item[${i}] exists. If the item exists, check whether the @text in TextViews matched the parameters. If the item does not exists, scroll up and check the item again

I think you're approaching this from the wrong angle. First you ought to assume the recycler view "works as intended" by design. You don't need to ensure it does what it's supposed to do, but you do want to ensure that if you give it 5 items, those items are correctly bound to what you expect, and that the bindings are correct.

In Espresso/Android you'd normally instantiate your Activity/Fragment "scenario", and override the injected dependencies (namely, for e.g.: the data source where your items normally come from), to replace them with a simpler/fake/faster data set.

So instead of making a network request during your test you'd simply provide a known/hardcoded set of values.

E.g.:

If your activity/viewModel use a repository to fetch this list, you can inject a mock that returns a List that you hardcoded in the test and that you know.

So when the activity starts for real, it uses this fake repository.

At this point then you KNOW what the screen should look like. If your fake list had 10 items, then your RecyclerView should be capable of rendering these 10 items.

For that you'd use actions like:

onView(withId(R.id.your_recycler_view))
   .perform(actionOnItemAtPosition<YourViewHolder>(0, click()))

For example, to "click" on an Item at position 0. Or you can use many of the other Espresso actions, assertions, matchers, to determine if certain text is present, etc.

Related