Unit tests in Android has two types.
– The Local unit test does not have relate to Android framework, it does not need device or emulator for run the test.
– Instrumented unit test is a test that relates to Android framework, it needs device or emulator for run the test.

I use Android Studio 2.1, If you use Android Studio 2.0 or above, you will see the both androidTest and test enabled. But if you use Android Studio version lower than 2.0, you had to choose one of the two types to enable for a run the tests, that mean you had to switch between local unit tests and instrumented unit tests.
In this blog, we will talk about the local unit test. Let’s start!
Setting up your project
Add JUnit dependency in a build.gradle in-app module. Actually, it was added when your project created.
dependencies { testCompile 'junit:junit:4.12' }
And add runner
defaultConfig { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }
Then, sync your Gradle
.
Create Math Class
We will start the simple Math class for understanding easier.
public class Math { public float sum(float x, float y) { return x + y; } public float minus(float x, float y) { return x - y; } public float multiply(float x, float y) { return x * y; } public float divide(float x, float y) { if (y == 0) { throw new IllegalArgumentException("Divide by zero!"); } return x / y; } }
Write your first test
Create class MathTest in local unit tests package, we will start with testing sum function.
public class MathTest { @Test public void sum() { Math math = new Math(); float result = math.sum(3, 2); assertTrue(result == 5); } }
We test sum method by calling math.sum()
and we expect that result of 3 + 2 is 5. If it correct, it will show that the test passed.
Add the rest of method.
public class MathTest { private Math math; @Before public void setUp() { math = new Math(); } @Test public void sum() { float result = math.sum(3, 2); assertTrue(result == 5); } @Test public void minus() { float result = math.minus(-5, 10); assertTrue(result == -15); } @Test public void multiply() { float result = math.multiply(10, -20); assertTrue(result == -200); } @Test public void divide() { float result = math.divide(10, 100); assertTrue(result == 0.1f); } }
We move initial math object to setUp method. Because we do not want to duplicate it in every test.
4 tests passed and use time to run it only 2ms. it’s extremely fast!!
@Before
annotation will run every time before each test, so math object will be create before sum and minus test running.
@After
is opposite of @Before
, that mean it will run every time after each test running.
But sometime you want it to run only once time, you should be use @BeforeClass or @AfterClass
instead.
And variable in @BeforeClass and @AfterClass
must be static.
private static Math math; @BeforeClass public static void setUp() { math = new Math(); } @AfterClass public static void tearDown() { }
Catch Exception
Divide method has throw exception when divider is 0. Because it can not find answer, it’s infinity!.
So we can test by add expected exception class.
@Test(expected = IllegalArgumentException.class) public void divideByZero() { math.divide(10, 0); }
or when you want to catch the exception message. you need to use ExpectedException rule. Adding expect exception class and message, before execute method.
@Rule public ExpectedException exception = ExpectedException.none(); @Test public void divideByZero() { exception.expect(IllegalArgumentException.class); exception.expectMessage("Divide by zero!"); math.divide(100, 0); }
Parameterized
Sometime you want to test the same method with many tests input. you need parameterized!.
Create new class and add parameterised runner, in this case we need to test sum method with many tests input.
@RunWith(Parameterized.class) public class MathAddParameterizedTest { }
Prepare test input and expected results
@Parameters public static Iterable<Object[]> input() { return Arrays.asList(new Object[][]{ {1, 2, 3}, {10, -10, 0}, {-20, 10, -10}, {-10, -33, -43} }); }
Add constructors and variables are relate with testing input and expected results.
Parameterised will run this constructor every time before run the order by test input.
private float operandOne; private float operandTwo; private float expectedResult; public MathAddParameterizedTest(float operandOne, float operandTwo, float expectedResult) { this.operandOne = operandOne; this.operandTwo = operandTwo; this.expectedResult = expectedResult; }
Add test of sum method.
private Math math; @Before public void setUp() { math = new Math(); } @Test public void sum() { float result = math.sum(operandOne, operandTwo); assertTrue(result == expectedResult); }
Run it!
Easy, right? 😀