Help us understand the problem. What is going on with this article?

Appiumを使ってスマートフォンアプリのテストを自動化する - Python編

More than 5 years have passed since last update.

1. はじめに

前回、「Appiumを使ってスマートフォンアプリのテストを自動化する - 概要編」でAppiumでスマートフォンアプリのテストを自動化できることを書きました。

今回はAppiumとPythonを使って、スマートフォンアプリのテストコードの作成方法について書いていきたいと思います。

(補足)
現時点(2013/7/20)では、iOSアプリのみを対象としています。
Androidアプリに関しては、後日記載します。

2. 前提条件

今回、使用した環境は以下のとおりです。

ソフトウェア バージョン
OS MacOS X バージョン 10.8.4
Python 2.7.4
pip 1.2.1
XCode 4.5.3

なお、Appiumのインストールについては前回記事:「Appiumを使ってスマートフォンアプリのテストを自動化する - 概要編」をご覧ください。

3. サンプルコードを動かす

まず始めにサンプルコードを使って動作を確認します。ここからの操作はターミナル上で行います。

GitHubからAppiumのソース一式を取得します。

git clone https://github.com/appium/appium.git

Appiumのソース一式を取得したら、TestAppのフォルダに移動します。

cd appium/sample-code/apps/TestApp/

xcodebuildコマンドを使って、iOSアプリをビルドします。ビルドに使用するiOSのSDKはiPhone Simulatorにします。

xcodebuild -sdk iphonesimulator

Pythonのサンプルコードが格納されているフォルダに移動します。

cd ../../examples/python/

サンプルコード実行前に、Pythonのseleniumモジュールが入っているかを確認してください。
入っていない場合はpipを使ってseleniumモジュールをインストールします。

# Pythonのseleniumモジュールが入っているかを確認します
pip freeze

# seleniumモジュールが入っていない場合、以下のコマンドを実行します
sudo pip install selenium

準備が整ったので、サンプルコードを動かします。

appium &
python simple.py

4. サンプルコードからテストコードの書き方を学ぶ

いろいろと探したのですが、Pythonでのテストコードの書き方に関するチュートリアルが見つからなかったのでサンプルコードをもとにテストコードの書き方をまとめたいと思います。
→ チュートリアルのようなものを見つけたらここの記事の内容を書き直します。

なお、サンプルコードの格納先は「appium/sample-code/examples/python/」になります。

サンプルコードを読むとselenuimモジュールのWebDriver APIを介してiOSアプリを動かしていることが分かります。

(1) unittest.TestCaseクラスを継承したテストクラスを作成します

import unittest


class AppiumSampleTest(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass

(2) テストクラスのsetUpメソッドで起動するiOSアプリをAppiumに登録します

def setUp(self):
    # iOSアプリが配置されている場所のパスを取得します
    # (osモジュールをインポートしておくこと)
    app = '(iOSアプリが配置されているパス)'

    # seleniumのwebdriverを使ってAppiumにiOSアプリを認識させます
    # (seleniumモジュールからwebdriverをインポートしておくこと)
    # command_executorで指定するドメイン部分とポート部分は
    # 利用している環境によって変わります
    self.driver = webdriver.Remote(
                command_executor = 'http://127.0.0.1:4723/wd/hub',
                desired_capabilities = {
                    'browserName' : 'iOS',
                    'platform' : 'Mac',
                    'version' : '6.0',  # iOSのバージョン
                    'app' : app     # 実行するiOSアプリが配置されているパス
                })

(3) テストクラスのtearDownメソッドでiOSアプリを終了します

def tearDown(self):
    self.driver.quit()

(4) テストメソッドを追加します

def test_ui_operation(self):
    # 1.スライダーの操作
    # 1-1.スライダーを取得する
    sliders = self.driver.find_elements_by_tag_name('slider')
    # 1-2.スライダーの初期値を評価する
    self.assertEqual(sliders[0].get_attribute('value'), '50%')
    # 1-3.タッチイベントを取得する
    drag = webdriver.common.touch_actions.TouchActions(self.driver)
    # 1-4.スライダーの設定値を-50%にする
    drag.flick_element(sliders[0], -0.5, 0, 0)
    # 1-5.スライダーを動かす
    drag.perform()
    # 1-6.スライダーの設定値が0%になっていることを評価する
    self.assertEqual(sliders[0].get_attribute('value'), '0%')

    # 2.テキストフィールドの操作
    # 2-1.テキストフィールドを取得する
    textFields = self.driver.find_elements_by_tag_name('textField')
    # 2-2.1番目のテキストフィールドに1を入力する
    textFields[0].send_keys(1)
    # 2-3.2番目のテキストフィールドに2を入力する
    textFields[1].send_keys(2)
    # 2-4.1番目のテキストフィールドと2番目のテキストフィールドの値の合計が3であることを評価する
    self.assertEqual(int(textFields[0].get_attribute('value'))
                         + int(textFields[1].get_attribute('value')), 3)

    # 3.ボタンの操作
    # 3-1.ボタンを取得する
    buttons = self.driver.find_elements_by_tag_name('button')
    # 3-2.ボタンをクリックする
    buttons[0].click()

    # 4.ラベルの操作
    # 4-1.ラベルを取得する
    texts = self.driver.find_elements_by_tag_name('staticText')
    # 4-2.ラベルの内容が3であることを評価する
    self.assertEqual(int(texts[0].get_attribute('value')), 3)

seleniumモジュールでのiOSアプリの画面部品の取り扱いをまとめると

画面部品の取得方法

画面部品 取得方法
UITextField self.driver.find_elements_by_tag_name('textField')
UIButton self.driver.find_elements_by_tag_name('button')
UILabel self.driver.find_elements_by_tag_name('staticText')
UISlider self.driver.find_elements_by_tag_name('slider')

画面部品の操作方法

画面部品 操作内容 操作方法
UITextField 値を入力する send_keysメソッドを使用する
UITextField 値を取得する get_attributeメソッドを使用する
UIButton ボタンをクリックする clickメソッドを使用する
UILabel ラベルの表示内容を取得する textプロパティを参照する
UISlider 設定値を変更する TouchActionsのflick_elementメソッドで値を設定する。設定後、TouchActionsのperformメソッドでスライダーを動かす。

となります。

(補足) 上記の表は、随時更新していきます。

なお、ソースコードの全体像は以下のとおりです。

# coding: utf-8

import unittest
import os
from selenium import webdriver


class AppiumSampleTest(unittest.TestCase):

    def setUp(self):
        # iOSアプリが配置されている場所のパスを取得します
        app = os.path.join('/tmp/appium',
                    'sample-code/apps/TestApp/build/Release-iphonesimulator',
                    'TestApp.app')
        app = os.path.abspath(app)

        # seleniumのwebdriverを使ってAppiumにiOSアプリを認識させます
        # command_executorで指定するドメイン部分とポート部分は
        # 利用している環境によって変わります
        self.driver = webdriver.Remote(
            command_executor='http://localhost:4723/wd/hub',
            desired_capabilities={
                'browserName': 'iOS',
                'platform': 'Mac',
                'version': '6.0',
                'app': app
            })

    def test_ui_operation(self):
        # スライダーの操作
        sliders = self.driver.find_elements_by_tag_name('slider')
        self.assertEqual(sliders[0].get_attribute('value'), '50%')
        drag = webdriver.common.touch_actions.TouchActions(self.driver)
        drag.flick_element(sliders[0], -0.5, 0, 0)
        drag.perform()
        self.assertEqual(sliders[0].get_attribute('value'), '0%')

        # テキストフィールドの操作
        textFields = self.driver.find_elements_by_tag_name('textField')
        textFields[0].send_keys(1)
        textFields[1].send_keys(2)
        self.assertEqual(int(textFields[0].get_attribute('value'))
                         + int(textFields[1].get_attribute('value')), 3)

        # ボタンの操作
        buttons = self.driver.find_elements_by_tag_name('button')
        buttons[0].click()

        # ラベルの操作
        texts = self.driver.find_elements_by_tag_name('staticText')
        self.assertEqual(int(texts[0].get_attribute('value')), 3)

    def tearDown(self):
        self.driver.quit()


if __name__ == '__main__':
    unittest.main()

5. 参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした