Могу ли я использовать assert на устройствах Android?
Я хочу использовать Assert ключевое слово в моем приложения для Android, чтобы уничтожить мое приложение в некоторых случаях на эмуляторе или устройстве во время тестирования. Это возможно?
кажется, что эмулятор просто игнорирует мои утверждения.
9 ответов:
API предоставляет JUnit Assert.
можно сделать
import static junit.framework.Assert.*;теперь вы можете использовать все функции, такие как assertTrue, assertEquals, assertNull, которые предоставляются в рамках junit.
будьте осторожны, чтобы не импортировать JUnit4 framework через eclipse, это будет организация.пакет junit. Вы должны использовать junit.рамках пакета, чтобы заставить его работать на Android устройстве или эмуляторе.
см. встроенный документ управления виртуальной машиной (необработанный HTML из источник дерева или красиво отформатирована копировать).
В принципе, виртуальная машина Dalvik по умолчанию игнорирует проверки утверждений, даже если они есть .байт-код DeX включает в себя код для выполнения проверки. Проверка заявления включается одним из двух способов:
(1) установив системное свойство "debug.утверждать " через:
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; // 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.asserttest.AssertActivity.onCreate:(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: new-instance v1, Ljava/lang/AssertionError; // class@000c 000390: 7010 0b00 0100 |0012: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V // method@000b 000396: 2701 |0015: throw v1 000398: 0e00 |0016: return-void
обратите внимание, как статический конструктор вызывает метод desiredAssertionStatus на объекте класса и устанавливает переменную класса $assertionsDisabled; также обратите внимание, что в onCreate () весь код для запуска java.ленг.AssertionError компилируется, но его выполнение зависит от значения $assertionsDisabled, которое задается для объекта класса в статическом конструкторе.
похоже, что класс Assert JUnit-это то, что используется преимущественно, поэтому, вероятно, это безопасная ставка. Гибкость ключевого слова assert - это возможность включать утверждения во время разработки и отключать их для доставки битов, а вместо этого изящно отказывать.
надеюсь, что это помогает.
когда утверждения включены, то
assertключевое слово просто выдаетAssertionErrorкогда логическое выражениеfalse.так ИМО, лучшая альтернатива, esp. если вы не хотите зависеть от 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, чтобы удалить эти вызовы для производственного кода.
В "Android на практике" предлагается использовать:
$adb shell setprop dalvik.vm.enableassertions allесли эти настройки не сохраняются на вашем телефоне, то вы можете создать /data/local.Prop файл со свойствами, как:
dalvik.vm.enableassertions=all
Это было чертовски из меня, что мои утверждения не работали, пока я не проверил проблему на google... Я отказался от простых утверждений и буду использовать методы утверждения junits.
для удобства я использую:
импорт статического junit.рамки.Утверждать.*;
из-за статического импорта я могу позже написать:
assertTrue(...); вместо того, чтобы утверждать.assertTrue(...);
Если вы беспокоитесь о доставке кода с помощью JUnit asserts in (или любого другого пути к классу), вы можете использовать параметр конфигурации ProGuard "assumenosideeffects", который удалит путь к классу в предположении, что его удаление ничего не делает с кодом.
например.
-assumenosideeffects junit.framework.Assert { *; }У меня есть общая библиотека отладки, в которую я помещаю все свои методы тестирования, а затем использую эту опцию, чтобы удалить ее из моих выпущенных приложений.
Это также устраняет трудноразличимую проблему обрабатываются строки, которые никогда не используются в коде выпуска. Например, если вы пишете метод журнала отладки, и в этом методе вы проверяете режим отладки перед записью строки, вы все еще создаете строку, выделяете память, вызываете метод, но затем решаете ничего не делать. Удаление класса затем полностью удаляет вызовы, что означает, что пока ваша строка построена внутри вызова метода, она также уходит.
убедитесь, что это действительно безопасно только полосы линии, однако, как это делается без проверки со стороны ProGuard. Удаление любого метода возврата void будет нормально, однако если вы принимаете какие-либо возвращаемые значения из того, что вы удаляете, убедитесь, что вы не используете их для реальной операционной логики.
чтобы добавить к ответу Zulaxia на удаление Junit-Proguard уже является частью Android SDK / Eclipse, и на следующей странице вы узнаете, как его включить.
http://developer.android.com/guide/developing/tools/proguard.html
также выше не будет работать с последней конфигурацией proguard по умолчанию, потому что он использует флаг-dontoptimize, который должен быть снят, и некоторые из оптимизаций включены.
вы можете использовать утверждения, но для их надежного использования требуется некоторая работа. Системное свойство
debug.assert- это не надежный. См. раздел проблемы 175697,65183,36786 и 17324.чтобы сделать утверждения надежными на Android, вы должны перевести каждый
assertзаявление к чему-то, с чем могут иметь дело все среды выполнения. Это можно сделать с помощью исходного препроцессора перед компилятором Java. Например, рассмотрим это заявление:assert x == 0: "Failure message";в отладочной сборке препроцессор переведет это в
ifо себе:{ if( !(x == 0) ) throw new AssertionError( "Failure message" ); }в производственной сборке, в пустой оператор:
;обратите внимание, что такие утверждения обязательно включаются или отключаются во время сборки исходным препроцессором, а не во время выполнения виртуальной машиной. Это отличается от обычной практики Java.
Я не мог найти готовый препроцессор, поэтому мне пришлось писать сценарий моей (см. часть, посвященную утверждениям). Лицензия на копирование здесь.
использовать стандартную Java assert ключевое слово, например:
assert a==b;чтобы это работало, вы должны добавить одну строку в /system/build.опора, и перезагрузить телефон:
debug.assert=1это будет работать на укоренившихся телефонов. Используйте некоторый файловый менеджер, способный редактировать сборку.опора (например, X-plore).
плюсы: большинство (все?) Android телефоны поставляются с утверждениями отключены. Даже если ваш код случайно утверждает false, приложение не будет прерывать или сбой. Однако, на вашем устройство разработки вы получите исключение утверждения.
Comments