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 varietà di attività e configurazioni di layout. Data la versatilità dei frammenti, è importante verificare che offrano un'esperienza coerente ed efficiente nell'uso delle risorse. Nota:
- Il frammento non deve dipendere da un'attività principale o da un frammento specifico.
- 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 fragment-testing
di AndroidX
fornisce la classe FragmentScenario
per creare frammenti e modificarne
Lifecycle.State
.
Dichiarazione delle dipendenze
Per utilizzare FragmentScenario
, definisci l'elemento fragment-testing
nel
file build.gradle
dell'app utilizzando debugImplementation
, come mostrato nel
seguente esempio:
trendy
dependencies { def fragment_version = "1.7.1" debugImplementation "androidx.fragment:fragment-testing:$fragment_version" }
Kotlin
dependencies { val fragment_version = "1.7.1" debugImplementation("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 di asserzioni disponibili, consulta la pagina relativa alla configurazione di un progetto per AndroidX Test.
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 di visualizzazione principale di un'attività. Questo campo contenente attività è altrimenti vuoto.launch()
, per i test senza l'interfaccia utente del frammento.FragmentScenario
allega questo tipo di frammento a un'attività vuota, priva di una vista principale.
Dopo aver avviato uno di questi tipi di frammenti, FragmentScenario
indirizza 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 suoi elementi UI utilizzando i test della UI 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)
...
}
}
Fornire dipendenze
Se i frammenti hanno dipendenze, puoi fornire versioni di test di queste dipendenze fornendo un FragmentFactory
personalizzato ai metodi launchInContainer()
o launch()
.
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val someDependency = TestDependency()
launchFragmentInContainer {
EventFragment(someDependency)
}
...
}
}
Per ulteriori informazioni sull'utilizzo di FragmentFactory
per fornire dipendenze ai frammenti, consulta Gestione dei frammenti.
Sposta il frammento in 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
. Tuttavia, nei test delle unità più granulari, 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 diverso del ciclo di vita, 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 per qualsiasi motivo il proprio stato.
L'esempio seguente avvia un frammento di test in stato INITIALIZED
e poi 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 che ha poche risorse, il sistema potrebbe eliminare l'attività contenente il frammento. Questa situazione richiede all'app di ricreare il frammento quando l'utente vi torna.
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, quindi li ricrea. Quando la classe FragmentScenario
ricrea il frammento in fase di test, il frammento torna allo stato del ciclo di vita in cui si trovava prima di essere eliminato.
Interazione con i frammenti UI
Per attivare le azioni dell'interfaccia utente nel frammento in fase di test, utilizza i matcher di visualizzazione Espresso per interagire con gli elementi della vista:
@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 rispondere 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()
}
}
}
Testa le azioni della finestra di dialogo
FragmentScenario
supporta anche il test dei
frammenti di dialogo. Anche se i frammenti di dialogo contengono elementi UI, il loro layout viene compilato in una finestra separata anziché nell'attività stessa. Per questo motivo, utilizza FragmentScenario.launch()
per testare i frammenti di finestra di dialogo.
L'esempio seguente verifica la procedura di chiusura della finestra 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())
}
}