Crea test delle unità locali

Un test locale viene eseguito direttamente sulla tua workstation, anziché su un dispositivo Android dispositivo o emulatore. Pertanto, utilizza la Java Virtual Machine (JVM) locale, anziché su un dispositivo Android. I test locali consentono di valutare della logica dell'app. Tuttavia, la mancata interazione con i Il framework Android crea un limite nei tipi di test che puoi eseguire.

Un test delle unità verifica il comportamento di una piccola sezione di codice, l'unità sotto test. Per farlo, esegue il codice e controlla il risultato.

I test delle unità sono generalmente semplici, ma la loro configurazione può rappresentare un problema quando l'unità di misura sotto test non è progettato in base alla verificabilità:

  • Il codice che vuoi verificare deve essere accessibile da un test. Per Ad esempio, non puoi testare direttamente un metodo privato. Devi, invece, testare il corso utilizzando le API pubbliche.
  • Per eseguire i test delle unità isolando, le dipendenze dell'unità sottoposti a test devono essere sostituiti con componenti sotto il tuo controllo, come falsi o in un altro doppio di test. Questo è particolarmente problematico se il codice dipende il framework Android.

Per scoprire le strategie più comuni per i test delle unità in Android, leggi l'articolo Cosa test.

Località dei test locali

Per impostazione predefinita, i file di origine per i test delle unità locali vengono inseriti module-name/src/test/. Questa directory esiste già quando ne crei una nuova utilizzando Android Studio.

Aggiunta di dipendenze di test

Devi anche configurare le dipendenze di test per fare in modo che il progetto utilizzi API standard fornite dal framework di test JUnit.

Per farlo, apri il file build.gradle del modulo dell'app e specifica quanto segue librerie come dipendenze. Utilizza la funzione testImplementation per indicare al set di origini di test locali e non all'applicazione:

dependencies {
  // Required -- JUnit 4 framework
  testImplementation "junit:junit:$jUnitVersion"
  // Optional -- Robolectric environment
  testImplementation "androidx.test:core:$androidXTestVersion"
  // Optional -- Mockito framework
  testImplementation "org.mockito:mockito-core:$mockitoVersion"
  // Optional -- mockito-kotlin
  testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
  // Optional -- Mockk framework
  testImplementation "io.mockk:mockk:$mockkVersion"
}

Crea una classe di test delle unità locali

Scrivi la classe di test delle unità locali come classe di test JUnit 4.

Per farlo, crea una classe contenente uno o più metodi di test, di solito in module-name/src/test/. Un metodo di test inizia con l'annotazione @Test e contiene il codice da esercitare e verificare un singolo aspetto del componente che che vuoi testare.

L'esempio seguente mostra come implementare una classe di test delle unità locali. La metodo di test emailValidator_correctEmailSimple_returnsTrue()tenta di verificare isValidEmail(),che è un metodo disponibile all'interno dell'app. La funzione di test restituisce true seisValidEmail() restituisce anche true.

Kotlin

import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test

class EmailValidatorTest {
  @Test fun emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"))
  }

}

Java

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

class EmailValidatorTest {
  @Test
  public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"));
  }
}

Devi creare test leggibili per valutare se i componenti nel tuo restituiscono i risultati previsti. Ti consigliamo di usare una libreria di asserzioni come come junit.Assert, Hamcrest o Verità. Lo snippet riportato sopra è un esempio di come utilizzare junit.Assert.

Libreria Android simulabile

Quando esegui i test delle unità locali, il plug-in Android per Gradle include una contenente tutte le API del framework Android, corretta nel utilizzata nel progetto. La biblioteca contiene tutti i metodi pubblici e di queste API, ma il codice all'interno dei metodi è stato rimosso. Se presente dei metodi a cui si accede, il test genera un'eccezione.

In questo modo è possibile creare test locali quando si fanno riferimento a classi in Android come Context. Ma soprattutto, consente di usare un modello con le classi di Android.

Simulazione delle dipendenze di Android

Un problema tipico consiste nel scoprire che una classe utilizza una risorsa stringa. Puoi ottenere risorse stringa richiamando il metodo getString() nel metodo Context . Tuttavia, un test locale non può utilizzare Context o nessuno dei suoi metodi perché appartengono al framework Android. Idealmente, la chiamata a getString() sarebbe hanno abbandonato la classe, ma non è sempre una pratica. La soluzione è crea una simulazione o uno stub di Context che restituisca sempre lo stesso valore quando Metodo getString() richiamato.

Con la libreria Android simulabile e framework di simulazione come Mockito o MockK, puoi programmare comportamento di simulazioni delle classi Android nei test delle unità.

Per aggiungere un oggetto fittizio al test delle unità locali utilizzando Mockito, segui questo modello di programmazione:

  1. Includi la dipendenza della libreria Mockito nel file build.gradle, ad esempio descritto in Configurare l'ambiente di test.
  2. All'inizio della definizione della classe di test delle unità, aggiungi il metodo Annotazione @RunWith(MockitoJUnitRunner.class). Questa annotazione indica runner di test simulato per verificare che l'utilizzo del framework sia corretto e semplifica l'inizializzazione degli oggetti fittizi.
  3. Per creare un oggetto fittizio per una dipendenza Android, aggiungi l'annotazione @Mock prima della dichiarazione del campo.
  4. Per evitare il comportamento della dipendenza, puoi specificare una condizione restituisce un valore quando la condizione è soddisfatta utilizzando gli attributi when() e thenReturn() di machine learning.

L'esempio seguente mostra come creare un test delle unità che utilizza una simulazione Oggetto Context in Kotlin creato con Mockito-Kotlin.

import android.content.Context
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock

private const val FAKE_STRING = "HELLO WORLD"

@RunWith(MockitoJUnitRunner::class)
class MockedContextTest {

  @Mock
  private lateinit var mockContext: Context

  @Test
  fun readStringFromContext_LocalizedString() {
    // Given a mocked Context injected into the object under test...
    val mockContext = mock<Context> {
        on { getString(R.string.name_label) } doReturn FAKE_STRING
    }

    val myObjectUnderTest = ClassUnderTest(mockContext)

    // ...when the string is returned from the object under test...
    val result: String = myObjectUnderTest.getName()

    // ...then the result should be the expected one.
    assertEquals(result, FAKE_STRING)
  }
}

Per scoprire di più sull'utilizzo del framework Mockito, consulta l'articolo sull'API Mockito riferimento e la classe SharedPreferencesHelperTest nel codice campione: Prova anche il codelab di test su Android.

Errore: "Metodo ... non preso in giro"

La libreria Android simulabile genera un'eccezione se tenti di accedere a uno qualsiasi dei suoi con il messaggio Error: "Method ... not mocked.

Se le eccezioni generate sono problematiche per i test, puoi modificare il valore in modo che i metodi restituiscano nullo o zero, a seconda del tipo restituito. Per farlo, aggiungi la seguente configurazione nel file build.gradle di primo livello in Groovy:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }