gradle-android-test-plugin+Robolectricでテスト
参考: http://starzero.hatenablog.com/entry/2013/12/22/201149
gradle-android-test-pluginがいつの間にかDEPRECATEDになっているっていうのを知らずに(ry まぁ他に手段ってのもなかなかなものなので、とりあえずRobolectric演習的に使ってみる
以前、「DialogFragmentのテスト」っていうのを書いてるけど、これをRobolectricでやるにはどんな感じなのか的な事をやってみた
その前に
上記参考先にも書いてますが、どうもRobolectric2.2だと上手く行かない模様なので事前事項として一応書いておく。無論、Robolectric2.3-SNAPSHOTではAPI Level 19はまだサポートされていない模様
構造
├── app │ ├── build.gradle │ └── src │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── sample │ │ │ └── test │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable-hdpi │ │ ├── drawable-ldpi │ │ ├── drawable-mdpi │ │ ├── drawable-xhdpi │ │ ├── drawable-xxhdpi │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── sample │ └── test │ ├── MainActivityTest.java │ └── RobolectricGradleTestRunner.java ├── build.gradle ├── libraries │ └── sample_library │ ├── build.gradle │ └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ │ └── sample │ │ └── test │ │ └── SampleDialogFragment.java │ └── res │ └── layout │ └── dialog.xml └── settings.gradle
RobolectricGradleTestRunner.javaはgithubからポチってくる
settings.gradleは
include ":app"
include ":libraries:sample_library"
な感じだけなので(ry
AndroidManifest.xmlではAPI Level19がサポートされてないので指定しない
build.gradle
buildscript {
repositories {
mavenCentral()
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
}
}
dependencies {
classpath "com.android.tools.build:gradle:0.8.+"
classpath "com.squareup.gradle:gradle-android-test-plugin:0.9.1-SNAPSHOT"
}
}
allprojects {
repositories {
mavenCentral()
// Robolectric2.3-SNAPSHOTを取ってくるのに必要
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
}
}
}
libraries/sample_library/build.gradle
apply plugin: "android-library"
dependencies {
compile "com.google.android:support-v4:r7"
}
android {
compileSdkVersion 18
buildToolsVersion "19.0.1"
}
libraries/sample_library/src/main/java/sample/test/SampleDialogFragment.java
package sample.test;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/**
R.layout.dialog
<?xml version="1.0" ?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/dialog_text"
android:layout_width="fill_parent"
android:layout_height="match_parent" />
</LinearLayout>
*/
public class SampleDialogFragment extends DialogFragment
implements DialogInterface.OnClickListener {
private Handler mHandler = new Handler();
private Activity mActivity;
private View mView;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
mActivity = getActivity();
mView = mActivity.getLayoutInflater().inflate(R.layout.dialog, null);
}
@Override
public Dialog onCreateDialog(Bundle bundle) {
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setView(mView);
builder.setPositiveButton("OK", this);
return builder.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
mHandler.postDelayed(
new Thread() {
@Override
public void run() {
final EditText editor = (EditText)mView.findViewById(R.id.dialog_text);
Toast.makeText(
mActivity,
editor.getText().toString(),
Toast.LENGTH_LONG
).show();
}
},
3000
);
}
}
適当にDialogを出してそこで入力させたテキストをToastで出すだけ。つまりテスト要件も
- DialogFragmentを取って
- Dialog取って
- EditText取って (ついでに値ぶち込んで)
- Positive Buttonクリックさせて
- Toastが出るか
app/build.gradle
apply plugin: "android"
apply plugin: "android-test"
dependencies {
compile project(":libraries:sample_library")
compile "com.actionbarsherlock:actionbarsherlock:4.4.0@aar"
testCompile "junit:junit:4.11"
testCompile "org.hamcrest:hamcrest-all:1.3"
testCompile "org.robolectric:robolectric:2.3-SNAPSHOT"
}
android {
compileSdkVersion 18
buildToolsVersion "19.0.1"
}
app/src/main/java/sample/test/MainActivity.java
package sample.test;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import com.actionbarsherlock.app.SherlockFragmentActivity;
public class MainActivity extends SherlockFragmentActivity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
DialogFragment fragment = new SampleDialogFragment();
fragment.show(getSupportFragmentManager(), "sample_dialog_fragment");
}
}
まーただDialogFragmentをshowしているだけ。ここまでがアプリ側で、これからこれをRobolectricでテストする
app/src/test/java/sample/test/MainActivityTest.java
※さっきも書いたけどRobolectricGradleTestCaseポチってくるの忘れずに
package sample.test;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.support.v4.app.FragmentManager;
import android.widget.Button;
import android.widget.EditText;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.shadows.ShadowToast;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
@RunWith(RobolectricGradleTestRunner.class)
public class MainActivityTest {
@Test
public void test1() {
MainActivity activity = Robolectric.buildActivity(MainActivity.class)
.create()
.start()
.get();
// DialogFragmentをポチってくる
FragmentManager fm = activity.getSupportFragmentManager();
SampleDialogFragment fragment = (SampleDialogFragment)fm.findFragmentByTag("sample_dialog_fragment");
assertThat(fragment, notNullValue());
// Dialogをポチってくる
AlertDialog dialog = (AlertDialog)fragment.getDialog();
assertThat(dialog, notNullValue());
// EditTextをポチってきてテキストを設定しておく
EditText dialogTextView = (EditText)dialog.findViewById(R.id.dialog_text);
assertThat(dialogTextView, notNullValue());
dialogTextView.setText("hoge@gradle-robolectric");
// Positive Buttonをポチってクリックさせてやる
Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
positiveButton.performClick();
// 実体はShadowLooper.idleMainLooper(interval);
// Android標準テスト方式で言えばwaitForIdleSync的なAPIなんじゃないかと
Robolectric.idleMainLooper(5000);
// わざとテストをfailさせてる
assertThat(ShadowToast.getTextOfLatestToast(), is("fuga"));
}
}
終わり。普通にtestタスク動かすと
ってな感じで設定したテキストが反映された結果のToastが取得できている模様
再度言っておくけど、gradle-android-test-plugin自体はDEPRECATEDになっているので
んまぁRobolectric演習的な感じでやってみたっていう事で本ネタ終了
追記
以下で書いてるコードは https://github.com/kinjouj/my-gradle-android-project のdemoブランチに置いてあります