Bessere Methode zum Debuggen nur Code aktivieren

8

Ich schreibe meine erste Android-Anwendung und ich benutze großzügig assert () von junit.framework.Assert

Ich möchte einen Weg finden, um sicherzustellen, dass die Behauptungen nur in den Debug-Build kompiliert werden, nicht in den Release-Build.

Ich weiß, wie man das Attribut android: debuggable aus dem Manifest abfragt, damit ich eine Variable erstellen und dies in der folgenden Abbildung ausführen kann:

static final boolean mDebug = ...

if (mDebug)     Assert.assertNotNull (anzeigen);

Gibt es einen besseren Weg, dies zu tun? d.h. ich würde es vorziehen, kein if () mit jedem assert zu verwenden.

Danke

    
jbww 18.02.2011, 16:12
quelle

3 Antworten

19

Ich denke, dass das assert -Schlüsselwort der Java-Sprache wahrscheinlich das ist, was Sie wollen. Unter den Deckblättern kompiliert das Schlüsselwort assert im Wesentlichen zu Dalvik-Byte-Code, der zwei Dinge tut:

  1. Überprüft, ob die statische Variable assertionsDisabled (gesetzt im statischen Konstruktor der Klasse über einen Aufruf von java.lang.Class.desiredAssertionStatus() )! = 0 ist und wenn ja, tut nichts
  2. Wenn 0 ist, überprüft es den Assertionsausdruck und gibt java.lang.AssertionError aus, wenn der Ausdruck in false aufgelöst wird, wodurch Ihre Anwendung effektiv beendet wird.

In der Dalvik-Laufzeitumgebung sind die Assertions standardmäßig deaktiviert, und daher gibt desiredAssertionStatus immer 1 (genauer gesagt, einen Wert ungleich Null) zurück. Dies ist vergleichbar mit dem Ausführen im "Einzelhandels" -Modus. Um den "Debug" -Modus zu aktivieren, können Sie den folgenden Befehl für den Emulator oder das Gerät ausführen:

%Vor%

und das sollte den Trick machen (sollte auf dem Emulator oder jedem gerooteten Debugger-fähigen Gerät funktionieren).

Beachten Sie jedoch, dass der oben erwähnte Dalvik-Code, der den Wert von assertionsDisabled prüft und einen AssertionError liefert, wenn der Ausdruck falsch ist, immer in Ihrem Byte-Code enthalten ist und eine großzügige Beregnung von assert s in Ihrem Code dazu führen kann Bytecode aufgebläht.

Bitte sehen Sie dies für ein bisschen mehr Detail: Kann ich Assert auf Android-Geräten verwenden?

    
scorpiodawg 08.04.2011, 04:19
quelle
8

Wenn Sie sich Sorgen über den Versandcode mit den JUnit-Behauptungen in (oder einem anderen Klassenpfad) machen, können Sie die ProGuard-Konfigurationsoption 'assemptnosideeffects' verwenden, die einen Klassenpfad entfernt, unter der Annahme, dass das Entfernen nichts tut zum Code.

z.

%Vor%

Ich habe eine gemeinsame Debug-Bibliothek, in die ich alle meine Testmethoden einfüge, und verwende dann diese Option, um sie aus meinen freigegebenen Apps zu entfernen.

Dadurch wird auch das schwer zu erkennende Problem der manipulierten Zeichenfolgen beseitigt, die im Freigabecode niemals verwendet werden. Wenn Sie zum Beispiel eine Debug-Log-Methode schreiben und in dieser Methode vor dem Protokollieren der Zeichenfolge den Debug-Modus prüfen, konstruieren Sie immer noch die Zeichenfolge, weisen Speicher zu, rufen die Methode auf und entscheiden sich dann für nichts. Wenn die Klasse entfernt wird, werden die Aufrufe vollständig entfernt. Das heißt, solange Ihre Zeichenfolge innerhalb des Methodenaufrufs erstellt wird, wird sie ebenfalls entfernt.

Stellen Sie sicher, dass es wirklich sicher ist, die Leitungen nur zu entfernen, wie es ohne Überprüfung des ProGuard-Teils geschieht. Das Entfernen von Void-Rückgabe-Methoden ist in Ordnung. Wenn Sie jedoch Rückgabewerte von dem entfernen, was Sie entfernen, stellen Sie sicher, dass Sie sie nicht für die tatsächliche Betriebslogik verwenden.

    
Zulaxia 15.09.2011 07:01
quelle
0

Ich meine, wenn Sie ein Sprachfeature wie assert () verwenden, sollte der Compiler das entfernen können. Dies ist jedoch eine tatsächliche Klasse, und wenn eine Klasse durch ausführbaren Code referenziert wird, wird sie vom Compiler in das Endprodukt aufgenommen oder davon ausgegangen.

Nichtsdestotrotz hindert Sie nichts daran, ein Skript zu erstellen, das vor der Kompilierung alle Verweise auf die Assert-Klasse in Ihrer gesamten Codebasis entfernt.

Ein anderer Ansatz wäre, ein Testprojekt zu erstellen, das auf Ihre Anwendung abzielt und innerhalb von JUnit-Tests die Assert in den Bereichen aufruft, in denen Sie sicher arbeiten wollen. Ich persönlich mag diesen Ansatz, weil es eine schöne und saubere Trennung von Test und Anwendung ist.

Wenn Sie sich nur Sorgen machen, dass Sie überall eine if-Anweisung haben, dann wickeln Sie Assert einfach mit Ihrer eigenen Klasse DebuggableAssert ab, die diese Überprüfung vor jedem Aufruf von Assert.X durchführt. Es wird etwas weniger leistungsfähig sein, da die Methode den Ein- / Ausstieg und die Bedingungen hat, aber wenn Sie Ihren Code besser halten können, dann könnte es sich lohnen.

    
Greg Giacovelli 18.02.2011 16:32
quelle

Tags und Links