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.
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.
Yanıtlar:
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.
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.
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ı?
adb shell setprop debug.assert 1
Eclipse'de yapmanın bir yolu var mı ?
su
sonra 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.
İddialar etkinleştirildiğinde, assert
anahtar kelime AssertionError
boole ifadesi olduğu zaman basitçe bir atar false
.
Yani IMO, en iyi alternatif, özellikle. Junit'e bağlı olmaktan hoşlanmıyorsanız, AssertionError
aş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.
"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
chmod 644
) yapıldığından da emin olmanız gerekebilir .
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;
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.
-assumenosideeffects class junit.framework.Assert { *; }
İddiaları kullanabilirsiniz, ancak bunları güvenilir bir şekilde kullanmak biraz çalışma gerektirir. Sistem özelliği debug.assert
güvenilmezdir; 175697 , 65183 , 36786 ve 17324 sorunlarına bakın .
Yöntemlerden biri, her bir assert
ifadeyi 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 if
ifadeye ç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 .
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.
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.