Android cihazlarda assert kullanabilir miyim?


88

Bazı durumlarda emülatörde veya test sırasında cihazımda uygulamamı yok etmek için android uygulamalarımda Assert anahtar sözcüğünü kullanmak istiyorum . Mümkün mü?

Öykünücü iddialarımı görmezden geliyor gibi görünüyor.



1
Kabul edilen cevabın oldukça yanıltıcı olduğunu unutmayın.
azaltıcı aktivite

Yanıtlar:


-7

API, JUnit Assert sağlar .

Yapabilirsin

import static junit.framework.Assert.*;

artık junit çerçevesinde sağlanan assertTrue, assertEquals, assertNull gibi tüm işlevleri kullanabilirsiniz.

Junit4 çerçevesini tutulma yoluyla içe aktarmamaya dikkat edin, bu org.junit paketi olacaktır. Bir android cihazda veya emülatörde çalışmasını sağlamak için junit.framework paketini kullanmanız gerekir.


51
OP, junit.framework'dan farklı olarak JIT tarafından optimize edilebilen “assert keyword” istedi. Ve tam da bu nedenle buraya geldim. Umarım diğer cevaplardan bazıları daha yararlı olur.
Martin

27
Kaba olmaktan nefret ediyorum ama bu kabul edilen cevap olmamalı çünkü soruya cevap vermiyor (@Martin'in yorumuna katılıyorum). Diğer cevaplar assert anahtar kelimesinin nasıl düzgün çalışacağını açıklar, örneğin "adb shell setprop debug.assert 1" komutunu çalıştırın
jfritz42

3
OP, assert anahtar kelimesini sorduğu için olumsuz oy verildi. @scorpiodawg süreci aşağıda özetledi: stackoverflow.com/a/5563637/484261

scorpiodawg'ın cevabı sadece bir yıl sonra geldi, bu yüzden sanırım bu cevap sadece OP'nin bir sebepten dolayı bir cevabı kabul edilmiş olarak işaretlemek zorunda hissettiği için kabul edildi. Bu tutum, SO konusunda çok sayıda yanıtı eksik ya da düpedüz berbat yapar.
eşzamansız

145

Gömülü Sanal Makine Kontrolü belgesine bakın ( kaynak ağacından ham HTML veya güzel biçimlendirilmiş bir kopya).

Temel olarak Dalvik VM, .dex bayt kodu kontrolü gerçekleştirmek için kod içeriyor olsa bile, varsayılan olarak onaylama kontrollerini yok sayacak şekilde ayarlanmıştır. İddiaların kontrol edilmesi iki yoldan biriyle açılır:

(1) "debug.assert" sistem özelliğini şu şekilde ayarlayarak:

adb shell setprop debug.assert 1

Bunu yaptıktan sonra uygulamanızı yeniden yüklediğiniz sürece amaçlandığı gibi çalıştığını doğruladığım veya

(2) dalvik VM'ye "--enable-assert" komut satırı argümanını göndererek bu uygulama geliştiricilerin yapabileceği bir şey olmayabilir (burada yanılıyorsam biri beni düzeltebilir).

Temel olarak, genel olarak, bir paket düzeyinde veya ilgili düzeyde iddiaları etkinleştiren bir sınıf düzeyinde ayarlanabilen bir bayrak vardır. Bayrak, varsayılan olarak kapalıdır, bunun sonucunda onaylama kontrolleri atlanır.

Örnek Aktivitemde aşağıdaki kodu yazdım:


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

Bu kod için, oluşturulan dalvik bayt kodu (Android 2.3.3 için):


// 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

Statik yapıcının Class nesnesi üzerinde istenilenAssertionStatus metodunu nasıl çağırdığına ve sınıf çapında $ assertionsDisabled değişkenini nasıl ayarladığına dikkat edin; ayrıca onCreate () içinde, java.lang.AssertionError'ı atacak tüm kodun derlendiğine, ancak yürütülmesinin statik yapıcıdaki Class nesnesi için ayarlanan $ assertionsDisabled değerine bağlı olduğuna dikkat edin.

Görünüşe göre JUnit'in Assert sınıfı ağırlıklı olarak kullanılan şeydir, bu yüzden bunu kullanmak muhtemelen güvenli bir bahis. Assert anahtar kelimesinin esnekliği, geliştirme sırasında iddiaları açma ve bunları nakliye bitleri için kapatma ve bunun yerine sorunsuz bir şekilde başarısız olma yeteneğidir.

Bu yardımcı olur umarım.


Görünüşe göre Google, göz atılabilir kaynağı kaldırmış (burada diğer soruların yanıtlarında buna referanslar gördüm). Yapacağınız en iyi şey, kaynağı bulmak veya bunu bir arama motorunda aramaya çalışmaktır. "Dalvik / embedded-vm-control.html" arayın. İşte ona sahip olan bir yer: assembla.com/code/android-gb-for-sharp-is01/git/nodes/dalvik/… . Bu yardımcı olur umarım.
scorpiodawg

Çok faydalı, teşekkürler. Yine de ikinci ve son paragrafta yapılan ayrım beni karıştırıyor. İki tür önermeyi tartışıyoruz: Birincisi, jUnit Assert paketinin assertNotNull () gibi yöntemleri ve ikincisi Java dili 'assert' anahtar sözcüğü. Cevabınız her ikisi için de geçerli mi? Örneğin, eğer ben import static junit.framework.Assert.*ve sonra onun yöntemlerinden birini kullanırsam, mesela assertNotNull("It's null!", someObject);, bu iddia nakliye bitlerinde kapatılır mı?
Jeffro

1
Merhaba Jeffro, buna inanmıyorum - junit.framework.Assert, giriş koşulunun yanlış olduğu bulunduğunda bir istisna atan bir sınıftır. Öte yandan assert anahtar sözcüğü dilde yerleşiktir. Bu yardımcı olur umarım.
scorpiodawg

3
adb shell setprop debug.assert 1Eclipse'de yapmanın bir yolu var mı ?
Pacerier

1
Root iseniz, cihazda çalışan bir terminalden de onaylar yapılabilir. Önce susonra setprop debug.assert 1. Demonte edilmiş olarak gösterdiğiniz kodun bir yayın yapısında kalacağını unutmayın ( stackoverflow.com/a/5590378/506073 ). Javac derleyicisine iddiaları yayınlamamasının söylenebileceğine inanmıyorum, bu yüzden bir şekilde çıkarılmaları gerekir. Bunun basit bir çözümü, proguard'ın sizin için çıkarabileceği anahtar sözcüğü kendi işlevinize yerleştirmektir.
ahcox

10

İddialar etkinleştirildiğinde, assertanahtar kelime AssertionErrorboole ifadesi olduğu zaman basitçe bir atar false.

Yani IMO, en iyi alternatif, özellikle. Junit'e bağlı olmaktan hoşlanmıyorsanız, AssertionErroraşağıda gösterildiği gibi açık bir şekilde atmaktır :

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

Yukarıdaki ifadeye bir alternatif şudur:

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

Yöntem şu şekilde tanımlandığında:

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

Oracle java belgeleri , kabul edilebilir bir alternatif olarak atılmasını önerirAssertionError .

Sanırım Proguard'ı bu üretim kodu çağrılarını kaldıracak şekilde yapılandırabilirsiniz.


Ancak iddiaları nasıl etkinleştirirsiniz? Android Studio'da mısınız?
SMBiggs

8

"Uygulamada Android" de aşağıdakilerin kullanılması önerilir:

$adb shell setprop dalvik.vm.enableassertions all

Bu ayarlar telefonunuzda kalıcı değilse, aşağıdaki özelliklere sahip /data/local.prop dosyası oluşturabilirsiniz:

dalvik.vm.enableassertions=all

Stackoverflow.com/a/18556839/2004714 başına , dosyanın salt okunur ( chmod 644) yapıldığından da emin olmanız gerekebilir .
Paulo

5

Google'da konuyu kontrol edene kadar iddialarımın işe yaramadığı beni çok rahatsız ediyordu ... Basit iddialardan vazgeçtim ve junits iddia yöntemleriyle devam edeceğim.

Kolaylık sağlamak amacıyla kullanıyorum:

import statik junit.framework.Assert. *;

Statik içe aktarım nedeniyle daha sonra yazabilirim:

assertTrue (...); Assert.assertTrue (...) yerine;


4

JUnit'in (veya başka herhangi bir sınıf yolunun) içinde bulunduğu gönderim koduyla ilgili endişeleriniz varsa, ProGuard yapılandırma seçeneğini 'assumenosideeffects' kullanabilirsiniz; bu, kaldırmanın kod için hiçbir şey yapmadığı varsayımıyla bir sınıf yolunu ortadan kaldıracaktır. .

Örneğin.

-assumenosideeffects junit.framework.Assert {
*;
}

Tüm test yöntemlerimi koyduğum ortak bir hata ayıklama kitaplığım var ve ardından bu seçeneği yayımlanan uygulamalarımdan çıkarmak için kullanıyorum.

Bu ayrıca, yayın kodunda asla kullanılmayan, işlenen dizelerin tespit edilmesi zor sorununu da ortadan kaldırır. Örneğin, bir hata ayıklama günlüğü yöntemi yazarsanız ve bu yöntemde dizeyi günlüğe kaydetmeden önce hata ayıklama modunu kontrol ederseniz, yine de dizeyi oluşturuyorsunuz, bellek ayırıyorsunuz, yöntemi çağırıyorsunuz, ancak sonra hiçbir şey yapmamayı seçiyorsunuz. Sınıfın çıkarılması, çağrıları tamamen kaldırır, yani dizeniz yöntem çağrısı içinde oluşturulduğu sürece, o da ortadan kalkar.

Bununla birlikte, ProGuard'ın kısmında herhangi bir kontrol yapılmadan yapıldığından, sadece çizgileri çıkarmanın gerçekten güvenli olduğundan emin olun. Herhangi bir void döndürme yöntemini kaldırmak iyi olacaktır, ancak kaldırdığınız şeyden herhangi bir dönüş değeri alıyorsanız, bunları gerçek operasyonel mantık için kullanmadığınızdan emin olun.


1
Bence doğru sözdizimi:-assumenosideeffects class junit.framework.Assert { *; }
Pooks

Kafa karıştırıcı cevap. Bahsedilen komut proguard hatasına neden olur. Pooks tarafından düzeltilen komut hala ikili dex dosyasından iddiaları kaldırmıyor.
Pointer Null

Aynı sorunu yaşıyorum @PointerNull. kaldırılmayacak iddiası.
Mehdi

3

İddiaları kullanabilirsiniz, ancak bunları güvenilir bir şekilde kullanmak biraz çalışma gerektirir. Sistem özelliği debug.assertgüvenilmezdir; 175697 , 65183 , 36786 ve 17324 sorunlarına bakın .

Yöntemlerden biri, her bir assertifadeyi herhangi bir çalışma zamanının başa çıkabileceği bir şeye çevirmektir . Bunu Java derleyicisinin önünde bir kaynak ön işlemcisi ile yapın. Örneğin, şu ifadeyi alın:

assert x == 0: "Failure message";

Bir hata ayıklama derlemesi için, ön işlemciniz yukarıdakileri bir ififadeye çevirir :

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

Bir üretim yapısı için boş bir ifadeye:

;

Bunun, çalışma zamanının aksine (olağan uygulama) derleme zamanında iddiaları kontrol edeceğini unutmayın.

Hazır bir önişlemci bulamadım, bu yüzden bir tane senaryo yazdım . İddialarla ilgili kısma bakın. Kopyalama lisansı burada .


1

Zulaxia'nın Junit'in çıkarılması konusundaki cevabına eklemek için - Proguard zaten Android SDK / Eclipse'in bir parçası ve aşağıdaki sayfa size nasıl etkinleştireceğinizi anlatıyor.

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

Ayrıca yukarıdakiler en son varsayılan proguard yapılandırmasıyla çalışmaz çünkü çıkarılması gereken -dontoptimize bayrağını kullanır ve optimizasyonların bir kısmı açılır.


0

Standart Java assert anahtar sözcüğünü kullanın , örneğin:

assert a==b;

Bunun çalışması için /system/build.prop'a bir satır eklemeniz ve telefonu yeniden başlatmanız gerekir:

debug.assert=1

Bu, köklü telefonda çalışır. Build.prop'u düzenleyebilen bir dosya yöneticisi kullanın (örn. X-plore).

Artılar: Çoğu (tümü?) Android telefon onaylar devre dışı bırakılmış olarak gönderilir. Kodunuz yanlışlıkla yanlış olduğunu iddia etse bile, uygulama kesintiye uğramaz veya çökmez. Ancak, geliştirme cihazınızda onay istisnası alacaksınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.