Android 奇怪的测试分片

Android weird test sharding

我正在 Android 上试验测试分片,结果很奇怪:

+ adb -s emulator-5580 shell am instrument -e numShards 2 -e shardIndex 0 -e class com.package.etc.automation.Tests.SanityTest.SanityTest -w com.package.etc.test/android.support.test.runner.AndroidJUnitRunner

com.package.etc.automation.Tests.SanityTest.SanityTest:..........

Time: 306.578

OK (10 tests)


+ adb -s emulator-5582 shell am instrument -e numShards 2 -e shardIndex 1 -e class com.package.etc.automation.Tests.SanityTest.SanityTest -w com.package.etc.test/android.support.test.runner.AndroidJUnitRunner

com.package.etc.automation.Tests.SanityTest.SanityTest:......................

Time: 645.723

OK (22 tests)

如您所见,adb 将测试分为两个不均衡的组。第二个的测试次数是第一个的两倍,执行的时间也是第一个的两倍。如果你问我,这不是最好的并行性。

是否有可能控制测试的分布,或者至少强制 adb 平均分配测试?

我们来追查一下。

当测试套件 started, TestRequestBuilder is built upon JUnit Filters. ShardingFilter is one of them and is added. Adding it means that previously added Filter is "intersected" with new one - method public boolean shouldRun(Description description) 被调用。如果你看它,更有可能是这个片段:

if (description.isTest()) {
    return (Math.abs(description.hashCode()) % mNumShards) == mShardIndex;
}

并用您的数字 (numShards=2) 代替,您会注意到,这只是一个奇偶校验。从统计上讲,生成的 HashCode 奇偶校验分布可能不是 50%。此外,当您的测试 class 中的某些测试被忽略、禁用并与启用的测试交织在一起时,您甚至可以更加干扰特定方法 hashcodeJunit Description uniqueId 是从方法和 class 名称生成)。

这只是统计数据。正如您在 :

中看到的那样

How the groups are divided is arbitrary