78

Stiamo costruendo un'applicazione Android complessa composta da molti schermi e flussi di lavoro distribuiti su molte attività. I nostri flussi di lavoro sono simili a quelli che potresti vedere sugli sportelli bancomat di una banca, ad esempio, c'è un Activity per accedere in quelle transizioni a un menu principale Activity che può passare ad altre attività in base alle scelte dell'utente.Come si esegue il test di un'applicazione Android su più attività?

Poiché abbiamo così tanti flussi di lavoro, abbiamo bisogno di creare test automatici che abbracciano più attività in modo da poter testare un flusso di lavoro da un capo all'altro. Ad esempio, utilizzando l'esempio ATM, vorremmo inserire un PIN valido, verificare che ci invii al menu principale, scegliere prelevare contanti, verificare che ci troviamo sullo schermo di prelievo, ecc. Ecc., E alla fine ritrovarci torna nel menu principale o "disconnesso".

Abbiamo giocato con l'API di prova che vengono con Android (ad esempio ActivityInstrumentationTestCase2) e anche con Positron, ma nessuno sembra in grado di test oltre i limiti di un solo Activity, e mentre siamo in grado di trovare qualche utilità in questi strumenti per alcune unità di test, non soddisfano le nostre esigenze per gli scenari di test che attraversano più attività.

Siamo aperti a un framework xUnit, a script, a registratori/riproduzioni GUI, ecc. E apprezzeremmo qualsiasi consiglio.

+2

Come di Android 4.1, ora c'è un nuovo framework di test da Android che consente di test tra attività e l'intero sistema: http://developer.android.com/tools/testing/testing_ui.html –

+1

[Robotium] (https://code.google.com/p/robotium/) soddisfa anche questa esigenza e in solo un paio di righe. – Dori

risposta

64

mi sento un po 'scomoda circa la risposta alla mia domanda di taglie, ma qui è ...

Ho cercato di alta e bassa su questo e non posso credere non c'è una risposta pubblicata da nessuna parte. Sono venuto molto vicino Posso sicuramente eseguire test che coprono le attività ora, ma la mia implementazione sembra avere alcuni problemi di temporizzazione in cui i test non sempre passano in modo affidabile. Questo è l'unico esempio che conosco dei test su più attività con successo. Spero che la mia estrazione e la sua anonimizzazione non abbiano introdotto errori. Questo è un test semplice in cui si digita un'username e una password in un'attività di accesso, e poi osservo un messaggio di benvenuto corretta viene visualizzato su una diversa attività di "benvenuto":

package com.mycompany; 

import android.app.*; 
import android.content.*; 
import android.test.*; 
import android.test.suitebuilder.annotation.*; 
import android.util.*; 
import android.view.*; 
import android.widget.*; 

import static org.hamcrest.core.Is.*; 
import static org.hamcrest.core.IsNull.*; 
import static org.hamcrest.core.IsInstanceOf.instanceOf; 
import static org.junit.Assert.*; 
import static com.mycompany.R.id.*; 

public class LoginTests extends InstrumentationTestCase { 

    @MediumTest 
    public void testAValidUserCanLogIn() { 

     Instrumentation instrumentation = getInstrumentation(); 

     // Register we are interested in the authentication activiry... 
     Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(AuthenticateActivity.class.getName(), null, false); 

     // Start the authentication activity as the first activity... 
     Intent intent = new Intent(Intent.ACTION_MAIN); 
     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     intent.setClassName(instrumentation.getTargetContext(), AuthenticateActivity.class.getName()); 
     instrumentation.startActivitySync(intent); 

     // Wait for it to start... 
     Activity currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5); 
     assertThat(currentActivity, is(notNullValue())); 

     // Type into the username field... 
     View currentView = currentActivity.findViewById(username_field); 
     assertThat(currentView, is(notNullValue())); 
     assertThat(currentView, instanceOf(EditText.class)); 
     TouchUtils.clickView(this, currentView); 
     instrumentation.sendStringSync("MyUsername"); 

     // Type into the password field... 
     currentView = currentActivity.findViewById(password_field); 
     assertThat(currentView, is(notNullValue())); 
     assertThat(currentView, instanceOf(EditText.class)); 
     TouchUtils.clickView(this, currentView); 
     instrumentation.sendStringSync("MyPassword"); 

     // Register we are interested in the welcome activity... 
     // this has to be done before we do something that will send us to that 
     // activity... 
     instrumentation.removeMonitor(monitor); 
     monitor = instrumentation.addMonitor(WelcomeActivity.class.getName(), null, false); 

     // Click the login button... 
     currentView = currentActivity.findViewById(login_button; 
     assertThat(currentView, is(notNullValue())); 
     assertThat(currentView, instanceOf(Button.class)); 
     TouchUtils.clickView(this, currentView); 

     // Wait for the welcome page to start... 
     currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5); 
     assertThat(currentActivity, is(notNullValue())); 

     // Make sure we are logged in... 
     currentView = currentActivity.findViewById(welcome_message); 
     assertThat(currentView, is(notNullValue())); 
     assertThat(currentView, instanceOf(TextView.class)); 
     assertThat(((TextView)currentView).getText().toString(), is("Welcome, MyUsername!")); 
    } 
} 

Questo codice non è, ovviamente, molto leggibile. Ho effettivamente estratto in una semplice libreria con un'API inglese in questo modo posso solo dire cose come questa:

type("myUsername").intoThe(username_field); 
click(login_button); 

Ho provato ad una profondità di circa 4 attività e sono convinto che l'approccio funziona però come ho detto, sembra esserci un problema di temporizzazione occasionale che non ho completamente capito. Sono ancora interessato a conoscere altri modi per testare le attività.

+3

Si potrebbe provare ad aggiungere l'annotazione FlakyTest per ripetere automaticamente il test quando i problemi di temporizzazione causano un errore. Non una soluzione, in realtà, ma una soluzione praticabile in alcune situazioni. –

+0

Grazie per averlo scritto! Stavo cercando qualcosa con la funzionalità di ActivityMonitors per i miei test. Non riuscivo a trovarli. –

+0

Per quanto ne so, niente di quello che hai fatto sopra non può essere fatto usando 'ActivityInstrumentationTestCase2' – ericn

0

Non l'ho usato personalmente, ma ApplicationTestCase sembra che potrebbe essere quello che stai cercando.

+0

Purtroppo non ci sono esempi che indicano che sia il caso. – SingleShot

+0

Sì, sembra che tu abbia ragione ... è stato ingannato dal nome. Non riesco a capire questo fuori. L'approccio migliore che ho ottenuto finora è l'uso di ActivityUnitTestCase di positron per verificare che la prossima attività sia iniziata, ma ciò non aiuta a costruire storie coerenti. In alternativa, InstrumentationTestCase.launchActivity potrebbe consentire di avviare un numero arbitrario di attività, ma sto ancora cercando di capire il materiale della strumentazione. – Eric

0

C'è un altro modo per fare l'attività multipla usando ActivityInstrumentation classe .. E 'un normale scenario domotico ... prima ottenere l'attenzione di che cosa mai oggetto che si desidera e quindi inviare una chiave Semplice come quel codice di esempio

button.requestFocus(); 
sendKeys(KeyEvent.KEYCODE_ENTER); 

L'unica cosa è la comprensione delle ogni chiamate API ci aiuterà.

8

È sempre possibile utilizzare Robotium. Supporta i test blackbox proprio come Selenium ma per Android. Lo troverai su Robotium.org

+1

L'ultima volta che ho controllato che Robotium non può essere utilizzato tra le Attività. È stato corretto ora? http://stackoverflow.com/questions/3840034/how-do-i-write-a-solo-robotium-testcase-that-uses-the-builtin-camera-to-take-a-pi – user77115

+3

Ha sempre ha funzionato su Attività purché appartengano allo stesso processo. – Renas

21

Date un'occhiata a Robotium
'un test framework open-source creato per rendere automatica test black-box di applicazioni Android significativamente più veloce e più facile che ciò che è possibile con i test di strumentazione Android out-of-the -scatola.'

Homepage: http://www.robotium.org/
Fonte: http://github.com/jayway/robotium

Si prega di notare che il progetto Robotium è mantenuto dalla società per cui lavoro

+0

ciao, c'è uno strumento di registrazione per questo? Ho controllato molti siti web e ho trovato testdroid che registra gli script e lo esegue. Sfortunatamente non è un freeware, conosci qualche freeware che fa il processo di registrazione? – thndrkiss

+0

@thndrkiss: non conosco nessuno di questi strumenti. Se fai una domanda sul forum di Robotium, è probabile che tu abbia una risposta migliore. –

+2

Robotium è un risparmiatore di vita. Renderà il tuo test estremamente facile da scrivere (in pratica stai parlando in inglese: fai clic su questo, premi il pulsante indietro, ecc.) Puoi testare qualsiasi cosa ma non ti è richiesto di conoscere i dettagli minuscoli. Ha almeno due importanti vantaggi: puoi testare le app di cui non hai il codice sorgente, e si basa sull'interfaccia utente che lo rende molto robusto (cambi i tuoi controller/modelli molto più delle tue visualizzazioni ...) – tiktak

0

Will accettato il lavoro approccio con diverse attività da diverse applicazioni, firmato da diversi certificati? In caso contrario, Robotium è il modo migliore per testare le attività all'interno della stessa applicazione.

3

Ho creato uno strumento di registrazione e riproduzione per Android e lo ho reso disponibile su GitHub. È facile da configurare e utilizzare, non richiede programmazione, funziona contro dispositivi reali (che non devono essere radicati) e salva automaticamente gli screenshot durante i test.

+0

Questo sembra promettente. Per coloro che non vedono il punto: questa sembra essere una soluzione piuttosto buona per testare i gesti (toccando, trascinando e altre cose) – tiktak

1

su cui sto lavorando più o meno la stessa cosa, e io probabilmente andare con una variazione sul risposta accettata a questa domanda, ma ho incontrato Calculuon(gitHub) durante le mie ricerche per un soluzione.

3

Prima di tutto, utilizzare "ActivityInstrumentationTestCase2" e non "InstrumentationTestCase" come classe base. Uso Robotium e collaudo regolarmente tra più attività. Ho scoperto che devo specificare l'attività di login come tipo generico (e argomento di classe per il costruttore).

Il costruttore 'ActivityInstrumentationTestCase2' ignora l'argomento del pacchetto e non lo richiede. Il costruttore che accetta il pacchetto è deprecato.

Dal Javadocs: "ActivityInstrumentationTestCase2 (String pkg, classe activityClass) Questo costruttore è sconsigliato utilizzare ActivityInstrumentationTestCase2 (Class) invece"

Utilizzando la classe di base consigliata permette al quadro di gestire certi boilerplate, come iniziare la tua attività. Ciò avviene con la chiamata a 'getActivity()', se necessario.

3

Trovato utile con un paio di modifiche. In primo luogo getInstrumentation().waitForIdleSync() curerà il flakiness SingleShot parla di e anche InstrumentationTestCase ha una funzione lauchActivity che può sostituire le righe di attività di avvio.

+0

grazie, questa è roba buona! – icecreamman

2

si può fare in questo modo per evitare il fiocco tempi di attesa fuori sincrono:

final Button btnLogin = (Button) getActivity().findViewById(R.id.button); 
Instrumentation instrumentation = getInstrumentation(); 

// Register we are interested in the authentication activity... 
Instrumentation.ActivityMonitor aMonitor = 
     instrumentation.addMonitor(mynextActivity.class.getName(), null, false); 

getInstrumentation().runOnMainSync(new Runnable() { 
     public void run() { 
      btnLogin.performClick(); 
     } 
    }); 

getInstrumentation().waitForIdleSync(); 

//check if we got at least one hit on the new activity 
assertTrue(getInstrumentation().checkMonitorHit(aMonitor, 1)); 
4

Mi sorprende che nessuno ha menzionato alcuni dei principali automatizzato strumenti di test funzionali. Rispetto a Robotium, questi non richiedono la scrittura del codice Java.

MonkeyTalk: uno strumento open-source sostenuto dalla società Gorilla Logic.Pro: fornisce la registrazione e un linguaggio di scripting di livello superiore più facile per gli utenti non tecnici ed è multipiattaforma (include iOS). Considerati tali benefici come requisiti, abbiamo trovato che questa sia la soluzione migliore. Permette anche di customization oltre a ciò che può essere fatto nel loro linguaggio di scripting usando Javascript.

Calabash-Android: uno strumento open-source per le funzionalità in stile Cucumber. Pro: scrivi funzionalità nel linguaggio Gherkin che è Business Readable, Domain Specific Language che ti consente di descrivere il comportamento del software senza specificare in dettaglio come viene implementato tale comportamento. Supporto simile ma non esatto è disponibile per iOS in cucumber-ios. Le capacità di registrazione non sono buone, in quanto producono un output binario.

Un paio di altri riferimenti:

  • Ecco alcuni additional comparisons tra Robotium, Monkeytalk e Calabash. Menziona TestDroid come un'altra possibilità .
  • Questo blog menziona quanto sopra oltre a NativeDriver e Bot-bot.
0

Questa risposta è basata sulla risposta accettata ma modificata per risolvere il problema di temporizzazione che per me è diventato coerente dopo aver aggiunto circa una mezza dozzina di test. @ pajato1 ottiene il merito per aver risolto il problema di temporizzazione, come citato nei commenti di risposta accettati.

/** 
* Creates a test Activity for a given fully qualified test class name. 
* 
* @param fullyQualifiedClassName The fully qualified name of test activity class. 
* 
* @return The test activity object or null if it could not be located. 
*/ 
protected AbstractTestActivity getTestActivity(final String fullyQualifiedClassName) { 
    AbstractTestActivity result = null; 

    // Register our interest in the given activity and start it. 
    Log.d(TAG, String.format("Running test (%s) with main class: %s.", getName(), fullyQualifiedClassName)); 
    instrumentation = getInstrumentation(); 

    Intent intent = new Intent(Intent.ACTION_MAIN); 
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    intent.setClassName(instrumentation.getTargetContext(), fullyQualifiedClassName); 
    // Wait for the activity to finish starting 
    Activity activity = instrumentation.startActivitySync(intent); 

    // Perform basic sanity checks. 
    assertTrue("The activity is null! Aborting.", activity != null); 
    String format = "The test activity is of the wrong type (%s)."; 
    assertTrue(String.format(format, activity.getClass().getName()), activity.getClass().getName().equals(fullyQualifiedClassName)); 
    result = (AbstractTestActivity) activity; 

    return result; 
} 
-2

Prova il test di strumento di scimmia

Fase 1:

aprire il terminale Android in studio (Strumenti-> terminale aperto)

Fase 2:

Per usare la scimmia , apri un prompt dei comandi e semplicemente naviagte nella seguente directory.

export PATH=$PATH:/home/adt-bundle-linux-x86-20140702/sdk/platform-tools 

Fase 3:

aggiungere questo comando scimmia nel terminale e premere Invio ..

vedere la magia nel vostro emulatore.

adb shell monkey -p com.example.yourpackage -v 500 

500- è il conteggio della frequenza o il numero di eventi da inviare per il test.

è possibile modificare questo conteggio ..

Più di riferimento,

http://www.tutorialspoint.com/android/android_testing.htm

http://androidtesting.blogspot.in/2012/04/android-testing-with-monkey-tool.html

+0

I downvoters devono dire il motivo del downvoting ... questo è un codice funzionante ... e anche un metodo di test ufficiale. Se qualche errore sono pronto a correggere la mia risposta .. –

Problemi correlati