事象
Robolectricは、Config
アノテーションを用いて複数のAndroidSDKバージョンに対してテスト関数を連続で実行してくれる機能があります。
@Test
@Config(minSdk = 22, maxSdk = 34)
fun getSdkTest() {
}
この機能を用いて、SDK22〜34までをテストした際に OutOfMemoryError
が発生しました。
テスト対象のSDKの数を減らすと正常に完了するため、すべてのSDKバージョンのテスト完了ごとのメモリ解放ではなく、全てのテストが実行されるまで保持しているようです。
環境
- Gradle 8.9
- Gradle JDK 21.0.3
- JUnit 4.13.2
- robolectric 4.14.1
結論
対象モジュールの build.gradle.kts
に、以下のように最大ヒープサイズを指定したところ解消しました。
tasks.withType<Test> {
maxHeapSize = "1024m"
}
groovyの場合は、試していませんがおそらくこの記述となります。
test {
maxHeapSize = "1024m"
}
デフォルトのテスト時のメモリ上限はおそらく512m程度で設定されているようです。
試してダメだったこと
gradle.properties
のjvm引数での最大ヒープサイズの引き上げ
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
ヒープサイズといえばここの指定と思い引き上げましたが、Unitテストではこちらの指定は使われていないようで、効果無しです。
テストの分割
@Test
@Config(minSdk = 22, maxSdk = 29)
fun getSdkTest1() {
}
@Test
@Config(minSdk = 30, maxSdk = 34)
fun getSdkTest2() {
}
テスト関数を分けても、テストクラス自体を分けても、メモリを解放する挙動にはならず、一括テストでは効果はありませんでした。分割したテストを個別に実行するのであれば正常になります。
テスト完了毎にGCを呼ぶ
@After
fun tearDown() {
System.gc()
}
SDKバージョンごとにメモリ展開されたオブジェクトはGC対象ではないのでしょう。効果がありませんでした。