Join Chiu-Ki Chan for an in-depth discussion in this video Clear favorites, part of Effective Android Testing for Mobile Developers.
- [Instructor] RecipeActivityTest has a before function, that clears the favorites. We can move this logic to RecipeRobot, by Moving the Favorites there, and then Clearing it in the Constructor. Cut the lines from 35 to 41. In other words, the whole clearFavorites function. Go to RecipeRobot, and Paste it in. We will Remove the word Before in line 14, and we'll Change it Into a Constructor by Deleting the word Void, and then Renaming it to ReciptRobot.
Inside the function, favorites is not declared. So put your Mouse over Line 17 on the word Favorites, Press Alt + Enter, and Create Field. The default is private final InMemoryFavorites, which is fine. Next, go back to RecipeActivityTest, Scroll Down. In the function alreadyFavorite, in Line 56, you can see that we call the function Put on favorites.
However, we are actually going to be using the favorites inside the robot itself. So what we need to do, is to Delete this from the Test itself, and Move the Function into the Robot. Copy the Line 56, go to RecipeRobot, and then we will Add a New Function here. Public, RecipeRobot. We will call this function setFavorite. SetFavorite will take a parameter of the type String, and we'll call it id, meaning the recipe id.
Paste Into the Body of this Function. Replace the constant CARROTS_ID, with the Id From the Parameter. After that, say return this. Once again, we're moving this logic into the RecipeRobot, because the logic, the clear favorites, is inside the robot. If we have two different favorites, one in the Test, one in the RecipeRobot, the state is going to be inconsistent. Let's go back to the Test, and use this function.
We will need to Create a New Robot, new RecipeRobot, and then .setFavorite, and then we need to give the id, meaning CARROTS_ID. Delete Line 58. After we have set up the state, we are going to need to Launch the Recipe. This time, it is different from our noTitle example, because we actually need to pass it the recipe id. Let's go to the RecipeRobot, and Implement a New Launch Function.
Copy and Paste the lines 23 to 26 for the launch function, and Paste it afterwards. After the first parameter ActivityTestRule, Add Another One that is a String for the Id. Inside the function, instead of launching the activity with (null), we are going to Create an Intent. Intent_intent = new Intent. For the intent, we are going to put an extra for the recipe id, intent.putExtra.
The string is going to be the constant that we defined in RecipeActivity. So, (RecipeActivity.KEY_ID, and the value is the id that is in the parameter of this function. After that, in line 33, replace (null) with (intent). This means that we're actually launching the activity with this intent, so that we can pass in the recipe id. The last line return this, returning the robot is still good.
And now, Go Back to the Test. Right after line 57, we are going to call .launch, and we'll pass in the (activityRule), and also CARROTS_ID, as a second parameter. With that, we can Delete the Line LaunchRecipe. Finally, we want to verify that the title is selected. This is the how of what we are actually verifying on the UI. But what is the what? What is the semantics? What are we trying to do? We're trying to verify that this recipe is a favorite.
So we're going to Add that As a Function to RecipeRobot, which will use a function called isSelected, in ScreenRobot. Go to ScreenRobot. We will Add the Function check is selected. This is very similar to check is hidden, so we can copy and paste from that. Copy and Paste line 14 to 20, Paste it, and the Change the Name to checkIsSelected.
Inside the function in line 31, it's still checking (not(isDisplayed), we'll be checking that it is selected. So Replace (not(isDisplayed) with (isSelected). Now that we have defined check (isSelected), we can use it in RecipeRobot. Scroll to the End, and Add a Function called (isFavorite). As always, return the RecipeRobot. The function name is isFavorite.
Inside the function, return checkIsSelected, and we'll give it the view id for the title, (R.id.title). Finally, we're going to use this function in our test. Switch Back To the Test, and in line 58 Append thought .isFavorite. And now we can Delete the Line that Calls onView (withId) and (isSelected). Let's run the test.
Click on the Gutter, and Press Run. Alright, it passes. We have one more test method in this class, Click to favorite. This should give you a good starting point to use the robot pattern to refactor that, and extract the logic into ScreenRobot, and RecipeRobot. One last thing. It is good practice to remove variables that we don't use. In our case, it is favorites. Scroll Up, and favorites is in line 33.
Let's Delete that Line. Next, let's recap what we learned about the robot pattern.
- Why test?
- Local vs. on-device
- Code coverage
- UI testing
- Hermetic environment
- Dependency injection
- Testing with MVP