Questo argomento descrive come includere le API fornite dal framework nei test che valutano il comportamento di ogni frammento.
I frammenti fungono da contenitori riutilizzabili all'interno dell'app, consentendoti di presentare lo stesso layout dell'interfaccia utente in una serie di attività e configurazioni di layout. Data la versatilità dei frammenti, è importante verificare che forniscano un'esperienza coerente ed efficiente nell'uso delle risorse. Nota:
- Il frammento non deve dipendere da un'attività o da un frammento specifici.
- Non devi creare la gerarchia delle visualizzazioni di un frammento a meno che il frammento non sia visibile all'utente.
Per configurare le condizioni per l'esecuzione di questi test, la libreria AndroidX fragment-testing
fornisce la classe FragmentScenario
per creare frammenti e modificare Lifecycle.State
.
Dichiarazione delle dipendenze
Per utilizzare FragmentScenario
, definisci l'artefatto fragment-testing-manifest
nel file build.gradle
dell'app utilizzando debugImplementation
e l'artefatto fragment-testing
utilizzando androidTestImplementation
, come mostrato nell'esempio seguente:
trendy
dependencies { def fragment_version = "1.8.1" debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version" androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version" }
Kotlin
dependencies { val fragment_version = "1.8.1" debugImplementation("androidx.fragment:fragment-testing-manifest:$fragment_version") androidTestImplementation("androidx.fragment:fragment-testing:$fragment_version") }
Gli esempi di test in questa pagina utilizzano le asserzioni delle librerie Espresso e Truth. Per informazioni su altre librerie di test e asserzioni disponibili, consulta Configurare il progetto per il test AndroidX.
Crea un frammento
FragmentScenario
include i seguenti metodi per avviare i frammenti nei test:
launchInContainer()
, per testare l'interfaccia utente di un frammento.FragmentScenario
collega il frammento al controller della vista principale di un'attività. In caso contrario, il campo contenente attività è vuoto.launch()
, per i test senza l'interfaccia utente del frammento.FragmentScenario
allega questo tipo di frammento a un'attività vuota, che non ha una visualizzazione root.
Dopo aver avviato uno di questi tipi di frammenti, FragmentScenario
sposta il frammento sottoposto a test a uno stato specificato. Per impostazione predefinita, questo stato è RESUMED
,
ma puoi sostituirlo con l'argomento initialState
. Lo stato RESUMED
indica che il frammento è in esecuzione ed è visibile all'utente. Puoi valutare le informazioni sui relativi elementi UI utilizzando i test dell'interfaccia utente di Espresso.
I seguenti esempi di codice mostrano come avviare il frammento utilizzando ciascun metodo:
Esempio di lancioInContainer()
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" argument is optional.
val fragmentArgs = bundleOf(“selectedListItem” to 0)
val scenario = launchFragmentInContainer<EventFragment>(fragmentArgs)
...
}
}
Esempio di lancio()
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" arguments are optional.
val fragmentArgs = bundleOf("numElements" to 0)
val scenario = launchFragment<EventFragment>(fragmentArgs)
...
}
}
Fornisci le dipendenze
Se i tuoi frammenti hanno dipendenze, puoi fornire le versioni di test di queste dipendenze fornendo un valore FragmentFactory
personalizzato ai metodi launchInContainer()
o launch()
.
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val someDependency = TestDependency()
launchFragmentInContainer {
EventFragment(someDependency)
}
...
}
}
Per maggiori informazioni sull'utilizzo di FragmentFactory
per fornire
dipendenze ai frammenti, consulta
Gestore dei frammenti.
Porta il frammento a un nuovo stato
Nei test dell'interfaccia utente dell'app, in genere è sufficiente avviare il frammento
in fase di test e iniziare a testarlo da uno stato RESUMED
. Nei test delle unità più granulari, tuttavia, potresti anche valutare il comportamento del frammento durante la transizione da uno stato del ciclo di vita a un altro. Puoi specificare lo stato iniziale passando l'argomento initialState
a una qualsiasi delle funzioni launchFragment*()
.
Per portare il frammento a uno stato del ciclo di vita diverso, chiama
moveToState()
.
Questo metodo supporta i seguenti stati come argomenti: CREATED
,
STARTED
, RESUMED
e DESTROYED
. Questo metodo simula una situazione in cui il frammento o l'attività contenente il frammento cambia il proprio stato per qualsiasi motivo.
L'esempio seguente avvia un frammento di test nello stato INITIALIZED
e quindi lo sposta nello stato RESUMED
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>(
initialState = Lifecycle.State.INITIALIZED
)
// EventFragment has gone through onAttach(), but not onCreate().
// Verify the initial state.
scenario.moveToState(Lifecycle.State.RESUMED)
// EventFragment moves to CREATED -> STARTED -> RESUMED.
...
}
}
Ricrea il frammento
Se la tua app è in esecuzione su un dispositivo con scarse risorse, il sistema
potrebbe eliminare l'attività contenente il frammento. In questa situazione
è necessario che l'app ricrei il frammento quando l'utente vi ritorna.
Per simulare questa situazione, chiama recreate()
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.recreate()
...
}
}
FragmentScenario.recreate()
elimina il frammento e il relativo host e poi li ricrea. Quando la classe FragmentScenario
ricrea il frammento sottoposto a test, torna allo stato del ciclo di vita in cui si trovava prima di essere eliminato.
Interazione con i frammenti di UI
Per attivare le azioni dell'interfaccia utente nel frammento sottoposto a test, utilizza i matcher della visualizzazione Espresso per interagire con gli elementi nella visualizzazione:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
onView(withId(R.id.refresh)).perform(click())
// Assert some expected behavior
...
}
}
Se devi chiamare un metodo sul frammento stesso, ad esempio rispondendo a una selezione nel menu opzioni, puoi farlo in sicurezza ottenendo un riferimento al frammento utilizzando FragmentScenario.onFragment()
e passando un FragmentAction
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.onFragment { fragment ->
fragment.myInstanceMethod()
}
}
}
Azioni della finestra di dialogo di test
FragmentScenario
supporta anche il test dei
frammenti di dialogo. Sebbene i frammenti di finestre di dialogo contengano elementi UI, il loro layout viene completato in una finestra separata anziché nell'attività stessa. Per questo motivo, utilizza FragmentScenario.launch()
per testare i frammenti di finestre di dialogo.
L'esempio seguente verifica il processo di chiusura delle finestre di dialogo:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testDismissDialogFragment() {
// Assumes that "MyDialogFragment" extends the DialogFragment class.
with(launchFragment<MyDialogFragment>()) {
onFragment { fragment ->
assertThat(fragment.dialog).isNotNull()
assertThat(fragment.requireDialog().isShowing).isTrue()
fragment.dismiss()
fragment.parentFragmentManager.executePendingTransactions()
assertThat(fragment.dialog).isNull()
}
}
// Assumes that the dialog had a button
// containing the text "Cancel".
onView(withText("Cancel")).check(doesNotExist())
}
}