Test-Driven Development Tutorial for Android: Getting Started
- What Is TDD?
- Why Is TDD Important?
- The Five Steps of TDD
- Getting Started
- Download the Starter App
- Instrumentation and Unit Tests
- Writing a Failing Instrumentation Test
- Making the Tests Pass
- Writing a UI Test
- Writing a Failing UI Test
- Making the Tests Pass
- Writing a Test to Fix a Bug
- Making the Test Pass
- Writing a Test Before Refactoring
- Refactoring Your Code
- Where to Go From Here
Testing is an important part of software development. By including tests with your code, you can ensure that your code additions work and that later changes don’t break them. They can give you the peace of mind to develop quickly and catch bugs before they’re released.
Test-Driven Development, also known as TDD, is one way of ensuring to include tests with any new code. When following this process, you write the tests for the thing you are adding before you write the code to implement it. Using TDD when developing an Android app is what you will learn in this tutorial, and by the end, you’ll understand:
- The features and uses of TDD.
- Why TDD is useful.
- The steps for practicing TDD.
- How to use TDD in your own projects.
- How to write tests for ViewModel instances that use LiveData, both part of the Architecture Components from Google.
You should also have basic knowledge of ViewModel and LiveData (part of the Android Architecture Components library from Google), so have a look at Android Architecture Components: Getting Started.
Knowledge of mocking and testing on Android is helpful, but not necessary. You can learn about mocking with Mockito in Android Unit Testing with Mockito.
If you know Android, but are unfamiliar with Kotlin, take a look at Kotlin For Android: An Introduction.
What Is TDD?
TDD is a software-development process. You can apply TDD wherever you practice software development, whether it’s iOS, Android, back-end, front-end, embedded, etc. You may have also heard it described as Red-Green-Refactor. It’s a process in which you write the tests that specify the code you’re going to write before you start writing any of the code.
Why Is TDD Important?
There are a number of motives for using TDD, and they all have a lasting impact:
Refactoring is also built into this development process. By having this refactoring step built in, your code starts off squeaky clean!
- Faster development time: When you have well-written tests, they provide an excellent description of what your code should do. From the start, you have the end goal in mind. Writing these specifications as tests can help keep the result from drifting away from the initial idea.
- Automatic, up-to-date documentation: When you’re coming into a piece of code, you can look at the tests to help you understand what the code does. Because these are tests rather than a static document, you can be sure this form of documentation is likely up-to-date!
- More maintainable code: When practicing TDD, it encourages you to pay attention to the structure of your code. You will want to architect your app in a way that is easier to test, which is generally cleaner and easier to maintain and read. For example, decoupled classes are easier to set up test classes for, encouraging you to structure your classes this way.
- Greater confidence in your code: Tests help you to ensure that your code works the way it should. Because of this, you can have greater confidence that what you wrote is “complete.” In addition, with any changes that you make in the future, you can know that you didn’t break that functionality as long as the tests you wrote with the code are passing.
- Higher test coverage: This one is fairly obvious. If you’re writing tests along side the code you’re writing, you’re going to have more test coverage over the code! This is important to many organizations.
The Five Steps of TDD
Through the TDD process, you’ll write a number of tests. You usually want a test for the happy path and at least one sad path. If there is a method with a lot of branching, it’s ideal to have a test for each of the branches.
You accomplish TDD by following five steps, which you’ll walk through over the course of this tutorial:
- Add a test: Anytime you start a new feature, fix or refactor, you write a test for it. This test will specify how this change or addition should behave. You only write the test at this step and just enough code to make it compile.
- Run it and watch it fail: Here, you run the tests. If you did step one correctly, these tests should fail.
- Write the code to make the test pass: This is when you write your feature, fix or refactor. It will follow the specifications you laid down in the tests.
- Run the tests and see them pass: Now, you get to run the tests again! At this point, they should pass. If they don’t, go back to step three until all your tests are green!
- Do any refactoring: Now that you have a test that makes sure your implementation matches the specifications, you can adjust and refactor the implementation that you have to ensure that it’s clean and structured the way you want without any worries that you’ll break what you just wrote.
Sometimes, it’s important to be proud of the little things. In this tutorial, you’ll work on an app (and tests!) to keep track of Small Victories. This app has a place to put the name of the small victory you want to track, such as choosing a healthy snack. It will also include a counter, a way to increment your victories and an option to clear the victories.
Download the Starter App
Start by downloading the sample project using the
Once you have the project opened and synced, build and run the app. It won’t let you do much other than set your victory title yet (by tapping the text view near the top of the screen). The rest is for you to implement.
There are a couple of files that you should locate and become familiar with as they are the ones you’ll work with in this tutorial.
- MainActivity.kt: This is where you’ll put any changes that affect the view.
MainActivityTest.kt: Here is where the tests go for
ViewModelwill contain the logic you’ll work with.
VictoryViewModelTest.kt: Likewise, this is where you’ll test
You’ll also interact with the
VictoryRepository interface, but you won’t need to change anything there. Similarly, you will use
VictoryUiModel to represent state, but it won’t require any changes.