Unit Testing 

on 

Android
Buşra Deniz
@busradeniz
Droidcon Berlin 2015
ABOUT ME
busradeniz
busradeniz89@gmail.com
busradeniz.com
Certified Scrum Master & Mobile Software Developer @Netaş 

Co-Organizer @
Co-Organizer @
Master Student in SWE @Bogazici University
Co-Author of “Android Mutfağından Seçmeler”
AGENDA
01
02
03
04
What is unit test ?
Why test your code ?
Test Frameworks for Android
QA
UNIT TEST
Testing single unit of code
WHY TEST YOUR CODE ?
UN
Useful 

document

Reduce
testing
time
Bug fix
early
Refine 

Design
Unit
Test
Unit testing finds problems
early in the development cycle.
This includes both bugs in the
programmer's implementation
and flaws or missing parts of
the specification for the unit.
Unit testing provides a sort of living
documentation of the system.
Developers looking to learn what
functionality is provided by a unit,
and how to use it, can look at the
unit tests to gain a basic
understanding of the unit's interface
UT always forces you software parts
that can tests easily. While you are
writing unit tests for existing code,
you will realize that it is not too easy.
Your code should be proper in order
to isolate out parts of your SUT. By
this way, you need to refactor and
refine your code so as to write
successful unit tests.
Unit test covers the basic cases
of your software so the next
cycle of software testing can
include more complex scenarios.
For example, checking null
parameters can be handled in
unit tests so in the next cycle,
Test frameworks for Android
JUnit is a simple framework to write repeatable tests.
Asserts
Specify the expected output and compare
it with the output received
Test suites
Unit test cases are organized into test
suites for better management
Rules
Extend the functionality of JUnit by adding
behaviors to tests
Exception testing
Tests and verifies whether an exception
was thrown
Test setup and teardown
Sets up test data and tears down that data
or context, before and after running the
test
androidTestCompile ‘junit:junit:4.12’
Integration with build systems
Integrates the most popular build systems
for Java, including ANT, Maven, Gradle
Initial Test Case With Annotations
public class JUnitTestExamples {
@Before
public void setUp() {
//sets up test data, runs before test case
}

@Test
public void testAssertEquals() {
// test method
}

@After
public void tearDown() {
//tears down test data, runs after test case
}
}
JUnit annotations
@Test
@Before

@After

@BeforeClass

@AfterClass

@Ignore
Assertions
public class AssertTests {
@Test
public void testAssertArrayEquals() {
byte[] expected = "trial".getBytes();
byte[] actual = "trial".getBytes();
org.junit.Assert.assertArrayEquals("failure - byte arrays not same", expected, actual);
}
@Test
public void testAssertEquals() {
org.junit.Assert.assertEquals("failure - strings are not equal", "text", "text");
}
@Test
public void testAssertFalse() {
org.junit.Assert.assertFalse("failure - should be false", true);
}
@Test
public void testAssertNotNull() {
org.junit.Assert.assertNotNull("should not be null", new Object());
}
}
JUnit provides
overloaded assertion
methods for all
primitive types and
Objects and arrays
(of primitives or
Objects).
Test Suites
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestFeatureLogin.class,
TestFeatureLogout.class,
TestFeatureNavigate.class,
TestFeatureUpdate.class
})
public class FeatureTestSuite {
// the class remains empty,
// used only as a holder for the above annotations
}
Using “Suite” as a
runner allows you to
manually build a
suite containing tests
from many classes.
Mockito is a mocking framework that tastes really good. It lets you
write beautiful tests with clean & simple API.
mock() / @Mock
creates mock
optionally specify how it should behave via
Answer/ReturnValues/MockSettings
when()/given() to specify how a mock
should behave
spy() / @Spy
partial mocking, real methods are invoked
but still can be verified and stubbed
verify()
checks methods were called with given
arguments
@InjectMocks
automatically inject mocks/spies fields
annotated with @Spy or @Mock
androidTestCompile ‘org.mockito:mockito-core:1.9.5’
import static org.mockito.Mockito.*;
//mock creation
List mockedList = mock(List.class);
//using mock object
mockedList.add("one");
mockedList.clear();
//verification
verify(mockedList).add("one");
verify(mockedList).clear();
Once created, mock will remember all interactions.Then you can selectively verify whatever
interaction you are interested in.
mock()
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Mock private UserProvider userProvider;
private ArticleManager manager;
@Before public void setup() {
MockitoAnnotations.initMocks(this);
}
}
@Mock
List list = new LinkedList();
List spy = spy(list);
//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);
//using the spy calls real methods
spy.add("one");
spy.add("two");
//prints "one" - the first element of a list
System.out.println(spy.get(0));
//size() method was stubbed - 100 is printed
System.out.println(spy.size());
//optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");
spy() @Spy
@Spy Foo spyOnFoo = new Foo();
//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);
//using the spy calls real methods
spy.add("one");
spy.add("two");
//prints "one" - the first element of a list
System.out.println(spy.get(0));
//size() method was stubbed - 100 is printed
System.out.println(spy.size());
//optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");


Running tests is too slow because JUnit tests need an Android
emulator or device
java.lang.RuntimeException: Stub!
Robolectric lets you run your tests on your workstation, or on your
Continuous Integration environment in a regular JVM, without an
emulator.
@RunWith(RobolectricTestRunner.class)
public class WelcomeActivityTest {
@Test
public void clickingLogin_shouldStartLoginActivity() {
WelcomeActivity activity = Robolectric.setupActivity(WelcomeActivity.class);
activity.findViewById(R.id.login).performClick();
Intent expectedIntent = new Intent(activity, WelcomeActivity.class);
assertThat(shadowOf(activity).getNextStartedActivity()).isEqualTo(expectedIntent);
}
}
Robolectric supports
resource handling,
e.g., inflation of
views. You can also
use the
findViewById() to
search in a view.
androidTestCompile ‘org:robolectric:robolectric:2.4’
Test Coverage
JaCoCo is a free code coverage library for Java
it supports instruction, branch, line, method and class coverage
Test Coverage
The green lines represent
parts of the code which were
fully covered by tests. 



The yellow line means that
given branch was not fully
covered because its
condition never evaluated to
true.
The red line was never
executed by our tests.
Thanks
Buşra Deniz
@busradeniz
Droidcon Berlin 2015

Unit Testing on Android - Droidcon Berlin 2015

  • 1.
    
 Unit Testing 
 on
 Android Buşra Deniz @busradeniz Droidcon Berlin 2015
  • 2.
    ABOUT ME busradeniz busradeniz89@gmail.com busradeniz.com Certified ScrumMaster & Mobile Software Developer @Netaş 
 Co-Organizer @ Co-Organizer @ Master Student in SWE @Bogazici University Co-Author of “Android Mutfağından Seçmeler”
  • 3.
    AGENDA 01 02 03 04 What is unittest ? Why test your code ? Test Frameworks for Android QA
  • 4.
  • 5.
    WHY TEST YOURCODE ? UN Useful 
 document
 Reduce testing time Bug fix early Refine 
 Design Unit Test Unit testing finds problems early in the development cycle. This includes both bugs in the programmer's implementation and flaws or missing parts of the specification for the unit. Unit testing provides a sort of living documentation of the system. Developers looking to learn what functionality is provided by a unit, and how to use it, can look at the unit tests to gain a basic understanding of the unit's interface UT always forces you software parts that can tests easily. While you are writing unit tests for existing code, you will realize that it is not too easy. Your code should be proper in order to isolate out parts of your SUT. By this way, you need to refactor and refine your code so as to write successful unit tests. Unit test covers the basic cases of your software so the next cycle of software testing can include more complex scenarios. For example, checking null parameters can be handled in unit tests so in the next cycle,
  • 6.
  • 7.
    JUnit is asimple framework to write repeatable tests. Asserts Specify the expected output and compare it with the output received Test suites Unit test cases are organized into test suites for better management Rules Extend the functionality of JUnit by adding behaviors to tests Exception testing Tests and verifies whether an exception was thrown Test setup and teardown Sets up test data and tears down that data or context, before and after running the test androidTestCompile ‘junit:junit:4.12’ Integration with build systems Integrates the most popular build systems for Java, including ANT, Maven, Gradle
  • 8.
    Initial Test CaseWith Annotations public class JUnitTestExamples { @Before public void setUp() { //sets up test data, runs before test case }
 @Test public void testAssertEquals() { // test method }
 @After public void tearDown() { //tears down test data, runs after test case } } JUnit annotations @Test @Before
 @After
 @BeforeClass
 @AfterClass
 @Ignore
  • 9.
    Assertions public class AssertTests{ @Test public void testAssertArrayEquals() { byte[] expected = "trial".getBytes(); byte[] actual = "trial".getBytes(); org.junit.Assert.assertArrayEquals("failure - byte arrays not same", expected, actual); } @Test public void testAssertEquals() { org.junit.Assert.assertEquals("failure - strings are not equal", "text", "text"); } @Test public void testAssertFalse() { org.junit.Assert.assertFalse("failure - should be false", true); } @Test public void testAssertNotNull() { org.junit.Assert.assertNotNull("should not be null", new Object()); } } JUnit provides overloaded assertion methods for all primitive types and Objects and arrays (of primitives or Objects).
  • 10.
    Test Suites import org.junit.runner.RunWith; importorg.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ TestFeatureLogin.class, TestFeatureLogout.class, TestFeatureNavigate.class, TestFeatureUpdate.class }) public class FeatureTestSuite { // the class remains empty, // used only as a holder for the above annotations } Using “Suite” as a runner allows you to manually build a suite containing tests from many classes.
  • 11.
    Mockito is amocking framework that tastes really good. It lets you write beautiful tests with clean & simple API. mock() / @Mock creates mock optionally specify how it should behave via Answer/ReturnValues/MockSettings when()/given() to specify how a mock should behave spy() / @Spy partial mocking, real methods are invoked but still can be verified and stubbed verify() checks methods were called with given arguments @InjectMocks automatically inject mocks/spies fields annotated with @Spy or @Mock androidTestCompile ‘org.mockito:mockito-core:1.9.5’
  • 12.
    import static org.mockito.Mockito.*; //mockcreation List mockedList = mock(List.class); //using mock object mockedList.add("one"); mockedList.clear(); //verification verify(mockedList).add("one"); verify(mockedList).clear(); Once created, mock will remember all interactions.Then you can selectively verify whatever interaction you are interested in. mock() public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Mock private UserProvider userProvider; private ArticleManager manager; @Before public void setup() { MockitoAnnotations.initMocks(this); } } @Mock
  • 13.
    List list =new LinkedList(); List spy = spy(list); //optionally, you can stub out some methods: when(spy.size()).thenReturn(100); //using the spy calls real methods spy.add("one"); spy.add("two"); //prints "one" - the first element of a list System.out.println(spy.get(0)); //size() method was stubbed - 100 is printed System.out.println(spy.size()); //optionally, you can verify verify(spy).add("one"); verify(spy).add("two"); spy() @Spy @Spy Foo spyOnFoo = new Foo(); //optionally, you can stub out some methods: when(spy.size()).thenReturn(100); //using the spy calls real methods spy.add("one"); spy.add("two"); //prints "one" - the first element of a list System.out.println(spy.get(0)); //size() method was stubbed - 100 is printed System.out.println(spy.size()); //optionally, you can verify verify(spy).add("one"); verify(spy).add("two");
  • 14.
    
 Running tests istoo slow because JUnit tests need an Android emulator or device java.lang.RuntimeException: Stub! Robolectric lets you run your tests on your workstation, or on your Continuous Integration environment in a regular JVM, without an emulator.
  • 15.
    @RunWith(RobolectricTestRunner.class) public class WelcomeActivityTest{ @Test public void clickingLogin_shouldStartLoginActivity() { WelcomeActivity activity = Robolectric.setupActivity(WelcomeActivity.class); activity.findViewById(R.id.login).performClick(); Intent expectedIntent = new Intent(activity, WelcomeActivity.class); assertThat(shadowOf(activity).getNextStartedActivity()).isEqualTo(expectedIntent); } } Robolectric supports resource handling, e.g., inflation of views. You can also use the findViewById() to search in a view. androidTestCompile ‘org:robolectric:robolectric:2.4’
  • 16.
    Test Coverage JaCoCo isa free code coverage library for Java it supports instruction, branch, line, method and class coverage
  • 17.
    Test Coverage The greenlines represent parts of the code which were fully covered by tests. 
 
 The yellow line means that given branch was not fully covered because its condition never evaluated to true. The red line was never executed by our tests.
  • 18.