R8 / Android Gradle 插件是否足够智能以保持库 classes/methods 只在测试 apk 中需要?
Is R8 / Android Gradle Plugin smart enough to keep library classes/methods needed only in test apk?
假设我有一个依赖库的应用程序。这个库有两种方法:
void usedInApp()
void usedInTest()
在我调用的应用程序中 usedInApp()
。我还有一个调用 usedInTest()
的仪器测试。如果我 运行 仪器测试 ./gradlew app:connectedDebugAndroidTest
是 R8/AGP 足够聪明知道要保留 usedInTest()
还是会被删除?
由于应用程序未使用 usedInTest
,R8 会将其删除,并且当 运行 测试您的测试时,它将失败并显示 MethodNotFouldError
。所以你需要一个保留规则来确保 usedInTest
在测试时仍然在应用程序中。一种好方法是添加注释,例如KeepForTesting
并在应用程序中注释测试需要什么。然后添加此保留规则:
-keep,allowobfuscation class * {
@KeepForTesting *;
}
注意 allowobfuscation
修饰符。这允许将这些测试方法重命名为更短的名称。当 Android Studio 构建测试时,它会自动添加 -applymapping
选项以及构建应用程序时生成的映射文件。这样,在测试中对 usedInTest
的引用将在 运行ning R8 之后重命名为应用程序中的实际方法。
对于 R8 本身,我们通过分析 R8 测试来找到 R8 的哪些部分未在 public API 上用于测试,从而实现了自动化。从中我们综合保持规则来保持这一点。然后我们可以在 R8 上 运行 R8,然后 运行 在该版本的 R8 上进行所有测试——这也是我们最终发布的版本。
假设我有一个依赖库的应用程序。这个库有两种方法:
void usedInApp()
void usedInTest()
在我调用的应用程序中 usedInApp()
。我还有一个调用 usedInTest()
的仪器测试。如果我 运行 仪器测试 ./gradlew app:connectedDebugAndroidTest
是 R8/AGP 足够聪明知道要保留 usedInTest()
还是会被删除?
由于应用程序未使用 usedInTest
,R8 会将其删除,并且当 运行 测试您的测试时,它将失败并显示 MethodNotFouldError
。所以你需要一个保留规则来确保 usedInTest
在测试时仍然在应用程序中。一种好方法是添加注释,例如KeepForTesting
并在应用程序中注释测试需要什么。然后添加此保留规则:
-keep,allowobfuscation class * {
@KeepForTesting *;
}
注意 allowobfuscation
修饰符。这允许将这些测试方法重命名为更短的名称。当 Android Studio 构建测试时,它会自动添加 -applymapping
选项以及构建应用程序时生成的映射文件。这样,在测试中对 usedInTest
的引用将在 运行ning R8 之后重命名为应用程序中的实际方法。
对于 R8 本身,我们通过分析 R8 测试来找到 R8 的哪些部分未在 public API 上用于测试,从而实现了自动化。从中我们综合保持规则来保持这一点。然后我们可以在 R8 上 运行 R8,然后 运行 在该版本的 R8 上进行所有测试——这也是我们最终发布的版本。