¿Puedo usar assert en dispositivos Android?

Quiero utilizar la palabra clave Assert en mis aplicaciones de Android para destruir mi aplicación en algunos casos en el emulador o en mi dispositivo durante las pruebas. es posible?

Parece que el emulador simplemente ignora mis afirmaciones.

La API proporciona el JUnit Assert .

Tu puedes hacer

import static junit.framework.Assert.*; 

ahora puede usar todas las funciones como assertTrue, assertEquals, assertNull que se proporcionan en el marco junit.

Tenga cuidado de no importar el framework Junit4 a través de eclipse, ese sería el paquete org.junit. Debe usar el paquete junit.framework para que funcione en un dispositivo Android o en el emulador.

Consulte el documento de Control de VM integrado (HTML sin procesar del árbol de fonts o una copia con un formato agradable ).

Básicamente, la máquina virtual de Dalvik está configurada para ignorar las comprobaciones de aserción de manera predeterminada, incluso si el código de byte .dex incluye el código para realizar la comprobación. La verificación de aserciones se activa de una de estas dos maneras:

(1) configurando la propiedad del sistema “debug.assert” a través de:

 adb shell setprop debug.assert 1 

que verifiqué funciona de la manera prevista siempre que reinstale su aplicación después de hacer esto, o

(2) enviando el argumento de la línea de comando “–enable-assert” a la máquina virtual de dalvik, que podría no ser algo que los desarrolladores de aplicaciones probablemente puedan hacer (alguien me corrige si me equivoco aquí).

Básicamente, existe un indicador que puede establecerse globalmente, a nivel de paquete o a nivel de clase, lo que permite realizar afirmaciones en ese nivel respectivo. El indicador está desactivado de manera predeterminada, como resultado de lo cual se omiten las comprobaciones de aserción.

Escribí el siguiente código en mi actividad de ejemplo:

 public class AssertActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); int x = 2 + 3; assert x == 4; } } 

Para este código, el código de dalvik byte que se genera es (para Android 2.3.3):

 // Static constructor for the class 000318: |[000318] com.example.asserttest.AssertActivity.:()V 000328: 1c00 0300 |0000: const-class v0, Lcom/example/asserttest/AssertActivity; // class@0003 00032c: 6e10 0c00 0000 |0002: invoke-virtual {v0}, Ljava/lang/Class;.desiredAssertionStatus:()Z // method@000c 000332: 0a00 |0005: move-result v0 000334: 3900 0600 |0006: if-nez v0, 000c // +0006 000338: 1210 |0008: const/4 v0, #int 1 // #1 00033a: 6a00 0000 |0009: sput-boolean v0, Lcom/example/asserttest/AssertActivity;.$assertionsDisabled:Z // field@0000 00033e: 0e00 |000b: return-void 000340: 1200 |000c: const/4 v0, #int 0 // #0 000342: 28fc |000d: goto 0009 // -0004 

// Static constructor for the class 000318: |[000318] com.example.asserttest.AssertActivity.:()V 000328: 1c00 0300 |0000: const-class v0, Lcom/example/asserttest/AssertActivity; // class@0003 00032c: 6e10 0c00 0000 |0002: invoke-virtual {v0}, Ljava/lang/Class;.desiredAssertionStatus:()Z // method@000c 000332: 0a00 |0005: move-result v0 000334: 3900 0600 |0006: if-nez v0, 000c // +0006 000338: 1210 |0008: const/4 v0, #int 1 // #1 00033a: 6a00 0000 |0009: sput-boolean v0, Lcom/example/asserttest/AssertActivity;.$assertionsDisabled:Z // field@0000 00033e: 0e00 |000b: return-void 000340: 1200 |000c: const/4 v0, #int 0 // #0 000342: 28fc |000d: goto 0009 // -0004

:
:

// onCreate ()
00035c: | [00035c] com.example.prueba de aparición.Actividades.enCrear: (Landroid / os / Bundle;) V
00036c: 6f20 0100 3200 | 0000: invoke-super {v2, v3}, Landroid / app / Activity; .onCreate: (Landroid / os / Bundle;) V // method @ 0001
000372: 1501 037f | 0003: const / high16 v1, #int 2130903040 // # 7f03
000376: 6e20 0500 1200 | 0005: invoke-virtual {v2, v1}, Lcom / example / asserttest / AssertActivity; .setContentView: (I) V // method @ 0005
00037c: 1250 | 0008: const / 4 v0, #int 5 // # 5
00037e: 6301 0000 | 0009: sget-boolean v1, Lcom / example / asserttest / AssertActivity;. $ AssertionsDisabled: Z // field @ 0000
000382: 3901 0b00 | 000b: if-nez v1, 0016 // + 000b
000386: 1251 | 000d: const / 4 v1, #int 5 // # 5
000388: 3210 0800 | 000e: if-eq v0, v1, 0016 // +0008
00038c: 2201 0c00 | 0010: nueva instancia v1, Ljava / lang / AssertionError; // clase @ 000c
000390: 7010 0b00 0100 | 0012: invoke-direct {v1}, Ljava / lang / AssertionError;. :() V // method @ 000b
000396: 2701 | 0015: lanzar v1
000398: 0e00 | 0016: retorno-vacío

Observe cómo el constructor estático invoca el método desiredAssertionStatus en el objeto Class y establece la variable class-wide $ assertionsDisabled; También observe que en onCreate (), todo el código para lanzar java.lang.AssertionError está comstackdo, pero su ejecución depende del valor de $ assertionsDisabled que se establece para el objeto Class en el constructor estático.

Parece que la clase de Assert de JUnit es la que se usa predominantemente, por lo que es una apuesta segura usar eso. La flexibilidad de la palabra clave assert es la capacidad de activar las afirmaciones en el momento del desarrollo y desactivarlas para enviar bits y, en su lugar, fallar con elegancia.

Espero que esto ayude.

Cuando las aserciones están habilitadas, la palabra clave assert simplemente arroja un AssertionError cuando la expresión booleana es false .

Entonces IMO, la mejor alternativa, esp. si eres reacio a depender de junit, es lanzar un AssertionError explícitamente como se muestra a continuación:

 assert x == 0 : "x = " + x; 

Una alternativa a la statement anterior es:

 Utils._assert(x == 0, "x = " + x); 

Donde el método se define como:

 public static void _assert(boolean condition, String message) { if (!condition) { throw new AssertionError(message); } } 

Los documentos de Oracle java recomiendan lanzar un AssertionError como una alternativa aceptable.

Supongo que puede configurar Proguard para eliminar estas llamadas de código de producción.

En “Android in Practice”, se sugiere utilizar:

 $adb shell setprop dalvik.vm.enableassertions all 

si esta configuración no se conserva en su teléfono, puede crear el archivo /data/local.prop con propiedades como:

 dalvik.vm.enableassertions=all 

Me estaba molestando, que mis afirmaciones no funcionaron, hasta que revisé el problema en Google … dejé de aserciones simples e iré con los métodos de afirmación de junits.

Para fines de conveniencia, estoy usando:

import static junit.framework.Assert. *;

Debido a la importación estática, puedo escribir más tarde:

assertTrue (…); en lugar de Assert.assertTrue (…);

Si le preocupa el código de envío con el JUnit afirma en (o cualquier otra ruta de clase), puede utilizar la opción de configuración de ProGuard ‘assumenosideeffects’, que eliminará una ruta de clase en el supuesto de que su eliminación no hace nada al código .

P.ej.

 -assumenosideeffects junit.framework.Assert { *; } 

Tengo una biblioteca de depuración común en la que puse todos mis métodos de prueba, y luego uso esta opción para quitarla de mis aplicaciones lanzadas.

Esto también elimina el problema difícil de detectar de las cadenas manipuladas que nunca se utilizan en el código de lanzamiento. Por ejemplo, si escribe un método de registro de depuración y en ese método busca el modo de depuración antes de registrar la cadena, aún está construyendo la cadena, asignando memoria, llamando al método, pero luego optando por no hacer nada. Al eliminar la clase, se eliminan por completo las llamadas, lo que significa que, mientras se construya la cadena dentro de la llamada al método, también desaparecerá.

Sin embargo, asegúrese de que es realmente seguro tirar las líneas, ya que se hace sin verificación por parte de ProGuard. La eliminación de cualquier método de devolución de vacíos estará bien; sin embargo, si toma cualquier valor devuelto de lo que está eliminando, asegúrese de no utilizarlo para la lógica operativa real.

Para agregar a la respuesta de Zulaxia sobre la eliminación de Junit, Proguard ya es parte de Android SDK / Eclipse y la página siguiente te dice cómo habilitarlo.

http://developer.android.com/guide/developing/tools/proguard.html

Además, lo anterior no funcionará con la última configuración predeterminada de proguard, ya que utiliza el indicador -dontoptimize que se debe quitar y se activan algunas de las optimizaciones.

Puede usar aserciones, pero toma algún trabajo usarlas de manera confiable. La propiedad del sistema debug.assert no es confiable. Ver los números 175697 , 65183 , 36786 y 17324 .

Para hacer que las afirmaciones sean confiables en Android, debe traducir cada statement de afirmación a algo que todos los tiempos de ejecución puedan manejar. Esto se puede hacer con un preprocesador de origen en frente del comstackdor de Java. Por ejemplo, considere esta afirmación:

 assert x == 0: "Failure message"; 

En una comstackción de depuración, el preprocesador traduciría esto a una instrucción if :

 { if( !(x == 0) ) throw new AssertionError( "Failure message" ); } 

En una comstackción de producción, a una statement vacía:

 ; 

Tenga en cuenta que tales afirmaciones se habilitan o deshabilitan necesariamente en el momento de la comstackción por el preprocesador de origen, y no en tiempo de ejecución por la máquina virtual. Esto difiere de la práctica convencional de Java.

No pude encontrar un preprocesador listo, así que tuve que escribir el mío (ver la parte que trata sobre las afirmaciones). Licencia para copiar está aquí .

Utilice la palabra clave Java assert estándar, por ejemplo:

 assert a==b; 

Para que esto funcione, debe agregar una línea a /system/build.prop y reiniciar el teléfono:

 debug.assert=1 

Esto funcionaría en el teléfono rooteado. Utilice algún administrador de archivos capaz de editar build.prop (por ejemplo, X-plore).

Ventajas: la mayoría de los teléfonos Android (¿todos?) Se envían con aserciones deshabilitadas. Incluso si su código afirma accidentalmente que es falso, la aplicación no se interrumpirá ni se bloqueará. Sin embargo, en su dispositivo de desarrollo obtendrá una excepción de afirmación.