SlideShare a Scribd company logo
1 of 161
Download to read offline
introduction to android
        testing
       a hands-on approach
                 OSCON 2012



   Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                     1
diego torres milano
    android system engineer
           flextronics

http://dtmilano.blogspot.com



  Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                    2
“Never test the depth of
the water with both feet.”
                                                           -- Anonymous



     Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          3
agenda

android testing background

test driven development

code coverage

continuous integration

behavior driven development


    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      4
operating systems
                                                       May 2012
                  Others
                                          iOS
                                         250M




                  Android
                   400M




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  5
android testing
    background



Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  6
WhatWhy
When
  how
                                                   ?
 Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                   7
types of test
                              tests


unit
                                                              functional


performance
                                   integration


       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           8
types of test
                         by programmers for programmers
unit
                         in a programming language

                         JUnit is the de-facto standard

                         test objects in isolation

                         in a repeatable way

                         usually rely on mock objects



       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         9
types of test
                              tests


unit
                                                              functional


performance
                                   integration


       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           10
types of test
by business & QA people                                     functional
in a business domain language

test completeness & correctness

BDD has gained some popularity

FitNesse can help




        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          11
types of test
                              tests


unit
                                                              functional


performance
                                   integration


       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           12
types of test
how components work together                               integration
modules have been unit tested

android components need integration
with the system

testing framework facilitates
integration




        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          13
types of test
                              tests


unit
                                                              functional


performance
                                   integration


       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           14
types of test
                         measure performance in a
performance              repeatable way

                         if cannot be measure cannot be
                         improved

                         premature optimization does more
                         harm than good

                         measure-change-measure



       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         15
types of test
                              tests


unit
                                                              functional


performance
                                   integration


       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           16
class diagram
                                                                             Assert
     <<iface>>
                                    TestCase
        Test



  InstrumentationTestCase                               AndroidTestCase


                          ActivityInstrumentationTestCase2

ActivityUnitTestCase

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                      17
InstrumentationTestCase
                                             instrumentation instantiated
                                             before application

                                             allows for monitoring
                                             interaction

                                             send keys and input events

                                             manual lifecycle

                                             direct or indirect base
                                             class of other tests


           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             18
class diagram
                                                                             Assert
     <<iface>>
                                    TestCase
        Test



  InstrumentationTestCase                               AndroidTestCase


                          ActivityInstrumentationTestCase2

ActivityUnitTestCase

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                      19
ActivityUnitTestCase
                                            isolated testing of single
                                            Activity

                                            minimal connection to
                                            the system

                                            uses mocks for
                                            dependencies

                                            some Activity methods
                                            should not be called



          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            20
class diagram
                                                                             Assert
     <<iface>>
                                    TestCase
        Test



  InstrumentationTestCase                               AndroidTestCase


                          ActivityInstrumentationTestCase2

ActivityUnitTestCase

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                      21
ActivityInstrumentationTestCase2
functional
testing of a single Activity

has access to Instrumentation

creates the AUT using system
infrastructure

custom intent can be provided



       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         22
class diagram
                                                                             Assert
     <<iface>>
                                    TestCase
        Test



  InstrumentationTestCase                               AndroidTestCase


                          ActivityInstrumentationTestCase2

ActivityUnitTestCase

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                      23
access to Context                                    AndroidTestCase

access to Resources

base class for Application, Provider
and Service test cases

Context stored in mContext field

can start more than one Activity




       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         24
class diagram
                                                                             Assert
     <<iface>>
                                    TestCase
        Test



  InstrumentationTestCase                               AndroidTestCase


                          ActivityInstrumentationTestCase2

ActivityUnitTestCase

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                      25
test driven development



   Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                     26
test driven development                                         advantages:

                                                                •the tests are written
                                                                one way or another

                                                                •developers take more
                                                                responsibility for the
                                                                quality of their work




 strategy of writing tests along development

 test cases written prior to the code

 single test added, then the code to satisfy it




     Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                         27
activity diagram
                                                                    design decisions are
                                                                    taken in single steps
                                                                    and finally the code
      write test                                                    satisfying the tests is
                                                                    improved by
                                                                    refactoring it



             run
                    [fails]
                                     code
[passes]


                                 refactor



  Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                              28
temperature converter
                        Title
 celsius
                                                100
                                                                      autoupdate
                                                    32
fahrenheit


                             keyboard



           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                   29
requirements

        converts between temperature
        units

        one temperature is entered and
        the other is updated

        error is displayed in the field

        right aligned, 2 decimal digits

        entry fields start empty


Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  30
understanding
        requirements

to write a test you must understand the
requirement

destination is quickly identified

if requirement change, changing the
corresponding test helps verify it



    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      31
github


$ mkdir myworkdir
$ cd myworkdir
$ git clone git://github.com/dtmilano/I2AT-
  OSCON-2012.git



      Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                        32
creating the
 main project
TemperatureConverter uses
   conventional settings




           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             33
select build
     target
TemperatureConverter uses
      Android 4.0.3




           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             34
creating the test
     project
Automatically selected values
for TemperatureConverterTest
           project




           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             35
running the tests

[13:21:28 - TemperatureConverterTest]
Launching instrumentation
android.test.InstrumentationTestRunner on
device XXX
[13:21:28 - TemperatureConverterlTest-local]
Failed to launch test


        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          36
warning due to the
                                                                     parameterized base class




creating the test
       case
               Use:
ActivityInstrumentationTestCase2
        as the base class
TemperatureConverterActivity as
       the class under test




            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                                37
creating test
    stubs
Select: onCreate(Bundle) to
   create a method stub




          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            38
fix constructor
/**
  * Constructor
  * @param name
  */
public TemperatureConverterActivityTests(String name) {
     super(TemperatureConverterActivity.class);
     setName(name);
}




           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             39
running the tests

junit.framework.AssertionFailedError:
   Not yet implemented at
        com.dtmilano.i2at.tc.test.
           TemperatureConverterActivityTests.
              testOnCreateBundle(
   TemperatureConverterActivityTests.java:50)



          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            40
fixture
protected void setUp(String name) throws Exception {
   super.setUp();

    mActivity = getActivity();                     references the
    assertNotNull(mActivity);                       main package



    mCelsius = (EditText)mActivity.findViewById(
       com.dtmilano.i2at.tc.R.id.celsius);
    assertNotNull(mCelsius);
    mFahrenheit = (EditText)mActivity.findViewById(com...);
    assertNotNull(mFahrenheit);
}
              Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                41
layout
satisfy the test needs
  assign celsius and
     fahrenheit ids




            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                              42
fix the test
! /**
! * Test method for {@link TemperatureConverterActivity
       #onCreate(android.os.Bundle)}.
! */
! public void testOnCreateBundle() {
! ! assertNotNull(mActivity);
! }




             Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                               43
ui tests: visibility

@SmallTest
public void testFieldsOnScreen() {
   final View origin =
           mActivity.getWindow().getDecorView();
   ViewAsserts.assertOnScreen(origin, mCelsius);
   ViewAsserts.assertOnScreen(origin, mFahrenheit);
}



         Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           44
annotations
                                         @SmallTest

                                         @MediumTest

                                         @LargeTest

                                         @UiThreadTest

                                         @Suppress

                                         @FlakyTest


Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  45
ui tests: alignment

@SmallTest
public void testAlignment() {
! ! ViewAsserts.assertRightAligned(mCelsius,
            mFahrenheit);
! ! ViewAsserts.assertLeftAligned(mCelsius,
            mFahrenheit);
}

        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          46
ui tests: initialization

@SmallTest
public void testFieldsShouldStartEmpty() {
! ! assertTrue("".equals(mCelsius.getText()
            .toString()));
! ! assertTrue("".equals(mFahrenheit.getText()
            .toString()));
}

         Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           47
ui tests: justification
@SmallTest
public void testJustification() {
! ! final int expected =
       Gravity.RIGHT|Gravity.CENTER_VERTICAL;
! ! assertEquals(expected,
            mCelsius.getGravity());
! ! assertEquals(expected,
            mFahrenheit.getGravity());
}
         Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           48
running the tests
                                                       video plays on
                                                       click >>>




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                        49
gravity
 add right and
center_vertical
   gravity for
     celsius
 and fahrenheit


     Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                       50
running the tests
                                                         video plays on
                                                         click >>>




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          51
temperature conversion   run on the
!   @UiThreadTest             main thread
!   public void testFahrenheitToCelsiusConversion() {
                              specialized
!   ! mCelsius.clear();          class
!   ! mFahrenheit.clear();                  errors are
                                            underlined in red
!   ! final double f = 32.5;
!   ! mFahrenheit.requestFocus();
!   ! mFahrenheit.setNumber(f);
                                                              converter
!   ! mCelsius.requestFocus();                                 helper
!   ! final double expected =
              TemperatureConverter.fahrenheitToCelsius(f);
!   ! final double actual = mCelsius.getNumber();
!   ! final double delta = Math.abs(expected - actual);
!   ! assertTrue(delta < 0.005);
!   }
               Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                 52
EditNumber class
  EditNumber class
  extends EditText




        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          53
TemperatureCon
    verter
TemperatureConverter
  is a helper class




        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          54
refactor
public class TemperatureConverterActivityTests
  extends ActivityInstrumentationTestCase2<
       TemperatureConverterActivity> {

   private TemperatureConverterActivity
        mActivity;    new class
   private EditNumber mCelsius;
   private EditNumber mFahrenheit;

          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            55
temperature conversion
!   @UiThreadTest
!   public void testFahrenheitToCelsiusConversion() {
!   ! mCelsius.clear();
!   ! mFahrenheit.clear();    all compiler errors
!   ! final double f = 32.5;         corrected
!   ! mFahrenheit.requestFocus();
!   ! mFahrenheit.setNumber(f);
!   ! mCelsius.requestFocus();
!   ! final double expected =
              TemperatureConverter.fahrenheitToCelsius(f);
!   ! final double actual = mCelsius.getNumber();
!   ! final double delta = Math.abs(expected - actual);
!   ! assertTrue(delta < 0.005);
!   }
             Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                               56
OMG!


[TemperatureConverterTests-OSCON-2012] Test
run failed: Instrumentation run failed due to
'Process crashed.'
[TemperatureConverterTests-OSCON-2012] Test
run finished



         Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           57
exception in logcat
java.lang.ClassCastException:
   android.widget.EditText at
       com.dtmilano.i2at.tc.test.
       TemperatureConverterActivityTests.setUp
       (TemperatureConverterActivityTests.java: 52)

52:!! mCelsius = (EditNumber)
          mActivity.findViewById(
              com.dtmilano.i2at.tc.R.id.celsius);
          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            58
change widget
    type
          Select
com.dtmilano.i2at.tc.EditNum
            ber




            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                              59
layout
<com.dtmilano.i2at.tc.EditNumber
    android:layout_height="wrap_content"
! ! android:layout_width="match_parent"
    android:inputType="numberDecimal"
! ! android:id="@+id/celsius"
    android:gravity="right|center_vertical">
! ! <requestFocus />
</com.dtmilano.i2at.tc.EditNumber>

        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          60
running the tests

              what?




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  61
celsius to fahrenheit
                              Fahrenheit


 150

112.5

  75
                     f = 9/5 * c + 32
 37.5

   0
                     c = (f-32) * 5/9
-37.5

 -75
        -40 -30    -20    -10      0      10     20     30     40
                              Celsius

   Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                     62
converter

public class TemperatureConverter {

! public static double fahrenheitToCelsius(double f) {
	   / TODO Auto-generated method stub
    	/
! ! return 0;
! }

}


           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             63
TemperatureConv
   erterTests
   Test case as base class
    create method stubs
  TemperatureConverter as
            CUT




          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            64
method stubs
select the methods you want
      stubs created for




          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            65
conversion test

public final void testFahrenheitToCelsius() {
! ! for (double c: sConversionTableDouble.keySet()) {
! ! ! final double f = sConversionTableDouble.get(c);
! ! ! final double ca =
          TemperatureConverter.fahrenheitToCelsius(f);
! ! ! final double delta = Math.abs(ca - c);
! ! ! assertTrue(delta < 0.005);
! ! }
! }

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             66
conversion table
private static final HashMap<Double, Double>
         sConversionTableDouble =
! ! !          new HashMap<Double, Double>();
!
static {
! ! sConversionTableDouble.put(0.0, 32.0);
! ! sConversionTableDouble.put(100.0, 212.0);
! ! sConversionTableDouble.put(-1.0, 30.20);
! ! sConversionTableDouble.put(-100.0, -148.0);
! ! sConversionTableDouble.put(32.0, 89.60);
! ! sConversionTableDouble.put(-40.0, -40.0);
! ! sConversionTableDouble.put(-273.0, -459.40);
}
       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         67
add f -> c conversion

public class TemperatureConverter {

! public static double fahrenheitToCelsius(double f) {
! ! return (f-32) * 5/9.0;
! }

}



            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                              68
run the tests




                                                     this assertion
                                                          fails


Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      69
creating test
      case
use AndroidTestCase as base
           class
  use EditNumber as CUT




          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            70
method stubs
select the constructors
 select other methods




        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          71
fixture

/* (non-Javadoc)
 * @see android.test.AndroidTestCase#setUp()
 */
protected void setUp() throws Exception {
    super.setUp();

    mEditNumber = new EditNumber(getContext());

}

        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          72
test

public final void testClear() {
! ! final String value = "123.45";
! ! mEditNumber.setText(value);
! ! mEditNumber.clear();
! ! final String expected = "";
! ! final String actual =
           mEditNumber.getText().toString();
! ! assertEquals(expected, actual);
}

      Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                        73
implementation
public class EditNumber extends EditText {

    / ...
     /

! public void clear() {
! !   setText(null);
! }

}


    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      74
test set number
public final void testSetNumber() {
       final double expected = 123.45;
       mEditNumber.setNumber(expected);
       final double actual =
           mEditNumber.getNumber();
       assertEquals(expected, actual);
}




      Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                        75
set number
public class EditNumber extends EditText {

   / ...
    /

   public void setNumber(double f) {
      setText(Double.toString(f));
   }




       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         76
test get number
public final void testGetNumber() {
! ! final double expected = 123.45;
! ! mEditNumber.setNumber(expected);
! ! final double actual =
           mEditNumber.getNumber();
! ! assertEquals(expected, actual);
}




   Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                     77
get number
public class EditNumber extends EditText {

    / ...
     /

!   public void getNumber() {
       final String s = getText().toString();
       if ( "".equals(s) ) {
            return Double.NaN;
       }
! !     return Double.valueOf(s);
! }
}
       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         78
run the tests


               testFahrenheitToCelsiusConversion
                         is still failing




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  79
what’s the problem ?
clear() works

requestFocus() works

setNumber() works

fahrenheitToCelsius() works

getNumber() works

so ?



       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         80
temperature converter
                        Title
 celsius
                                                100
                                                                      autoupdate
                                                    32
fahrenheit


                             keyboard



           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                   81
TemperatureChan
   geWatcher
 create it as an inner class
 check abstract
 implements TextWatcher
 inherited abstract methods
 create 2 EditNumber fields
 mSource & mDest


           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             82
generate
   constructor
use the fields
public access
omit call to super()




           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             83
the watcher
public abstract class TemperatureChangeWatcher
           implements TextWatcher {
! ! private EditNumber mSource;
! ! private EditNumber mDest;
! !
! ! public TemperatureChangeWatcher(
           EditNumber source, EditNumber dest) {
! ! ! this.mSource = source;
! ! ! this.mDest = dest;
! ! }
    / ...
     /
}
           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             84
on text changed
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
! if ( !mDest.hasWindowFocus() || mDest.hasFocus() || s == null ) return;
! final String str = s.toString();
! if ( "".equals(str) ) {
! ! mDest.setText(""); return;     we should define
! }                                        it
! try {
! ! final double result = convert(Double.parseDouble(str));
! ! mDest.setNumber(result);
! }
! catch (NumberFormatException e) {
! ! / WARNING: this is thrown while a number is entered, for example just a '-'
        /
! }
! catch (Exception e) {
! ! mSource.setError("ERROR: " + e.getLocalizedMessage());
! }
}
                 Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                   85
abstract convert method
public abstract class TemperatureChangeWatcher
       implements TextWatcher {
  //...

    protected abstract double convert(double temp);

    //...
}

             Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                               86
find views
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(
           R.layout.activity_temperature_converter);

    mCelsius =
          (EditNumber) findViewById(R.id.celsius);
    mFahrenheit =
          (EditNumber) findViewById(R.id.fahrenheit);
}
           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             87
add change listeners
@Override
public void onCreate(Bundle savedInstanceState) {
   / ...
    /
   mCelsius.addTextChangedListener(
                                                            we should create
           new TemperatureChangeWatcher(mCelsius, mFahrenheit) {
                                                                    it
! ! !          @Override protected double convert(double temp) {
! ! ! !           return TemperatureConverter.celsiusToFahrenheit(temp);
! ! !          }!
           });
   mFahrenheit.addTextChangedListener(
           new TemperatureChangeWatcher(mFahrenheit, mCelsius) {
! ! !          @Override protected double convert(double temp) {
! ! ! !           return TemperatureConverter.fahrenheitToCelsius(temp);
! ! !          }
           });
}

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                               88
add conversion
public class TemperatureConverter {

! public static double fahrenheitToCelsius(double f) {
! ! return (f-32) * 5/9.0;
! }

!   public static double celsiusToFahrenheit(double c) {
!   ! / TODO Auto-generated method stub
       /
!   ! return 0;
!   }
}

              Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                89
adding test
public class TemperatureConverterTests extends TestCase {
   / ...
    /
! /**
! * Test method for {@link TemperatureConverter#fahrenheitToCelsius(double)}.
! */
! public final void testCelsiusToFahrenheit() {
! ! for (double c: sConversionTableDouble.keySet()) {
! ! ! final double f = sConversionTableDouble.get(c);
! ! ! final double fa = TemperatureConverter.celsiusToFahrenheit(c);
! ! ! final double delta = Math.abs(fa - f);
! ! ! assertTrue("delta=" + delta + " for f=" + f + " fa=" + fa, delta < 0.005);
! ! }
! }
}


                  Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                    90
running the tests




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  91
implementing conversion
public class TemperatureConverter {

! public static double fahrenheitToCelsius(double f) {
! ! return (f-32) * 5/9.0;
! }

! public static double celsiusToFahrenheit(double c) {
! ! return 9/5.0 * c + 32;
! }
}


            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                              92
running the tests




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  93
test xml attributes
public final void testSetDecimalPlacesAttributeFromXml() {
   LayoutInflater inflater = (LayoutInflater)getContext()
        .getSystemService(
            Context.LAYOUT_INFLATER_SERVICE);
   View root = inflater.inflate(
       com.dtmilano.i2at.tc.R.layout.activity..., null);
   EditNumber editNumber = (EditNumber)
       root.findViewById(com.dtmilano.i2at.tc.R.id.celsius);
   assertNotNull(editNumber);
   / i2at:decimalPlaces="2" is set in main.xml
    /
   assertEquals(2, editNumber.getDecimalPlaces());
}
             Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                               94
decimal places
public void setNumber(double d) {
   final String str =
       String.format("%." + mDecimalPlaces + "f", d);
   setText(str);
}

public void setDecimalPlaces(int places) {
   mDecimalPlaces = places;
}

public int getDecimalPlaces() {
   return mDecimalPlaces;
}
         Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                           95
define attributes

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <declare-styleable name="i2at">
      <attr name="decimalPlaces" format="integer" />
   </declare-styleable>

</resources>



               Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                 96
add attributes
   xmlns:i2at="http:/ /schemas.android.com/apk/res/
com.dtmilano.i2at.tc"

   <com.dtmilano.i2at.tc.EditNumber
      android:id="@+id/celsius"
      i2at:decimalPlaces="2"
      android:ems="10"
      ... >
      <requestFocus />
   </com.dtmilano.i2at.tc.EditNumber>
            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                              97
init using attributes
public EditNumber(Context context, AttributeSet attrs) {
   super(context, attrs);
   init(context, attrs, -1);
}

private void init(Context context, AttributeSet attrs, int defStyle) {
    final TypedArray a =
        context.obtainStyledAttributes(attrs, R.styleable.i2at);
    setDecimalPlaces(a.getInteger(
         R.styleable.i2at_decimalPlaces, DEFAULT_DECIMAL_PLACES));
    a.recycle();
}


                Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                  98
know decimal places

protected void setUp() throws Exception {
   super.setUp();

    mEditNumber =
      new EditNumber(getContext());
    mEditNumber.setDecimalPlaces(2);
}

        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          99
test signed number
@SmallTest
public void testFahrenheitToCelsiusConversion_input() throws Throwable {
   runTestOnUiThread(new Runnable() {
       @Override
       public void run() { mCelsius.clear(); mFahrenheit.clear(); }
   });
   final String c = "-123.4";
   getInstrumentation().sendStringSync(c);
   assertEquals(c, mCelsius.getText().toString());
   final double expected =
       TemperatureConverter.celsiusToFahrenheit(Double.parseDouble(c));
   final double actual = mFahrenheit.getNumber();
   final double delta = Math.abs(expected - actual);
   assertTrue(delta < 0.005);
}
                Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                  100
add attributes
<com.dtmilano.i2at.tc.EditNumber
   android:id="@+id/celsius"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   i2at:decimalPlaces="2"
   android:ems="10"
   android:gravity="center_vertical|right"
   android:inputType="numberSigned|numberDecimal" >
   <requestFocus />
</com.dtmilano.i2at.tc.EditNumber>

           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             101
running the tests




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  102
code coverage



Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  103
code coverage
measures the amount of source code tested

android relies on emma (http://emma.sf.net)

supported coverage types:
  class

  method

  line

  block

    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      104
coverage report


overall coverage summary

overall stats summary

coverage breakdown by package




    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      105
building with ant
disable project’s Build Automatically in Eclipse

convert project to ant

$ android update project --path $PWD 
   --name TemperatureConverter-OSCON-2012 
   --target android-15 --subprojects

$ android update test-project 
   --main $PWD 
   --path $PWD/tests

        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          106
run
 configuration
run build.xml as Ant build...                                    clean, emma,
use emma transient target                                        debug, install,
                                                                     test




            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                   107
ant 1.8
specify ant 1.8 home

                                                  Ant home...




        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          108
coverage
run build.xml

coverage analysis report is generated

is currently only supported on the emulator
and rooted devices

get coverage file

$ adb pull /data/data/com.example.i2at.tc/files/
coverage.ec coverage.ec

      Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                        109
on some user devs
                                         Give the app
                                         WRITE_EXTERNAL_S
                                         TORAGE permission

                                         Add emma.dump.file
                                         build property

                                         Use an external
                                         storage location (i.e.
                                         sdcard)


Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  110
coverage report




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  111
coverage breakdown
                                               method
           name                         class%        block%                  line%
                                                 %

   TemperatureConverter                 100%            67%            82%    67%

TemperatureConverterActivity            100%           100%            91%    93%

        EditNumber                      100%           100%            98%    96%



            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                      112
constructor not covered




   Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                     113
private constructor
public class TemperatureConverter {
! private TemperatureConverter() {
! ! / do nothing
      /
! }
! public static double fahrenheitToCelsius(double f) {
! ! return (f-32) * 5/9.0;
! }
! public static double celsiusToFahrenheit(double c) {
! ! return 9/5.0 * c + 32;
! }
}
            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                              114
access private
                constructor
public final void testPrivateConstructor() throws Exception {
! Constructor<TemperatureConverter> ctor =
                               circumvent
      TemperatureConverter.class.getDeclaredConstructor();
                               restriction
! ctor.setAccessible(true);
! TemperatureConverter tc =
      ctor.newInstance((Object[])null);
! assertNotNull(tc);
}



           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             115
returning NaN




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  116
missing tests
public final void testGetNumber_emptyText() {
   mEditNumber.setText("");
   final double actual = mEditNumber.getNumber();
   assertEquals(Double.NaN, actual);
}

public final void testGetNumber_nullText() {
   mEditNumber.setText(null);
   final double actual = mEditNumber.getNumber();
   assertEquals(Double.NaN, actual);
}

       Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                         117
finished
 application
this is the final result




        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          118
requirements

        converts between temperature
        units

        one temperature is entered and
        the other is updated

        error is displayed in the field

        right aligned, 2 decimal digits

        entry fields start empty


Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  119
running tests



Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  120
alternatives


eclipse
command line
android application


   Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                     121
run configurations
Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  122
am instrument
                           Waits until the
  -w                 instrumentation terminates
                      before terminating itself

                         Outputs results in raw
   -r
                                format

-e <key>             Provides testing options as
 <value>                   key-value pairs

  Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                    123
command line
all tests:
$ adb shell am instrument -w 
     com.dtmilano.i2at.tc.test/
     android.test.InstrumentationTestRunner

functional tests:
$ adb shell am instrument -w 
    -e func true 
    com.dtmilano.i2at.tc.test/
    android.test.InstrumentationTestRunner
        Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                          124
Activity
public class TemperatureConverterTestsActivity
     extends Activity {

! private static final String TAG =
     "TemperatureConverterTestsActivity";

! private static final int TIMEOUT = 15000;
!
! private TextView mResults;
! private LogcatAsyncTask mLogcat;
...
          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            125
lifecycle methods
@Override
protected void onCreate(Bundle savedInstanceState) {
! ! super.onCreate(savedInstanceState);
! ! setContentView(R.layout.main);
! ! mResults = (TextView) findViewById(R.id.results);
}
@Override
protected void onDestroy() {
! ! super.onDestroy();
! ! if (mLogcat != null) { mLogcat.cancel(true); }
}
          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            126
getInstrumentationInfo

private InstrumentationInfo
getInstrumentationInfo(final String packageName) {
! ! final List<InstrumentationInfo> list =
          getPackageManager()
! ! ! ! .queryInstrumentation(packageName, 0);
! ! return (!list.isEmpty()) ? list.get(0) : null;
}



           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             127
run tests
public void runTests(View v) {
   final String pn = getPackageName().replaceFirst(".test$", "");
   final InstrumentationInfo info = getInstrumentationInfo(pn);
   if (info != null) {
!      final ComponentName cn = new ComponentName(info.packageName,
! !        ! info.name);
!       if (startInstrumentation(cn, null, null)) {
!      !      mLogcat = new LogcatAsyncTask();
! !           mLogcat.execute(TIMEOUT);
!       }
   } else {
!      Toast.makeText(this,
! ! !         "Cannot find instrumentation for " + pn, Toast.LENGTH_SHORT)
              .show();
! }
}
               Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                 128
task to read logcat
private class LogcatAsyncTask extends AsyncTask<Integer, String, Void> {
! / TestRunner and silence others
    /
! private static final String CMD = "logcat -v time TestRunner:I *:S";
! private BufferedReader mReader;
! private Process mProc;

!   public LogcatAsyncTask() {
!   ! try {
!   ! ! mProc = Runtime.getRuntime().exec(CMD);
!   ! ! mReader = new BufferedReader(new InputStreamReader(
!   ! ! ! ! mProc.getInputStream()));
!   ! } catch (Exception e) {
!   ! ! Log.e(TAG, "Creating proc", e);
!   ! }
!   }


            Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                              129
progress update

@Override
protected void onProgressUpdate(String... values)
{
! ! if (!TextUtils.isEmpty(values[0])) {
! ! ! mResults.append("n" + values[0]);
! ! }
}

          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            130
@Override
                do in background
protected Void doInBackground(Integer... params) {
! ! final long timeout = System.currentTimeMillis() + params[0];
! ! try {
! ! ! do {
! ! ! ! Thread.sleep(50); publishProgress(mReader.readLine());
! ! ! } while (System.currentTimeMillis() < timeout);
! ! } catch (Exception e) {
! ! ! publishProgress("ERROR: " + e);
! ! } finally {
! ! ! publishProgress("END"); mProc.destroy();
! ! }
! ! return null;
! }
}             Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                131
in action
Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  132
continuous integration



  Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                    133
continuous integration


agile technique for software engineering

received broad adoption in recent years

prevents “integration hell”

integrate changes frequently



    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      134
requirements


version control system

automated build

self tested

artifacts and tests results easy to find



    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      135
installation



download war from http://jenkins-ci.org

$ java -jar jenkins.war




     Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                       136
jenkins home




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  137
android plugin




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  138
new job




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  139
ant properties




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  140
build artifacts




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  141
build dependency




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  142
android emulator




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  143
invoke ant




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  144
test project


Create test project

Set repository URL

Trigger build after main project

Build with ant



    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      145
xml test results

download xmlinstrumentationtestrunner.jar

replace instrumentation by
android:name="com.neenbedankt.android.test.
XMLInstrumentationTestRunner"

customize project configuration



    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      146
junit test result




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  147
build step

PKG=com.dtmilano.i2at.tc
OUTDIR=/mnt/sdcard/Android/data/$PKG/files/
OUTFILE=test-results.xml
ADB=/opt/android-sdk/platform-tools/adb

$ADB pull "$OUTDIR/$OUTFILE" "$WORKSPACE/
TemperatureConverter-OSCON-2012/tests/bin/
$OUTFILE"


          Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                            148
test report




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  149
coverage trend


Enable record emma coverage

Specify emma XML report files

Change health reporting

Modify build.xml to support XML reports



    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      150
code coverage




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  151
line coverage




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  152
behavior driven
   development



Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  153
behavior driven
       development

evolution of Test Driven Development

inclusion of business participant

common vocabulary

based on Neuro Linguistics Programming



    Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                      154
fitnesse




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  155
test suite




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  156
slim test fixture
package com.example.i2at.tc.test.fitnesse.fixture;
import com.example.i2at.tc.TemperatureConverter;

public class TemperatureConverterCelsiusToFahrenheitFixture {
! private double celsius;

!   public void setCelsius(double celsius) {
!   ! this.celsius = celsius;
!   }

!   public String fahrenheit() throws Exception {
!   ! try {
!   ! ! return String.valueOf(TemperatureConverter.celsiusToFahrenheit(celsius));
!   ! } catch (RuntimeException e) {
!   ! ! return e.getLocalizedMessage();
!   ! }
!   }
}
                  Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                                    157
test run




Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  158
questions ?



Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  159
android application
          testing guide
  Apply testing techniques and tools
• Learn the nuances of Unit and
  Functional testing
• Understand different development
  methodologies such as TDD and BDD
• Apply Continuous Integration
• Improve applications using
  performance tests
• Expose your application to a wide
  range of conditions




           Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                             160
thank you



Copyright (C) 2011-2012 Diego Torres Milano All rights reserved
                                                                  161

More Related Content

Viewers also liked

Android Building, Testing and reversing
Android Building, Testing and reversingAndroid Building, Testing and reversing
Android Building, Testing and reversingEnrique López Mañas
 
Android Testing, Why So Hard?!
Android Testing, Why So Hard?!Android Testing, Why So Hard?!
Android Testing, Why So Hard?!Annyce Davis
 
Testing Android
Testing AndroidTesting Android
Testing AndroidMarc Chung
 
Unit testing in android
Unit testing in androidUnit testing in android
Unit testing in androidLi-Wei Cheng
 
Unit testing on Android (Droidcon Dubai 2015)
Unit testing on Android (Droidcon Dubai 2015)Unit testing on Android (Droidcon Dubai 2015)
Unit testing on Android (Droidcon Dubai 2015)Danny Preussler
 
Unit testing and Android
Unit testing and AndroidUnit testing and Android
Unit testing and AndroidTomáš Kypta
 
Mobile Performance Testing - Best Practices
Mobile Performance Testing - Best PracticesMobile Performance Testing - Best Practices
Mobile Performance Testing - Best PracticesEran Kinsbrunner
 
Rapid Android Application Security Testing
Rapid Android Application Security TestingRapid Android Application Security Testing
Rapid Android Application Security TestingNutan Kumar Panda
 
Oh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to MutationOh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to MutationPaul Blundell
 
How ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second EditionHow ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second Editionpenanochizzo
 
Performance Testing for Mobile Apps & Sites using Apache JMeter
Performance Testing for Mobile Apps & Sites using Apache JMeterPerformance Testing for Mobile Apps & Sites using Apache JMeter
Performance Testing for Mobile Apps & Sites using Apache JMeterAlon Girmonsky
 
Android testing
Android testingAndroid testing
Android testingJinaTm
 
Android testing
Android testingAndroid testing
Android testingBitbar
 
Android & iPhone App Testing
 Android & iPhone App Testing Android & iPhone App Testing
Android & iPhone App TestingSWAAM Tech
 
Android Automation Testing with Selendroid
Android Automation Testing with SelendroidAndroid Automation Testing with Selendroid
Android Automation Testing with SelendroidVikas Thange
 
Android Unit Tesing at I/O rewind 2015
Android Unit Tesing at I/O rewind 2015Android Unit Tesing at I/O rewind 2015
Android Unit Tesing at I/O rewind 2015Somkiat Puisungnoen
 

Viewers also liked (20)

Android Building, Testing and reversing
Android Building, Testing and reversingAndroid Building, Testing and reversing
Android Building, Testing and reversing
 
Android Testing, Why So Hard?!
Android Testing, Why So Hard?!Android Testing, Why So Hard?!
Android Testing, Why So Hard?!
 
Testing Android
Testing AndroidTesting Android
Testing Android
 
Android testing
Android testingAndroid testing
Android testing
 
Testing With Open Source
Testing With Open SourceTesting With Open Source
Testing With Open Source
 
Unit testing in android
Unit testing in androidUnit testing in android
Unit testing in android
 
Unit testing on Android (Droidcon Dubai 2015)
Unit testing on Android (Droidcon Dubai 2015)Unit testing on Android (Droidcon Dubai 2015)
Unit testing on Android (Droidcon Dubai 2015)
 
Unit testing and Android
Unit testing and AndroidUnit testing and Android
Unit testing and Android
 
Mobile Performance Testing - Best Practices
Mobile Performance Testing - Best PracticesMobile Performance Testing - Best Practices
Mobile Performance Testing - Best Practices
 
Rapid Android Application Security Testing
Rapid Android Application Security TestingRapid Android Application Security Testing
Rapid Android Application Security Testing
 
Oh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to MutationOh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to Mutation
 
Testing on Android
Testing on AndroidTesting on Android
Testing on Android
 
How ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second EditionHow ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second Edition
 
Performance Testing for Mobile Apps & Sites using Apache JMeter
Performance Testing for Mobile Apps & Sites using Apache JMeterPerformance Testing for Mobile Apps & Sites using Apache JMeter
Performance Testing for Mobile Apps & Sites using Apache JMeter
 
Introduction to android testing
Introduction to android testingIntroduction to android testing
Introduction to android testing
 
Android testing
Android testingAndroid testing
Android testing
 
Android testing
Android testingAndroid testing
Android testing
 
Android & iPhone App Testing
 Android & iPhone App Testing Android & iPhone App Testing
Android & iPhone App Testing
 
Android Automation Testing with Selendroid
Android Automation Testing with SelendroidAndroid Automation Testing with Selendroid
Android Automation Testing with Selendroid
 
Android Unit Tesing at I/O rewind 2015
Android Unit Tesing at I/O rewind 2015Android Unit Tesing at I/O rewind 2015
Android Unit Tesing at I/O rewind 2015
 

Similar to Android Testing Hands-On Approach

Cross Platform Game Development with GDAP, December 2012
Cross Platform Game Development with GDAP, December 2012Cross Platform Game Development with GDAP, December 2012
Cross Platform Game Development with GDAP, December 2012jobandesther
 
Structured development in BMC Remedy AR System
Structured development in BMC Remedy AR SystemStructured development in BMC Remedy AR System
Structured development in BMC Remedy AR Systemgramlin42
 
Using design pattern for mobile
Using design pattern for mobileUsing design pattern for mobile
Using design pattern for mobileluca mezzalira
 
Quality Best Practices & Toolkit for Enterprise Flex
Quality Best Practices & Toolkit for Enterprise FlexQuality Best Practices & Toolkit for Enterprise Flex
Quality Best Practices & Toolkit for Enterprise FlexFrançois Le Droff
 
UX Concerns across Mobile Platforms
UX Concerns across Mobile PlatformsUX Concerns across Mobile Platforms
UX Concerns across Mobile PlatformsJoseph Labrecque
 
Android for Enterprise - Teleca @ Droidcon Berlin 2011
Android for Enterprise - Teleca @ Droidcon Berlin 2011Android for Enterprise - Teleca @ Droidcon Berlin 2011
Android for Enterprise - Teleca @ Droidcon Berlin 2011Peter Decker
 
Aras and T-Systems: Supplier Management
Aras and T-Systems: Supplier ManagementAras and T-Systems: Supplier Management
Aras and T-Systems: Supplier ManagementAras
 
Fatc - Productivity by Design
Fatc - Productivity by DesignFatc - Productivity by Design
Fatc - Productivity by DesignMichael Chaize
 
Tdd in android (mvp)
Tdd in android (mvp)Tdd in android (mvp)
Tdd in android (mvp)Prateek Jain
 

Similar to Android Testing Hands-On Approach (12)

Cross Platform Game Development with GDAP, December 2012
Cross Platform Game Development with GDAP, December 2012Cross Platform Game Development with GDAP, December 2012
Cross Platform Game Development with GDAP, December 2012
 
Structured development in BMC Remedy AR System
Structured development in BMC Remedy AR SystemStructured development in BMC Remedy AR System
Structured development in BMC Remedy AR System
 
Sikuli
SikuliSikuli
Sikuli
 
Using design pattern for mobile
Using design pattern for mobileUsing design pattern for mobile
Using design pattern for mobile
 
Quality Best Practices & Toolkit for Enterprise Flex
Quality Best Practices & Toolkit for Enterprise FlexQuality Best Practices & Toolkit for Enterprise Flex
Quality Best Practices & Toolkit for Enterprise Flex
 
UX Concerns across Mobile Platforms
UX Concerns across Mobile PlatformsUX Concerns across Mobile Platforms
UX Concerns across Mobile Platforms
 
Android for Enterprise - Teleca @ Droidcon Berlin 2011
Android for Enterprise - Teleca @ Droidcon Berlin 2011Android for Enterprise - Teleca @ Droidcon Berlin 2011
Android for Enterprise - Teleca @ Droidcon Berlin 2011
 
Aras and T-Systems: Supplier Management
Aras and T-Systems: Supplier ManagementAras and T-Systems: Supplier Management
Aras and T-Systems: Supplier Management
 
Fatc - Productivity by Design
Fatc - Productivity by DesignFatc - Productivity by Design
Fatc - Productivity by Design
 
The Promise of Interoperability
The Promise of InteroperabilityThe Promise of Interoperability
The Promise of Interoperability
 
Business Models for Interoperability
Business Models for InteroperabilityBusiness Models for Interoperability
Business Models for Interoperability
 
Tdd in android (mvp)
Tdd in android (mvp)Tdd in android (mvp)
Tdd in android (mvp)
 

More from OSCON Byrum

OSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom FifieldOSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom FifieldOSCON Byrum
 
Protecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent LicenseProtecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent LicenseOSCON Byrum
 
Using Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open DataUsing Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open DataOSCON Byrum
 
Finite State Machines - Why the fear?
Finite State Machines - Why the fear?Finite State Machines - Why the fear?
Finite State Machines - Why the fear?OSCON Byrum
 
Open Source Automotive Development
Open Source Automotive DevelopmentOpen Source Automotive Development
Open Source Automotive DevelopmentOSCON Byrum
 
How we built our community using Github - Uri Cohen
How we built our community using Github - Uri CohenHow we built our community using Github - Uri Cohen
How we built our community using Github - Uri CohenOSCON Byrum
 
The Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in PythonThe Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in PythonOSCON Byrum
 
Distributed Coordination with Python
Distributed Coordination with PythonDistributed Coordination with Python
Distributed Coordination with PythonOSCON Byrum
 
An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)OSCON Byrum
 
Oscon 2013 Jesse Anderson
Oscon 2013 Jesse AndersonOscon 2013 Jesse Anderson
Oscon 2013 Jesse AndersonOSCON Byrum
 
US Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David MertzUS Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David MertzOSCON Byrum
 
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...OSCON Byrum
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of usOSCON Byrum
 
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking OSCON Byrum
 
Declarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScriptDeclarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScriptOSCON Byrum
 
Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...OSCON Byrum
 
A Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed ApplicationsA Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed ApplicationsOSCON Byrum
 
Life After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data CloudLife After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data CloudOSCON Byrum
 
Faster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypesFaster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypesOSCON Byrum
 
Comparing open source private cloud platforms
Comparing open source private cloud platformsComparing open source private cloud platforms
Comparing open source private cloud platformsOSCON Byrum
 

More from OSCON Byrum (20)

OSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom FifieldOSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
 
Protecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent LicenseProtecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent License
 
Using Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open DataUsing Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open Data
 
Finite State Machines - Why the fear?
Finite State Machines - Why the fear?Finite State Machines - Why the fear?
Finite State Machines - Why the fear?
 
Open Source Automotive Development
Open Source Automotive DevelopmentOpen Source Automotive Development
Open Source Automotive Development
 
How we built our community using Github - Uri Cohen
How we built our community using Github - Uri CohenHow we built our community using Github - Uri Cohen
How we built our community using Github - Uri Cohen
 
The Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in PythonThe Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in Python
 
Distributed Coordination with Python
Distributed Coordination with PythonDistributed Coordination with Python
Distributed Coordination with Python
 
An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)
 
Oscon 2013 Jesse Anderson
Oscon 2013 Jesse AndersonOscon 2013 Jesse Anderson
Oscon 2013 Jesse Anderson
 
US Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David MertzUS Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David Mertz
 
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of us
 
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
 
Declarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScriptDeclarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScript
 
Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...
 
A Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed ApplicationsA Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed Applications
 
Life After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data CloudLife After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data Cloud
 
Faster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypesFaster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypes
 
Comparing open source private cloud platforms
Comparing open source private cloud platformsComparing open source private cloud platforms
Comparing open source private cloud platforms
 

Recently uploaded

Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 

Recently uploaded (20)

Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 

Android Testing Hands-On Approach

  • 1. introduction to android testing a hands-on approach OSCON 2012 Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 1
  • 2. diego torres milano android system engineer flextronics http://dtmilano.blogspot.com Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 2
  • 3. “Never test the depth of the water with both feet.” -- Anonymous Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 3
  • 4. agenda android testing background test driven development code coverage continuous integration behavior driven development Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 4
  • 5. operating systems May 2012 Others iOS 250M Android 400M Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 5
  • 6. android testing background Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 6
  • 7. WhatWhy When how ? Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 7
  • 8. types of test tests unit functional performance integration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 8
  • 9. types of test by programmers for programmers unit in a programming language JUnit is the de-facto standard test objects in isolation in a repeatable way usually rely on mock objects Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 9
  • 10. types of test tests unit functional performance integration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 10
  • 11. types of test by business & QA people functional in a business domain language test completeness & correctness BDD has gained some popularity FitNesse can help Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 11
  • 12. types of test tests unit functional performance integration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 12
  • 13. types of test how components work together integration modules have been unit tested android components need integration with the system testing framework facilitates integration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 13
  • 14. types of test tests unit functional performance integration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 14
  • 15. types of test measure performance in a performance repeatable way if cannot be measure cannot be improved premature optimization does more harm than good measure-change-measure Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 15
  • 16. types of test tests unit functional performance integration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 16
  • 17. class diagram Assert <<iface>> TestCase Test InstrumentationTestCase AndroidTestCase ActivityInstrumentationTestCase2 ActivityUnitTestCase Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 17
  • 18. InstrumentationTestCase instrumentation instantiated before application allows for monitoring interaction send keys and input events manual lifecycle direct or indirect base class of other tests Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 18
  • 19. class diagram Assert <<iface>> TestCase Test InstrumentationTestCase AndroidTestCase ActivityInstrumentationTestCase2 ActivityUnitTestCase Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 19
  • 20. ActivityUnitTestCase isolated testing of single Activity minimal connection to the system uses mocks for dependencies some Activity methods should not be called Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 20
  • 21. class diagram Assert <<iface>> TestCase Test InstrumentationTestCase AndroidTestCase ActivityInstrumentationTestCase2 ActivityUnitTestCase Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 21
  • 22. ActivityInstrumentationTestCase2 functional testing of a single Activity has access to Instrumentation creates the AUT using system infrastructure custom intent can be provided Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 22
  • 23. class diagram Assert <<iface>> TestCase Test InstrumentationTestCase AndroidTestCase ActivityInstrumentationTestCase2 ActivityUnitTestCase Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 23
  • 24. access to Context AndroidTestCase access to Resources base class for Application, Provider and Service test cases Context stored in mContext field can start more than one Activity Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 24
  • 25. class diagram Assert <<iface>> TestCase Test InstrumentationTestCase AndroidTestCase ActivityInstrumentationTestCase2 ActivityUnitTestCase Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 25
  • 26. test driven development Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 26
  • 27. test driven development advantages: •the tests are written one way or another •developers take more responsibility for the quality of their work strategy of writing tests along development test cases written prior to the code single test added, then the code to satisfy it Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 27
  • 28. activity diagram design decisions are taken in single steps and finally the code write test satisfying the tests is improved by refactoring it run [fails] code [passes] refactor Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 28
  • 29. temperature converter Title celsius 100 autoupdate 32 fahrenheit keyboard Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 29
  • 30. requirements converts between temperature units one temperature is entered and the other is updated error is displayed in the field right aligned, 2 decimal digits entry fields start empty Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 30
  • 31. understanding requirements to write a test you must understand the requirement destination is quickly identified if requirement change, changing the corresponding test helps verify it Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 31
  • 32. github $ mkdir myworkdir $ cd myworkdir $ git clone git://github.com/dtmilano/I2AT- OSCON-2012.git Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 32
  • 33. creating the main project TemperatureConverter uses conventional settings Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 33
  • 34. select build target TemperatureConverter uses Android 4.0.3 Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 34
  • 35. creating the test project Automatically selected values for TemperatureConverterTest project Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 35
  • 36. running the tests [13:21:28 - TemperatureConverterTest] Launching instrumentation android.test.InstrumentationTestRunner on device XXX [13:21:28 - TemperatureConverterlTest-local] Failed to launch test Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 36
  • 37. warning due to the parameterized base class creating the test case Use: ActivityInstrumentationTestCase2 as the base class TemperatureConverterActivity as the class under test Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 37
  • 38. creating test stubs Select: onCreate(Bundle) to create a method stub Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 38
  • 39. fix constructor /** * Constructor * @param name */ public TemperatureConverterActivityTests(String name) { super(TemperatureConverterActivity.class); setName(name); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 39
  • 40. running the tests junit.framework.AssertionFailedError: Not yet implemented at com.dtmilano.i2at.tc.test. TemperatureConverterActivityTests. testOnCreateBundle( TemperatureConverterActivityTests.java:50) Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 40
  • 41. fixture protected void setUp(String name) throws Exception { super.setUp(); mActivity = getActivity(); references the assertNotNull(mActivity); main package mCelsius = (EditText)mActivity.findViewById( com.dtmilano.i2at.tc.R.id.celsius); assertNotNull(mCelsius); mFahrenheit = (EditText)mActivity.findViewById(com...); assertNotNull(mFahrenheit); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 41
  • 42. layout satisfy the test needs assign celsius and fahrenheit ids Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 42
  • 43. fix the test ! /** ! * Test method for {@link TemperatureConverterActivity #onCreate(android.os.Bundle)}. ! */ ! public void testOnCreateBundle() { ! ! assertNotNull(mActivity); ! } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 43
  • 44. ui tests: visibility @SmallTest public void testFieldsOnScreen() { final View origin = mActivity.getWindow().getDecorView(); ViewAsserts.assertOnScreen(origin, mCelsius); ViewAsserts.assertOnScreen(origin, mFahrenheit); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 44
  • 45. annotations @SmallTest @MediumTest @LargeTest @UiThreadTest @Suppress @FlakyTest Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 45
  • 46. ui tests: alignment @SmallTest public void testAlignment() { ! ! ViewAsserts.assertRightAligned(mCelsius, mFahrenheit); ! ! ViewAsserts.assertLeftAligned(mCelsius, mFahrenheit); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 46
  • 47. ui tests: initialization @SmallTest public void testFieldsShouldStartEmpty() { ! ! assertTrue("".equals(mCelsius.getText() .toString())); ! ! assertTrue("".equals(mFahrenheit.getText() .toString())); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 47
  • 48. ui tests: justification @SmallTest public void testJustification() { ! ! final int expected = Gravity.RIGHT|Gravity.CENTER_VERTICAL; ! ! assertEquals(expected, mCelsius.getGravity()); ! ! assertEquals(expected, mFahrenheit.getGravity()); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 48
  • 49. running the tests video plays on click >>> Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 49
  • 50. gravity add right and center_vertical gravity for celsius and fahrenheit Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 50
  • 51. running the tests video plays on click >>> Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 51
  • 52. temperature conversion run on the ! @UiThreadTest main thread ! public void testFahrenheitToCelsiusConversion() { specialized ! ! mCelsius.clear(); class ! ! mFahrenheit.clear(); errors are underlined in red ! ! final double f = 32.5; ! ! mFahrenheit.requestFocus(); ! ! mFahrenheit.setNumber(f); converter ! ! mCelsius.requestFocus(); helper ! ! final double expected = TemperatureConverter.fahrenheitToCelsius(f); ! ! final double actual = mCelsius.getNumber(); ! ! final double delta = Math.abs(expected - actual); ! ! assertTrue(delta < 0.005); ! } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 52
  • 53. EditNumber class EditNumber class extends EditText Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 53
  • 54. TemperatureCon verter TemperatureConverter is a helper class Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 54
  • 55. refactor public class TemperatureConverterActivityTests extends ActivityInstrumentationTestCase2< TemperatureConverterActivity> { private TemperatureConverterActivity mActivity; new class private EditNumber mCelsius; private EditNumber mFahrenheit; Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 55
  • 56. temperature conversion ! @UiThreadTest ! public void testFahrenheitToCelsiusConversion() { ! ! mCelsius.clear(); ! ! mFahrenheit.clear(); all compiler errors ! ! final double f = 32.5; corrected ! ! mFahrenheit.requestFocus(); ! ! mFahrenheit.setNumber(f); ! ! mCelsius.requestFocus(); ! ! final double expected = TemperatureConverter.fahrenheitToCelsius(f); ! ! final double actual = mCelsius.getNumber(); ! ! final double delta = Math.abs(expected - actual); ! ! assertTrue(delta < 0.005); ! } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 56
  • 57. OMG! [TemperatureConverterTests-OSCON-2012] Test run failed: Instrumentation run failed due to 'Process crashed.' [TemperatureConverterTests-OSCON-2012] Test run finished Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 57
  • 58. exception in logcat java.lang.ClassCastException: android.widget.EditText at com.dtmilano.i2at.tc.test. TemperatureConverterActivityTests.setUp (TemperatureConverterActivityTests.java: 52) 52:!! mCelsius = (EditNumber) mActivity.findViewById( com.dtmilano.i2at.tc.R.id.celsius); Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 58
  • 59. change widget type Select com.dtmilano.i2at.tc.EditNum ber Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 59
  • 60. layout <com.dtmilano.i2at.tc.EditNumber android:layout_height="wrap_content" ! ! android:layout_width="match_parent" android:inputType="numberDecimal" ! ! android:id="@+id/celsius" android:gravity="right|center_vertical"> ! ! <requestFocus /> </com.dtmilano.i2at.tc.EditNumber> Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 60
  • 61. running the tests what? Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 61
  • 62. celsius to fahrenheit Fahrenheit 150 112.5 75 f = 9/5 * c + 32 37.5 0 c = (f-32) * 5/9 -37.5 -75 -40 -30 -20 -10 0 10 20 30 40 Celsius Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 62
  • 63. converter public class TemperatureConverter { ! public static double fahrenheitToCelsius(double f) { / TODO Auto-generated method stub / ! ! return 0; ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 63
  • 64. TemperatureConv erterTests Test case as base class create method stubs TemperatureConverter as CUT Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 64
  • 65. method stubs select the methods you want stubs created for Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 65
  • 66. conversion test public final void testFahrenheitToCelsius() { ! ! for (double c: sConversionTableDouble.keySet()) { ! ! ! final double f = sConversionTableDouble.get(c); ! ! ! final double ca = TemperatureConverter.fahrenheitToCelsius(f); ! ! ! final double delta = Math.abs(ca - c); ! ! ! assertTrue(delta < 0.005); ! ! } ! } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 66
  • 67. conversion table private static final HashMap<Double, Double> sConversionTableDouble = ! ! ! new HashMap<Double, Double>(); ! static { ! ! sConversionTableDouble.put(0.0, 32.0); ! ! sConversionTableDouble.put(100.0, 212.0); ! ! sConversionTableDouble.put(-1.0, 30.20); ! ! sConversionTableDouble.put(-100.0, -148.0); ! ! sConversionTableDouble.put(32.0, 89.60); ! ! sConversionTableDouble.put(-40.0, -40.0); ! ! sConversionTableDouble.put(-273.0, -459.40); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 67
  • 68. add f -> c conversion public class TemperatureConverter { ! public static double fahrenheitToCelsius(double f) { ! ! return (f-32) * 5/9.0; ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 68
  • 69. run the tests this assertion fails Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 69
  • 70. creating test case use AndroidTestCase as base class use EditNumber as CUT Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 70
  • 71. method stubs select the constructors select other methods Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 71
  • 72. fixture /* (non-Javadoc) * @see android.test.AndroidTestCase#setUp() */ protected void setUp() throws Exception { super.setUp(); mEditNumber = new EditNumber(getContext()); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 72
  • 73. test public final void testClear() { ! ! final String value = "123.45"; ! ! mEditNumber.setText(value); ! ! mEditNumber.clear(); ! ! final String expected = ""; ! ! final String actual = mEditNumber.getText().toString(); ! ! assertEquals(expected, actual); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 73
  • 74. implementation public class EditNumber extends EditText { / ... / ! public void clear() { ! ! setText(null); ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 74
  • 75. test set number public final void testSetNumber() { final double expected = 123.45; mEditNumber.setNumber(expected); final double actual = mEditNumber.getNumber(); assertEquals(expected, actual); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 75
  • 76. set number public class EditNumber extends EditText { / ... / public void setNumber(double f) { setText(Double.toString(f)); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 76
  • 77. test get number public final void testGetNumber() { ! ! final double expected = 123.45; ! ! mEditNumber.setNumber(expected); ! ! final double actual = mEditNumber.getNumber(); ! ! assertEquals(expected, actual); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 77
  • 78. get number public class EditNumber extends EditText { / ... / ! public void getNumber() { final String s = getText().toString(); if ( "".equals(s) ) { return Double.NaN; } ! ! return Double.valueOf(s); ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 78
  • 79. run the tests testFahrenheitToCelsiusConversion is still failing Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 79
  • 80. what’s the problem ? clear() works requestFocus() works setNumber() works fahrenheitToCelsius() works getNumber() works so ? Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 80
  • 81. temperature converter Title celsius 100 autoupdate 32 fahrenheit keyboard Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 81
  • 82. TemperatureChan geWatcher create it as an inner class check abstract implements TextWatcher inherited abstract methods create 2 EditNumber fields mSource & mDest Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 82
  • 83. generate constructor use the fields public access omit call to super() Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 83
  • 84. the watcher public abstract class TemperatureChangeWatcher implements TextWatcher { ! ! private EditNumber mSource; ! ! private EditNumber mDest; ! ! ! ! public TemperatureChangeWatcher( EditNumber source, EditNumber dest) { ! ! ! this.mSource = source; ! ! ! this.mDest = dest; ! ! } / ... / } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 84
  • 85. on text changed @Override public void onTextChanged(CharSequence s, int start, int before, int count) { ! if ( !mDest.hasWindowFocus() || mDest.hasFocus() || s == null ) return; ! final String str = s.toString(); ! if ( "".equals(str) ) { ! ! mDest.setText(""); return; we should define ! } it ! try { ! ! final double result = convert(Double.parseDouble(str)); ! ! mDest.setNumber(result); ! } ! catch (NumberFormatException e) { ! ! / WARNING: this is thrown while a number is entered, for example just a '-' / ! } ! catch (Exception e) { ! ! mSource.setError("ERROR: " + e.getLocalizedMessage()); ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 85
  • 86. abstract convert method public abstract class TemperatureChangeWatcher implements TextWatcher { //... protected abstract double convert(double temp); //... } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 86
  • 87. find views @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView( R.layout.activity_temperature_converter); mCelsius = (EditNumber) findViewById(R.id.celsius); mFahrenheit = (EditNumber) findViewById(R.id.fahrenheit); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 87
  • 88. add change listeners @Override public void onCreate(Bundle savedInstanceState) { / ... / mCelsius.addTextChangedListener( we should create new TemperatureChangeWatcher(mCelsius, mFahrenheit) { it ! ! ! @Override protected double convert(double temp) { ! ! ! ! return TemperatureConverter.celsiusToFahrenheit(temp); ! ! ! }! }); mFahrenheit.addTextChangedListener( new TemperatureChangeWatcher(mFahrenheit, mCelsius) { ! ! ! @Override protected double convert(double temp) { ! ! ! ! return TemperatureConverter.fahrenheitToCelsius(temp); ! ! ! } }); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 88
  • 89. add conversion public class TemperatureConverter { ! public static double fahrenheitToCelsius(double f) { ! ! return (f-32) * 5/9.0; ! } ! public static double celsiusToFahrenheit(double c) { ! ! / TODO Auto-generated method stub / ! ! return 0; ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 89
  • 90. adding test public class TemperatureConverterTests extends TestCase { / ... / ! /** ! * Test method for {@link TemperatureConverter#fahrenheitToCelsius(double)}. ! */ ! public final void testCelsiusToFahrenheit() { ! ! for (double c: sConversionTableDouble.keySet()) { ! ! ! final double f = sConversionTableDouble.get(c); ! ! ! final double fa = TemperatureConverter.celsiusToFahrenheit(c); ! ! ! final double delta = Math.abs(fa - f); ! ! ! assertTrue("delta=" + delta + " for f=" + f + " fa=" + fa, delta < 0.005); ! ! } ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 90
  • 91. running the tests Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 91
  • 92. implementing conversion public class TemperatureConverter { ! public static double fahrenheitToCelsius(double f) { ! ! return (f-32) * 5/9.0; ! } ! public static double celsiusToFahrenheit(double c) { ! ! return 9/5.0 * c + 32; ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 92
  • 93. running the tests Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 93
  • 94. test xml attributes public final void testSetDecimalPlacesAttributeFromXml() { LayoutInflater inflater = (LayoutInflater)getContext() .getSystemService( Context.LAYOUT_INFLATER_SERVICE); View root = inflater.inflate( com.dtmilano.i2at.tc.R.layout.activity..., null); EditNumber editNumber = (EditNumber) root.findViewById(com.dtmilano.i2at.tc.R.id.celsius); assertNotNull(editNumber); / i2at:decimalPlaces="2" is set in main.xml / assertEquals(2, editNumber.getDecimalPlaces()); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 94
  • 95. decimal places public void setNumber(double d) { final String str = String.format("%." + mDecimalPlaces + "f", d); setText(str); } public void setDecimalPlaces(int places) { mDecimalPlaces = places; } public int getDecimalPlaces() { return mDecimalPlaces; } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 95
  • 96. define attributes <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="i2at"> <attr name="decimalPlaces" format="integer" /> </declare-styleable> </resources> Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 96
  • 97. add attributes xmlns:i2at="http:/ /schemas.android.com/apk/res/ com.dtmilano.i2at.tc" <com.dtmilano.i2at.tc.EditNumber android:id="@+id/celsius" i2at:decimalPlaces="2" android:ems="10" ... > <requestFocus /> </com.dtmilano.i2at.tc.EditNumber> Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 97
  • 98. init using attributes public EditNumber(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, -1); } private void init(Context context, AttributeSet attrs, int defStyle) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.i2at); setDecimalPlaces(a.getInteger( R.styleable.i2at_decimalPlaces, DEFAULT_DECIMAL_PLACES)); a.recycle(); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 98
  • 99. know decimal places protected void setUp() throws Exception { super.setUp(); mEditNumber = new EditNumber(getContext()); mEditNumber.setDecimalPlaces(2); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 99
  • 100. test signed number @SmallTest public void testFahrenheitToCelsiusConversion_input() throws Throwable { runTestOnUiThread(new Runnable() { @Override public void run() { mCelsius.clear(); mFahrenheit.clear(); } }); final String c = "-123.4"; getInstrumentation().sendStringSync(c); assertEquals(c, mCelsius.getText().toString()); final double expected = TemperatureConverter.celsiusToFahrenheit(Double.parseDouble(c)); final double actual = mFahrenheit.getNumber(); final double delta = Math.abs(expected - actual); assertTrue(delta < 0.005); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 100
  • 101. add attributes <com.dtmilano.i2at.tc.EditNumber android:id="@+id/celsius" android:layout_width="match_parent" android:layout_height="wrap_content" i2at:decimalPlaces="2" android:ems="10" android:gravity="center_vertical|right" android:inputType="numberSigned|numberDecimal" > <requestFocus /> </com.dtmilano.i2at.tc.EditNumber> Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 101
  • 102. running the tests Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 102
  • 103. code coverage Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 103
  • 104. code coverage measures the amount of source code tested android relies on emma (http://emma.sf.net) supported coverage types: class method line block Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 104
  • 105. coverage report overall coverage summary overall stats summary coverage breakdown by package Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 105
  • 106. building with ant disable project’s Build Automatically in Eclipse convert project to ant $ android update project --path $PWD --name TemperatureConverter-OSCON-2012 --target android-15 --subprojects $ android update test-project --main $PWD --path $PWD/tests Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 106
  • 107. run configuration run build.xml as Ant build... clean, emma, use emma transient target debug, install, test Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 107
  • 108. ant 1.8 specify ant 1.8 home Ant home... Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 108
  • 109. coverage run build.xml coverage analysis report is generated is currently only supported on the emulator and rooted devices get coverage file $ adb pull /data/data/com.example.i2at.tc/files/ coverage.ec coverage.ec Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 109
  • 110. on some user devs Give the app WRITE_EXTERNAL_S TORAGE permission Add emma.dump.file build property Use an external storage location (i.e. sdcard) Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 110
  • 111. coverage report Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 111
  • 112. coverage breakdown method name class% block% line% % TemperatureConverter 100% 67% 82% 67% TemperatureConverterActivity 100% 100% 91% 93% EditNumber 100% 100% 98% 96% Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 112
  • 113. constructor not covered Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 113
  • 114. private constructor public class TemperatureConverter { ! private TemperatureConverter() { ! ! / do nothing / ! } ! public static double fahrenheitToCelsius(double f) { ! ! return (f-32) * 5/9.0; ! } ! public static double celsiusToFahrenheit(double c) { ! ! return 9/5.0 * c + 32; ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 114
  • 115. access private constructor public final void testPrivateConstructor() throws Exception { ! Constructor<TemperatureConverter> ctor = circumvent TemperatureConverter.class.getDeclaredConstructor(); restriction ! ctor.setAccessible(true); ! TemperatureConverter tc = ctor.newInstance((Object[])null); ! assertNotNull(tc); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 115
  • 116. returning NaN Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 116
  • 117. missing tests public final void testGetNumber_emptyText() { mEditNumber.setText(""); final double actual = mEditNumber.getNumber(); assertEquals(Double.NaN, actual); } public final void testGetNumber_nullText() { mEditNumber.setText(null); final double actual = mEditNumber.getNumber(); assertEquals(Double.NaN, actual); } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 117
  • 118. finished application this is the final result Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 118
  • 119. requirements converts between temperature units one temperature is entered and the other is updated error is displayed in the field right aligned, 2 decimal digits entry fields start empty Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 119
  • 120. running tests Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 120
  • 121. alternatives eclipse command line android application Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 121
  • 122. run configurations Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 122
  • 123. am instrument Waits until the -w instrumentation terminates before terminating itself Outputs results in raw -r format -e <key> Provides testing options as <value> key-value pairs Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 123
  • 124. command line all tests: $ adb shell am instrument -w com.dtmilano.i2at.tc.test/ android.test.InstrumentationTestRunner functional tests: $ adb shell am instrument -w -e func true com.dtmilano.i2at.tc.test/ android.test.InstrumentationTestRunner Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 124
  • 125. Activity public class TemperatureConverterTestsActivity extends Activity { ! private static final String TAG = "TemperatureConverterTestsActivity"; ! private static final int TIMEOUT = 15000; ! ! private TextView mResults; ! private LogcatAsyncTask mLogcat; ... Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 125
  • 126. lifecycle methods @Override protected void onCreate(Bundle savedInstanceState) { ! ! super.onCreate(savedInstanceState); ! ! setContentView(R.layout.main); ! ! mResults = (TextView) findViewById(R.id.results); } @Override protected void onDestroy() { ! ! super.onDestroy(); ! ! if (mLogcat != null) { mLogcat.cancel(true); } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 126
  • 127. getInstrumentationInfo private InstrumentationInfo getInstrumentationInfo(final String packageName) { ! ! final List<InstrumentationInfo> list = getPackageManager() ! ! ! ! .queryInstrumentation(packageName, 0); ! ! return (!list.isEmpty()) ? list.get(0) : null; } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 127
  • 128. run tests public void runTests(View v) { final String pn = getPackageName().replaceFirst(".test$", ""); final InstrumentationInfo info = getInstrumentationInfo(pn); if (info != null) { ! final ComponentName cn = new ComponentName(info.packageName, ! ! ! info.name); ! if (startInstrumentation(cn, null, null)) { ! ! mLogcat = new LogcatAsyncTask(); ! ! mLogcat.execute(TIMEOUT); ! } } else { ! Toast.makeText(this, ! ! ! "Cannot find instrumentation for " + pn, Toast.LENGTH_SHORT) .show(); ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 128
  • 129. task to read logcat private class LogcatAsyncTask extends AsyncTask<Integer, String, Void> { ! / TestRunner and silence others / ! private static final String CMD = "logcat -v time TestRunner:I *:S"; ! private BufferedReader mReader; ! private Process mProc; ! public LogcatAsyncTask() { ! ! try { ! ! ! mProc = Runtime.getRuntime().exec(CMD); ! ! ! mReader = new BufferedReader(new InputStreamReader( ! ! ! ! ! mProc.getInputStream())); ! ! } catch (Exception e) { ! ! ! Log.e(TAG, "Creating proc", e); ! ! } ! } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 129
  • 130. progress update @Override protected void onProgressUpdate(String... values) { ! ! if (!TextUtils.isEmpty(values[0])) { ! ! ! mResults.append("n" + values[0]); ! ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 130
  • 131. @Override do in background protected Void doInBackground(Integer... params) { ! ! final long timeout = System.currentTimeMillis() + params[0]; ! ! try { ! ! ! do { ! ! ! ! Thread.sleep(50); publishProgress(mReader.readLine()); ! ! ! } while (System.currentTimeMillis() < timeout); ! ! } catch (Exception e) { ! ! ! publishProgress("ERROR: " + e); ! ! } finally { ! ! ! publishProgress("END"); mProc.destroy(); ! ! } ! ! return null; ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 131
  • 132. in action Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 132
  • 133. continuous integration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 133
  • 134. continuous integration agile technique for software engineering received broad adoption in recent years prevents “integration hell” integrate changes frequently Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 134
  • 135. requirements version control system automated build self tested artifacts and tests results easy to find Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 135
  • 136. installation download war from http://jenkins-ci.org $ java -jar jenkins.war Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 136
  • 137. jenkins home Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 137
  • 138. android plugin Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 138
  • 139. new job Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 139
  • 140. ant properties Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 140
  • 141. build artifacts Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 141
  • 142. build dependency Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 142
  • 143. android emulator Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 143
  • 144. invoke ant Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 144
  • 145. test project Create test project Set repository URL Trigger build after main project Build with ant Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 145
  • 146. xml test results download xmlinstrumentationtestrunner.jar replace instrumentation by android:name="com.neenbedankt.android.test. XMLInstrumentationTestRunner" customize project configuration Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 146
  • 147. junit test result Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 147
  • 148. build step PKG=com.dtmilano.i2at.tc OUTDIR=/mnt/sdcard/Android/data/$PKG/files/ OUTFILE=test-results.xml ADB=/opt/android-sdk/platform-tools/adb $ADB pull "$OUTDIR/$OUTFILE" "$WORKSPACE/ TemperatureConverter-OSCON-2012/tests/bin/ $OUTFILE" Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 148
  • 149. test report Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 149
  • 150. coverage trend Enable record emma coverage Specify emma XML report files Change health reporting Modify build.xml to support XML reports Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 150
  • 151. code coverage Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 151
  • 152. line coverage Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 152
  • 153. behavior driven development Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 153
  • 154. behavior driven development evolution of Test Driven Development inclusion of business participant common vocabulary based on Neuro Linguistics Programming Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 154
  • 155. fitnesse Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 155
  • 156. test suite Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 156
  • 157. slim test fixture package com.example.i2at.tc.test.fitnesse.fixture; import com.example.i2at.tc.TemperatureConverter; public class TemperatureConverterCelsiusToFahrenheitFixture { ! private double celsius; ! public void setCelsius(double celsius) { ! ! this.celsius = celsius; ! } ! public String fahrenheit() throws Exception { ! ! try { ! ! ! return String.valueOf(TemperatureConverter.celsiusToFahrenheit(celsius)); ! ! } catch (RuntimeException e) { ! ! ! return e.getLocalizedMessage(); ! ! } ! } } Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 157
  • 158. test run Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 158
  • 159. questions ? Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 159
  • 160. android application testing guide Apply testing techniques and tools • Learn the nuances of Unit and Functional testing • Understand different development methodologies such as TDD and BDD • Apply Continuous Integration • Improve applications using performance tests • Expose your application to a wide range of conditions Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 160
  • 161. thank you Copyright (C) 2011-2012 Diego Torres Milano All rights reserved 161