🤖

超簡単!Maestroで始めるReact NativeのE2Eテスト

2023/06/29に公開

はじめに

こんにちは!
犬専用の音楽アプリ オトとりっぷでエンジニアしています、足立です!

https://www.oto-trip.com/

この記事では、Maestro というモバイル向け E2E テストフレームワークを試してみようと思います。
テストケース作成からテスト実施までストレスなく実施可能なフレームワークですので、ぜひ皆様もお試しください!

目次

  • Maestro とは?
  • 導入方法
    • Maestro
    • React Native
  • お試し結果
    • maestro test
    • maestro studio

Maestro とは?

Maestro is the simplest and most effective mobile UI testing framework.
(自動翻訳)Maestro は、最もシンプルで効果的なモバイル UI テストフレームワークです。

https://maestro.mobile.dev/

公式からの引用ですが、他のテストフレームワークとの違いは

  • 不安定性の改善
  • Sleepなどの遅延処理が不要
  • テストは YAML 形式で記述

とのことです。なんか、いけてるっぽい感じがします。
わかりやすくまとめてくださっているスライドがありますので、詳細はそちらをお勧めいたします。

https://speakerdeck.com/kgmyshin/uitesutohamoumaestrodeiinokamosirenaihua

また先日開催された、App.js Conf 2023 で紹介されています。

https://www.youtube.com/watch?v=uoCzBdFCoqc

導入方法

Maestro

以下の公式の手順に従います。

https://maestro.mobile.dev/getting-started/installing-maestro

$ curl -Ls "https://get.maestro.mobile.dev" | bash

# iOS向けの追加設定
$ brew tap facebook/fb
$ brew install facebook/fb/idb-companion

これだけです!
6 月 28 日現在の Maestro のバージョンは 1.29.0 でした。

$ maestro -v
1.29.0

筆者の環境は macOS ですが、シミュレーターには Android を使用しています。
iPhone シミュレーターとの相性が悪いのか、動作が不安定だったためです。
Maestro 自体が Kotlin で書かれていることと関係があるのかはわかりません。

React Native

まずは、いつものセットアップから始めます。

$ npx react-native@latest init AwesomeProject
$ cd AwesomeProject

これで初期プロジェクトの作成が完了しました。
次にApp.tsxを E2E テストしたくなるような内容に書き換えます。
(少し長いので、トグル表示にしています。)

App.tsx
App.tsx
import React, {useState} from 'react';
import {
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from 'react-native';

export default function App() {
  const [username, setUsername] = useState<string>('');
  const [password, setPassword] = useState<string>('');
  const [valid, setValid] = useState(false);

  return (
    <View style={styles.container}>
      <View style={styles.inputGroup}>
        <Text style={styles.label}>Username</Text>
        <TextInput
          style={styles.input}
          placeholder="Username"
          onChange={e => setUsername(e.nativeEvent.text)}
          testID="usernameInput"
        />
      </View>
      <View style={styles.inputGroup}>
        <Text style={styles.label}>Password</Text>
        <TextInput
          style={styles.input}
          placeholder="Password"
          secureTextEntry
          onChange={e => setPassword(e.nativeEvent.text)}
          testID="passwordInput"
        />
      </View>
      <TouchableOpacity
        style={styles.button}
        onPress={() => {
          if (username.length > 0 && password.length > 0) {
            setValid(true);
          } else {
            setValid(false);
          }
        }}
        testID="signInButton">
        <Text style={styles.buttonText}>Sign in</Text>
      </TouchableOpacity>
      {valid ? (
        <Text style={styles.successText}>Sign in successfully</Text>
      ) : null}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: '#fff',
    justifyContent: 'center',
  },
  inputGroup: {
    marginBottom: 16,
  },
  label: {
    fontSize: 12,
    fontWeight: 'bold',
    marginBottom: 6,
  },
  input: {
    borderRadius: 8,
    borderWidth: 1,
    borderColor: 'gray',
    padding: 12,
    width: '100%',
    fontSize: 18,
  },
  button: {
    borderRadius: 8,
    padding: 12,
    backgroundColor: 'black',
    alignItems: 'center',
    marginBottom: 8,
  },
  buttonText: {
    fontSize: 16,
    fontWeight: 'bold',
    color: 'white',
  },
  successText: {
    fontSize: 16,
    color: 'green',
    alignSelf: 'center',
  },
});

簡単な SignIn ページが完成しました。
このページをテストしてみたいと思います。

お試し結果

maestro test

兎にも角にも UI テストやってみましょう!
まずはテスト設定用の YAML ファイルを作成します。
React Native での YAML ファイルの細かい書き方はこちらに記載があります。

login.yml
# 起動するアプリIDを指定します
appId: com.awesomeproject
---
# アプリを再起動します
- launchApp

# testIDに"usernameInput"を持つ要素をクリックします
- tapOn:
    id: "usernameInput"
# "ototrip"と入力します
- inputText: "ototrip"

# testIDに"passwordInput"を持つ要素をクリックします
- tapOn:
    id: "passwordInput"
# "password"と入力します
- inputText: "password"

# "Sign in"と表示された要素をクリックします
- tapOn: "Sign in"

次にシミュレータを立ち上げます。

$ npm run start
a - run on Android

そして、テストを起動します。

$ maestro test login.yml

めちゃくちゃ簡単です!
これだけで E2E テストが実施できました。

maestro studio

ここまでやってみて疑問に思うのは、「でもテストケース作るの大変なんでしょう?」です。
そこで登場するのが、maestro studioという機能です。

使い方は簡単で、React Native プロジェクトを立ち上げた状態でmaestro studioと Studio サーバを立ち上げるだけです。
実際に使っている様子がこちらです。

左側に見えるのが Android のシミュレーターです。右側に見えるのが Safari ブラウザです。
ブラウザはhttp://localhost:9999/interactに接続しています。

シミュレーターの画面がそのままブラウザ上に同期されており、さらにワンクリックでその UI 要素を特定することが可能です。また逆にブラウザから指示を送るとシミュレーター上でその通り実行され、次々と処理をテストケースに落としていくことができました。

そして、最後に指示書を Export すると完了です。

たったこれだけです!
注意事項として、筆者の環境では Chrome でローカルホストに接続できなかったので、Safari でお試しください。

これならエンジニアでなくても必要なテストケースを作成することができそうですね。
E2E テストでの問題点であるテストケースの維持が難しいが、これだとハードルが下がりそうです。
コマンドはこちらのページに紹介されていますので、簡単に見つけることができます。

最後に

ここまで読んでいただきありがとうございました。
以下の記事を参考にしていますので、詳細を確認されたい方はそちらをご覧ください。

https://dev.to/b42/test-your-react-native-app-with-maestro-5bfj

E2E テストがここまで直感的に実施できるのはありがたいですね!
オトとりっぷでもぜひ導入を検討したいと思います。

また、犬専用の音楽アプリに興味を持っていただけたら、ぜひダウンロードしてみてください!

https://www.oto-trip.com/

Discussion