更好的方法只调试断言代码

jbw*_*bww 8 android

我正在编写我的第一个Android应用程序,我很自由地使用junit.framework.Assert中的asserts()

我想找到一种方法来确保断言只被编译到调试版本中,而不是发布版本中.

我知道如何从清单查询android:debuggable属性,所以我可以创建一个变量,并在以下fashon中完成此操作:

static final boolean mDebug = ...

if(mDebug)Assert.assertNotNull(view);

有一个更好的方法吗?即我不想在每个断言中使用if().

谢谢

sco*_*awg 19

我认为Java语言的assert关键字可能就是你想要的.在封面下,assert关键字基本上编译成Dalvik字节代码,它执行两项操作:

  1. 检查静态变量assertionsDisabled(通过调用在类'静态构造函数中设置java.lang.Class.desiredAssertionStatus())是否为!= 0,如果是,则不执行任何操作
  2. 如果它 0,则它检查断言表达式并抛出java.lang.AssertionError表达式解析后的表达式false,从而有效地终止应用程序.

默认情况下,Dalvik运行时关闭断言,因此desiredAssertionStatus始终返回1(或更准确地说,返回一些非零值).这类似于以"零售"模式运行.要打开"调试"模式,可以对模拟器或设备运行以下命令:

adb shell setprop debug.assert 1
Run Code Online (Sandbox Code Playgroud)

这应该做的伎俩(应该在模拟器或任何有根的调试就绪设备上工作).

但请注意,前面提到的Dalvik代码检查表达式是否为false ,assertionsDisabled并且AssertionError如果表达式为false,则会始终包含在字节代码中,并且在代码中自由地使用asserts会导致字节代码膨胀.

有关详细信息,请参阅此内容:我可以在Android设备上使用assert吗?


Zul*_*xia 8

如果您担心在(或任何其他类路径)中使用JUnit断言传送代码,您可以使用ProGuard配置选项'assumenosideeffects',这将删除类路径,前提是删除它对代码不执行任何操作.

例如.

-assumenosideeffects class junit.framework.Assert {
*;
}
Run Code Online (Sandbox Code Playgroud)

我有一个通用的调试库,我将所有测试方法都放入其中,然后使用此选项从我发布的应用程序中删除它.

这也消除了从未在发布代码中使用的字符串被操纵的难以发现的问题.例如,如果您编写调试日志方法,并且在该方法中,在记录字符串之前检查调试模式,您仍在构造字符串,分配内存,调用方法,但随后选择不执行任何操作.剥离类然后完全删除调用,这意味着只要你的字符串在方法调用中构造,它就会消失.

然而,确保将线条剥离是真的安全,因为没有检查ProGuard的部分.删除任何void返回方法都没问题,但是如果要从删除的内容中获取任何返回值,请确保不将它们用于实际操作逻辑.