unit testing on android - droidcon berlin 2015

18
Unit Testing on Android Buşra Deniz @busradeniz Droidcon Berlin 2015

Upload: busra-deniz-csm

Post on 07-Aug-2015

118 views

Category:

Software


2 download

TRANSCRIPT

Unit Testing

on AndroidBuşra Deniz

@busradeniz

Droidcon Berlin 2015

ABOUT ME

busradeniz

[email protected]

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.AssertsSpecify the expected output and compare it with the output received

Test suitesUnit test cases are organized into test suites for better management

RulesExtend the functionality of JUnit by adding behaviors to tests

Exception testingTests and verifies whether an exception was thrown

Test setup and teardownSets up test data and tears down that data or context, before and after running the test

androidTestCompile ‘junit:junit:4.12’

Integration with build systemsIntegrates the most popular build systems for Java, including ANT, Maven, Gradle

Initial Test Case With Annotations

public class JUnitTestExamples {@Beforepublic 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

Assertionspublic 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() / @Mockcreates mockoptionally specify how it should behave via Answer/ReturnValues/MockSettingswhen()/given() to specify how a mock should behave

spy() / @Spypartial mocking, real methods are invoked but still can be verified and stubbed

verify()checks methods were called with given arguments

@InjectMocksautomatically 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 CoverageJaCoCo 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