比較的最近、UI Androidアプリケーションをテストするための素晴らしいEspressoライブラリが登場しました。 アナログよりも優れている点は何度も確認されています。 要するに、彼らはこれが彼ら自身のOS(以前は彼ら自身がRobotiumを使用していた)のためのGoogleの開発であるという事実と、簡潔な構文と作業速度にある。 そこで、私たちは最新の状態に保ち、エスプレッソを使用することにしました。 しかし、すでに持っているプラスはありません。BDD( http://en.wikipedia.org/wiki/Behavior-driven_development )が必要です。jsonとhtmlでスクリーンショットとレポートが必要です。CIですべて実行します。結局のところ! しかし、まず最初に。 キュウリ( http://habrahabr.ru/post/62958/ )とエスプレッソ( http://habrahabr.ru/post/212425/ )を簡単な例で友達にする方法を説明します。 Appiumにうんざりしている人、Robotiumから逃れたい人、Androidテストに関心がある人は誰でも猫をお願いします。
接続
Gradleをプロジェクトのビルドおよび依存関係解決ツールとして使用します。 ウェブサイトhttp://gradleplease.appspot.com/をまだご覧になっていない方にお勧めします 。 探しているモジュールの名前を伝え、Gradleに接続するための文字列を返します。
プロジェクトを作成し、タスクに必要なEspressoとCucumberモジュールに接続してみましょう。そのため、次のようにbuild.gradleファイルの依存関係ブロックを追加します。
dependencies { androidTestCompile('com.jakewharton.espresso:espresso-support-v4:1.1-r3') androidTestCompile 'info.cukes:cucumber-core:1.1.8' androidTestCompile 'info.cukes:cucumber-java:1.1.8' androidTestCompile 'info.cukes:cucumber-html:0.2.3' androidTestCompile ('info.cukes:cucumber-android:1.2.2') androidTestCompile ('info.cukes:cucumber-junit:1.1.8') { exclude group: 'org.hamcrest', module: 'hamcrest-core' exclude group: 'org.hamcrest', module: 'hamcrest-integration' exclude group: 'org.hamcrest', module: 'hamcrest-library' } }
Espressoツールを使用するには、GoogleInstrumentationTestRunnerでテストを実行する必要があります。 したがって、Cucumberを接続するには、このクラスから継承する必要があります。このクラス内ですべての制御を行います。
public class CucuRunner extends GoogleInstrumentationTestRunner{ private CucumberInstrumentationCore helper; public CucuRunner() { helper = new CucumberInstrumentationCore(this); } @Override public void onCreate(Bundle arguments) { helper.create(arguments); super.onCreate(arguments); } @Override public void onStart() { helper.start(); } }
build.gradleで新しく作成したインストルメンテーションテストランナーを指定することを忘れないでください
defaultConfig { ... testInstrumentationRunner 'habrahabr.ru.myapplication.test.CucuRunner' ... }
手順
次に、テストシナリオで使用するステップを作成する必要があります。 私たちの場合、それらは1つのケースに組み合わされた小さなテストになります。 これを行うには、Espressoの標準テストセットから継承される適切なクラスを作成して、必要なすべての要素にアクセスできるようにします。 このクラスに注釈を追加します。このクラスでは、これらがCucumberテストであり、それらの作業の結果を、対応する形式のレポートの必要なディレクトリに配置する必要があることを示します。 Espressoテストはデバイスで実行されるため、コンピューターディレクトリにアクセスできないことに注意してください。 したがって、すべてをアプリケーションのディレクトリに配置します。
@CucumberOptions(format = {"pretty","html:/data/data/habrahabr.ru.myapplication/html", "json:/data/data/habrahabr.ru.myapplication/jreport"},features = "features") public class CucumberActivitySteps extends ActivityInstrumentationTestCase2<MainActivity> {
これで、ステップの実装を直接処理できます。 これを行うには、BDD、つまり、Given、When、Thenに従って、目的に応じてメソッドを分割する必要があります。 これを行うには、正規表現、入力引数の役割を果たすグループ、およびEspresso呼び出しを使用するステップの本文に基づいて、スクリプトファイルで一致を見つけるための文字列を含む注釈を使用します。
@Given("^ (\\d)$") public void givenLoginTryCounter(Integer counterValue) { String checkString = String.format(getActivity().getResources().getString(R.string.login_try_left), counterValue); onView(withId(R.id.lblCounter)).check(matches(withText(checkString))); } @When("^ $") public void clickOnBackButton() { ViewActions.pressBack(); } @When("^ '(.+)' '(.+)'$") public void userLogin(String login, String password) { onView(withId(R.id.txtUsername)).perform(ViewActions.clearText()); onView(withId(R.id.txtPassword)).perform(ViewActions.clearText()); onView(withId(R.id.txtUsername)).perform(ViewActions.typeText(login)); onView(withId(R.id.txtPassword)).perform(ViewActions.typeText(password)); onView(withId(R.id.btnLogin)).perform(ViewActions.click()); } @Then("^ (\\d)$") public void checkLoginTryCounter(Integer counterValue) { givenLoginTryCounter(counterValue); } @Then("^ $") public void checkLoginButtonDisabled() { onView(withId(R.id.btnLogin)).check(matches(not(isEnabled()))); }
スクリーンショット
最後の手順が正常に完了しなかった場合、スクリーンショットを撮り、結果の画像をレポートに追加します。 Cucumberが残りの作業を行い、エラー発生時の画面の状態を確認できます。 次の方法は、たとえば、会話のある写真を撮るのには適していませんが、これは別の議論のトピックです。
@After public void embedScreenshot(Scenario scenario) { if(scenario.isFailed()) { Bitmap bitmap; final Activity activity = getActivity(); View view = getActivity().getWindow().getDecorView(); view.setDrawingCacheEnabled(true); bitmap = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(false); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); scenario.embed(stream.toByteArray(), "image/png"); } }
シナリオ
最も楽しい部分が残った。 CucumberActivityStepsで説明されている手順を手にすると、テスト自体を人間の言語で書くことができ、開発者だけでなく、他のすべての利害関係者も利用できます。
Feature: Scenario: , Given 3 When 'RandomName' 'wrongPassword' Then 2 And ' .'
これらのスクリプトは、実行クラスがそれらを検索する機能ディレクトリに保存します(CucumberOptionsアノテーションを参照)。
デバイスからレポートを取得する
テストを実行すると、それらは合格しますが、レポートはデバイスに残ります。 そのため、テストが完了したら、そこから取得する必要があります。 build.gradleファイルに移動し、対応するタスクを作成します。adbユーティリティとpullコマンドを使用して、レポートファイルを指定されたディレクトリにコピーします。
task afterTests(type: Exec, dependsOn:runCucuTests) { commandLine "${android.sdkDirectory}" + "/platform-tools/adb", 'pull', '/data/data/habrahabr.ru.myapplication/html', System.getProperty("user.dir") + "/cucumber_reports" }
IDEからすべてを開始できるようになりました。適切な起動構成を作成するだけで、テストが完了したら、タスクを実行してレポートを取得できます。
レポートは上記のディレクトリに保存されます
CIの起動
ただし、IDEを介してテストを実行するのではなく、コンソールからテストを実行する必要があり、connectedCheckは私たちに適していません。 そこで、新しいタスクを作成しています。 そして、残念なことに、アプリケーションを作成してデバイスにインストールし、コマンドを送信してadbを介してテストを開始することほど良いものは考えられませんでした。 そして、このすべての後、上記のタスクでレポートを取得します。
task runCucuTests(type: Exec, dependsOn:'installDebugTest'){ commandLine "${android.sdkDirectory}" + "/platform-tools/adb", 'shell', 'am', 'instrument', '-w', 'habrahabr.ru.myapplication.test/.CucuRunner', 'echo', 'off' finalizedBy('afterTests') }
原則として、これはすでにCIでテストを実行するのに十分です。
出力では、次のレポートを取得します。
そして、失敗したシナリオごとに、スクリーンショットが添付されます。
これはおそらく停止します。 ここでは、テスト中にコンソールへの通常の出力を取得したり、進行状況に関する情報を含めたり、レポートファイルを美しくしたりするなど、多くの点を改善したいと考えています。 このような機会があればいいのですが。 興味のある方は、プロジェクト自体がGithubに投稿されます : https : //github.com/Stabilitron/espresso-cucumber-example
ご清聴ありがとうございました。 あなたへの安定したリリース!