Saya ingin menggunakan kata kunci Assert di aplikasi android saya untuk menghancurkan aplikasi saya dalam beberapa kasus di emulator, atau perangkat saya selama pengujian. Apakah ini mungkin?
Sepertinya emulator mengabaikan pernyataan saya.
Saya ingin menggunakan kata kunci Assert di aplikasi android saya untuk menghancurkan aplikasi saya dalam beberapa kasus di emulator, atau perangkat saya selama pengujian. Apakah ini mungkin?
Sepertinya emulator mengabaikan pernyataan saya.
Jawaban:
API menyediakan JUnit Assert .
Anda dapat melakukan
import static junit.framework.Assert.*;
sekarang Anda dapat menggunakan semua fungsi seperti assertTrue, assertEquals, assertNull yang disediakan dalam kerangka junit.
Berhati-hatilah untuk tidak mengimpor kerangka kerja Junit4 melalui eclipse, yang akan menjadi paket org.junit. Anda harus menggunakan paket junit.framework agar dapat berfungsi di perangkat android atau emulator.
Lihat dokumen Kontrol VM Tertanam (HTML mentah dari pohon sumber , atau salinan yang diformat dengan baik ).
Pada dasarnya, VM Dalvik diatur untuk mengabaikan pemeriksaan pernyataan secara default, meskipun kode byte .dex menyertakan kode untuk melakukan pemeriksaan. Memeriksa pernyataan diaktifkan dengan salah satu dari dua cara berikut:
(1) dengan menyetel properti sistem "debug.assert" melalui:
adb shell setprop debug.assert 1
yang saya verifikasi berfungsi selama Anda memasang ulang aplikasi setelah melakukan ini, atau
(2) dengan mengirimkan argumen baris perintah "--enable-assert" ke VM dalvik yang mungkin tidak dapat dilakukan oleh pengembang aplikasi (ada yang mengoreksi saya jika saya salah di sini).
Pada dasarnya, ada sebuah flag yang dapat disetel baik secara global, pada tingkat paket, atau pada tingkat kelas yang memungkinkan pernyataan pada tingkat yang bersangkutan. Bendera dinonaktifkan secara default, akibatnya pemeriksaan pernyataan dilewati.
Saya menulis kode berikut dalam Contoh Aktivitas saya:
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;
}
}
Untuk kode ini, kode byte dalvik yang dihasilkan adalah (untuk 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
Perhatikan bagaimana konstruktor statis memanggil metode yang diinginkanAssertionStatus pada objek Kelas dan menyetel variabel seluruh kelas $ assertionsDisabled; juga perhatikan bahwa di onCreate (), semua kode untuk melempar java.lang.AssertionError dikompilasi, tetapi eksekusinya bergantung pada nilai $ assertionsDisabled yang disetel untuk objek Kelas di konstruktor statis.
Tampaknya kelas Assert JUnit adalah yang paling banyak digunakan, jadi kemungkinan besar aman untuk menggunakannya. Fleksibilitas kata kunci assert adalah kemampuan untuk mengaktifkan pernyataan pada waktu pengembangan dan menonaktifkannya untuk pengiriman bit dan malah gagal dengan baik.
Semoga ini membantu.
import static junit.framework.Assert.*
dan kemudian saya menggunakan salah satu metodenya, seperti assertNotNull("It's null!", someObject);
, apakah pernyataan ini dinonaktifkan dalam bit pengiriman?
adb shell setprop debug.assert 1
di Eclipse?
su
, lalu setprop debug.assert 1
. Perhatikan bahwa kode yang Anda tunjukkan dibongkar akan tetap dalam versi rilis ( stackoverflow.com/a/5590378/506073 ). Saya tidak percaya kompiler javac dapat diberitahu untuk tidak mengeluarkan pernyataan sehingga mereka perlu dilucuti. Solusi sederhana untuk itu adalah membungkus kata kunci yang menegaskan dalam fungsi Anda sendiri yang dapat dihapus oleh proguard untuk Anda.
Saat pernyataan diaktifkan, assert
kata kunci hanya melempar AssertionError
ketika ekspresi boolean adalah false
.
Jadi IMO, alternatif terbaik, esp. Jika Anda menolak untuk bergantung pada junit, adalah dengan melemparkan secara AssertionError
eksplisit seperti yang ditunjukkan di bawah ini:
assert x == 0 : "x = " + x;
Alternatif dari pernyataan di atas adalah:
Utils._assert(x == 0, "x = " + x);
Dimana metode tersebut didefinisikan sebagai:
public static void _assert(boolean condition, String message) {
if (!condition) {
throw new AssertionError(message);
}
}
Dokumen java Oracle merekomendasikan untuk melempar AssertionError
sebagai alternatif yang dapat diterima.
Saya kira Anda dapat mengkonfigurasi Proguard untuk menghapus panggilan ini untuk kode produksi.
Dalam "Android in Practice", disarankan untuk menggunakan:
$adb shell setprop dalvik.vm.enableassertions all
jika pengaturan ini tidak bertahan di ponsel Anda, maka Anda dapat membuat file /data/local.prop dengan properti seperti:
dalvik.vm.enableassertions=all
chmod 644
).
Itu mengganggu saya, bahwa pernyataan saya tidak berhasil, sampai saya memeriksa masalah di google ... Saya menyerah pada pernyataan sederhana dan akan menggunakan metode pernyataan junits.
Untuk tujuan kenyamanan saya menggunakan:
impor junit.framework.Assert statis. *;
Karena impor statis saya nanti dapat menulis:
assertTrue (...); bukannya Assert.assertTrue (...);
Jika Anda khawatir tentang kode pengiriman dengan pernyataan JUnit di (atau jalur kelas lainnya), Anda dapat menggunakan opsi konfigurasi ProGuard 'assumenosideeffects', yang akan menghapus jalur kelas dengan asumsi bahwa menghapusnya tidak berpengaruh pada kode .
Misalnya.
-assumenosideeffects junit.framework.Assert {
*;
}
Saya memiliki pustaka debug umum tempat saya memasukkan semua metode pengujian saya, dan kemudian menggunakan opsi ini untuk menghapusnya dari aplikasi yang saya rilis.
Ini juga menghilangkan masalah sulit ditemukan dari string yang dimanipulasi yang tidak pernah digunakan dalam kode rilis. Misalnya jika Anda menulis metode log debug, dan dalam metode itu Anda memeriksa mode debug sebelum mencatat string, Anda masih membuat string, mengalokasikan memori, memanggil metode tersebut, tetapi kemudian memilih untuk tidak melakukan apa-apa. Melucuti kelas kemudian menghapus panggilan sepenuhnya, yang berarti selama string Anda dibangun di dalam pemanggilan metode, itu juga hilang.
Namun, pastikan benar-benar aman untuk hanya menghapus garis, karena ini dilakukan tanpa memeriksa bagian ProGuard. Menghapus metode pengembalian kosong akan baik-baik saja, namun jika Anda mengambil nilai pengembalian apa pun dari apa pun yang Anda hapus, pastikan Anda tidak menggunakannya untuk logika operasional yang sebenarnya.
-assumenosideeffects class junit.framework.Assert { *; }
Anda dapat menggunakan pernyataan, tetapi perlu beberapa upaya untuk menggunakannya dengan andal. Properti sistem debug.assert
tidak dapat diandalkan; lihat masalah 175697 , 65183 , 36786 dan 17324 .
Salah satu metode adalah menerjemahkan setiap assert
pernyataan menjadi sesuatu yang dapat ditangani oleh runtime apa pun. Lakukan ini dengan preprocessor sumber di depan compiler Java. Misalnya, ambil pernyataan ini:
assert x == 0: "Failure message";
Untuk build debug, preprocessor Anda akan menerjemahkan pernyataan di atas ke if
:
{ if( !(x == 0) ) throw new AssertionError( "Failure message" ); }
Untuk produksi build, ke pernyataan kosong:
;
Perhatikan bahwa ini akan mengontrol pernyataan pada waktu pembuatan, sebagai kebalikan dari waktu berjalan (praktik biasa).
Saya tidak dapat menemukan preprocessor yang sudah jadi, jadi saya membuat skrip . Lihat bagian berurusan dengan pernyataan. Lisensi untuk menyalin ada di sini .
Untuk menambah jawaban Zulaxia tentang menghapus Junit - Proguard sudah menjadi bagian dari Android SDK / Eclipse dan halaman berikut memberi tahu Anda cara mengaktifkannya.
http://developer.android.com/guide/developing/tools/proguard.html
Juga di atas tidak akan berfungsi dengan konfigurasi proguard default terbaru karena menggunakan flag -dontoptimize yang harus dihilangkan dan beberapa pengoptimalan dihidupkan.
Gunakan kata kunci pernyataan Java standar , misalnya:
assert a==b;
Agar ini berfungsi, Anda harus menambahkan satu baris ke /system/build.prop, dan reboot ponsel:
debug.assert=1
Ini akan berfungsi pada ponsel yang di-rooting. Gunakan beberapa pengelola file yang mampu mengedit build.prop (mis. X-plore).
Plus: sebagian besar (semua?) Ponsel Android dikirimkan dengan pernyataan dinonaktifkan. Meskipun kode Anda secara tidak sengaja menyatakan sebagai salah, aplikasi tidak akan mengganggu atau crash. Namun, pada perangkat pengembangan Anda, Anda akan mendapatkan pengecualian pernyataan.