Estamos creando una aplicación de Android compleja que consta de muchas pantallas y flujos de trabajo distribuidos en muchas Actividades. Nuestros flujos de trabajo son similares a los que puede ver en el cajero automático de un banco, por ejemplo, hay un Activity
inicio de sesión que cambia a un menú principal Activity
que puede pasar a otras actividades según las opciones del usuario.
Dado que tenemos tantos flujos de trabajo, necesitamos crear pruebas automatizadas que abarquen múltiples actividades para que podamos probar un flujo de trabajo de un extremo a otro. Por ejemplo, usando el ejemplo del cajero automático, querríamos ingresar un PIN válido, verificar que nos envía al menú principal, elegir retirar efectivo, verificar que estamos en la pantalla de retiro de efectivo, etc., etc., y finalmente encontrarnos de nuevo en el menú principal o "desconectado".
Hemos jugado con las API de prueba que vienen con Android (por ejemplo ActivityInstrumentationTestCase2
) y también con Positron , pero ninguna parece capaz de probar más allá de los límites de una sola Activity
, y aunque podemos encontrar alguna utilidad en estas herramientas para algunas pruebas unitarias, ganaron. Satisface nuestras necesidades de escenarios de prueba que abarcan múltiples Actividades.
Estamos abiertos a un marco xUnit, secuencias de comandos, grabadoras / reproducciones de GUI, etc. y agradeceríamos cualquier consejo.
fuente
Respuestas:
Me siento un poco incómodo por responder mi propia pregunta sobre recompensas, pero aquí está ...
He buscado alto y bajo sobre esto y no puedo creer que no haya una respuesta publicada en ninguna parte. Me he acercado mucho. Definitivamente puedo ejecutar pruebas que abarcan actividades ahora, pero mi implementación parece tener algunos problemas de sincronización donde las pruebas no siempre pasan de manera confiable. Este es el único ejemplo que conozco de pruebas exitosas en múltiples actividades. Con suerte, mi extracción y anonimización no introdujo errores. Esta es una prueba simplista en la que escribo un nombre de usuario y contraseña en una actividad de inicio de sesión, y luego observo que se muestra un mensaje de bienvenida adecuado en una actividad de "bienvenida" diferente:
package com.mycompany; import android.app.*; import android.content.*; import android.test.*; import android.test.suitebuilder.annotation.*; import android.util.*; import android.view.*; import android.widget.*; import static org.hamcrest.core.Is.*; import static org.hamcrest.core.IsNull.*; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.*; import static com.mycompany.R.id.*; public class LoginTests extends InstrumentationTestCase { @MediumTest public void testAValidUserCanLogIn() { Instrumentation instrumentation = getInstrumentation(); // Register we are interested in the authentication activiry... Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(AuthenticateActivity.class.getName(), null, false); // Start the authentication activity as the first activity... Intent intent = new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName(instrumentation.getTargetContext(), AuthenticateActivity.class.getName()); instrumentation.startActivitySync(intent); // Wait for it to start... Activity currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5); assertThat(currentActivity, is(notNullValue())); // Type into the username field... View currentView = currentActivity.findViewById(username_field); assertThat(currentView, is(notNullValue())); assertThat(currentView, instanceOf(EditText.class)); TouchUtils.clickView(this, currentView); instrumentation.sendStringSync("MyUsername"); // Type into the password field... currentView = currentActivity.findViewById(password_field); assertThat(currentView, is(notNullValue())); assertThat(currentView, instanceOf(EditText.class)); TouchUtils.clickView(this, currentView); instrumentation.sendStringSync("MyPassword"); // Register we are interested in the welcome activity... // this has to be done before we do something that will send us to that // activity... instrumentation.removeMonitor(monitor); monitor = instrumentation.addMonitor(WelcomeActivity.class.getName(), null, false); // Click the login button... currentView = currentActivity.findViewById(login_button; assertThat(currentView, is(notNullValue())); assertThat(currentView, instanceOf(Button.class)); TouchUtils.clickView(this, currentView); // Wait for the welcome page to start... currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5); assertThat(currentActivity, is(notNullValue())); // Make sure we are logged in... currentView = currentActivity.findViewById(welcome_message); assertThat(currentView, is(notNullValue())); assertThat(currentView, instanceOf(TextView.class)); assertThat(((TextView)currentView).getText().toString(), is("Welcome, MyUsername!")); } }
Obviamente, este código no es muy legible. De hecho, lo he extraído en una biblioteca simple con una API similar al inglés, así que puedo decir cosas como esta:
type("myUsername").intoThe(username_field); click(login_button);
Probé a una profundidad de aproximadamente 4 actividades y estoy satisfecho de que el enfoque funcione, aunque, como dije, parece haber un problema de tiempo ocasional que no he descubierto por completo. Todavía estoy interesado en conocer otras formas de realizar pruebas en todas las actividades.
fuente
ActivityInstrumentationTestCase2
Eche un vistazo a Robotium, 'un marco de prueba de código abierto creado para hacer que las pruebas automáticas de caja negra de las aplicaciones de Android sean significativamente más rápidas y fáciles de lo que es posible con las pruebas de instrumentación de Android listas para usar
'.
Inicio: http://www.robotium.org/
Fuente: http://github.com/jayway/robotium
Tenga en cuenta que el proyecto Robotium es mantenido por la empresa para la que trabajo
fuente
Siempre puedes usar Robotium. Admite pruebas de caja negra como Selenium pero para Android. Lo encontrará en Robotium.org
fuente
Me sorprende que nadie haya mencionado algunas de las principales herramientas de pruebas funcionales automatizadas . En comparación con Robotium, estos no requieren escribir código Java.
MonkeyTalk : una herramienta de código abierto respaldada por la empresa Gorilla Logic. Ventajas: proporciona grabación y un lenguaje de scripting de alto nivel más fácil para los usuarios no técnicos y es multiplataforma (incluye iOS). Dados esos beneficios como requisitos, hemos descubierto que esta es la mejor solución. También permite la personalización más allá de lo que se puede hacer en su lenguaje de scripting usando Javascript.
Calabash-Android : una herramienta de código abierto para funciones de estilo pepino. Ventajas: escriba características en el lenguaje Gherkin, que es legible para empresas, lenguaje específico de dominio que le permite describir el comportamiento del software sin detallar cómo se implementa ese comportamiento. Hay disponible soporte similar pero no exacto para iOS en cucumber-ios . Las capacidades de grabación no son tan buenas, ya que producen una salida binaria.
Un par de otras referencias:
fuente
Creé una herramienta de grabación y reproducción para Android y la puse a disposición en GitHub . Es fácil de configurar y usar, no requiere programación, se ejecuta en dispositivos reales (que no tienen que estar enraizados) y guarda automáticamente las capturas de pantalla mientras reproduce las pruebas.
fuente
En primer lugar, use 'ActivityInstrumentationTestCase2', no 'InstrumentationTestCase', como su clase base. Utilizo Robotium y pruebo rutinariamente en múltiples Actividades. Descubrí que tengo que especificar la actividad de inicio de sesión como el tipo genérico (y el argumento de clase para el constructor).
El constructor 'ActivityInstrumentationTestCase2' ignora el argumento del paquete y no lo requiere. El constructor que toma el paquete está en desuso.
De los Javadocs: "ActivityInstrumentationTestCase2 (String pkg, Class activityClass) Este constructor está en desuso. Utilice ActivityInstrumentationTestCase2 (Class) en su lugar"
El uso de la clase base recomendada permite que el marco maneje ciertos estándares, como comenzar su actividad. Eso se hace mediante la llamada a 'getActivity ()', si es necesario.
fuente
Encontré esto útil con un par de modificaciones. En primer lugar
getInstrumentation().waitForIdleSync()
, curará la descamación de la que habla SingleShot y tambiénInstrumentationTestCase
tiene unalauchActivity
función que puede reemplazar las líneas de actividad de inicio.fuente
puede hacerlo así para evitar que los tiempos de espera de las escamas no estén sincronizados:
final Button btnLogin = (Button) getActivity().findViewById(R.id.button); Instrumentation instrumentation = getInstrumentation(); // Register we are interested in the authentication activity... Instrumentation.ActivityMonitor aMonitor = instrumentation.addMonitor(mynextActivity.class.getName(), null, false); getInstrumentation().runOnMainSync(new Runnable() { public void run() { btnLogin.performClick(); } }); getInstrumentation().waitForIdleSync(); //check if we got at least one hit on the new activity assertTrue(getInstrumentation().checkMonitorHit(aMonitor, 1));
fuente
Estoy trabajando en prácticamente lo mismo, y probablemente iré con una variación de la respuesta aceptada a esta pregunta, pero encontré Calculuon ( gitHub ) durante mis búsquedas de una solución.
fuente
No lo he usado personalmente, pero ApplicationTestCase parece que podría ser lo que estás buscando.
fuente
¿El enfoque aceptado funcionará con diferentes actividades de diferentes aplicaciones, firmadas por diferentes certificados? Si no es así, Robotium es la mejor manera de probar actividades dentro de la misma aplicación.
fuente
Hay otra forma de hacer la actividad múltiple usando la clase ActivityInstrumentation. Es un escenario de automatización normal ... Primero obtenga el foco de cualquier objeto que desee y luego envíe una clave Simple como ese código de muestra
button.requestFocus(); sendKeys(KeyEvent.KEYCODE_ENTER);
Lo único que nos ayudará es comprender todas las llamadas a la API.
fuente
Esta respuesta se basa en la respuesta aceptada, pero modificada para resolver el problema del tiempo que para mí se volvió consistente después de agregar alrededor de media docena de pruebas. @ pajato1 recibe el crédito por resolver el problema del tiempo, como se cita en los comentarios de respuesta aceptados.
/** * Creates a test Activity for a given fully qualified test class name. * * @param fullyQualifiedClassName The fully qualified name of test activity class. * * @return The test activity object or null if it could not be located. */ protected AbstractTestActivity getTestActivity(final String fullyQualifiedClassName) { AbstractTestActivity result = null; // Register our interest in the given activity and start it. Log.d(TAG, String.format("Running test (%s) with main class: %s.", getName(), fullyQualifiedClassName)); instrumentation = getInstrumentation(); Intent intent = new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName(instrumentation.getTargetContext(), fullyQualifiedClassName); // Wait for the activity to finish starting Activity activity = instrumentation.startActivitySync(intent); // Perform basic sanity checks. assertTrue("The activity is null! Aborting.", activity != null); String format = "The test activity is of the wrong type (%s)."; assertTrue(String.format(format, activity.getClass().getName()), activity.getClass().getName().equals(fullyQualifiedClassName)); result = (AbstractTestActivity) activity; return result; }
fuente
Prueba las pruebas de la herramienta Monkey
Paso 1:
abra la terminal de estudio de Android (Herramientas-> terminal abierta)
Paso 2:
Para usar monkey, abra un símbolo del sistema y simplemente navegue al siguiente directorio.
export PATH=$PATH:/home/adt-bundle-linux-x86-20140702/sdk/platform-tools
Paso 3:
agregue este comando de mono en la terminal y presione enter ..
vea la magia en su emulador.
adb shell monkey -p com.example.yourpackage -v 500
500: es el recuento de frecuencia o el número de eventos que se enviarán para la prueba.
puedes cambiar este recuento ..
Más referencia,
http://www.tutorialspoint.com/android/android_testing.htm
http://androidtesting.blogspot.in/2012/04/android-testing-with-monkey-tool.html
fuente