Concetti fondamentali sul test di app Android

Questa pagina illustra i principi fondamentali dei test delle app Android, tra cui: le best practice principali e i relativi vantaggi.

Vantaggi dei test

I test sono parte integrante del processo di sviluppo dell'app. Eseguendo test la tua app in modo coerente, puoi verificarne la correttezza, il funzionamento comportamento e usabilità prima di rilasciarla pubblicamente.

Puoi testare manualmente la tua app navigando al suo interno. Potresti usare emulatori e dispositivi diversi, cambiare la lingua di sistema e provare a generare ogni errore dell'utente o attraversare ogni flusso utente.

Tuttavia, i test manuali presentano una scarsa scalabilità e può essere facile trascurare di regressione lineare nel comportamento della tua app. I test automatici prevedono l'utilizzo di strumenti che eseguono test per conto tuo, ovvero più velocemente, più ripetibile e ti offre feedback più utili sulla tua app nelle prime fasi di sviluppo e il processo di sviluppo.

Tipi di test in Android

Le applicazioni mobile sono complesse e devono funzionare bene in molti ambienti. Come esistono molti tipi di test.

Oggetto

Ad esempio, sono disponibili diversi tipi di test a seconda dell'argomento:

  • Test funzionale: la mia app fa ciò che dovrebbe?
  • Test del rendimento: lo fa in modo rapido ed efficiente?
  • Test di accessibilità: funziona bene con i servizi di accessibilità?
  • Test di compatibilità: funziona bene su qualsiasi dispositivo e livello API?

Ambito

I test variano anche in base alle dimensioni o al grado di isolamento:

  • I test delle unità o i piccoli test verificano solo una piccola parte dell'app. come un metodo o una classe.
  • I test end-to-end o test di grandi dimensioni verificano parti più grandi dell'app nella contemporaneamente, ad esempio un'intera schermata o un flusso utente.
  • I test medi sono a metà e verificano l'integrazione tra due più unità.
di Gemini Advanced.
I test possono essere piccoli, medi o grandi.
Figura 1: ambiti di test in un'applicazione tipica.

Esistono molti modi per classificare i test. Tuttavia, la distinzione più importante per gli sviluppatori di app è la piattaforma in cui vengono eseguiti i test.

Confronto tra test strumentati e locali

Puoi eseguire test su un dispositivo Android o su un altro computer:

  • I test strumentati vengono eseguiti su un dispositivo Android fisico o emulato. L'app viene sviluppata e installata insieme a un'app di test che inserisce comandi e legge lo stato. I test strumentali sono in genere i test dell'interfaccia utente, l'avvio di un'app e interagendo con quest'ultima.
  • I test locali vengono eseguiti sulla macchina di sviluppo o su un server, chiamati anche test lato host. Di solito sono piccole e veloci, isolano il soggetto sottoposto a test dal resto dell'app.
di Gemini Advanced.
I test possono essere eseguiti come test instrumentati su un dispositivo o test locali sulla macchina di sviluppo.
Figura 2: diversi tipi di test a seconda di dove vengono eseguiti.

Non tutti i test delle unità sono locali e non tutti i test end-to-end vengono eseguiti su un dispositivo. Per esempio:

  • Test locale importante: puoi utilizzare un simulatore Android eseguito in locale, ad esempio Robolectric.
  • Test con strumenti di piccole dimensioni: puoi verificare che il codice funzioni correttamente con una come un database SQLite. Puoi eseguire questo test più dispositivi per verificare l'integrazione con più versioni di SQLite.

Esempi

I seguenti snippet mostrano come interagire con l'UI in un test dell'interfaccia utente con strumenti che fa clic su un elemento e verifica che un altro .

espresso

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

UI di scrittura

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

Questo snippet mostra parte di un test delle unità per un ViewModel (locale, lato host) test):

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

Definizione di una strategia di test

In un mondo ideale, dovresti testare ogni riga di codice della tua app su ogni dispositivo con cui è compatibile la tua app. Purtroppo, questo approccio è troppo lento costoso per essere pratico.

Una buona strategia di test trova il giusto equilibrio tra la fedeltà di un il test, la velocità e l'affidabilità. La somiglianza tra l'ambiente di test e un dispositivo reale determina la fedeltà del test. Vengono eseguiti test di affidabilità superiore dispositivi emulati o il dispositivo fisico stesso. Potrebbero essere eseguiti test di fedeltà inferiore sulla JVM della workstation locale. I test ad alta precisione sono spesso più lenti e richiedono più risorse, pertanto non tutti i test devono essere ad alta fedeltà.

Test irregolari

Gli errori si verificano anche nelle esecuzioni di test progettate e implementate correttamente. Ad esempio: quando esegui un test su un dispositivo reale, potrebbe iniziare un aggiornamento automatico durante una fase di test e far sì che non vada a buon fine. L'utilizzo di lieve condizioni di gara nel codice si verificano solo una piccola percentuale delle volte. Test che non superano il 100% sono irregolari.

Architettura verificabile

Con un'architettura dell'app testabile, il codice segue una struttura che consente per testare facilmente le diverse parti in modo isolato. Le architetture testabili hanno altri vantaggi, come una migliore leggibilità, manutenibilità, scalabilità e riutilizzabili.

Un'architettura non testabile produce quanto segue:

  • Test più grandi, più lenti e più irregolari. Le classi che non possono essere sottoposte a test di unità potrebbero avere in base ai test di integrazione o dell'interfaccia utente più grandi.
  • Meno opportunità di test di scenari diversi. I test più grandi sono più lenti, quindi il test di tutti i possibili stati di un'app potrebbe non essere realistico.

Per scoprire di più sulle linee guida sull'architettura, consulta la guida alle app dell'architettura.

Approcci al disaccoppiamento

Se puoi estrarre parte di una funzione, una classe o un modulo dal resto, è più facile ed efficace. Questa pratica è nota come disaccoppiamento e è il concetto più importante per l'architettura testabile.

Le tecniche di disaccoppiamento più comuni includono:

  • Suddividi un'app in livelli, ad esempio presentazione, dominio e dati. Puoi suddividono anche un'app in moduli, uno per funzionalità.
  • Evita di aggiungere logica a entità con dipendenze grandi, ad esempio attività e frammenti. Usa queste classi come punto di accesso al framework e Spostare UI e logica di business altrove, ad esempio in un oggetto Composable, ViewModel o livello del dominio.
  • Evita le dipendenze del framework dirette nelle classi contenenti la logica di business. Ad esempio, non utilizzare i contesti Android in ViewModels.
  • Rendi più facile sostituire le dipendenze. Ad esempio, utilizza interfacce invece di implementazioni concrete. Utilizza le funzionalità di Inserimento delle dipendenze anche se non utilizzi un framework DI.

Passaggi successivi

Ora che sai perché eseguire i test e quali sono i due tipi principali di test, puoi leggi Che cosa verificare.

In alternativa, se vuoi creare il tuo primo test e imparare facendo pratica, controlla nei codelab per i test.