Join Chiu-Ki Chan for an in-depth discussion in this video TDD: Red, Green, Refactor, part 2, part of Effective Android Testing for Mobile Developers.
- [Instructor] Now that we have created a dummy recipe, let's use test-driven development to parse out as fields. Go back to ReceiptTest. We are going to enter another red/green/refactor cycle. We will want to know that the id is what we expected. Take a look at the text file. The id should be water. Go back to the test and add the line assertEquals("water", recipe.id).
Run the test, again, it fails, because we are in the red part of the red/green/refactor cycle. So let's go to the recipe and actually implement the part where we parse out the id. To do that, we will need to create a BufferedReader out of the InputStream. BufferedReader, we'll call it reader, = new BufferedReader, and then inside we'll have a new InputStreamReader, which we'll give it stream.
Next, we are going to read out of this reader line by line. For (String line = reader.readLine(); line != null; line = reader.readLine(). You can see that the reader reader.readLine has exception, so we'll wrap the whole thing in a Try/Catch block. Try, catch (IOException e).
Whenever we have an error, we are going to go ahead and just return null. I'm going to close some of the panels, so that we can see all the code. All right, let's go back inside the for loop, in line 28, we are going to try to find the id. Take a look at water.txt. The format is id=water. In other words, we want to find that the line starts with this prefix.
If line.startswith("id=")), then we want to assign the id with that substring, i.e. the part that comes after this prefix. To do that, it is actually better to have this id = string as a constant, so go ahead and highlight that, right-click, Refactor, Extract, Constant. We'll call it ID_PREFIX.
Usually when Android Studio do that for you, it will be a public static final string. I would change it to private because parses outside of recipe don't need to use it. Scroll back down and now we can use ID_PREFIX in line 31, line.substring(ID_PREFIX.length()). This means that we want to skip the whole prefix and extract the rest of the line.
Once we extracted the id, we don't need to do anything until the next line, so go ahead and add continue. Let's run the test. Yeah, it passes. I'm going to show you how to write the remaining of this test by repeating what we just did. Press Cmd + D to replicate this line so that we can also check the title. Let's take a look at the text file. The title, water, should have a capital letter.
So we'll come back and fix that. Run the test. At some point you may not actually run the test every single time knowing that it will fail, but it is still good practice to start with a failing test, so that we have an objective. Next, we'll go back to the recipe file, and repeat what we did for the id and do the same thing for the title. Copy line 30 to 33, paste it, and we will replace the string id with TITLE.
Make sure you assign the value to title instead of id. TITLE_PREFIX needs to be created, so press Alt + Enter, and say Create constant field. It's going to be a string, and the value is going to be title=. Scroll back down to make sure that everything is compiling, and then run the test. Now we are green again. Finally, we will also verify the description.
Press Cmd + D, change the second field to be recipe.description, and then go to the text file, and copy the expected description into that string. In RecipeTest.java, we will paste the string so that we can verify it. Okay, you are already getting bored but yes, we will press run, and then it will fail. Go back to Recipe.java and we will need to assign the value of the remaining lines into the descBuilder, so that it'll be used in the description.
descBuilder.append(line). This is not good enough because what happen when we call readLine is that the trailing new line character is going to be stripped so we need to put it back in. If it is a first line we don't want to do it, so if the descBuilder.length is greater than zero, meaning that it is not the first line, then, descBuilder.append, the new line character, which is \n.
Run the test. Yeah, it passed. Test-driven development is a great way to write your code because you can iterate very quickly and also, by the end of it, you will end up with a test that verifies that your code is correct.
- Why test?
- Local vs. on-device
- Code coverage
- UI testing
- Hermetic environment
- Dependency injection
- Testing with MVP