際際滷

際際滷Share a Scribd company logo
Android Test Driven Development




             Carlo Codega
 carlo.codega@funambol.com
            Milano, 21 Maggio 2010
Agenda
   Introduzione al Test Driven Development
   Unit testing vs Functional testing
   Unit testing:
      Componenti indipendenti da Android: JUnit
      Componenti dipendenti da Android, isolabili dal resto dellapplicazione
      Macro componenti: Application, Activity, Service e ContentProvider
      Generazione di test suite
      Esecuzione di test suite con adb (Android Debug Bridge)
   Functional testing:
      Componenti che hanno interfaccia utente: Activity
      Integration testing sullintera applicazione: Instrumentation
   Stress testing: Monkey tool
Introduzione al TDD
Perch辿 fare TDD in Android:

1. Scrivere codice che funziona :)
2. Scrivere i test prima dellimplementazione funzionale
3. Pensare al design dellapplicazione prima dellimplementazione
   reale
4. Evitare i bachi di regression. Scrivere speci鍖ci test case per ogni
   bug trovato
5. Facilitare il refactoring del codice
Unit testing vs Functional testing
   Unit tests:
      Servono a veri鍖care che tutte le componenti di un programma
       funzionano correttamente
      Vengono fatti solitamente dagli stessi sviluppatori che hanno
       implementato il codice
      Vengono scritti in un determinato linguaggio di programmazione


   Funcional tests (o acceptance tests):
      Servono a veri鍖care se un programma risponde ai requisiti dellutente
      Vengono fatti da persone di QA (Quality Assurance)
      Vengono scritti in un linguaggio di alto livello
Unit testing vs Functional testing
     Unit testing       Functional testing
Android testing framework
   Android integra al suo interno un framework per il testing:
      Package android.test

   Basato su JUnit 3
   Supporta:
      Unit testing: TestCase, AndroidTestCase
      Functional testing: InstrumentationTestCase

   Include delle utility per facilitare la creazione di test suite
   Android Debug Bridge (adb) per eseguire i test su emulatore o
    device reale
Unit testing
   Componenti indipendenti da Android: JUnit classico




                            TestCase




   Aiuta a separare la logica dal contesto
   Esempio: MorseCode
Unit testing
   MorseCode (Android SDK)
Unit testing


                    = dipendende da Android
       Activity
                    = indipendende da Android




      MorseCode   MorseCodeConverter
Unit testing
class MorseCodeConverter {
   static   final   long   SPEED_BASE = 100;
   static   final   long   DOT = SPEED_BASE;
   static   final   long   DASH = SPEED_BASE * 3;
   static   final   long   GAP = SPEED_BASE;

   /** The characters from 'A' to 'Z' */
   private static final long[][] LETTERS = new long[][] {
        /* A */ new long[] { DOT, GAP, DASH },
        /* B */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DOT },
        /* C */ new long[] { DASH, GAP, DOT, GAP, DASH, GAP, DOT },
        ...
   };

   /** The characters from '0' to '9' */
   private static final long[][] NUMBERS = new long[][] {
        /* 0 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DASH },
        /* 1 */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DASH },
        ...
   };
Unit testing

    /** Return the pattern data for a given character */
    static long[] pattern(char c) {
      ...
    }

     /** Return the pattern data for a given string */
    static long[] pattern(String str) {
      ...
    }
}
Unit testing



                  TestCase




           MorseCodeConverterTest
Unit testing

public class MorseCodeConverterTest extends TestCase {

    public void testCharacterS() throws Exception {

         long[] expectedBeeps = {   MorseCodeConverter.DOT,
                                    MorseCodeConverter.DOT,
                                    MorseCodeConverter.DOT,
                                    MorseCodeConverter.DOT,
                                     MorseCodeConverter.DOT };

         long[] beeps = MorseCodeConverter.pattern('s');

         assertEquals(expectedBeeps, beeps);
    }
}
Unit testing
 Componenti dipendenti da Android:



                          AndroidTestCase




 Viene utilizzato per le componenti che richiedono laccesso al
  Context:
    eseguire Intent, lanciare Activity e Service
    accedere al File System e ContentProvider

 Esempio: AndroidKeyValueStore
Unit testing




    AndroidKeyValueStore   Context
Unit testing
public class AndroidKeyValueStore {

    private SQLiteDatabase dbStore;
    private DatabaseHelper mDatabaseHelper;

    public AndroidKeyValueStore(Context context) {
        mDatabaseHelper = new DatabaseHelper(context,
             "dbname, "tablename");
        open();
        // Create table
        dbStore.execSQL(...);
        close();
    }

    public void open() {
        if(dbStore == null) {
             dbStore = mDatabaseHelper.getWritableDatabase();
        }
    }
Unit testing

    public void close() {
        dbStore.close();
        dbStore = null;
    }

    public void put(String key, String value) {
        dbStore.execSQL(...);
    }

    public String get(String key) {
        dbStore.execSQL(...);
    }
}
Unit testing



               AndroidTestCase




           AndroidKeyValueStoreTest
Unit testing
public class AndroidKeyValueStoreTest extends AndroidTestCase {

    private AndroidKeyValueStore store;

    protected void setUp() {
        store = new AndroidKeyValueStore(getContext());
        store.load();
    }

    protected void tearDown() {
        store.close();
    }

    public void testPutGet() throws Exception {
        store.put("aKey", "aValue");
        String value = store.get(aKey);
        assertEquals(value, "aValue");
    }
}
Unit testing
   Test di macro componenti in ambiente controllato:
      Controllo globale sul ciclo di vita del componente
      Application:
           ApplicationTestCase <T extends Application>

      Activity (functional test):
           ActivityTestCase
           ActivityInstrumentationTestCase<T extends Activity>    (deprecato)
           ActivityInstrumentationTestCase2<T extends Activity>

      Service:
           ServiceTestCase<T extends Service>

      ContentProvider:
           ProviderTestCase <T extends ContentProvider>    (deprecato)
           ProviderTestCase2 <T extends ContentProvider>
Unit testing


                      AndroidTestCase




ApplicationTestCase   ServiceTestCase   ProviderTestCase
Unit testing


               InstrumentationTestCase




          ActivityInstrumentationTestCase




          Instrumentation = Functional testing !!
Unit testing
Generazione di test suite per raggruppare e classi鍖care i TestCase:



               TestSuite




              MyTestSuite                TestSuiteBuilder
Unit testing
Includere tutti i test case appartenenti ad un package:

public class SomeTests extends TestSuite {
    public static Test suite() {
          return new TestSuiteBuilder(SomeTests.class)
             .includePackages("com.myapp.package1", "com.myapp.package2")
             .build();
    }
}

public class AllTests extends TestSuite {
    public static Test suite() {
          return new TestSuiteBuilder(AllTests.class)
             .includeAllPackagesUnderHere().build();
    }
}
Unit testing
Struttura dei test:

> AndroidManifest.xml
  src
  res
  tests > AndroidManifest.xml
          src > com > myapp > AllTests.java
                              SomeTests.java
                              package1 > TestCase1.java
                                            TestCase2.java
                              package2 > AndroidTestCase1.java
                                            AndroidTestCase2.java
Unit testing
AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.myapp.tests">

    <application>
        <uses-library android:name="android.test.runner />
    </application>

    <instrumentation android:name="android.test.InstrumentationTestRunner
        android:targetPackage="com.myapp
        android:label=MyApp Tests"/>

</manifest>
Unit testing
Eseguire test suite con adb (Android Debug Bridge):

   Eseguire tutti i test:
      adb shell am instrument -w com.myapp/android.test.InstrumentationTestRunner

   Eseguire una singola TestSuite o un singolo TestCase:
      adb shell am instrument -w -e class com.myapp.SomeTests
       com.myapp/android.test.InstrumentationTestRunner
      adb shell am instrument -w -e class com.myapp.package1.TestCase1
       com.myapp/android.test.InstrumentationTestRunner


   Eseguire solo unit tests:
      Test che non derivano da InstrumentationTestCase
      adb shell am instrument -w -e unit true
       com.myapp/android.test.InstrumentationTestRunner
Unit testing
   Classi鍖care per dimensione:
      adb shell am instrument -w -e size small
       com.myapp/android.test.InstrumentationTestRunner
      Classi鍖cati in base alle annotazioni:
          @SmallTest        >    -e size small
          @MediumTest       >    -e size medium
          @LargeTest        >    -e size large

   Output da adb:

     com.myapp.package1.TestCase1:........
     com.myapp.package1.TestCase2:.....
     com.myapp.package2.AndroidTestCase1:.........
     com.myapp.package2.AndroidTestCase1:......
     Test results for InstrumentationTestRunner=............................
     Time: 124.526

     OK (28 tests)
Unit testing
   Eseguire i test direttamente dallemulatore:
Functional testing
   Componenti che hanno interfaccia utente: Activity



                   ActivityInstrumentationTestCase




   Integration testing sullintera applicazione:



                            Instrumentation
Functional testing
   Componenti che hanno interfaccia utente: Activity



                      InstrumentationTestCase




                  ActivityInstrumentationTestCase
Functional testing
ActivityInstrumentationTestCase2<T extends Activity>


   Testing isolato per una singola Activity
   Tramite loggetto Instrumentation si pu嘆 interagire con linterfaccia
    utente
    possibile utilizzare le TouchUtils per simulare eventi touch
Functional testing
   Instrumentation:
     sendCharacterSync(int keyCode)
     sendKeySync(KeyEvent event)
     sendPointerSync(MotionEvent event)
     sendStringSync(String text)
     setInTouchMode(boolean inTouch)
Functional testing
   TouchUtils:
      clickView(InstrumentationTestCase test, View v)
      drag(InstrumentationTestCase test, 鍖oat fromX, 鍖oat toX, 鍖oat fromY,
       鍖oat toY, int stepCount)
      longClickView(InstrumentationTestCase test, View v)
      scrollToBottom(InstrumentationTestCase test, ViewGroup v)
      tapView(InstrumentationTestCase test, View v)
Functional testing
   Calculator
Functional testing



        Activity




       Calculator    Logic
Functional testing



      ActivityInstrumentationTestCase<Calculator>




                   CalculatorTest
Functional testing
public class CalculatorTest extends
    ActivityInstrumentationTestCase<Calculator> {

   Calculator mActivity = null;
   Instrumentation mInst = null;

   public CalculatorTest() {
       super("com.android.calculator2", Calculator.class);
   }

   protected void setUp() throws Exception {
       super.setUp();
       mActivity = getActivity();
       mInst = getInstrumentation();
   }
Functional testing
  private void press(int keycode) {
      mInst.sendKeyDownUpSync(keycode);
  }

  private boolean tap(int id) {
      View view = mActivity.findViewById(id);
      if(view != null) {
          TouchUtils.clickView(this, view);
          return true;
      }
      return false;
  }
  private String displayVal() {
      CalculatorDisplay display = (CalculatorDisplay)
          mActivity.findViewById(R.id.display);
      EditText box = (EditText)display.getCurrentView();
      return box.getText().toString();
  }
Functional testing
 public void testPressSomeKeys() {

      // Make sure that we clear the output
      press(KeyEvent.KEYCODE_ENTER);
      press(KeyEvent.KEYCODE_CLEAR);

      // 3 + 4 * 5 => 23
      press(KeyEvent.KEYCODE_3);
      press(KeyEvent.KEYCODE_PLUS);
      press(KeyEvent.KEYCODE_4);
      press(KeyEvent.KEYCODE_9 | KeyEvent.META_SHIFT_ON);
      press(KeyEvent.KEYCODE_5);
      press(KeyEvent.KEYCODE_ENTER);

      assertEquals(displayVal(), "23");
  }
Functional testing
  public void testTapSomeButtons() {

     // Make sure that we clear the output
     tap(R.id.equal);
     tap(R.id.del);

     // 567 / 3 => 189
     tap(R.id.digit5);
     tap(R.id.digit6);
     tap(R.id.digit7);
     tap(R.id.div);
     tap(R.id.digit3);
     tap(R.id.equal);

     assertEquals(displayVal(), "189");
Functional testing

         // make sure we can continue calculations also
         // 189 - 789 => -600
         tap(R.id.minus);
         tap(R.id.digit7);
         tap(R.id.digit8);
         tap(R.id.digit9);
         tap(R.id.equal);

         assertEquals(displayVal(), -600");
     }
}


   Le primitive sono semplici e astratte: press, tap, assert
Functional testing
   Integration testing sullintera applicazione:
      De鍖nire un linguaggio di alto livello per testare lapplicazione dal
       punto di vista dellutente
      Implementare un interprete del linguaggio per tradurre i comandi in
       azioni effettuate tramite loggetto Instrumentation


   Implementare un custom Instrumentation ci permette di avere il
    totale controllo sullapplicazione


   Il manifest di test deve contenere una copia del manifest
    dellapplicazione originale e la de鍖nizione di un nuovo
    Instrumentation per poter eseguire i test di integrazione
Functional testing
AndroidManifest.xml

<manifest package="com.myapp">

    <application android:label=MyApp">
        <activity android:name="com.myapp.Activity" />
        <service android:name="com.myapp.Service" />
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.myapp"
        android:label="MyApp Tests" />

    <instrumentation android:name="com.myapp.CustomInstrumentation
        android:targetPackage="com.myapp"
        android:label="MyApp Integration Tests" />

</manifest>
Functional testing
   De鍖nire un linguaggio di alto livello per simulare le azioni
    dellutente (esempio: Funambol integration tests):
      StartMainApp()
      KeyPress(String command, int count)
      WriteString(String text)
      CreateEmptyContact()
      DeleteAllContacts()
      Include(String scriptUrl)


   Linguaggio utilizzato dal QA per scrivere i test partendo dagli
    acceptance tests
Functional testing


    Instrumentation




 CustomInstrumentation   CommandRunner   Robot
Functional testing
   CustomInstrumentation:
     Carica lo script di test e lo esegue tramite il CommandRunner
   CommandRunner:
     Interpreta lo script
     Traduce ogni comando in azione eseguita tramite il Robot
   Robot:
     Esegue delle azioni sullapplicazione tramite un riferimento
       alloggetto Instrumentation
Functional testing
   Acceptance test case:
    1. On Device add a record in the Contacts section 鍖lling in all possible
       鍖elds
    2. Fire synchronization and wait for sync complete
    3. Check the new contact is added to the server
Functional testing
# Create on Device side a new Contact (Andrea Bianchi)
CreateEmptyContact()
SetContactField(FirstName,"Andrea")
SetContactField(LastName, "Bianchi")
SetContactField(TelHome, "0382665765979")
SetContactField(TelCell, "3445674")
SetContactField(Birthday, "1987-09-13")
...
SaveContact()

# Fire the synchronization and wait that is complete
KeyPress(KeyFire)
WaitForSyncToComplete(2,20)

# Verify Exchanged Data
CheckExchangedData("Contacts",1,0,0,0,0,0)
RefreshServer()

# Verify if the contact is added on the Server
CheckNewContactOnServer("Andrea", "Bianchi", true)
Functional testing
   Eseguire i test di integrazione:
      adb shell am instrument [options] -w
       com.myapp/com.myapp.CustomInstrumentation

       possibile speci鍖care dei parametri aggiuntivi tramite il 鍖ag -e (extra)

      I parametri vengono passati tramite una Bundle attraverso il metodo
       onCreate() delloggetto Instrumentation:
          public void onCreate(Bundle arguments)

      Dallemulatore:
          Dev Tools / Instrumentation / MyApp Integration Tests
Stress testing
   Monkey tool:
     Applicazione command line che pu嘆 essere eseguita su emulatore o
      device reale
     Genera eventi utente pseudo-casuali:
         Click
         Touch
         Gestures
     Con鍖gurabile:
         -p <allowed-package-name>: lista dei package sui quali 竪 possibile
          generare eventi
     Usage:
         adb shell monkey [options] <event-count>
Q&A

More Related Content

What's hot (20)

TDD patterns and TDD strategies
TDD patterns and TDD strategiesTDD patterns and TDD strategies
TDD patterns and TDD strategies
Alessandro Ceseno
Fe05 test drivenjavascriptdevelopment
Fe05   test drivenjavascriptdevelopmentFe05   test drivenjavascriptdevelopment
Fe05 test drivenjavascriptdevelopment
DotNetCampus
Unit testing 101
Unit testing 101Unit testing 101
Unit testing 101
Daniel Londero
Java Unit Testing - Introduction
Java Unit Testing - IntroductionJava Unit Testing - Introduction
Java Unit Testing - Introduction
fgianneschi
Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...
Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...
Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...
Emerasoft, solutions to collaborate
Unit testing in Visual Studio 2013
Unit testing in Visual Studio 2013Unit testing in Visual Studio 2013
Unit testing in Visual Studio 2013
DomusDotNet
Workshop: Introduzione ad TDD
Workshop: Introduzione ad TDDWorkshop: Introduzione ad TDD
Workshop: Introduzione ad TDD
Marcello Missiroli
DotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql ServerDotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql Server
Alessandro Alpi
TTT - Test, Tools and Tips - jug roma
TTT - Test, Tools and Tips - jug romaTTT - Test, Tools and Tips - jug roma
TTT - Test, Tools and Tips - jug roma
diego mauricio lagos morales
Java Unit Testing - JUnit (1)
Java Unit Testing - JUnit (1)Java Unit Testing - JUnit (1)
Java Unit Testing - JUnit (1)
fgianneschi
Software Testing & Test Driven Development
Software Testing & Test Driven DevelopmentSoftware Testing & Test Driven Development
Software Testing & Test Driven Development
Sergio Santoro
Java Unit Testing - JUnit (2)
Java Unit Testing - JUnit (2)Java Unit Testing - JUnit (2)
Java Unit Testing - JUnit (2)
fgianneschi
Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...
Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...
Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...
MicheleDamian
Java Unit Testing - In container and database testing
Java Unit Testing - In container and database testingJava Unit Testing - In container and database testing
Java Unit Testing - In container and database testing
fgianneschi
Qualit del Software
Qualit del SoftwareQualit del Software
Qualit del Software
Yeser Rema
JMeter
JMeterJMeter
JMeter
JUG Genova
Dependency injection: the good parts
Dependency injection:  the good partsDependency injection:  the good parts
Dependency injection: the good parts
Massimo Groppelli
Progetto e implementazione di una pipeline di sviluppo software con tecnologi...
Progetto e implementazione di una pipeline di sviluppo software con tecnologi...Progetto e implementazione di una pipeline di sviluppo software con tecnologi...
Progetto e implementazione di una pipeline di sviluppo software con tecnologi...
Mattia Milleri
PowerMock TDD User Group Milano
PowerMock TDD User Group MilanoPowerMock TDD User Group Milano
PowerMock TDD User Group Milano
Massimo Groppelli
Test Prestazionali di Web Service
Test Prestazionali di Web ServiceTest Prestazionali di Web Service
Test Prestazionali di Web Service
Daniele Palladino
TDD patterns and TDD strategies
TDD patterns and TDD strategiesTDD patterns and TDD strategies
TDD patterns and TDD strategies
Alessandro Ceseno
Fe05 test drivenjavascriptdevelopment
Fe05   test drivenjavascriptdevelopmentFe05   test drivenjavascriptdevelopment
Fe05 test drivenjavascriptdevelopment
DotNetCampus
Java Unit Testing - Introduction
Java Unit Testing - IntroductionJava Unit Testing - Introduction
Java Unit Testing - Introduction
fgianneschi
Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...
Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...
Webinar: Testing automatico: la scelta vincente per ottenere una riduzione d...
Emerasoft, solutions to collaborate
Unit testing in Visual Studio 2013
Unit testing in Visual Studio 2013Unit testing in Visual Studio 2013
Unit testing in Visual Studio 2013
DomusDotNet
Workshop: Introduzione ad TDD
Workshop: Introduzione ad TDDWorkshop: Introduzione ad TDD
Workshop: Introduzione ad TDD
Marcello Missiroli
DotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql ServerDotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql Server
Alessandro Alpi
Java Unit Testing - JUnit (1)
Java Unit Testing - JUnit (1)Java Unit Testing - JUnit (1)
Java Unit Testing - JUnit (1)
fgianneschi
Software Testing & Test Driven Development
Software Testing & Test Driven DevelopmentSoftware Testing & Test Driven Development
Software Testing & Test Driven Development
Sergio Santoro
Java Unit Testing - JUnit (2)
Java Unit Testing - JUnit (2)Java Unit Testing - JUnit (2)
Java Unit Testing - JUnit (2)
fgianneschi
Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...
Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...
Analisi di prestazione dell'interprete tuProlog su piattaforma Java - Present...
MicheleDamian
Java Unit Testing - In container and database testing
Java Unit Testing - In container and database testingJava Unit Testing - In container and database testing
Java Unit Testing - In container and database testing
fgianneschi
Qualit del Software
Qualit del SoftwareQualit del Software
Qualit del Software
Yeser Rema
Dependency injection: the good parts
Dependency injection:  the good partsDependency injection:  the good parts
Dependency injection: the good parts
Massimo Groppelli
Progetto e implementazione di una pipeline di sviluppo software con tecnologi...
Progetto e implementazione di una pipeline di sviluppo software con tecnologi...Progetto e implementazione di una pipeline di sviluppo software con tecnologi...
Progetto e implementazione di una pipeline di sviluppo software con tecnologi...
Mattia Milleri
PowerMock TDD User Group Milano
PowerMock TDD User Group MilanoPowerMock TDD User Group Milano
PowerMock TDD User Group Milano
Massimo Groppelli
Test Prestazionali di Web Service
Test Prestazionali di Web ServiceTest Prestazionali di Web Service
Test Prestazionali di Web Service
Daniele Palladino

Similar to Android Test Driven Development (20)

Il testing con zend framework
Il testing con zend frameworkIl testing con zend framework
Il testing con zend framework
Zend by Rogue Wave Software
Presentazione Testing automatizzato
Presentazione Testing automatizzatoPresentazione Testing automatizzato
Presentazione Testing automatizzato
angelolu
Un'infrastruttura di test per un sistema PACS
Un'infrastruttura di test per un sistema PACSUn'infrastruttura di test per un sistema PACS
Un'infrastruttura di test per un sistema PACS
Giacomo Petronio
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
Alessandro Alpi
Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...
Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...
Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...
Boymix81
Googletest, tdd e mock
Googletest, tdd e mockGoogletest, tdd e mock
Googletest, tdd e mock
yuroller
CONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVERCONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVER
DotNetCampus
01 Android - Introduction
01   Android - Introduction01   Android - Introduction
01 Android - Introduction
spawn150
Software Testing e TDD
Software Testing e TDDSoftware Testing e TDD
Software Testing e TDD
Domenico Briganti
Presentazione: uno studio sull'efficacia di checker automatici per la moderni...
Presentazione: uno studio sull'efficacia di checker automatici per la moderni...Presentazione: uno studio sull'efficacia di checker automatici per la moderni...
Presentazione: uno studio sull'efficacia di checker automatici per la moderni...
Idriss Riouak
Unit Testing
Unit TestingUnit Testing
Unit Testing
Andrea Tosato
Java lezione 14
Java lezione 14Java lezione 14
Java lezione 14
Sergio Ronchi
Dominare il codice legacy
Dominare il codice legacyDominare il codice legacy
Dominare il codice legacy
Tommaso Torti
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
Davide Cerbo
Junit tutorial
Junit tutorialJunit tutorial
Junit tutorial
fdesimone
Applicazioni native in java
Applicazioni native in javaApplicazioni native in java
Applicazioni native in java
Federico Paparoni
Webbit 2004: Tiger, java
Webbit 2004: Tiger, javaWebbit 2004: Tiger, java
Webbit 2004: Tiger, java
Matteo Baccan
Py a1 python-unit_testing
Py a1 python-unit_testingPy a1 python-unit_testing
Py a1 python-unit_testing
Majong DevJfu
Presentazione Testing automatizzato
Presentazione Testing automatizzatoPresentazione Testing automatizzato
Presentazione Testing automatizzato
angelolu
Un'infrastruttura di test per un sistema PACS
Un'infrastruttura di test per un sistema PACSUn'infrastruttura di test per un sistema PACS
Un'infrastruttura di test per un sistema PACS
Giacomo Petronio
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
Alessandro Alpi
Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...
Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...
Presentazione della Tesi di Laurea Specialistica : STRUMENTI PER LA GENERAZIO...
Boymix81
Googletest, tdd e mock
Googletest, tdd e mockGoogletest, tdd e mock
Googletest, tdd e mock
yuroller
CONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVERCONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVER
DotNetCampus
01 Android - Introduction
01   Android - Introduction01   Android - Introduction
01 Android - Introduction
spawn150
Presentazione: uno studio sull'efficacia di checker automatici per la moderni...
Presentazione: uno studio sull'efficacia di checker automatici per la moderni...Presentazione: uno studio sull'efficacia di checker automatici per la moderni...
Presentazione: uno studio sull'efficacia di checker automatici per la moderni...
Idriss Riouak
Dominare il codice legacy
Dominare il codice legacyDominare il codice legacy
Dominare il codice legacy
Tommaso Torti
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
Davide Cerbo
Junit tutorial
Junit tutorialJunit tutorial
Junit tutorial
fdesimone
Applicazioni native in java
Applicazioni native in javaApplicazioni native in java
Applicazioni native in java
Federico Paparoni
Webbit 2004: Tiger, java
Webbit 2004: Tiger, javaWebbit 2004: Tiger, java
Webbit 2004: Tiger, java
Matteo Baccan
Py a1 python-unit_testing
Py a1 python-unit_testingPy a1 python-unit_testing
Py a1 python-unit_testing
Majong DevJfu

Android Test Driven Development

  • 1. Android Test Driven Development Carlo Codega carlo.codega@funambol.com Milano, 21 Maggio 2010
  • 2. Agenda Introduzione al Test Driven Development Unit testing vs Functional testing Unit testing: Componenti indipendenti da Android: JUnit Componenti dipendenti da Android, isolabili dal resto dellapplicazione Macro componenti: Application, Activity, Service e ContentProvider Generazione di test suite Esecuzione di test suite con adb (Android Debug Bridge) Functional testing: Componenti che hanno interfaccia utente: Activity Integration testing sullintera applicazione: Instrumentation Stress testing: Monkey tool
  • 3. Introduzione al TDD Perch辿 fare TDD in Android: 1. Scrivere codice che funziona :) 2. Scrivere i test prima dellimplementazione funzionale 3. Pensare al design dellapplicazione prima dellimplementazione reale 4. Evitare i bachi di regression. Scrivere speci鍖ci test case per ogni bug trovato 5. Facilitare il refactoring del codice
  • 4. Unit testing vs Functional testing Unit tests: Servono a veri鍖care che tutte le componenti di un programma funzionano correttamente Vengono fatti solitamente dagli stessi sviluppatori che hanno implementato il codice Vengono scritti in un determinato linguaggio di programmazione Funcional tests (o acceptance tests): Servono a veri鍖care se un programma risponde ai requisiti dellutente Vengono fatti da persone di QA (Quality Assurance) Vengono scritti in un linguaggio di alto livello
  • 5. Unit testing vs Functional testing Unit testing Functional testing
  • 6. Android testing framework Android integra al suo interno un framework per il testing: Package android.test Basato su JUnit 3 Supporta: Unit testing: TestCase, AndroidTestCase Functional testing: InstrumentationTestCase Include delle utility per facilitare la creazione di test suite Android Debug Bridge (adb) per eseguire i test su emulatore o device reale
  • 7. Unit testing Componenti indipendenti da Android: JUnit classico TestCase Aiuta a separare la logica dal contesto Esempio: MorseCode
  • 8. Unit testing MorseCode (Android SDK)
  • 9. Unit testing = dipendende da Android Activity = indipendende da Android MorseCode MorseCodeConverter
  • 10. Unit testing class MorseCodeConverter { static final long SPEED_BASE = 100; static final long DOT = SPEED_BASE; static final long DASH = SPEED_BASE * 3; static final long GAP = SPEED_BASE; /** The characters from 'A' to 'Z' */ private static final long[][] LETTERS = new long[][] { /* A */ new long[] { DOT, GAP, DASH }, /* B */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DOT }, /* C */ new long[] { DASH, GAP, DOT, GAP, DASH, GAP, DOT }, ... }; /** The characters from '0' to '9' */ private static final long[][] NUMBERS = new long[][] { /* 0 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DASH }, /* 1 */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DASH }, ... };
  • 11. Unit testing /** Return the pattern data for a given character */ static long[] pattern(char c) { ... } /** Return the pattern data for a given string */ static long[] pattern(String str) { ... } }
  • 12. Unit testing TestCase MorseCodeConverterTest
  • 13. Unit testing public class MorseCodeConverterTest extends TestCase { public void testCharacterS() throws Exception { long[] expectedBeeps = { MorseCodeConverter.DOT, MorseCodeConverter.DOT, MorseCodeConverter.DOT, MorseCodeConverter.DOT, MorseCodeConverter.DOT }; long[] beeps = MorseCodeConverter.pattern('s'); assertEquals(expectedBeeps, beeps); } }
  • 14. Unit testing Componenti dipendenti da Android: AndroidTestCase Viene utilizzato per le componenti che richiedono laccesso al Context: eseguire Intent, lanciare Activity e Service accedere al File System e ContentProvider Esempio: AndroidKeyValueStore
  • 15. Unit testing AndroidKeyValueStore Context
  • 16. Unit testing public class AndroidKeyValueStore { private SQLiteDatabase dbStore; private DatabaseHelper mDatabaseHelper; public AndroidKeyValueStore(Context context) { mDatabaseHelper = new DatabaseHelper(context, "dbname, "tablename"); open(); // Create table dbStore.execSQL(...); close(); } public void open() { if(dbStore == null) { dbStore = mDatabaseHelper.getWritableDatabase(); } }
  • 17. Unit testing public void close() { dbStore.close(); dbStore = null; } public void put(String key, String value) { dbStore.execSQL(...); } public String get(String key) { dbStore.execSQL(...); } }
  • 18. Unit testing AndroidTestCase AndroidKeyValueStoreTest
  • 19. Unit testing public class AndroidKeyValueStoreTest extends AndroidTestCase { private AndroidKeyValueStore store; protected void setUp() { store = new AndroidKeyValueStore(getContext()); store.load(); } protected void tearDown() { store.close(); } public void testPutGet() throws Exception { store.put("aKey", "aValue"); String value = store.get(aKey); assertEquals(value, "aValue"); } }
  • 20. Unit testing Test di macro componenti in ambiente controllato: Controllo globale sul ciclo di vita del componente Application: ApplicationTestCase <T extends Application> Activity (functional test): ActivityTestCase ActivityInstrumentationTestCase<T extends Activity> (deprecato) ActivityInstrumentationTestCase2<T extends Activity> Service: ServiceTestCase<T extends Service> ContentProvider: ProviderTestCase <T extends ContentProvider> (deprecato) ProviderTestCase2 <T extends ContentProvider>
  • 21. Unit testing AndroidTestCase ApplicationTestCase ServiceTestCase ProviderTestCase
  • 22. Unit testing InstrumentationTestCase ActivityInstrumentationTestCase Instrumentation = Functional testing !!
  • 23. Unit testing Generazione di test suite per raggruppare e classi鍖care i TestCase: TestSuite MyTestSuite TestSuiteBuilder
  • 24. Unit testing Includere tutti i test case appartenenti ad un package: public class SomeTests extends TestSuite { public static Test suite() { return new TestSuiteBuilder(SomeTests.class) .includePackages("com.myapp.package1", "com.myapp.package2") .build(); } } public class AllTests extends TestSuite { public static Test suite() { return new TestSuiteBuilder(AllTests.class) .includeAllPackagesUnderHere().build(); } }
  • 25. Unit testing Struttura dei test: > AndroidManifest.xml src res tests > AndroidManifest.xml src > com > myapp > AllTests.java SomeTests.java package1 > TestCase1.java TestCase2.java package2 > AndroidTestCase1.java AndroidTestCase2.java
  • 26. Unit testing AndroidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.myapp.tests"> <application> <uses-library android:name="android.test.runner /> </application> <instrumentation android:name="android.test.InstrumentationTestRunner android:targetPackage="com.myapp android:label=MyApp Tests"/> </manifest>
  • 27. Unit testing Eseguire test suite con adb (Android Debug Bridge): Eseguire tutti i test: adb shell am instrument -w com.myapp/android.test.InstrumentationTestRunner Eseguire una singola TestSuite o un singolo TestCase: adb shell am instrument -w -e class com.myapp.SomeTests com.myapp/android.test.InstrumentationTestRunner adb shell am instrument -w -e class com.myapp.package1.TestCase1 com.myapp/android.test.InstrumentationTestRunner Eseguire solo unit tests: Test che non derivano da InstrumentationTestCase adb shell am instrument -w -e unit true com.myapp/android.test.InstrumentationTestRunner
  • 28. Unit testing Classi鍖care per dimensione: adb shell am instrument -w -e size small com.myapp/android.test.InstrumentationTestRunner Classi鍖cati in base alle annotazioni: @SmallTest > -e size small @MediumTest > -e size medium @LargeTest > -e size large Output da adb: com.myapp.package1.TestCase1:........ com.myapp.package1.TestCase2:..... com.myapp.package2.AndroidTestCase1:......... com.myapp.package2.AndroidTestCase1:...... Test results for InstrumentationTestRunner=............................ Time: 124.526 OK (28 tests)
  • 29. Unit testing Eseguire i test direttamente dallemulatore:
  • 30. Functional testing Componenti che hanno interfaccia utente: Activity ActivityInstrumentationTestCase Integration testing sullintera applicazione: Instrumentation
  • 31. Functional testing Componenti che hanno interfaccia utente: Activity InstrumentationTestCase ActivityInstrumentationTestCase
  • 32. Functional testing ActivityInstrumentationTestCase2<T extends Activity> Testing isolato per una singola Activity Tramite loggetto Instrumentation si pu嘆 interagire con linterfaccia utente possibile utilizzare le TouchUtils per simulare eventi touch
  • 33. Functional testing Instrumentation: sendCharacterSync(int keyCode) sendKeySync(KeyEvent event) sendPointerSync(MotionEvent event) sendStringSync(String text) setInTouchMode(boolean inTouch)
  • 34. Functional testing TouchUtils: clickView(InstrumentationTestCase test, View v) drag(InstrumentationTestCase test, 鍖oat fromX, 鍖oat toX, 鍖oat fromY, 鍖oat toY, int stepCount) longClickView(InstrumentationTestCase test, View v) scrollToBottom(InstrumentationTestCase test, ViewGroup v) tapView(InstrumentationTestCase test, View v)
  • 35. Functional testing Calculator
  • 36. Functional testing Activity Calculator Logic
  • 37. Functional testing ActivityInstrumentationTestCase<Calculator> CalculatorTest
  • 38. Functional testing public class CalculatorTest extends ActivityInstrumentationTestCase<Calculator> { Calculator mActivity = null; Instrumentation mInst = null; public CalculatorTest() { super("com.android.calculator2", Calculator.class); } protected void setUp() throws Exception { super.setUp(); mActivity = getActivity(); mInst = getInstrumentation(); }
  • 39. Functional testing private void press(int keycode) { mInst.sendKeyDownUpSync(keycode); } private boolean tap(int id) { View view = mActivity.findViewById(id); if(view != null) { TouchUtils.clickView(this, view); return true; } return false; } private String displayVal() { CalculatorDisplay display = (CalculatorDisplay) mActivity.findViewById(R.id.display); EditText box = (EditText)display.getCurrentView(); return box.getText().toString(); }
  • 40. Functional testing public void testPressSomeKeys() { // Make sure that we clear the output press(KeyEvent.KEYCODE_ENTER); press(KeyEvent.KEYCODE_CLEAR); // 3 + 4 * 5 => 23 press(KeyEvent.KEYCODE_3); press(KeyEvent.KEYCODE_PLUS); press(KeyEvent.KEYCODE_4); press(KeyEvent.KEYCODE_9 | KeyEvent.META_SHIFT_ON); press(KeyEvent.KEYCODE_5); press(KeyEvent.KEYCODE_ENTER); assertEquals(displayVal(), "23"); }
  • 41. Functional testing public void testTapSomeButtons() { // Make sure that we clear the output tap(R.id.equal); tap(R.id.del); // 567 / 3 => 189 tap(R.id.digit5); tap(R.id.digit6); tap(R.id.digit7); tap(R.id.div); tap(R.id.digit3); tap(R.id.equal); assertEquals(displayVal(), "189");
  • 42. Functional testing // make sure we can continue calculations also // 189 - 789 => -600 tap(R.id.minus); tap(R.id.digit7); tap(R.id.digit8); tap(R.id.digit9); tap(R.id.equal); assertEquals(displayVal(), -600"); } } Le primitive sono semplici e astratte: press, tap, assert
  • 43. Functional testing Integration testing sullintera applicazione: De鍖nire un linguaggio di alto livello per testare lapplicazione dal punto di vista dellutente Implementare un interprete del linguaggio per tradurre i comandi in azioni effettuate tramite loggetto Instrumentation Implementare un custom Instrumentation ci permette di avere il totale controllo sullapplicazione Il manifest di test deve contenere una copia del manifest dellapplicazione originale e la de鍖nizione di un nuovo Instrumentation per poter eseguire i test di integrazione
  • 44. Functional testing AndroidManifest.xml <manifest package="com.myapp"> <application android:label=MyApp"> <activity android:name="com.myapp.Activity" /> <service android:name="com.myapp.Service" /> <uses-library android:name="android.test.runner" /> </application> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.myapp" android:label="MyApp Tests" /> <instrumentation android:name="com.myapp.CustomInstrumentation android:targetPackage="com.myapp" android:label="MyApp Integration Tests" /> </manifest>
  • 45. Functional testing De鍖nire un linguaggio di alto livello per simulare le azioni dellutente (esempio: Funambol integration tests): StartMainApp() KeyPress(String command, int count) WriteString(String text) CreateEmptyContact() DeleteAllContacts() Include(String scriptUrl) Linguaggio utilizzato dal QA per scrivere i test partendo dagli acceptance tests
  • 46. Functional testing Instrumentation CustomInstrumentation CommandRunner Robot
  • 47. Functional testing CustomInstrumentation: Carica lo script di test e lo esegue tramite il CommandRunner CommandRunner: Interpreta lo script Traduce ogni comando in azione eseguita tramite il Robot Robot: Esegue delle azioni sullapplicazione tramite un riferimento alloggetto Instrumentation
  • 48. Functional testing Acceptance test case: 1. On Device add a record in the Contacts section 鍖lling in all possible 鍖elds 2. Fire synchronization and wait for sync complete 3. Check the new contact is added to the server
  • 49. Functional testing # Create on Device side a new Contact (Andrea Bianchi) CreateEmptyContact() SetContactField(FirstName,"Andrea") SetContactField(LastName, "Bianchi") SetContactField(TelHome, "0382665765979") SetContactField(TelCell, "3445674") SetContactField(Birthday, "1987-09-13") ... SaveContact() # Fire the synchronization and wait that is complete KeyPress(KeyFire) WaitForSyncToComplete(2,20) # Verify Exchanged Data CheckExchangedData("Contacts",1,0,0,0,0,0) RefreshServer() # Verify if the contact is added on the Server CheckNewContactOnServer("Andrea", "Bianchi", true)
  • 50. Functional testing Eseguire i test di integrazione: adb shell am instrument [options] -w com.myapp/com.myapp.CustomInstrumentation possibile speci鍖care dei parametri aggiuntivi tramite il 鍖ag -e (extra) I parametri vengono passati tramite una Bundle attraverso il metodo onCreate() delloggetto Instrumentation: public void onCreate(Bundle arguments) Dallemulatore: Dev Tools / Instrumentation / MyApp Integration Tests
  • 51. Stress testing Monkey tool: Applicazione command line che pu嘆 essere eseguita su emulatore o device reale Genera eventi utente pseudo-casuali: Click Touch Gestures Con鍖gurabile: -p <allowed-package-name>: lista dei package sui quali 竪 possibile generare eventi Usage: adb shell monkey [options] <event-count>
  • 52. Q&A