ぼちぼち、Androidのテストをせねばならぬ。
TwoSpinnersでいろいろやっていたのは、あれは結合テスト的な、実際に動かすテストだったのだけど、ユニットテストのやり方も知っておきたい。
Android Studio 2.1.2でやってみよう。
Android Studioでプロジェクトを新規作成し、Activityだけを持つアプリを作った。
そしてそこに、New ModuelesでAndroid Libraryを追加。
com.hiro99ma.blogpost.myaarというのがそれだ。
デフォルトでExampleUnitTestというものがあるので、それを動かしてみよう。
ツリーから右クリックし、'Run ExampleUnitTest'を選択。
エラーだ。
Process finished with exit code 1
Class not found: "com.hiro99ma.blogpost.myaar.ExampleUnitTest"Empty test suite.
あるのに!
AARだからダメなのかと思ったが、appの方も同じだった。
何かしないとダメらしい。
Building Local Unit Tests | Android Developers
今回やろうとしているのは、Local Unit Testということになる。
書いてあることは、
- build.gradleのdependenciesにjunit(とオプションでmockito)を追加
- テストclassを作る
- Mockのことを飛ばすと、もうRun Local Unit Tests
手順が違うように見えないが。。。
あ、「Sync Projectしろ」とあるな。
ツールバーのアイコンをクリックして、同じようにRunさせると、今度は動いた!
Syncしてなかっただけ、ということか。
でも、Syncが必要なときはだいたいメッセージが出ていたと思うが。。。
まあいい。
ちなみに、テスト内容は「assertEquals(4, 2 + 2);」と単純なものだ。
最初に期待値を書いて、次に評価対象を書く。
逆でも結果としては変わらないと思うけど、たとえば第1引数を5にして失敗させると、こうなる。
ExpectedとActualが出力されるので、やっぱり期待値と評価対象は合わせておいた方がよいだろう。
私はGoogleTestでそれを知らず、全部引数を逆に書いてがっかりしたことがあるのでね。。。
では、自分でclassを作って、それのテストまでやってみよう。
public class MyAar {
private Context mContext;
public MyAar(Context context) {
mContext = context;
}public String getString(int resId) {
return mContext.getString(resId);
}
}
エディタ側の方で、クラス名にカーソルを当てていると電球マークが出てくるので、マウスでクリックしてメニューを開く。
Alt+Enterでもよいかも。
「Create Test」があるので、選択。
Android 2.1.2では、こういう画面が出てきた。
setUp, tearDown、あとはgetString()にチェックしてOK。
そうすると、Choose Destination Directoryダイアログが出てくる。
2つ候補が出てくるが、開いたときは下の方がフォーカスされていた。
上の方はApplicationTest.javaが既にあって、これはテストのメイン処理みたいなものじゃなかろうか。
だから、デフォルトのままでよかろう。
そうすると、MyAarTestというクラスを作ってくれた。
public class MyAarTest {
@Before
public void setUp() throws Exception {}
@After
public void tearDown() throws Exception {}
@Test
public void testGetString() throws Exception {}
}
まあ、空っぽですな。
じゃあテストを書いてみようか、というところで、Contextをどうやって持ってきてよいかということになる。
ここでまた、Android Developerのサイトに戻ろう。
Mockitoというのを使うと、いいらしい。
伊藤さんのMockか、と思ったが、モヒートらしい。。。
サイトではbuild.gradleのdependenciesに追加しているが、こういうのはGUIからでもできたはず、とProject StructureのDependenciesで「mockito-core」を検索してみた。
betaねぇ。。。
まあいいや、それにしてみよう。
build.gradleも見ておく。
testCompile 'junit:junit:4.12'
androidTestCompile 'org.mockito:mockito-core:2.0.71-beta'
追加されたのだけど、最初からあるjunitとちょっと違うな。
まあ、それもよしとしよう。
サイトをまねして@Mockと書いたが、classの前に「@RunWit(MockitoJUnitRunner.class)」の記載もいるようだ。
が、それを追加してもまだだめで、MockitoJUnitRunner.classすらも怒られている。
importを追加しても、そんなの使ってないよ、という感じだ。
ここで、build.gradleのandroidTestCompileをtestCompileに変更すると、直った。
ちっ。
そんなこんなで書いたのが、こういうテストclass。
@RunWith(MockitoJUnitRunner.class)
public class MyAarTest {
MyAar mAar;@Mock
Context mMockContext;@Before
public void setUp() throws Exception {
mAar = new MyAar(mMockContext);
}@After
public void tearDown() throws Exception {
mAar = null;
}@Test
public void testGetString() throws Exception {
Mockito.when(mMockContext.getString(R.string.app_name)).thenReturn("Hello");
String str = mAar.getString(R.string.app_name);
assertThat("Hellos", is(str)); //★第1引数がExpectedのつもりで書いてる
}
}
最後のassertThat()は、サイトのをまねした。
失敗させないと、動いているかどうかわからんので、Mockの方は"Hello"、期待値は"Hellos"としてみた。
結果は、
ああ、ちゃんと失敗しているね。
ん?
Expectedが"Hello"になってる。。。
引数の意味がassertEqual()とは逆なのか。
Assert (JUnit API)
第1引数がactualで、第2引数がMatcherというものらしい。
なんというか、言葉をしゃべるように、
assertThat(実際の値, is(期待値))
→「実際の値 is 期待値」
ということかしらね。
まあ、私も期待値を後ろに書きたい方だからよいのだけど、他のassertと順番が逆なのは嫌だな。
こちらに、assertThat()じゃないと回避できないというか不便というか、そういう問題があるという話が載っていた。
assertEquals()は古い。assertThat()+Matcherを使う。 : Java好き
特にこだわりが無いなら、assertThat()にしておけば困らないのかな。
ただ、見た目が「assertTrue()」に似てるので、そこは気をつけねば。。。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。