AppiumでE2Eテスト自動化のススメ

Nyle
Nyle
Nov 6, 2014 · 11 min read

今日は、最近私が試しているアプリのE2Eテスト自動化の話をしようかと思います。

現在弊社ではApplivというiOSアプリを開発しています。
iOSアプリで、またiPad対応はしていないため、動作確認は今までiPhone 5Sなどの主要端末でテストすれば、大多数のユーザには問題ないと判断できるような、そんな状況でした。

しかし今年の9月にiPhone6 iPhone6 Plusが発売されて、状況は一変、とまではいきませんが、今までのようにはいかなくなりました。
新しい解像度の追加(しかも2つ)、1つのStoryboardでのマルチデバイス対応、iOS8の移行率の低さ…
結果として、ユーザが使用する端末・OSの組み合わせが増えたため、動作確認もその組み合わせ分増えることになりました。

今までE2Eテスト、つまり最終的な動きの部分が期待通り動いているか、という所については人力でカバーできる範囲でしたが、さすがに6倍にもなると専任の人を用意するか、またはE2Eテストをある程度自動化できないか考える必要が出てきました。

今回はそんな過程で見つけた、「Appium」というテスト自動化のためのフレームワークを紹介します。

Appiumとは?

Appiumとは、iOSやAndroidのモバイルアプリのテストを、Selenium WebDriver APIを使用して実行できるフレームワークです。

Appiumの特徴としては、以下のような物が挙げられます。

  • iOS、Androidの両方に対応している
  • アプリに手を加えずにテストできる
  • 多くの言語でテストコードを書ける
  • Selenium WebDriverのリソースを活かせる

補足ですが、「アプリに手を加えずにテストできる」というのは、アプリ内にテストのみで必要になるコードやSDKを入れる必要がないということです。なので、Xcodeでビルドされたappファイルやアーカイブ用のipaファイルをテスト実行時に指定するだけで、テストが出来ちゃいます。

また特徴にも挙げましたが、テストコードに使用できる言語はRuby、Python、Java、JavaScript、C#、Objective-Cと非常に幅広いです。

今回はこの中で、JavaScriptを使ってテストコードを書いてみますが、他の言語についてもこちらに各言語のサンプルコードが掲載されています。

Appium Inspectorを使って動作をコード化

テストを書く、といっても今回はE2Eテストですので、テスト時に本来であれば手で行う動作をコード化する必要があります。

AppiumにはAppium Inspectorというツールが提供されているので、このツールを使用してテストコードを生成することが出来ます。なので、まずはAppium Inspectorを使用してテストコードを生成してみましょう。

今回テスト対象として使うアプリは、先ほどのGitHubリポジトリに含まれているTestAppというのを使用しますので、事前にこのアプリをビルドしてappファイルを作成しておきます。

Appium Inspectorは、Appiumの公式ページのトップにDownload Appiumというリンクがあるので、そちらからダウンロードできます。ダウンロードしたzipファイルを展開するとAppiumのアプリケーションが展開されるので、そちらを起動します。

Screenshot 2014-11-03 13.37.07
Screenshot 2014-11-03 13.37.07

Appleロゴのボタンをクリックすると設定項目が表示されます。

こちらに、以下の設定を行います。

  • App Path: TestAppのappの場所
  • Force Device: iPhone 6
  • Platform Version: 8.1

今回はXcode 6.1が入っているマシンで試したので上記設定になりますが、Xcodeのバージョンやインストールしているシミュレーターの種類によって使えるデバイスとOSバージョンが異なるので、環境が違う場合は適宜設定を変更してください。

設定が完了したら、右端のLaunchボタンでAppiumサーバを起動します。

その後、虫眼鏡マークのボタンをクリックすると、シミュレータとAppium Inspectorが自動で起ち上がります。

Inspector上では、動作対象となる要素をリストから選択して、そこに対する動作を下のTouchやTextなどから選択することで、シミュレータを制御することが出来ます。

また、上にあるRecordボタンを押した上で要素のアクションを実行すると、その動作が自動的に下のウィンドウのコードが書かれている箇所に出力されます。

このコードもAppiumがサポートしている複数言語から選択することができ、またテストのひな形も自動で埋め込まれます。

今回は以下の手順をテストコードにしてみたいと思います。

  1. View内の一番上のTextFieldに5と入力
  2. View内の上から2番目のTextFieldに8と入力
  3. 上2つのTextField直下にある「Compute Sum」をタップ
  4. ボタン直下のLabelに、1と2で入力した値の合計値が表示されるか

4はテスト結果の確認となるので、1~3までの手順をInspectorで行います。

実際に上記手順をInspectorを使って出力されたのが、以下のコードです。

"use strict";var wd = require("wd");
var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
chai.should();
chaiAsPromised.transferPromiseness = wd.transferPromiseness;
var desired = {
"appium-version": "1.0",
platformName: "iOS",
platformVersion: "8.1",
deviceName: "iPhone 6",
app: "[appファイルへの絶対パス]",
};
var browser = wd.promiseChainRemote("0.0.0.0", 4723);browser.init(desired).then(function() {
return browser
.elementByName("IntegerA").sendKeys("5")
.elementByName("IntegerB").sendKeys("8")
.elementByName("ComputeSumButton").click()
.fin(function() {
return browser.quit();
});
}).done();
このコードに手順4のアサーションを追加し、さらにnode.jsのテストフレームワークであるmochaを使ってテストできるように修正します。
"use strict";var wd = require("wd");
var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
chai.should();
chaiAsPromised.transferPromiseness = wd.transferPromiseness;
describe("iOSアプリのテスト", function () {
this.timeout(300000);
var driver;
before(function () {
driver = wd.promiseChainRemote("0.0.0.0", 4723);
var desired = {
"appium-version": "1.0",
platformName: "iOS",
platformVersion: "8.1",
deviceName: "iPhone 6",
app: "[appファイルへの絶対パス]",
};
return driver.init(desired);
});
after(function () {
return driver.quit();
});
it("2つのTextFieldの値の合計値が表示されるか", function () {
return driver
.elementByName("IntegerA").sendKeys("5")
.elementByName("IntegerB").sendKeys("8")
.elementByName("ComputeSumButton").click()
.elementByName("Answer")
.then(function (element) {
return element.getAttribute("value").should.eventually.equal("13");
});
});
});
これでテストケースが完成しましたので、早速試してみましょう。Appiumでテスト実行テストはmochaを使用するので、事前に以下でmochaコマンドを使用できるようにする必要があります。npm install -g mochaまた、node.js自体がそもそもインストールされていない場合は、上記コード実行前にnode.jsのインストールを行ってください。ここまできたらあとは簡単、Appiumサーバが起動していることを確認して、あとはmocha [テストコードのファイル名].jsでOKです。すると...
Screenshot 2014-11-03 13.45.24
Screenshot 2014-11-03 13.45.24
お...
Screenshot 2014-11-03 13.43.14
Screenshot 2014-11-03 13.43.14
おぉ...
Screenshot 2014-11-03 13.43.21
Screenshot 2014-11-03 13.43.21
おぉぉ...
Screenshot 2014-11-03 13.44.03
Screenshot 2014-11-03 13.44.03
細切れの画像だとなかなか伝わりにくいですが、勝手にiPhoneシミュレータが動いて、勝手にTextFieldに数値を入力して、勝手にボタンを押していきました...誰も触っていないのに勝手にシミュレータが動き出すのはなんだか不思議な感覚になりますが、これでちゃんとテストが実行されています。コンソールには、以下のような結果が出力されています。iOSアプリのテスト
✓ 2つのTextFieldの値の合計値が表示されるか (5196ms)
1 passing (21s)
こんな風にテストできちゃうんですね、すごい
おわりに今回は非常に簡単なテストケースだったので、正直なところ人がやった方が早く終わるんじゃないかという感じになってしまいましたが、これが複数の端末・OSでの検証が必要で、さらにテストケースがもっと多い場合は、Appiumを使ってテストを行うのもアリなんじゃないかと思います。ちなみに今回使用したWD.jsでは、メソッドの一覧をこちらに記載しているので、これを見ればどのような動作ができるのか把握することが出来ます。一覧にはtakeScreenshotなどもあるので、エビデンスを残すとかもできそうですね。また、今回テストで使用したmochaは、出力形式をxunitにすることでJenkinsなどのCIと連携することも出来るので、どこかのMac上でJenkinsを立てて、テストをリモートで行うことなんかもできてしまいます。iPhone6、6 Plus、iOS8の登場でいよいよiOSにもアダプティブなUIが求められるようになってしまいましたが、そんな中でも品質を下げず、かつ迅速なリリースを可能にするためにも、Appiumのようなツールを有効に活用できればいいなと思います。

Nyle Engineering Blog

ナイル株式会社のエンジニアブログです。ナイル社内で利用している技術の情報や、社内の様子などを発信しています。

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store