Могу ли я использовать assert на устройствах Android?

Я хочу использовать ключевое слово Assert в моих приложениях для Android, чтобы в некоторых случаях уничтожить мое приложение на эмуляторе или на моем устройстве во время тестирования. Это возможно?

Кажется, что эмулятор просто игнорирует мои утверждения.

Ответ 1

API предоставляет JUnit Assert.

Вы можете сделать

import static junit.framework.Assert.*;

теперь вы можете использовать все функции, такие как assertTrue, assertEquals, assertNull, которые предусмотрены в структуре junit.

Будьте осторожны, чтобы не импортировать структуру Junit4 через eclipse, это будет пакет org.junit. Вы должны использовать пакет junit.framework, чтобы заставить его работать на устройстве Android или эмуляторе.

Ответ 2

См. документ Embedded VM Control (необработанный HTML из исходное дерево или красиво отформатированный).

В принципе, VM Dalvik установлен для игнорирования проверок утверждения по умолчанию, хотя код байта .dex содержит код для выполнения проверки. Проверка утверждений включается одним из двух способов:

(1), установив системное свойство "debug.assert" с помощью:

adb shell setprop debug.assert 1

который я проверил, работает по назначению, пока вы переустанавливаете свое приложение после этого, или

(2), отправив аргумент командной строки "--enable-assert" в виртуальную машину dalvik, которая может не быть чем-то, что разработчики приложений могут сделать (кто-то поправьте меня, если я ошибаюсь здесь).

В принципе, существует флаг, который может быть установлен либо глобально, либо на уровне пакета, либо на уровне класса, который позволяет утверждать на соответствующем уровне. По умолчанию флаг отключен, в результате чего проверки утверждения пропускаются.

В моем примере я написал следующий код:


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;
  }
}

Для этого кода создается байт-код dalvik (для 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; // [email protected]
00032c: 6e10 0c00 0000                         |0002: invoke-virtual {v0}, Ljava/lang/Class;.desiredAssertionStatus:()Z // [email protected]
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 // [email protected]
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.asserttest.AssertActivity.onCreate:(Landroid/os/Bundle;)V 00036c: 6f20 0100 3200 |0000: invoke-super {v2, v3}, Landroid/app/Activity;.onCreate:(Landroid/os/Bundle;)V // [email protected] 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 // [email protected] 00037c: 1250 |0008: const/4 v0, #int 5 // #5 00037e: 6301 0000 |0009: sget-boolean v1, Lcom/example/asserttest/AssertActivity;.$assertionsDisabled:Z // [email protected] 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: new-instance v1, Ljava/lang/AssertionError; // [email protected] 000390: 7010 0b00 0100 |0012: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V // [email protected] 000396: 2701 |0015: throw v1 000398: 0e00 |0016: return-void

Обратите внимание на то, как статический конструктор вызывает метод wishAssertionStatus в объекте Class и устанавливает переменную класса $assertionsDisabled; также обратите внимание, что в onCreate() весь код для броска java.lang.AssertionError скомпилирован, но его выполнение зависит от значения $assertionsDisabled, которое установлено для объекта Class в статическом конструкторе.

Похоже, что класс JUnit Assert - это то, что используется преимущественно, поэтому, скорее всего, это безопасная ставка для использования. Гибкость ключевого слова assert - возможность включить утверждения во время разработки и отключить их для отправки битов и вместо этого изящно выйти из строя.

Надеюсь, что это поможет.

Ответ 3

Когда утверждения разрешены, ключевое слово assert просто бросает AssertionError, когда логическое выражение false.

Итак, ИМО, лучшая альтернатива, особенно. если вы не склонны зависеть от junit, нужно явно бросать AssertionError, как показано ниже:

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

Альтернативой приведенному выше утверждению является:

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

Если метод определен как:

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

Oracle java docs рекомендует выбрасывать AssertionError в качестве приемлемой альтернативы.

Я предполагаю, что вы можете настроить Proguard, чтобы отключить эти вызовы для производственного кода.

Ответ 4

В "Android on Practice" предлагается использовать:

$adb shell setprop dalvik.vm.enableassertions all

если эти настройки не сохраняются на вашем телефоне, вы можете создать файл /data/local.prop со следующими свойствами:

dalvik.vm.enableassertions=all

Ответ 5

Это извинило меня, что мои утверждения не работали, пока я не проверил проблему на google... Я отказался от простых утверждений и пошлю с методами утверждения юнитов.

Для удобства я использую:

import static junit.framework.Assert. *;

Из-за статического импорта я могу позже написать:

assertTrue (...); вместо Assert.assertTrue(...);

Ответ 6

Если вы беспокоитесь о доставке кода с утверждениями JUnit в (или любом другом пути к классу), вы можете использовать опцию конфигурации ProGuard "precenosideeffects", которая будет вытеснять путь класса в предположении, что удаление этого не делает ничего к коду.

Eg.

-assumenosideeffects junit.framework.Assert {
*;
}

У меня есть общая библиотека отладки, в которую я помещаю все свои методы тестирования, а затем использую эту опцию, чтобы удалить ее из моих выпущенных приложений.

Это также устраняет сложную проблему с манипуляциями строк, которые никогда не используются в коде выпуска. Например, если вы пишете метод журнала отладки, и в этом методе вы проверяете режим отладки перед записью строки, вы все равно строите строку, выделяете память, вызывая метод, но затем выбираете ничего не делать. Вырезая класс, затем полностью удаляет вызовы, то есть до тех пор, пока ваша строка будет построена внутри вызова метода, она также исчезнет.

Удостоверьтесь, что действительно безопасно просто снимать линии, однако это делается без проверки части ProGuard. Удаление любого метода возврата void будет прекрасным, однако если вы принимаете какие-либо возвращаемые значения из того, что вы удаляете, убедитесь, что вы не используете их для реальной операционной логики.

Ответ 7

Чтобы добавить к Zulaxia ответ на удаление Junit - Proguard уже входит в Android SDK/Eclipse, и на следующей странице вы узнаете, как включить его.

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

Кроме того, выше не будет работать с последней конфигурацией proguard по умолчанию, поскольку он использует флаг -dontoptimize, который необходимо удалить, и некоторые из оптимизаций включены.

Ответ 8

Вы можете использовать утверждения, но для их надежной работы требуется определенная работа. Системное свойство debug.assert не является надежным. См. Вопросы 175697, 65183, 36786 и 17324.

Чтобы сделать утверждения надежными на Android, вы должны перевести каждый оператор assert на что-то, с чем могут справиться все время работы. Это можно сделать с помощью исходного препроцессора перед компилятором Java. Например, рассмотрим это утверждение:

assert x == 0: "Failure message";

В сборке отладки препроцессор переведет это в оператор if:

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

В сборке сборки, в пустой оператор:

;

Обратите внимание, что такие утверждения обязательно включены или отключены во время сборки исходным препроцессором, а не во время выполнения виртуальной машиной. Это отличается от обычной практики Java.

Я не смог найти готовый препроцессор, поэтому мне пришлось script мой собственный (см. часть, посвященную утверждениям), Лицензия на копирование здесь.

Ответ 9

Используйте стандартное ключевое слово Java assert, например:

assert a==b;

Для этого вам нужно добавить одну строку в /system/build.prop и перезагрузить телефон:

debug.assert=1

Это будет работать на корневом телефоне. Используйте некоторый файловый менеджер, способный редактировать build.prop(например, X-plore).

Достоинства: большинство (все?) телефоны Android поставляются с отключенными утверждениями. Даже если ваш код случайно утверждает false, приложение не будет прерывать или сбой. Однако на вашем устройстве разработки вы получите исключение утверждения.