问题
The Situation
I'm writing a timetable-viewing application and the first feature to be implemented is choosing the course for which to view the timetable.
The user chooses the name of their course from a list and is taken to another screen to further specify which year, group etc. of the course they're currently in. The screens to choose your course and edit your course details are as follows:
The Goal
Inspired by the Google I/O 17 talk on Test-Driven Development on Android, what I wish to write is a UI test case to test this feature. Specifically, I want my test to confirm that if the user clicks on one of the course names they will be taken to the 'edit course details' screen and that the course title at the top e.g. 'Accounting and Finance' matches the one that was clicked in the list.
The Problem
The test, using Espresso, for the specific case of choosing the course titled 'Accounting and Finance' and seeing if the correct title shows up on the next screen, would look (roughly) like this:
@Test
public void chooseCourse() {
onView(withId(R.id.rv_course_list))
.perform(RecyclerViewActions.actionOnItemAtPosition(
/*Somehow find position of Accounting and Finance*/,
click())
);
onView(withId(R.id.course_title))
.check(matches(withText("Accounting and Finance")))
.check(matches(isDisplayed()));
}
My problem is that the RecyclerView
course list will be populated using results from a HTTP request or a SQLite database at runtime and there is no way of knowing beforehand whether the list will contain 'Accounting and Finance' or something else (I don't want the test to fail just because a specific course isn't in the list when the application runs).
Taking this into consideration I cannot hard-code the course name into the test. Please note that I'm not trying to write a unit test where I would just mock the dependency of obtaining the course list to ensure that 'Accounting and Finance' is in the list (and would probably just isolate the ChooseCourseActivity
class, capturing its Intent
s).
In the video I linked to above, the presenter talks us through a UI test of the add-note feature of a notes application where the test is as follows:
- Click on the 'add note' button
- Enter title and description of the note
- Click on the 'save note' button
- Verify that a new note with the details from step 2 is contained in the list
In that scenario hard-coding the text (title and description) used to find the views works great because the code in the test determines the contents of the view i.e. the note in the notes list. In my case, the contents of the view will be determined by a HTTP response or db query
The Question
- How do I write an adequate UI test for the choose-course feature before implementing it?
- Is the method used in the video to test the notes app simply not applicable to my feature (because I cannot hard-code the course title that is to be chosen from the list)?
- Am I just misunderstanding UI testing and should be mocking dependencies (even though the speaker in the video did not)?
Edit: The best solution to this problem seems to be what is called 'hermetic testing' and this blog describes how to apply it to android UI.
回答1:
You can test this in a few different ways and I've used a combination of all of them within my apps.
1) You can mock your network/database layer as you suggested.
2) You can make a call to your API in your test to get your 'expected' data set and then verify that it appears correctly in your UI.
3) You can Stub your networking layer to allow you to inject known data and not rely on your networking endpoint. Retrofit in particular makes it very easy to do this.
4) You can test against live endpoints using a known test dataset that won't change frequently.
I tend to use Espresso both for UI level tests and full blown regression tests. In the UI level tests, I stub out the networking/on device persistence layer and just test the client side with datasets that I inject during the test. For regression tests, I care about testing the integration with my API and for those I use a testing account that has known unchanging data.
来源:https://stackoverflow.com/questions/44806049/how-to-write-an-android-ui-test-where-the-contents-of-views-are-determined-at-ru