Я хочу использовать ключевое слово Assert в своих приложениях для Android, чтобы в некоторых случаях уничтожить мое приложение на эмуляторе или на моем устройстве во время тестирования. Это возможно?
Похоже, эмулятор просто игнорирует мои утверждения.
Ответы:
API предоставляет JUnit Assert .
Ты можешь сделать
import static junit.framework.Assert.*;
теперь вы можете использовать все функции, такие как assertTrue, assertEquals, assertNull, которые имеются в структуре junit.
Будьте осторожны, чтобы не импортировать фреймворк Junit4 через eclipse, это будет пакет org.junit. Вы должны использовать пакет junit.framework, чтобы он работал на устройстве Android или в эмуляторе.
источник
См. Документ Embedded VM Control (необработанный HTML- код из исходного дерева или хорошо отформатированная копия).
По сути, виртуальная машина Dalvik по умолчанию настроена на игнорирование проверок утверждений, хотя байтовый код .dex включает код для выполнения проверки. Проверка утверждений включается одним из двух способов:
(1) установив системное свойство «debug.assert» через:
adb shell setprop debug.assert 1
который я проверил, работает по назначению, если вы переустановите приложение после этого, или
(2) отправив аргумент командной строки «--enable-assert» в виртуальную машину dalvik, что, возможно, не под силу разработчикам приложений (кто-нибудь поправит меня, если я ошибаюсь).
По сути, есть флаг, который может быть установлен либо глобально, на уровне пакета, либо на уровне класса, который разрешает утверждения на соответствующем уровне. По умолчанию флаг выключен, в результате чего проверки утверждений пропускаются.
Я написал следующий код в своем образце Activity:
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
Обратите внимание, как статический конструктор вызывает метод желаемогоAssertionStatus для объекта класса и устанавливает переменную класса $ assertionsDisabled; также обратите внимание, что в onCreate () весь код для выброса java.lang.AssertionError компилируется, но его выполнение зависит от значения $ assertionsDisabled, которое установлено для объекта Class в статическом конструкторе.
Похоже, что в основном используется класс JUnit Assert, поэтому его использование, вероятно, будет безопасным. Гибкость ключевого слова assert заключается в возможности включать утверждения во время разработки и отключать их для доставки битов, вместо этого корректно завершая работу.
Надеюсь это поможет.
источник
import static junit.framework.Assert.*
и затем использую один из его методов, напримерassertNotNull("It's null!", someObject);
, отключено ли это утверждение в битах доставки?adb shell setprop debug.assert 1
в Eclipse?su
Тогда сначалаsetprop debug.assert 1
. Обратите внимание, что код, который вы показываете в дизассемблированном виде, останется в сборке выпуска ( stackoverflow.com/a/5590378/506073 ). Я не верю, что компилятору javac можно сказать, чтобы он не выдавал утверждения, поэтому их нужно как-то убрать. Простое решение этого - заключить ключевое слово assert в вашу собственную функцию, которую proguard может лишить вас.Когда утверждения включены,
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 рекомендуют бросать
AssertionError
в качестве приемлемой альтернативы.Я думаю, вы можете настроить Proguard, чтобы исключить эти вызовы производственного кода.
источник
В «Android на практике» предлагается использовать:
$adb shell setprop dalvik.vm.enableassertions all
если эти настройки не сохранены на вашем телефоне, вы можете создать файл /data/local.prop со свойствами, например:
dalvik.vm.enableassertions=all
источник
chmod 644
).Меня чертовски мучило то, что мои утверждения не работали, пока я не проверил проблему в Google ... Я отказался от простых утверждений и перейду к методам утверждения junits.
Для удобства я использую:
import static junit.framework.Assert. *;
Из-за статического импорта позже я могу написать:
assertTrue (...); вместо Assert.assertTrue (...);
источник
Если вас беспокоит доставка кода с утверждениями JUnit (или любым другим путем к классам), вы можете использовать параметр конфигурации ProGuard 'assumenosideeffects', который удалит путь к классу при условии, что его удаление ничего не делает для кода. .
Например.
У меня есть общая библиотека отладки, в которую я помещаю все свои методы тестирования, а затем использую эту опцию, чтобы удалить ее из моих выпущенных приложений.
Это также устраняет трудно обнаруживаемую проблему манипулирования строками, которые никогда не используются в коде выпуска. Например, если вы пишете метод журнала отладки и в этом методе проверяете режим отладки перед записью строки, вы все равно создаете строку, выделяете память, вызываете метод, но затем не решаете ничего делать. Удаление класса затем полностью удаляет вызовы, то есть, пока ваша строка создается внутри вызова метода, она также исчезает.
Однако убедитесь, что это действительно безопасно, так как это делается без каких-либо проверок со стороны ProGuard. Удаление любого метода возврата void будет нормально, однако, если вы берете какие-либо возвращаемые значения из того, что удаляете, убедитесь, что вы не используете их для реальной операционной логики.
источник
-assumenosideeffects class junit.framework.Assert { *; }
Вы можете использовать утверждения, но для их надежного использования потребуется определенная работа. Системное свойство
debug.assert
ненадежно; см. проблемы 175697 , 65183 , 36786 и 17324 .Один из способов - преобразовать каждый
assert
оператор в то, с чем может справиться любая среда выполнения. Сделайте это с помощью исходного препроцессора перед компилятором Java. Например, возьмите это утверждение:assert x == 0: "Failure message";
Для отладочной сборки ваш препроцессор переведет приведенное выше в
if
оператор:{ if( !(x == 0) ) throw new AssertionError( "Failure message" ); }
Для производственной сборки пустому оператору:
;
Обратите внимание, что это будет контролировать утверждения во время сборки, а не во время выполнения (обычная практика).
Я не нашел готового препроцессора, поэтому написал его . См. Часть, посвященную утверждениям. Лицензия на копирование здесь .
источник
Чтобы добавить к ответу Zulaxia на удаление Junit - Proguard уже является частью Android SDK / Eclipse, и на следующей странице рассказывается, как его включить.
http://developer.android.com/guide/developing/tools/proguard.html
Также вышеупомянутое не будет работать с последней конфигурацией proguard по умолчанию, потому что в ней используется флаг -dontoptimize, который необходимо убрать и включить некоторые оптимизации.
источник
Используйте стандартное ключевое слово Java assert , например:
assert a==b;
Чтобы это сработало, вам нужно добавить одну строку в /system/build.prop и перезагрузить телефон:
debug.assert=1
Это будет работать на рутированном телефоне. Воспользуйтесь каким-нибудь файловым менеджером, способным редактировать build.prop (например, X-plore).
Плюсы: большинство (все?) Android-телефоны поставляются с отключенными утверждениями. Даже если ваш код случайно подтвердит значение false, приложение не прервется или не завершится. Однако на вашем устройстве разработки вы получите исключение утверждения.
источник