Ich möchte das Schlüsselwort Assert in meinen Android-Apps verwenden, um meine App in einigen Fällen auf dem Emulator oder meinem Gerät während des Tests zu zerstören. Ist das möglich?
Es scheint, dass der Emulator meine Behauptungen einfach ignoriert.
Antworten:
Die API stellt den JUnit Assert bereit .
Du kannst tun
Jetzt können Sie alle Funktionen wie assertTrue, assertEquals und assertNull verwenden, die im junit-Framework bereitgestellt werden.
Achten Sie darauf, das Junit4-Framework nicht über Eclipse zu importieren. Dies ist das Paket org.junit. Sie müssen das Paket junit.framework verwenden, damit es auf einem Android-Gerät oder dem Emulator funktioniert.
quelle
Weitere Informationen finden Sie im Dokument Embedded VM Control (unformatiertes HTML aus dem Quellbaum oder eine gut formatierte Kopie).
Grundsätzlich ist die Dalvik-VM so eingestellt, dass Assertionsprüfungen standardmäßig ignoriert werden, obwohl der .dex-Bytecode den Code zur Durchführung der Prüfung enthält. Das Überprüfen von Zusicherungen kann auf zwei Arten aktiviert werden:
(1) durch Setzen der Systemeigenschaft "debug.assert" über:
was ich überprüft habe, funktioniert wie beabsichtigt, solange Sie Ihre App danach neu installieren, oder
(2) indem Sie das Befehlszeilenargument "--enable-assert" an die dalvik VM senden, was App-Entwickler wahrscheinlich nicht können (jemand korrigiert mich, wenn ich mich hier irre).
Grundsätzlich gibt es ein Flag, das entweder global, auf Paketebene oder auf Klassenebene gesetzt werden kann, um Zusicherungen auf dieser jeweiligen Ebene zu ermöglichen. Das Flag ist standardmäßig deaktiviert, wodurch die Assertionsprüfungen übersprungen werden.
Ich habe den folgenden Code in meine Beispielaktivität geschrieben:
Für diesen Code lautet der generierte Dalvik-Byte-Code (für Android 2.3.3):
Beachten Sie, wie der statische Konstruktor die gewünschte MethodeAssertionStatus für das Class-Objekt aufruft und die klassenweite Variable $ assertionsDisabled festlegt. Beachten Sie auch, dass in onCreate () der gesamte Code zum Auslösen von java.lang.AssertionError kompiliert wird, seine Ausführung jedoch vom Wert von $ assertionsDisabled abhängt, der für das Class-Objekt im statischen Konstruktor festgelegt ist.
Es scheint, dass die Assert-Klasse von JUnit überwiegend verwendet wird, daher ist es wahrscheinlich eine sichere Wette, dies zu verwenden. Die Flexibilität des Schlüsselworts assert besteht darin, dass Assertions zur Entwicklungszeit aktiviert und für den Versand von Bits deaktiviert werden können und stattdessen ordnungsgemäß fehlschlagen.
Hoffe das hilft.
quelle
import static junit.framework.Assert.*
und dann beispielsweise eine ihrer Methoden verwendeassertNotNull("It's null!", someObject);
, ist diese Behauptung in Versandbits deaktiviert?adb shell setprop debug.assert 1
in Eclipse zu tun ?su
dannsetprop debug.assert 1
. Beachten Sie, dass der Code, den Sie zerlegt anzeigen, in einem Release-Build verbleibt ( stackoverflow.com/a/5590378/506073 ). Ich glaube nicht, dass dem Javac-Compiler gesagt werden kann, er solle keine Behauptungen aufstellen, daher müssen sie irgendwie entfernt werden. Eine einfache Lösung besteht darin, das Schlüsselwort assert in Ihre eigene Funktion zu verpacken, die proguard für Sie entfernen kann.Wenn Zusicherungen aktiviert sind, löst das
assert
Schlüsselwort einfach ein aus,AssertionError
wenn der boolesche Ausdruck lautetfalse
.Also IMO, die beste Alternative, insb. Wenn Sie abgeneigt sind, von junit abhängig zu sein, werfen Sie eine
AssertionError
explizit wie unten gezeigt:Eine Alternative zur obigen Aussage ist:
Wo die Methode definiert ist als:
In den Oracle Java-Dokumenten wird empfohlen , eine
AssertionError
als akzeptable Alternative zu verwenden.Ich denke, Sie können Proguard so konfigurieren, dass diese Aufrufe für Produktionscode entfernt werden.
quelle
In "Android in der Praxis" wird empfohlen, Folgendes zu verwenden:
Wenn diese Einstellungen auf Ihrem Telefon nicht beibehalten werden, können Sie die Datei /data/local.prop mit folgenden Eigenschaften erstellen:
quelle
chmod 644
).Es hat mich verdammt nervt, dass meine Behauptungen nicht funktionierten, bis ich das Problem bei Google überprüft habe ... Ich habe einfache Behauptungen aufgegeben und werde mich für die Assertionsmethoden von junits entscheiden.
Aus praktischen Gründen verwende ich:
importiere statisches junit.framework.Assert. *;
Aufgrund des statischen Imports kann ich später schreiben:
assertTrue (...); anstelle von Assert.assertTrue (...);
quelle
Wenn Sie Bedenken hinsichtlich des Versandcodes mit den JUnit-Asserts in (oder einem anderen Klassenpfad) haben, können Sie die ProGuard-Konfigurationsoption 'assumenosideeffects' verwenden, mit der ein Klassenpfad unter der Annahme entfernt wird, dass das Entfernen des Codes nichts mit dem Code zu tun hat .
Z.B.
Ich habe eine gemeinsame Debug-Bibliothek, in die ich alle meine Testmethoden eingefügt habe, und verwende diese Option, um sie aus meinen veröffentlichten Apps zu entfernen.
Dies beseitigt auch das schwer zu erkennende Problem der Manipulation von Zeichenfolgen, die im Release-Code niemals verwendet werden. Wenn Sie beispielsweise eine Debug-Protokollmethode schreiben und bei dieser Methode vor dem Protokollieren der Zeichenfolge nach dem Debug-Modus suchen, erstellen Sie die Zeichenfolge weiterhin, weisen Speicher zu, rufen die Methode auf und entscheiden sich dann dafür, nichts zu tun. Wenn Sie die Klasse entfernen, werden die Aufrufe vollständig entfernt. Solange Ihre Zeichenfolge im Methodenaufruf erstellt wird, wird sie ebenfalls entfernt.
Stellen Sie jedoch sicher, dass es wirklich sicher ist, nur die Leitungen zu entfernen, da dies ohne Überprüfung durch ProGuard erfolgt. Das Entfernen einer ungültigen Rückgabemethode ist in Ordnung. Wenn Sie jedoch Rückgabewerte von dem entfernen, was Sie entfernen, stellen Sie sicher, dass Sie diese nicht für die tatsächliche Betriebslogik verwenden.
quelle
-assumenosideeffects class junit.framework.Assert { *; }
Sie können Zusicherungen verwenden, aber es erfordert einige Arbeit, um sie zuverlässig zu verwenden. Die Systemeigenschaft
debug.assert
ist unzuverlässig. siehe Ausgaben 175697 , 65183 , 36786 und 17324 .Eine Methode besteht darin, jede
assert
Anweisung in etwas zu übersetzen , mit dem sich jede Laufzeit befassen kann. Tun Sie dies mit einem Quell-Präprozessor vor dem Java-Compiler. Nehmen Sie zum Beispiel diese Aussage:Bei einem Debug-Build würde Ihr Präprozessor das Obige in eine
if
Anweisung übersetzen:Für einen Produktionsaufbau zu einer leeren Anweisung:
Beachten Sie, dass dies die Behauptungen zur Erstellungszeit im Gegensatz zur Laufzeit (die übliche Praxis) steuern würde.
Ich konnte keinen vorgefertigten Präprozessor finden, also habe ich einen geschrieben . Siehe den Teil, der sich mit Behauptungen befasst. Die Lizenz zum Kopieren finden Sie hier .
quelle
Zulaxias Antwort zum Entfernen von Junit - Proguard ist bereits Teil von Android SDK / Eclipse. Auf der folgenden Seite erfahren Sie, wie Sie es aktivieren.
http://developer.android.com/guide/developing/tools/proguard.html
Außerdem funktioniert das oben Gesagte nicht mit der neuesten Standard-Proguard-Konfiguration, da das Flag -dontoptimize verwendet wird, das entfernt und einige der Optimierungen aktiviert werden müssen.
quelle
Verwenden Sie das Standard-Java- Assert- Schlüsselwort, zum Beispiel:
Damit dies funktioniert, müssen Sie eine Zeile zu /system/build.prop hinzufügen und das Telefon neu starten:
Dies würde auf gerooteten Telefonen funktionieren. Verwenden Sie einen Dateimanager, der build.prop bearbeiten kann (z. B. X-plore).
Pluspunkte: Die meisten (alle?) Android-Telefone werden mit deaktivierten Zusicherungen ausgeliefert. Selbst wenn Ihr Code versehentlich auf false gesetzt wird, wird die App nicht unterbrochen oder stürzt ab. Auf Ihrem Entwicklungsgerät wird jedoch eine Assertionsausnahme angezeigt.
quelle