support - test android
Android espresso iniciar sesiĆ³n una vez antes de ejecutar pruebas (5)
Agregue la siguiente función en su archivo de prueba, reemplace el código en el bloque de prueba con el suyo que realiza las acciones de inicio de sesión.
@Before
fun setUp() {
// Login if it is on the LoginActivity
try {
// Type email and password
Espresso.onView(ViewMatchers.withId(R.id.et_email))
.perform(ViewActions.typeText("a_test_account_username"), ViewActions.closeSoftKeyboard())
Espresso.onView(ViewMatchers.withId(R.id.et_password))
.perform(ViewActions.typeText("a_test_account_password"), ViewActions.closeSoftKeyboard())
// Click login button
Espresso.onView(ViewMatchers.withId(R.id.btn_login)).perform(ViewActions.click())
} catch (e: NoMatchingViewException) {
//view not displayed logic
}
}
Con esta anotación @Antes, esta función de configuración se ejecutará antes que cualquier otra prueba que tenga en este archivo de prueba. Si la aplicación llega a la Actividad de inicio de sesión, inicie sesión en esta función de configuración. El ejemplo aquí asume que hay un EditText para correo electrónico y contraseña, así como un botón de inicio de sesión. Utiliza Expresso para escribir el correo electrónico y la contraseña, luego presiona el botón de inicio de sesión. El bloque try catch es para asegurarse de que si no está aterrizando en la Actividad de inicio de sesión, detectará el error y no hará nada, y si no aterrizó en la Actividad de inicio de sesión, entonces es bueno realizar otras pruebas de todos modos.
Nota: este es el código Kotlin, pero parece muy similar a Java.
He estado tratando de cubrir mi aplicación de Android con pruebas y recientemente comencé a usar espresso . Muy impresionado con eso hasta ahora. Sin embargo, la mayor parte de la funcionalidad de mi aplicación requiere que los usuarios estén conectados. Y como todas las pruebas son independientes, esto requiere el registro de un nuevo usuario para cada prueba. Esto funciona bien, sin embargo, el tiempo requerido para cada prueba aumenta considerablemente debido a esto.
Estoy tratando de encontrar una manera de registrar un usuario una vez en una clase (de pruebas) y luego usar esa misma cuenta de usuario para realizar todas las pruebas en esa clase.
Una forma en la que he podido hacer esto es tener solo un método de prueba ( @Test
) que ejecute todas las demás pruebas en el orden que deseo. Sin embargo, este es un enfoque de todo o nada, ya que la tarea gradle cAT
solo genera los resultados una vez al final sin proporcionar información sobre las pruebas intermedias que pueden haber pasado o fallado.
También probé el enfoque @BeforeClass
que, sin embargo, no funcionó (no hubo salida de gradle de la clase en la que había usado esto incluso con la opción de depuración y pareció que tomó mucho tiempo antes de pasar a la siguiente clase de pruebas).
¿Existe un mejor enfoque para registrar un usuario una vez al inicio de una clase y luego cerrar la sesión una vez que finaliza la prueba?
Cualquier ayuda apreciada.
El enfoque con el inicio de sesión con @Before es bueno, pero si su inicio de sesión es lento, el tiempo de prueba combinado será muy lento.
Aquí hay un gran truco que funciona. La estrategia es simple: ejecute cada prueba en orden y falle cada prueba antes de que tengan la oportunidad de ejecutarse si falla una determinada prueba (en este caso, prueba de inicio de sesión).
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@LargeTest
public class YourTestsThatDependsOnLogin {
private static failEverything;
@Before
public void beforeTest() {
// Fail every test before it has a chance to run if login failed
if (failEverything) {
Assert.fail("Login failed so every test should fail");
}
}
@Test
public void test0_REQUIREDTEST_login() {
failEverything = true;
// Your code for login
// Your login method must fail the test if it fails.
login();
failEverything = false; // We are safe to continue.
}
// test1 test2 test3 etc...
}
Pros:
- Lo que solicitó funciona y es rápido (si su inicio de sesión es lento)
- Puede tener varias pruebas que dependen de diferentes inicios de sesión, lo que significa que puede hacer un montón de pruebas para user1, luego un montón de pruebas para user2, etc.
- Rápido de configurar.
Contras:
- No es un procedimiento estándar y alguien podría preguntarse por qué fallan tantas pruebas ...
- Debe burlarse de los usuarios en lugar de iniciar sesión. Debe probar su inicio de sesión por separado y las pruebas no deben depender entre sí.
Lo ideal sería probar la funcionalidad de inicio / cierre de sesión en un conjunto de pruebas que solo prueban diferentes escenarios de inicio / cierre de sesión, y permitir que las otras pruebas se centren en otros casos de uso. Sin embargo, dado que los otros escenarios dependen de que el usuario haya iniciado sesión, parece que una forma de resolver esto sería proporcionar una versión simulada del componente de la aplicación que maneja el inicio de sesión. Para las otras pruebas dependientes del inicio de sesión, inyectaría este simulacro al inicio y devolvería las credenciales de usuario simuladas con las que el resto de la aplicación puede trabajar.
Aquí hay un ejemplo donde se usa Dagger, Mockito y Espresso para lograr esto: https://engineering.circle.com/instrumentation-testing-with-dagger-mockito-and-espresso/
Mi aplicación también requiere que el usuario inicie sesión durante la ejecución de la prueba. Sin embargo, puedo iniciar sesión la primera vez y la aplicación recuerda mi nombre de usuario / contraseña durante la ejecución de la prueba. De hecho, recuerda las credenciales hasta que lo obligo a olvidarlas o desinstalar e instalar la aplicación nuevamente.
Durante una ejecución de prueba, después de cada prueba, mi aplicación pasa al fondo y se reanuda al comienzo de la siguiente prueba. Supongo que su aplicación requiere que un usuario ingrese sus credenciales cada vez que lo traiga al frente desde el fondo (¿quizás la aplicación bancaria?). ¿Hay una configuración en su aplicación que "Recordará sus credenciales"? En caso afirmativo, puede habilitarlo fácilmente después de iniciar sesión por primera vez en su ejecución de prueba.
Aparte de eso, creo que deberías hablar con los desarrolladores para que te proporcionen una forma de recordar tus credenciales.
Pruebo una aplicación que requiere este mismo escenario. La forma más fácil de solucionar esto es dividir el inicio y cierre de sesión en sus propias clases de prueba. Luego agrega todas sus clases de prueba a una suite, comenzando y terminando con las suites login y logout respectivamente. Tus suites de prueba terminan pareciéndose a esto.
@RunWith(Suite.class)
@Suite.SuiteClasses({
LoginSetup.class,
SmokeTests.class,
LogoutTearDown.class
})
EDITAR: Aquí hay un ejemplo de las pruebas LoginSetup y LogoutTearDown. Esta solución realmente debería ser solo para pruebas de extremo a extremo y comprender una pequeña parte de sus esfuerzos de prueba. fejd proporciona una solución para una pila de pruebas completa que también debe considerarse.
@LargeTest
public class SmokeSetup extends LogInTestFixture {
@Rule
public ActivityTestRule<LoginActivity> mLoginActivity = new ActivityTestRule<>(LoginActivity.class);
@Test
public void testSetup() throws IOException {
onView(withId(R.id.username_field)).perform(replaceText("username"));
onView(withId(R.id.password_field)).perform(replaceText("password"));
onView(withId(R.id.login_button)).perform(click());
}
}
@LargeTest
public class LogoutTearDown extends LogInTestFixture {
@Rule
public ActivityTestRule<MainActivity> mMainActivity = new ActivityTestRule<>(MainActivity.class);
@Test
public void testLogout() throws IOException {
onView(withId(R.id.toolbar_menu)).perform(click());
onView(withId(R.id.logout_button)).perform(click());
}
}