migrating-from-android-test-classes について
非推奨の Android プラットフォーム `android.test.*` クラスを AndroidX Test に置き換える移行ガイドです。旧式のテストを保守する開発者向けに、ランナー、基底クラス、アサーション、UI 操作の移行先を示します。
主な機能
- 01クラスごとの置き換え案内
- 02AndroidJUnitRunner への移行
- 03JUnit3 テストの JUnit4 化
- 04アサーションと UI 操作の置換
- 05テスト用コンテキストとモックの置換
活用シーン
- 01旧モジュールから `android.test.*` を除去
- 02テストを AndroidX ランナーへ移行
- 03Activity テストを ActivityScenario に変更
- 04MoreAsserts と TouchUtils の置換
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill migrating-from-android-test-classesインストール後、Claude Code で/migrating-from-android-test-classesを入力して読み込まれたか確認します。
詳細
android.test.* からの移行 — プラットフォームのレガシーテストクラスから AndroidX Test へ
Android SDK に含まれる android.test.* パッケージ(InstrumentationTestCase、ActivityInstrumentationTestCase2、AndroidTestCase、ServiceTestCase、MoreAsserts、TouchUtils、android.test.mock.*、…)は @Deprecated です。プラットフォームの Javadoc でも、すべてのクラスの移行先として AndroidX Test が案内されています。古いコードベースには今もこれらのクラスが残っており、JUnit4、Espresso、ActivityScenario、AndroidX ランナーへの移行を妨げています。このスキルでは、クラスごとの置き換え先と機械的な移行パターンを示します。
このスキルを使う場合
- IDE が
android.test.InstrumentationTestCase/AndroidTestCase/ActivityInstrumentationTestCase2/ServiceTestCase/MoreAsserts/ViewAsserts/TouchUtils/android.test.mock.*に@Deprecatedの警告を表示する場合。 - モジュールの
testInstrumentationRunnerがandroid.test.InstrumentationTestRunnerで、AndroidJUnitRunnerではテストの動作がおかしい(または検出されない)場合。 - ユーザーが特定のレガシーベースクラスの置き換え方法を尋ねている場合:「
TestCaseの外でのgetInstrumentation()」、「ActivityInstrumentationTestCase2を使わずにgetActivity()/setActivityIntent()を使う方法」、「AndroidTestCaseを使わずにgetContext()を使う方法」。 - テストが
junit.framework.TestCaseを継承している(JUnit3 スタイル:setUp()のオーバーライド、testFoo()という命名、junit.framework.AssertのassertEquals)一方で、チームが JUnit4 を希望している場合。 - ユーザーが
MoreAsserts.assertContentsInAnyOrder/assertEquals(int[], int[])/assertContainsRegex、ViewAsserts.assertOnScreen、TouchUtils.tapView/dragQuarterScreenDown、またはandroid.test.suitebuilder.annotation.SmallTestに言及している場合。
このスキルを使わない場合
- コードベースがすでに AndroidX Test を使用しており、質問がその使い方(ランナー、
ActivityScenario、Espresso、ServiceTestRule)に関する場合は、../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md、../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.md、../../../instrumentation/espresso/writing-espresso-tests/SKILL.mdを直接参照してください。 - 質問が
kotlin.testのアサーション(assertEquals、assertFailsWith)に関する場合は、../../../kotlin/kotlin-test/writing-tests-with-kotlin-test/SKILL.mdを使ってください。(MoreAssertsの呼び出しを置き換える有効な選択肢の 1 つはkotlin.testです。) - 対象のレガシークラスが Robolectric のシャドウ、または純粋な JVM コードで使われる JUnit3 の 非 Android
TestCaseの場合は、JVM/Robolectric 側について../../../jvm-tests/robolectric/using-robolectric-correctly/SKILL.mdと../../../jvm-tests/runner/configuring-junit4-on-android/SKILL.mdを使ってください。 - ユーザーが 新しい テストを書こうとしている場合は、最初から
android.test.*を使わず、AndroidX のスキルを直接使ってください。
前提条件
- テストクラスパスに AndroidX Test が含まれていること。必要な依存関係の正確な組み合わせ(
androidx.test:core、:runner、:rules、androidx.test.ext:junit)については、../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.mdを参照してください。ホスト/JVM テストについては、../../../jvm-tests/runner/configuring-junit4-on-android/SKILL.mdを参照してください。 - クラスパスに JUnit4 が含まれていること(
junit:junit:4.13.2、またはkotlin("test")経由)。レガシークラスは JUnit3 の形式です(TestCaseをextends)。移行先は JUnit4(@Testと@RunWith)です。 TouchUtils/ViewAsserts/ActivityInstrumentationTestCase2の UI 操作を使用していた機能には、Espresso(androidx.test.espresso:espresso-core)が必要です。
置き換え先一覧
レガシーの android.test.*(非推奨) | 代わりに使用 | 備考 |
|---|---|---|
InstrumentationTestRunner(testInstrumentationRunner) | androidx.test.runner.AndroidJUnitRunner | android.defaultConfig.testInstrumentationRunner を変更します。レガシーのランナーでは、JUnit4 や Espresso が正しく実行されません。 |
InstrumentationTestCase | @RunWith(AndroidJUnit4::class) + InstrumentationRegistry.getInstrumentation() | getInstrumentation() → androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()。injectInstrumentation(...) は廃止されています。sendKeys/runTestOnUiThread → getInstrumentation().runOnMainSync { … } または @UiThreadTest。 |
AndroidTestCase | @RunWith(AndroidJUnit4::class) + ApplicationProvider.getApplicationContext() | getContext() → ApplicationProvider.getApplicationContext<Context>()。getTestContext()(テスト APK のコンテキスト)→ InstrumentationRegistry.getInstrumentation().context。 |
ApplicationTestCase<T> | @RunWith(AndroidJUnit4::class) を使用し、ApplicationProvider.getApplicationContext() を介して Application を操作します | 1 対 1 で置き換えられる基底クラスはありません。現在、Application は単なるコンテキストです。直接アサートしてください。 |
ActivityInstrumentationTestCase2<T>、ActivityUnitTestCase<T>、SingleLaunchActivityTestCase<T> | ActivityScenario<T> / @get:Rule ActivityScenarioRule<T>(UI には Espresso も使用) | getActivity() → scenario.onActivity { activity -> … }。setActivityIntent(intent) → ActivityScenario.launch<T>(intent)。getInstrumentation().waitForIdleSync() → Espresso の自動同期。../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.md を参照してください。 |
| (独自実装の Fragment テストがある場合) | FragmentScenario / launchFragmentInContainer | ../../../instrumentation/scenarios/launching-fragments-with-fragmentscenario/SKILL.md。 |
ServiceTestCase<T> | androidx.test.rule.ServiceTestRule | startService(intent) / bindService(intent) はルールに移行します(@get:Rule val serviceRule = ServiceTestRule())。getService() → serviceRule.bindService(intent) から取得する IBinder。 |
ProviderTestCase2<T> | androidx.test.rule.provider.ProviderTestRule | ProviderTestCase2 は JUnit3 形式です。ProviderTestRule.Builder(MyProvider::class.java, AUTHORITY).build() が JUnit4 形式で、引き続き分離された ContentResolver を提供します。 |
LoaderTestCase | (Loader 自体が非推奨です) | まず Loader を ViewModel + コルーチン/Flow に移行し、その後 runTest / Turbine でテストしてください。 |
MoreAsserts(assertContentsInAnyOrder、assertEquals(int[], int[])、assertEmpty、assertNotEqual、assertContainsRegex、checkEqualsAndHashCodeMethods) | Google Truth(assertThat(list).containsExactly(...)、.isEmpty()、.containsMatch(regex))、Hamcrest、または順序付き配列には kotlin.test.assertContentEquals | プラットフォームの Javadoc では「Hamcrest を使用」とされています。Truth のほうが読みやすいです。androidx.test.ext:truth には Android 固有の Truth サブジェクトが含まれています。 |
ViewAsserts(assertOnScreen、assertHorizontalCenterAligned、assertBottomAligned、…) | Espresso の ViewMatchers + ViewAssertions(matches(isCompletelyDisplayed())、レイアウト関係を確認するカスタムマッチャー) | ../../../instrumentation/espresso/writing-espresso-tests/SKILL.md を参照してください。 |
TouchUtils(tapView、clickView、longClickView、dragQuarterScreenDown、scrollToBottom、dragViewToTop) | Espresso の ViewActions(click()、longClick()、swipeUp()/swipeDown()、scrollTo()、GeneralSwipeAction) | レガシーのメソッドには実行中の Instrumentation と Activity の参照が必要です。Espresso のアクションは onView(...).perform(...) 内で実行します。 |
android.test.UiThreadTest | androidx.test.annotation.UiThreadTest | インポートを変更するだけです。または getInstrumentation().runOnMainSync { … } / scenario.onActivity { … }(すでにメインスレッド上で実行されます)に置き換えてください。 |
android.test.FlakyTest | androidx.test.filters.FlakyTest | インポートを変更します。 |
android.test.suitebuilder.annotation.SmallTest / MediumTest / LargeTest / Suppress | androidx.test.filters.SmallTest / MediumTest / LargeTest / Suppress | インポートを変更します。ランナーは AndroidX のアノテーションに対して -e size small を読み取ります。 |
android.test.InstrumentationTestSuite、android.test.suitebuilder.TestSuiteBuilder | JUnit4 の @RunWith(Suite::class) + @Suite.SuiteClasses([...])、または AndroidJUnitRunner に @SmallTest/パッケージで検出させます | AndroidX ランナーを導入すれば、手動でのスイート構築はほとんど必要ありません。 |
android.test.mock.MockContext | 実際のコンテキスト(ApplicationProvider.getApplicationContext())、JVM 上の Robolectric のコンテキスト、または厳密に分離する場合は mock(Context::class.java)(Mockito/MockK) | MockContext はほとんどすべてのメソッドで UnsupportedOperationException をスローします。これは手動でスタブを実装するための基底クラスでしたが、モックフレームワークのほうが適しています。 |
android.test.mock.MockContentResolver + MockContentProvider | ProviderTestRule(分離されたリゾルバー)、または Robolectric/インストルメント化されたコンテキストから取得した実際の ContentResolver | スタブのリゾルバーが本当に必要な場合は、Mockito で ContentResolver をモックしてください。 |
android.test.mock.MockPackageManager | Mockito/MockK の mock(PackageManager::class.java) | プラットフォームの Javadoc には「Mockito などのモックフレームワークを使用」と明記されています。 |
android.test.mock.MockResources / MockCursor / MockDialogInterface / MockApplication / MockService | Mockito/MockK のモック、またはテストコンテキストから取得した実際のインスタンス | 同様に、これらはスタブ用の基底クラスでしたが、モックフレームワークに置き換えられます。 |
android.test.AndroidTestRunner、android.test.PerformanceTestCase、android.test.RepetitiveTest | AndroidJUnitRunner、androidx.benchmark(Microbenchmark/Macrobenchmark)、カスタム JUnit4 の @Rule、または単純なループ | PerformanceTestCase は androidx.benchmark よりも前のものです。本格的なパフォーマンステストには androidx.benchmark を使用してください。 |
extends junit.framework.TestCase + junit.framework.Assert の assertEquals(JUnit3 形式) | @RunWith(AndroidJUnit4::class) + @Test メソッド + org.junit.Assert.* / kotlin.test.* | メソッド名に test の接頭辞は不要になります。setUp/tearDown のオーバーライドは @Before/@After(または @BeforeTest/@AfterTest)になります。 |
プラットフォームの
@deprecatedJavadoc には、古い「Android Testing Support Library」/android.support.test.*の名前(例:ActivityTestRule)が記載されていることがよくあります。これらはandroidx.test.*に移行され、その後、再び非推奨になったものもいくつかあります。たとえば、ActivityTestRule→ActivityScenarioです。プラットフォームの Javadoc に文字どおり記載されているものではなく、上の表にある現在の移行先を使用してください。
ワークフロー
-
1. まずランナーを切り替えます。
android.defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"を設定し、AndroidX Test の依存関係を追加します。これが完了するまでは、JUnit4/Espresso/ActivityScenarioを実行できません。(../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md。) -
2. テストクラスを1つずつ、JUnit3からJUnit4に変換します。
extends …TestCaseを削除し、@RunWith(AndroidJUnit4::class)を追加して、テストメソッドに@Testを付けます。setUp()/tearDown()のオーバーライドを@Before/@Afterに変換し(superの呼び出しは不要です)、必要であればtestFooをfooに名前変更します。各レガシーアクセサーを、表にあるAndroidXの同等機能に置き換えます。 -
3. 基底クラスの特別な機能を、明示的なAndroidXのエントリーポイントに置き換えます。
getContext()→ApplicationProvider.getApplicationContext()、getInstrumentation()→InstrumentationRegistry.getInstrumentation()、getActivity()→ActivityScenarioとonActivity { }、getService()→ServiceTestRule.bindService(...)。 -
4. アサーションヘルパーを切り替えます。
MoreAsserts.*→ Truth/kotlin.test、ViewAsserts.*→ Espresso のViewAssertions、TouchUtils.*→ Espresso のViewActions。 -
5. モックコンテキストを切り替えます。
android.test.mock.MockContext/MockResources/MockPackageManagerを継承するものは、可能であれば実際のテストコンテキストに置き換え、それ以外の場合はMockito/MockKのモックに置き換えます。(../../../jvm-tests/mocking/mocking-with-mockito/SKILL.md。) -
6. レガシーインポートを削除し、
android.test.*やandroid.test.mock.*への参照が残っていないことを確認します。 モジュールがクリーンな状態であれば、import android.test.の行がゼロでもコンパイルできます。
パターン
パターン:ActivityInstrumentationTestCase2 → ActivityScenario
// WRONG — deprecated base class
class LoginActivityTest : ActivityInstrumentationTestCase2<LoginActivity>(LoginActivity::class.java) {
fun testTitleShown() {
val activity = activity // getActivity()
assertEquals("Sign in", activity.title)
}
}
// WRONG because: android.test.ActivityInstrumentationTestCase2 is @Deprecated; it ties the test to
// the legacy InstrumentationTestRunner, blocks JUnit4/Espresso, and getActivity() leaks the Activity
// off the main thread.
// RIGHT — ActivityScenario + JUnit4
@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
@get:Rule val scenario = ActivityScenarioRule(LoginActivity::class.java)
@Test fun titleShown() {
scenario.scenario.onActivity { activity ->
assertEquals("Sign in", activity.title)
}
onView(withId(R.id.title)).check(matches(withText("Sign in"))) // or assert via Espresso
}
}
パターン:AndroidTestCase → @RunWith(AndroidJUnit4) + ApplicationProvider
// WRONG
class FormatterTest : AndroidTestCase() {
fun testCurrency() {
val s = CurrencyFormatter(context).format(1099) // getContext()
assertEquals("$10.99", s)
}
}
// WRONG because: android.test.AndroidTestCase is @Deprecated; getContext() and the TestCase shape
// are the legacy world.
// RIGHT
@RunWith(AndroidJUnit4::class)
class FormatterTest {
private val context: Context = ApplicationProvider.getApplicationContext()
@Test fun currency() {
assertEquals("$10.99", CurrencyFormatter(context).format(1099))
}
}
パターン:MoreAsserts/TouchUtils の呼び出し
// WRONG
MoreAsserts.assertContentsInAnyOrder(ids, 3L, 1L, 2L) // android.test.MoreAsserts (deprecated)
TouchUtils.tapView(this, listView) // android.test.TouchUtils (deprecated)
ViewAsserts.assertOnScreen(rootView, listView) // android.test.ViewAsserts (deprecated)
// RIGHT
assertThat(service.ids()).containsExactly(1L, 2L, 3L) // Google Truth (order-insensitive)
onView(withId(R.id.list)).perform(click()) // Espresso ViewActions
onView(withId(R.id.list)).check(matches(isCompletelyDisplayed())) // Espresso ViewAssertions
パターン:android.test.mock.MockContext のサブクラス → 実際のコンテキストまたはMockito
// WRONG
class FakeContext : MockContext() { // android.test.mock.MockContext (deprecated)
override fun getPackageName() = "com.example"
// every other method throws UnsupportedOperationException
}
// RIGHT — a real test context if the SUT just reads from it
val context: Context = ApplicationProvider.getApplicationContext()
// RIGHT — a mock if you must control specific calls in isolation
val context = mock<Context> { on { packageName } doReturn "com.example" }
必須ルール
- MUST NOT
android.test.*またはandroid.test.mock.*のクラスを使った新しいテストを追加しないでください。これらはすべて@Deprecatedです。新しいテストでは AndroidX Test(AndroidJUnit4、ActivityScenario、ServiceTestRule、ProviderTestRule、Espresso)と、org.junit/kotlin.testのアサーションを使用してください。 - MUST テストクラスの移行を始める前(または最初の手順として)に、
testInstrumentationRunnerをandroidx.test.runner.AndroidJUnitRunnerに切り替えてください。レガシーのInstrumentationTestRunnerでは JUnit4/Espresso を実行できません。 - MUST
getActivity()/setActivityIntent()をActivityScenario(launch、onActivity { })に置き換えてください。ActivityTestRuleには置き換えないでください。ActivityTestRule自体も非推奨です。 - MUST
android.test.mock.MockContext/MockResources/MockPackageManager/MockContentResolverのサブクラスは、SUT が読み取りにしか使わない場合は実際のテストコンテキストに、それ以外の場合は Mockito/MockK のモックに置き換えてください。MockContextを基に新たな手作りのスタブを作り直さないでください。 - MUST JUnit3 形式(
extends TestCase、testFoo()、setUp()/tearDown()のオーバーライド、junit.framework.Assert)を JUnit4(@RunWith(AndroidJUnit4)、@Test、@Before/@After、org.junit.Assert/kotlin.test)に変換してください。クラスを中途半端に移行した状態にしないでください。 - MUST NOT プラットフォームの
@deprecatedJavadoc に記載された置き換え先をそのまま信用しないでください(多くの場合、すでに廃止されたandroid.support.test.*API が指定されています)。このスキルの表にある、現在の AndroidX の置き換え先に移行してください。 - PREFERRED: 変更ごとにテストクラスを1つずつ完全に移行し、最初にランナーの切り替えを適用してください。一部のクラスが
android.test.*、残りが AndroidX を使う中途半端な状態のモジュールは、把握が困難です。 - PREFERRED:
MoreAssertsの置き換えには、Hamcrest より Google Truth(Android のサブジェクトにはandroidx.test.ext:truth)を推奨します。失敗時のメッセージがより分かりやすくなります。
検証
-
git grep -n 'import android.test\.' -- '*.java' '*.kt'の結果が空であること(または、追跡対象で妥当な理由のある例外リストに限られていること)。 - どのモジュールの
testInstrumentationRunnerもandroid.test.InstrumentationTestRunnerではなく、すべてandroidx.test.runner.AndroidJUnitRunnerであること。 -
extends ActivityInstrumentationTestCase2/AndroidTestCase/InstrumentationTestCase/ServiceTestCase/ProviderTestCase2/junit.framework.TestCaseを使用するテストクラスがないこと。 -
MoreAsserts./ViewAsserts./TouchUtils.の参照が残っていないこと。 -
android.test.mock.MockContext/MockResources/MockPackageManager/MockContentResolverのサブクラスが残っていないこと。 - 移行したインストルメンテーションテストが
./gradlew :module:connectedDebugAndroidTestで成功し、移行したホストテストが./gradlew :module:testDebugUnitTestで成功すること。
参考資料
- developer.android.com/training/testing — AndroidX Test の概要。
android.test.*のすべての移行先です。 - developer.android.com/reference/android/test/package-summary —
android.testパッケージのリファレンス。すべてのクラスに非推奨のマークが付けられ、置き換え先が示されています。 frameworks/base/test-base/src/android/test/AndroidTestCase.java、InstrumentationTestCase.java、UiThreadTest.java、FlakyTest.java(AOSP) —@Deprecatedクラスで、Javadoc にはInstrumentationRegistry/androidx.test.annotation.UiThreadTest/androidx.test.filters.FlakyTestへの移行先が記載されています。frameworks/base/test-runner/src/android/test/ActivityInstrumentationTestCase2.java、ServiceTestCase.java、ProviderTestCase2.java、InstrumentationTestRunner.java、MoreAsserts.java、ViewAsserts.java、TouchUtils.java(AOSP) — 非推奨のランナー/基底クラスです。Javadoc では、置き換え先としてActivityTestRule/ServiceTestRule/AndroidJUnitRunner/Hamcrest/Espresso が挙げられています。frameworks/base/test-mock/src/android/test/mock/MockContext.java、MockPackageManager.java、MockContentResolver.java、MockResources.java、MockCursor.java(AOSP) — スタブコンテキストの基底クラスです。MockPackageManagerの Javadoc には、「Mockito のようなモックフレームワークを使用してください」と明記されています。- 横断参照:
../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md— 最初に確認するAndroidJUnitRunner/AndroidX Test の対応バージョン表です。 - 横断参照:
../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.md—ActivityInstrumentationTestCase2の置き換え先であるActivityScenario/ActivityScenarioRuleです。 - 横断参照:
../../../instrumentation/scenarios/launching-fragments-with-fragmentscenario/SKILL.md— 独自のフラグメントテスト基底クラスに使用できるFragmentScenarioです。 - 横断参照:
../../../instrumentation/espresso/writing-espresso-tests/SKILL.md—ViewAsserts/TouchUtilsの置き換えとなる Espresso のViewMatchers/ViewActions/ViewAssertionsです。 - 横断参照:
../../../jvm-tests/mocking/mocking-with-mockito/SKILL.md—android.test.mock.*の置き換えとなる、Context/PackageManager/Resourcesのモック化です。 - 横断参照:
../../../jvm-tests/robolectric/using-robolectric-correctly/SKILL.md— モックコンテキストの代替となる、JVM 上での実際の Android スタブです。 - 横断参照:
../../../kotlin/kotlin-test/writing-tests-with-kotlin-test/SKILL.md—MoreAssertsとjunit.framework.Assertの有効な置き換えの一つである、kotlin.testのアサーション(assertEquals、assertContentEquals、assertFailsWith)です。 - 横断参照:
../../../fundamentals/strategies/organizing-test-source-sets/SKILL.md— 移行したクラスを振り分けるsrc/test/とsrc/androidTest/です。