AppiumでFlutterアプリのテストを自動化する 実践編(JavaScript)

# はじめに

[AppiumでFlutterアプリのテストを自動化する 環境構築編 - Qiita](https://qiita.com/hiesiea/items/b4e31b6f1f585a93bae1)
の続きになります。
実際にテストコードを書いて、それを実行し、レポートを出力するところまでやります。
今回は「JavaScript」を使います。

# 前提条件

[AppiumでFlutterアプリのテストを自動化する 環境構築編 - Qiita](https://qiita.com/hiesiea/items/b4e31b6f1f585a93bae1)
で、Appiumの環境構築が完了していること

# なぜAppiumで自動化するのか

Flutterには、「Integration Test」という仕組みが存在します。

- [An introduction to integration testing - Flutter](https://flutter.dev/docs/cookbook/testing/integration/introduction)

これは結合テストを行うための仕組みですが、この仕組みを利用することで、UIテストを自動化することも可能になります。また、各OSごとにUIテストを用意せずとも、ワンソースで実装することができます。
ですが、テストしたいWidgetに対して逐一Keyを設定していかなければならないのと、全て手動で実装しないといけないのが難点になります。
Appiumはワンソースで実装することが容易ではありませんが、OSごとのデバイス設定やWidgetの取得方法などをうまく共通化することができればワンソースでも実現可能ですし、何よりレコード機能があるため、Appiumで自動化する選択肢もありだと考えています。
ただ何を優先するかはプロジェクトによりけりではあるので、どちらが正解というわけでもないと思います。

# プロジェクトの準備

[appium/sample-code/javascript-wd at master · appium/appium · GitHub](https://github.com/appium/appium/tree/master/sample-code/javascript-wd)
をベースにプロジェクトを準備します。
なぜこのプロジェクトを流用したかというと、レコード機能で取得した内容をコピペするだけで実装が容易にできるのと、Mochaというテスティングフレームワークがなかなか良さげ（レポート機能ついてたりとか）だったので採用しました。
基本的にはほぼ流用している形になります。

```json:package.json
{
  "name": "appium_test_js_wd",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "test": "mocha test/**/*.test.js",
    "clean": "rm -rf node_modules && rm -f package-lock.json && npm install"
  },
  "author": "",
  "license": "ISC",
  "engines": {
    "node": ">=6",
    "npm": ">=6"
  },
  "devDependencies": {
    "@babel/register": "^7.0.0",
    "@babel/core": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "chai": "^4.1.2",
    "mocha": "^6.0.0",
    "wd": "^1.5.0"
  }
}
```

```json:.babelrc
{
    "presets": [
      [
        "@babel/preset-env",
        {
          "targets": {
            "node": "6"
          }
        }
      ]
    ]
  }
```

mocha.optsでオプションを設定することができます。
```--reporter ```オプションでレポートの出力形式を設定することができます。

```:test/mocha.opts
--require @babel/register
--timeout 1800000
--reporter spec
```

```json:test/.eslintrc
{
    "rules": {
        "func-names": 0
    }
}
```

# Appium Desktopでテストコードを記録

テストコードの記録方法については以下に記載していますので参照してください。
[AppiumでFlutterアプリのテストを自動化する 実践編(Python) - Qiita](https://qiita.com/hiesiea/items/bf677a57200a1a24dda7)
使用するアプリは上記ページと同様です。
記録する言語は、「JS(wd)」を選択します。

# 記録したテストコードを実行できるようにする

例えば以下のように記載します。

```js:test/top/top.test.js
import wd from 'wd';
import chai from 'chai';

const {assert} = chai;

describe('カウントアップアプリ', function () {
  let driver;

  before(async function () {
    driver = await wd.promiseChainRemote("http://127.0.0.1:4723/wd/hub");

    const caps = {
      "platformName": "Android",
      "automationName": "Appium",
      "deviceName": "Android Emulator",
      "app": "/Users/Hitoshi/AndroidStudioProjects/flutter_app_for_appium/build/app/outputs/apk/release/app-release.apk"
    };

    await driver.init(caps);
    // ここで待たないと要素の取得に失敗してしまうので待つ
    await driver.setImplicitWaitTimeout(5000);
  });

  after(async function () {
    await driver.quit();
  });

  it('初期状態', async function () {
    let el1 = await driver.elementByXPath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.view.View[3]");
    const countText = await el1.text();
    assert.equal(countText, '0');
  });

  it('カウントアップされるか', async function () {
    let el1 = await driver.elementByXPath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.widget.Button");
    await el1.click();
    let el2 = await driver.elementByXPath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.view.View[3]");
    const countText = await el2.text();
    assert.equal(countText, '1');
  });
});
```

# テストコードの実行

コマンドでテストコードを実行します。

```
npm test
```

すると、以下のように表示されるはずです。
端末側もアプリが起動し、ボタンが押されてカウントアップされるはずです。

```
> appium_test_js_wd@1.0.0 test /Users/Hitoshi/src/appium-test/appium_test_js_wd
> mocha test/**/*.test.js



  カウントアップアプリ
    ✓ 初期状態 (2195ms)
    ✓ カウントアップされるか (2199ms)


  2 passing (42s)
```

# ソースコード

以下にアップしましたので参考にしてください。

- [hiesiea/appium_test_js_wd](https://github.com/hiesiea/appium_test_js_wd)