Join Chiu-Ki Chan for an in-depth discussion in this video RecipeRobot, part of Effective Android Testing for Mobile Developers.
- [Instructor] Let's create RecipeRobot, which extends ScreenRobot. Right click on the test package, new, Java Class. The name will be RecipeRobot. Right after the word RecipeRobot, we will add extends ScreenRobot of type RecipeRobot. We are going to use the function checkIsHidden to verify that the title view is hidden.
We will name this function noTitle. Public, RecipeRobot, and then noTitle. Inside the function, return checkIsHidden and give it the ID R.id.title. We need to import this ID, so go to the top and type import_com.sqisland.tutorial.recipes and then R. Next, we will try to use the RecipeRobot in our test.
Go to RecipeActivityTest.java, scroll up to the function recipeNotFound in line 43. The first thing we do is to launch activity. Well, right now, we don't have anything that can do that yet, so we'll need to go back to the RecipeRobot to implement that. In the beginning of RecipeRobot, in line six, we will add the function launch. Public, RecipeRobot, launch.
All these functions return RecipeRobot because we want to chain them together. You will see it when I start using it in the test itself. The launch function will need to take an ActivityTestRule. ActivityTestRule, rule. Inside the function, we will call rule.launchActivity and give it a null intent. At the end, return this, the RecipeRobot. Now, go back to the test and we will replace line 44 with the robot.
New, RecipeRobot and then in the next line we will do .launch and then the activityRule. We can delete the line that says activityRule.launchActivity because the functionality is taken care of in the launch function. The next two lines involve verifying the description and the title. We already wrote the title function, so let's use that. You can edit right after the launch line, .noTitle.
Finally, let's also write a function in the robot to verify that the description is recipeNotFound. Once again, we will use the same pattern that we used in the title. We will put the logic that is common, that can be reused, into the screenRobot and then we will use that function in the RecipeRobot in a semantic way. Go to screenRobot, make a new function. Public, T checkViewHasText.
The first parameter is the view that we want to check, @IdRes int viewId. The second is the text that we expect. In our case, we are going to be using a string resource, @StringRes and then int stringId. Inside the function, we will first call onView(withId) and give it the view ID.
Then, we will .check(matches(withText) and then the stringId. After that, once again, return the robot itself, return (T) this. Switch to RecipeRobot to use this function. We will call it description, public, RecipeRobot, description. This function takes a string res, which is going to be parse two checkViewHasTest.
@StringRes int stringId. Inside the function, return checkViewHasText, the ID R.id.description, and then the stringId. With that, go back to the test. In line 47, after .noTitle, add .description and then R.string.recipe_not_found.
The lines noTitle and description replaces our onView with id.description and onView with id.title, so we can delete those two lines. Okay, let's run the rest. Click on the green triangle next to the function name and click Run. Use the same selection. Alright, it passed. You go back to the code and compare this function with the next one, clickToFavorite.
You can see that, with RecipeRobot, we are verifying the logic, the what of our app. So, it says noTitle rather than onView(withId(R.id.title)) and then check that it matches notIsDisplayed. This is good for two things. One, your test is easier to read and understand, and two, the logic for checking that there's no title is put away inside another class in a central place.
So, if the UR of your app ever changes, you only have one place to update. Next, we will look into how to add logic to the RecipeRobot that is common to all test cases using the constructor.
- Why test?
- Local vs. on-device
- Code coverage
- UI testing
- Hermetic environment
- Dependency injection
- Testing with MVP