2010-08-29 14 views
9

Estoy intentando probar UI simple con el siguiente caso de prueba, La idea principal es establecer en la prueba parte del texto UI (para imitar la entrada del usuario) y luego hacer clic activamente en un evento .Prueba con elementos UI en Android view

public class StackTestCase 
extends ActivityInstrumentationTestCase2<Stack> 
{ 
private StackDemo mActivity; 

private EditText eaten; 
    public StuckTestCase() { 
     super("com.crocodil.software.stack", Stack.class); 


    } 
    public StuckTestCase(Class<Stack> activityClass) { 
     super("com.crocodil.software.stack", activityClass); 

    } 
    protected void setUp() throws Exception { 
     super.setUp(); 
     mActivity = this.getActivity(); 
     mCount = (Button) mActivity.findViewById(com.crocodil.software.stack.R.id.action); 
     eaten = (EditText) mActivity.findViewById(com.crocodil.software.stack.R.id.eaten); 

    } 

    public void testPreconditions() { 
     assertNotNull(mStatus); 
     } 

    public void testSimpleDefaults(){ 
     double status = Double.valueOf(mStatus.getText().toString()); 
     eaten.setText(2); 
     mCount.performClick(); 
     assertEquals((status-2),Double.valueOf(mStatus.getText().toString())); 
    } 

} 

el resultado correr es la excepción -

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
at android.view.ViewRoot.checkThread(ViewRoot.java:2802) 
at android.view.ViewRoot.playSoundEffect(ViewRoot.java:2581) 
at android.view.View.playSoundEffect(View.java:8516) 
at android.view.View.performClick(View.java:2407) 
at com.crocodil.software.stack.test.StackTestCase.testSimpleDefaults(StackTestCase.java:46) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:204) 
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:194) 
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:186) 
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169) 
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154) 
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:520) 
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447) 

Esto sucede en cada acceso a los elementos de interfaz de usuario y he podido evitarlo mediante el uso de las asas o tarea asíncrona? ¿alguna sugerencia?

Respuesta

30

Esta es una vieja pregunta, pero te estoy dando una respuesta de todos modos, en caso de que alguien se tropiece con ella.

No tiene permiso para cambiar los estados de los widgets UI desde cualquier lugar excepto el hilo principal (hilo UI). Su performClick debe hacerse así:

mActivity.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
    mCount.performClick(); 
    } 
}); 

Pero eso no es todo, también necesitará sincronizar su prueba de la instrumentación con la interfaz de usuario, añadiendo la siguiente línea:

getInstrumentation().waitForIdleSync(); 

La línea de sincronización generalmente se coloca inmediatamente después del código runOnUiThread().

+0

estoy frente a un problema tal que, 'waitForIdleSync();' llamada a sí misma se cuelga en un bucle infinito. Al depurar el problema, descubrimos que el mensaje 'emptyRunnable()' publicado a través del controlador no queda atrapado en 'MessageQueue'. Parece que hay un problema de sincronización presente. Pero no estoy seguro, cómo localizar el problema. – ArunJTS

6

El problema es que solo puede tocar/cambiar las vistas desde el subproceso de la interfaz de usuario. Puede usar un ejecutable como se describe en Rober o una anotación.

Puede ejecutar todos los métodos dentro de una prueba sobre el hilo de interfaz de usuario mediante la @UiThreadTest annotation:

Actualización:

Este @interface desfasada y en su nivel de API 24.
Use UiThreadTest en su lugar. Las nuevas pruebas se deben escribir usando el Android Testing Support Library.

@UiThreadTest 
public void testSimpleDefaults(){ 
    double status = Double.valueOf(mStatus.getText().toString()); 
    eaten.setText(2); 
    mCount.performClick(); 
    assertEquals((status-2),Double.valueOf(mStatus.getText().toString())); 
}