Cómo probar los fragmentos de tu app

Los fragmentos funcionan como contenedores reutilizables dentro de tu app, que te permiten presentar el mismo diseño de la interfaz de usuario en una variedad de actividades y configuraciones. Dada la versatilidad de estos fragmentos, es importante validar que proporcionen una experiencia uniforme y eficiente en cuanto a los recursos:

  • La apariencia de tu fragmento debe ser coherente en todas las configuraciones de diseño, incluidas las que admiten tamaños de pantalla más grandes o la orientación horizontal del dispositivo.
  • No crees una jerarquía de vista de fragmentos a menos que el usuario pueda verlo.

Este documento describe cómo incluir API provistas por el marco de trabajo en las pruebas que evalúan el comportamiento de cada fragmento.

Cómo cambiar el estado de un fragmento

A fin de ayudar a establecer las condiciones para realizar estas pruebas, AndroidX proporciona una biblioteca, FragmentScenario, que permite crear fragmentos y cambiar su estado.

Cómo configurar la ubicación del artefacto de prueba

Para usar FragmentScenario como se pretende, define el artefacto de prueba de fragmentos en el APK de prueba de tu app, como se muestra en el siguiente fragmento de código:

app/build.gradle

dependencies {
    // ...
    debugImplementation 'androidx.fragment:fragment-testing:1.1.0-alpha07'
}

Cómo crear un fragmento

FragmentScenario incluye métodos para iniciar los siguientes tipos de fragmentos:

Los métodos también admiten los siguientes tipos de fragmentos:

  • Fragmentos gráficos, que contienen una interfaz de usuario. Para iniciar este tipo de fragmento, invoca a launchFragmentInContainer(). FragmentScenario adjunta el fragmento al controlador de la vista raíz de una actividad. De lo contrario, la actividad que contenga estará vacía.
  • Fragmentos no gráficos (también denominados fragmentos sin interfaz gráfica), que almacenan o procesan a corto plazo la información incluida en varias actividades. Para iniciar este tipo de fragmento, invoca a launchFragment(). FragmentScenario adjunta este tipo de fragmento a una actividad completamente vacía, que no tiene una vista de raíz.

Después de iniciar uno de estos tipos de fragmentos, FragmentScenario cambia el fragmento bajo prueba al estado RESUMED. Este estado indica que el fragmento se está ejecutando. Si estás probando un fragmento gráfico, también es visible para los usuarios, por lo que puedes evaluar la información sobre los elementos de la IU utilizando pruebas de IU de Espresso.

Los siguientes fragmentos de código muestran cómo iniciar cada tipo de fragmento:

Ejemplo de fragmento gráfico

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        // The "state" and "factory" arguments are optional.
        val fragmentArgs = Bundle().apply {
            putInt("selectedListItem", 0)
        }
        val factory = MyFragmentFactory()
        val scenario = launchFragmentInContainer<MyFragment>(
                fragmentArgs, factory)
        onView(withId(R.id.text)).check(matches(withText("Hello World!")))
    }
}

Ejemplo de fragmento no gráfico

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        // The "state" and "factory" arguments are optional.
        val fragmentArgs = Bundle().apply {
            putInt("numElements", 0)
        }
        val factory = MyFragmentFactory()
        val scenario = launchFragment<MyFragment>(fragmentArgs, factory)
    }
}

Cómo recrear el fragmento

Si un dispositivo tiene pocos recursos, el sistema podría finalizar la actividad que contenga el fragmento, lo que requeriría que la aplicación recreara el fragmento cuando el usuario regrese a ella. Para simular esta situación, invoca a recreate():

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<MyFragment>()
        scenario.recreate()
    }
}

Cuando la clase FragmentScenario recrea el fragmento bajo prueba, este regresa al estado de ciclo de vida en el que se encontraba antes de que se lo recreara.

Cómo cambiar el fragmento a un nuevo estado

En las pruebas de IU de tu aplicación, generalmente es suficiente con iniciar y recrear el fragmento que se está probando. Sin embargo, en las pruebas unitarias más detalladas, también se puede evaluar el comportamiento del fragmento a medida que pasa de un estado de ciclo de vida a otro.

Para cambiar el estado de ciclo de vida de un fragmento, invoca a moveToState(). Este método admite los siguientes estados como argumentos: CREATED, STARTED, RESUMED y DESTROYED. Esta acción simula una situación en la que la actividad que contiene el fragmento cambia de estado porque la interrumpe otra aplicación o una acción del sistema.

En el siguiente fragmento de código, aparece un ejemplo de uso de moveToState():

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<MyFragment>()
        scenario.moveToState(State.CREATED)
    }
}

Cómo activar acciones en el fragmento

Para activar acciones en tu fragmento bajo prueba, usa los comprobadores de Espresso para interactuar con los elementos de tu vista:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<MyFragment>()
        onView(withId(R.id.refresh))
                .perform(click())
    }
}

Si necesitas invocar a un método en el propio fragmento, como responder a una selección en el menú de opciones, puedes hacerlo de forma segura implementando FragmentAction:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<MyFragment>()
        scenario.onFragment(fragment ->
            fragment.onOptionsItemSelected(clickedItem) {
                // Update fragment's state based on selected item.
            }
        }
    }
}