Join James P White for an in-depth discussion in this video JUnit basics, part of Android App Development: Unit Testing.
[Voiceover] - In the last video I indicated that there are two ways Android unit tests can be executed. If the code being tested doesn't have ties to the Android APIs, then the unit test can be executed as a local test. On your local machine by a JUnitRunner. If however, the code being tested utilizes Android APIs, then these should run on the Android device or emulator. Instrumented Tests, as they are called require the AndroidJUnitRunner, which is provided by the Android testing support library in order to execute.
In this chapter, we explore local unit tests. Specifically looking at the Junit API, and how to create tests that run on the JVM. In the next chapter, we explore instrumented unit tests, and how to create tests that run on the Android device or emulator. The foundation of both local unit tests, and instrumented unit tests is still JUnit. So, many of the principals in API covered in this introduction to local unit testing also apply to instrumented unit testing.
You've already heard a lot about JUnit. So what is it? JUnit has been around a long time by industry standards. It was created by Kent Beck of extreme programming fame, Erich Gamma of design patterns fame and others back in 1997. It was born out of Beck's development of a Smalltalk unit test framework called SUnit. In fact today, there are many unit test frameworks in various programming languages and environments that follow the SUnit, JUnit model. They're collectively referred to as xUnit test frameworks.
While there are other implementations of unit testing frameworks, JUnit has become the most widely used unit test framework on the planet. And the defacto standard unit test framework for Java developers. Creating unit tests with JUnit four has been made extremely easy with the use of Java annotations like test. Let's take a look the important JUnit API and annotations that make Java unit testing work. I've opened Android studio, and opened project 02_01_start. To begin, let's say I had a small Java class like this simple math class I wanted to unit test.
More specifically I want to unit test it's public interface, or public methods. Following best practices in JUnit testing I would create a mirror class that would hold the unit test against the simple math methods. By convention, it would be named simple math test. Simple math test is referred to as a test class, or test case. Methods in a test class are annotated with the JUnit test annotation and are called unit test methods.
We might start out testing with two test methods. One method for each of the public methods in simple math. You'll often see unit test methods have a test prefix name like test add or test if. This is a unit test convention based on the time before Java annotations existed. In older JUnit testing, developers were required to affix the prefix test to test methods in order to designate them as unit tests. The test annotation handles that today, but the test prefix has generally been kept around by convention to help identify tests, and to support legacy JUnit testing, say JUnit three for example, when needed.
Test methods must be public, take no arguments, and return void. Also note, an import is required in order to use the test annotation. The JUnitRunner that exercises tests creates a new instance of the test class using the zero argument constructor before invoking each test method and capturing the test results. This is to ensure each test is isolated from the next. Of course, at this time the unit test in my code are empty, and therefore not really testing anything yet.
There should be some code inside each of the methods to exercise methods of simple math. The general practice held in creating test methods is to first create an instance of the object to test. In this case, simple math. This is called the domain object, or object under test. Second, exercise the domain objects method you want to test. You often have to create object to pass in as parameters to the method you are testing. In this example, it's pretty straight forward.
Call on add or diff methods with simple integer parameters. Lastly, confirm the results returned by the method you are testing. JUnit provides a number of static methods on the class called org.junit.Assert to help in this last step. It is the results of the assert that are reported by the JunitRunner after execution. There are many assert methods. If we take a look at the JUnit documentation we'll see a full list. In my test, I use Assert, assertEquals.
AssertEquals is checking that the results of executing method, the last parameter to the assertEquals method, are equal to the expected results, which is the first parameter to the assertEquals call. There are also assertTrue, assertFalse, assertNotNull, assertArrayEquals, and many more assertion methods. We'll look at assertions in more detail in a later video in this chapter. The assert methods are also all over loaded with a second formula method that takes a message stream as it's first parameter.
This message stream serves as the air return by the JUnit runner whenever the assertion check fails. So for example, the unit test methods using assertEquals could be provided with message like this to present an error explanation when the unit test assertions fail. Because assert static methods are used so frequently in a test class, most developers use a static import to allow the assert methods to be referenced in the unit test without explicit name space reference, as I've done and shown here.
- Why unit test?
- Unit testing tools
- Local testing with JUnit
- Working with JUnit assertions, rules, and categories
- Executing instrumented tests
- Filtering tests
- Testing with UI Automator and other testing tools