
El patrón de Objeto de página apareció en las pruebas web y demostró ser muy bueno allí. Cuando comencé a automatizar las pruebas para aplicaciones de Android, lo primero que pensé al respecto. Busqué información en la red, pregunté a mis colegas y, en principio, no encontré razones para no intentarlo. Propongo ver qué salió de eso.
El clásico Objeto de página implica dos niveles de abstracción: elementos de página y pruebas. Destaco uno más: la lógica empresarial. Noto que la forma en que construye su marco afectará en gran medida la facilidad de escribir pruebas en el futuro, así como su soporte. Intento hacer que el código de prueba parezca un caso de prueba normal escrito por un probador ordinario. Es decir Empiezo desde el final:
- Estoy escribiendo un código de caso de prueba hermoso y claro,
- Implemento métodos del caso de prueba en la capa de lógica de negocios,
- Describo los elementos necesarios para la prueba.
Este enfoque es bueno porque no hacemos nada extra: el marco se basa tanto como sea necesario para que las pruebas funcionen. Podemos decir que este es el concepto de MVP en las pruebas: rápidamente hicieron una pieza, y ya ha comenzado a traer beneficios. Si primero escribe miles de líneas, describe las páginas de su aplicación y cómo interactuar con ellas, y después de tres meses sale del "agujero" para el primer clic y se da cuenta de que tenía que hacer todo de manera diferente, entonces la mayor parte de su creación estará condenada para siempre ". acumular polvo "en los sótanos de git ... Un verdadero probador sabe que cuanto antes se encuentre un error, más barato será repararlo. Utilice este enfoque en todo: escribió una prueba en un par de horas, la probó, no me gustó, la tiró, aprendió una lección, siguió conduciendo.
Entonces la entrada es:
- Aplicación de Android para operar en bolsa;
- Java para trabajar en la misma pila con los desarrolladores;
- marco básico UI Automator;
- necesita escribir una prueba de inicio de sesión en la aplicación.
Preparación del proyecto
Como intenté integrar lo más posible en el proceso de desarrollo, no comencé a crear un nuevo proyecto. Según la
documentación , las pruebas instrumentales deben colocarse en la carpeta
src/androidTest/java
. En mi caso, el recopilador ya se ha configurado, si tiene algo mal, lea sobre
la configuración de compilación . También necesitamos un entorno de desarrollo, Android SDK, emulador, herramientas, herramientas de plataforma y las plataformas necesarias para el emulador. Si usa Android Studio, entonces todo esto se puede instalar rápidamente a través del SDK Manager:

Capa de prueba
Como escribí anteriormente, automatizaremos la prueba de inicio de sesión en la aplicación. Recuerde que el código debería verse como un caso de prueba normal:
Precondición: ejecuta la aplicación.
Paso 1: inicie sesión con la cuenta myLogin / myPassword.
Paso 2: verifique el nombre del usuario actual.
Resultado esperado: el usuario actual es Ivan Ivanov.
Pequeño descargo de responsabilidad: de acuerdo con las mejores prácticas de la prueba de diseño, en la condición previa debe crear / encontrar una cuenta. Omití este momento por simplicidad de ejemplo.Nuestra clase se verá así:
@RunWith(AndroidJUnit4.class) public class LoginTests { private TestApplication myApp; @Before public void setUp() { myApp = new TestApplication(); } @Test public void testLogin() { myApp.login("myLogin","myPassword"); String currentUser = myApp.getCurrentUserName(); assertEquals("Wrong name", " ", currentUser); } @After public void tearDown() { myApp.close(); } }
Lógica de negocios
La prueba utiliza la clase
TestApplication()
y sus dos métodos:
login()
y
getCurrentUserName()
. Además, necesita un constructor de clase (iniciando la aplicación en él) y el método
close()
. El frente es claro:
public class TestApplication { private UiDevice device; private PageObject page; public TestApplication() { } public void login(String login, String password) { } public String getCurrentUserName() { return "" } public void close() { } }
Una instancia de nuestra clase tendrá dos variables:
device
, perteneciente a la clase android.support.test.uiautomator.UiDevice
: a través de él interactuamos con nuestro dispositivo;page
, la clase PageObject
, que crearemos en la siguiente sección.
Comencemos con el constructor. En él, cree instancias de nuestras variables y ejecute la aplicación:
public TestApplication() {
Un par de consejos para iniciar la aplicaciónPara un mayor control de la aplicación bajo prueba, puede agregar expectativas para que se inicie el iniciador (si ejecuta el emulador "en frío") y la aplicación misma. Esto también se aconseja en la
documentación .
Nota: ejecutar la aplicación a través de android.content.Context.getTargetContext()
solo es adecuado si sus pruebas están en el mismo proyecto que la aplicación misma. Si es por separado, será necesario recorrer el menú.La lógica empresarial de la prueba son los pasos específicos que el usuario debe seguir para obtener un resultado significativo (para el usuario). Iniciar sesión con su propio ultrasonido es un resultado significativo. Pasos: haga clic en el botón "Iniciar sesión", ingrese el nombre de usuario en el campo "Iniciar sesión", ingrese la contraseña en el campo "Contraseña", haga clic en el botón "Iniciar sesión". Por lo tanto, nuestro método está lleno de pasos:
public void login(String login, String password) { page.login().click(); page.loginEntry().setText(login); page.passwordEntry().setText(password); page.signIn().click(); }
Para obtener el usuario actual, todo es más simple, solo obtenga el valor del campo:
public String getCurrentUserName() { return page.currentUserName().getText(); } }
Y para cerrar la aplicación, simplemente haga clic en el botón Inicio:
public void close() { device.pressHome(); }
Descripción de los elementos de la página.
El concepto de esta capa es que debería devolver elementos listos para usar (en nuestro contexto, esta es la clase
android.support.test.uiautomator.UiObject2
). Es decir, el consumidor no debe preocuparse por el estado del objeto; si regresa, puede interactuar inmediatamente con él: haga clic, complete o lea el texto. Esta es una consecuencia importante: en esta capa nos daremos cuenta de las expectativas:
private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); }
El método definido anteriormente será utilizado por la interfaz pública de nuestra clase
PageObject
. Ejemplo para el campo de inicio de sesión:
public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); }
Queda por determinar el selector por el cual encontraremos el campo. La instancia de
android.support.test.uiautomator.BySelector
obtiene más convenientemente utilizando los métodos estáticos de la clase
android.support.test.uiautomator.By
. Estuve de acuerdo con el desarrollo de que en todas partes, siempre que sea posible, habrá una identificación de recursos única:
private BySelector loginEntrySelector() { return By.res(packageName, "login"); }
Es conveniente inspeccionar la interfaz en la utilidad uiautomatorviewer incluida en el paquete de herramientas (instalado en la sección Preparación):

Seleccione el elemento deseado y en la sección de detalles del Nodo miramos el id de recurso. Consiste en el nombre del paquete y, de hecho, el identificador. Obtuvimos el nombre del paquete en el constructor de la clase
TestApplication
y lo usamos al crear el
PageObject
.
Código completo:
clase PageObject public class PageObject { private UiDevice device; private final String packageName; private BySelector loginButtonSelector() { return By.res(packageName, "user_view"); } private BySelector loginEntrySelector() { return By.res(packageName, "login"); } private BySelector passwordEntrySelector() { return By.res(packageName, "password"); } private BySelector signInSelector() { return By.res(packageName, "btnLogin"); } private BySelector userNameSelector() { return By.res(packageName, "user_name"); } public PageObject(UiDevice device, String packageName) { this.device = device; this.packageName = packageName; } public UiObject2 login() { return getUiObject(loginButtonSelector()); } public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); } public UiObject2 passwordEntry() { return getUiObject(passwordEntrySelector()); } public UiObject2 signIn() { return getUiObject(signInSelector()); } public UiObject2 currentUserName() { return getUiObject(userNameSelector()); } private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); } }
Ejecutando pruebas
Eso es todo, queda por correr. Primero, conéctese al dispositivo o inicie el emulador. Verifique la conexión con el comando de
adb devices
(la utilidad adb es parte de herramientas de plataforma):
List of devices attached emulator-5554 device
Si tienes un gradle, entonces hazlo
gradlew.bat connectedAndroidTest
y disfruta cómo "robots inyectados, no humanos" (c).