Androidのテストフレームワークにて使われる、getContext、getTargetContextで取得されるコンテキストの理解を整理するために以下のそれぞれに分けて比較してみました。得られるコンテキストはテスト対象のパッケージ、テストパッケージ(xxxx.testというパッケージ名になるやつ)の2種類のどちらかになるはずです。
- AndtoidTestCaseを継承したテストケース
- InstrumentationTestCaseを継承したテストケース
- 何も継承しない(AndroidJUnit4で実施される)テストケース
AndroidTestCase
import android.test.AndroidTestCase; public class CheckAndroidTestCase extends AndroidTestCase { public void testThatTestContextInjected() { assertEquals("com.kazucocoa.example", getContext().getPackageName()); } }
AndroidTestCaseでは、getContextでテスト対象のパッケージを得ることができるだけです。どうやら、AndroidTestCaseではsetTargetContextが@hideされているらしいです。そのため、テストパッケージはそのままでは取得できないらしいです。
参照
InstrumentationTestCase
import android.test.InstrumentationTestCase; public class CheckInstrumentationTestCase extends InstrumentationTestCase { public void testThatTestContextInjected() { assertEquals("com.kazucocoa.example.test", getInstrumentation().getContext().getPackageName()); assertEquals("com.kazucocoa.example", getInstrumentation().getTargetContext().getPackageName()); } }
こちらは、getContextでテストパッケージ、getTargetContextでテスト対象のパッケージが取得できることがわかります。
AndroidJUnit4で実施されるテストケース
import android.support.test.InstrumentationRegistry; import org.junit.Test; import static org.junit.Assert.assertEquals; public class ApplicationTest { @Test public void testContextInjected() { assertEquals("com.kazucocoa.example.test", InstrumentationRegistry.getContext().getPackageName()); assertEquals("com.kazucocoa.example", InstrumentationRegistry.getTargetContext().getPackageName()); assertEquals("com.kazucocoa.example.test", InstrumentationRegistry.getInstrumentation().getContext().getPackageName()); assertEquals("com.kazucocoa.example", InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()); } @Test public void instrumentationRegisteryContexts() { assertEquals(InstrumentationRegistry.getContext(), InstrumentationRegistry.getInstrumentation().getContext()); assertEquals(InstrumentationRegistry.getTargetContext(), InstrumentationRegistry.getInstrumentation().getTargetContext()); } }
こちらも、getContextでテストパッケージ、getTargetContextでテスト対象のパッケージが取得できることがわかります。
また、getInstrumentationが挟まることで何か大きく変わるのかと思いましたが、コンテキストの取得という意味では変わりないようです。そうですよね。
テストコードを理解するときは、そのテストで使われるコンテキストがなんなのかを理解することは大事なので、ここらへんの基礎的な理解はしっかり持っておきたいところですね。
参考
- Testing Fundamentals
2種類のパッケージがあることで、テストパッケージにテスト専用のリソースを配置(/resとか)して閉じた環境でテスト実行が可能になります。
蛇足
そういえば、最近 @FlakyTest と呼ばれるアノテーションを見つけました。不安定なテストのことを、Flaky testとよく呼びます。
1つめ: android.support.test.filters
@Flakyは、テストのフィルタリングを行うためだけのアノテーション
2つめ: android.test
@FlakyTestは、テストが失敗したら勝手に再度トライしてくれるためのアノテーション
This annotation can be used on an InstrumentationTestCase’s test methods. When the annotation is present, the test method is re-executed if the test fails. The total number of executions is specified by the tolerance and defaults to 1.
@FlackyTestというアノテーションつけたら、2回実行してくれるのですね。