これまでのあらすじ
@ootakenさんのWindows Application DriverでWindowsアプリケーションのテストを自動化しようを見て、なかなか面白そうだったので、Pythonでもやってみようと思ったのです。
それだけだとつまらないので、RobotFrameworkのApplumLibraryを使ったキーワード駆動によるテストケースも試してみようと思いついたのでした。
RobotFrameworkって何?という方は、以前書いた記事を参照してください。
前回の記事(2年以上前だけど)ではSelenium2のキーワードライブラリを使用しましたが、今回はAppium用のライブラリを使います。
準備
まず、Windows Application Driverを以下のURLからダウンロードしてインストールします。
https://github.com/Microsoft/WinAppDriver/releases
また、Pythonのサンプルファイルもダウンロードしておきます。
https://github.com/Microsoft/WinAppDriver/blob/master/Samples/Python/calculatortest.py
次に、関係するPythonのライブラリをインストールします。
robotframework-appiumlibraryをインストールすれば、一式まとめて入ります。
> pip install robotframework-appiumlibrary
ちなみに確認環境は、Windows10 Home Version 1703 の64bit版+Python3.6.0です。
ライブラリのバージョンは以下になります。
>pip freeze
apipkg==1.4
Appium-Python-Client==0.24
colorama==0.3.7
coverage==4.3.4
decorator==4.0.11
docutils==0.13.1
execnet==1.4.1
mock==1.0.1
py==1.4.33
pytest==3.0.7
pytest-cov==2.4.0
pytest-pythonpath==0.7.1
pytest-xdist==1.15.0
robotframework==3.0.2
robotframework-appiumlibrary==1.4.3
sauceclient==0.2.1
selenium==3.3.3 ```
サンプルの実行
本家のPythonサンプルを実行してみますが、Windows Application DriverでWindowsアプリケーションのテストを自動化しようでのJavaのサンプル同様、日本語環境ではFailするので、Locatorの指定方法とAssertの判定方法を変更します。
python のunittestにはassertThatはないので、asserInを使いました。引数の順番が反転しているので注意。
"""
//******************************************************************************
//
// Copyright (c) 2016 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//******************************************************************************
"""
import unittest
from appium import webdriver
class SimpleCalculatorTests(unittest.TestCase):
def setUp(self):
#set up appium
desired_caps = {}
desired_caps["app"] = "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"
self.driver = webdriver.Remote(
command_executor='http://127.0.0.1:4723',
desired_capabilities= desired_caps)
def tearDown(self):
self.driver.quit()
def test_initialize(self):
self.driver.find_element_by_accessibility_id("clearButton").click()
self.driver.find_element_by_accessibility_id("num7Button").click()
result = self.driver.find_element_by_accessibility_id("CalculatorResults")
self.assertIn(" 7 ", str(result.text))
def test_addition(self):
self.driver.find_element_by_accessibility_id("num1Button").click()
self.driver.find_element_by_accessibility_id("plusButton").click()
self.driver.find_element_by_accessibility_id("num7Button").click()
self.driver.find_element_by_accessibility_id("equalButton").click()
result = self.driver.find_element_by_accessibility_id("CalculatorResults")
self.assertIn( " 8 ", str(result.text))
def test_combination(self):
self.driver.find_element_by_accessibility_id("num7Button").click()
self.driver.find_element_by_accessibility_id("multiplyButton").click()
self.driver.find_element_by_accessibility_id("num9Button").click()
self.driver.find_element_by_accessibility_id("plusButton").click()
self.driver.find_element_by_accessibility_id("num1Button").click()
self.driver.find_element_by_accessibility_id("equalButton").click()
self.driver.find_element_by_accessibility_id("divideButton").click()
self.driver.find_element_by_accessibility_id("num8Button").click()
self.driver.find_element_by_accessibility_id("equalButton").click()
result = self.driver.find_element_by_accessibility_id("CalculatorResults")
self.assertIn( " 8 ", str(result.text))
def test_division(self):
self.driver.find_element_by_accessibility_id("num8Button").click()
self.driver.find_element_by_accessibility_id("num8Button").click()
self.driver.find_element_by_accessibility_id("divideButton").click()
self.driver.find_element_by_accessibility_id("num1Button").click()
self.driver.find_element_by_accessibility_id("num1Button").click()
self.driver.find_element_by_accessibility_id("equalButton").click()
result = self.driver.find_element_by_accessibility_id("CalculatorResults")
self.assertIn( " 8 ", str(result.text))
def test_multiplication(self):
self.driver.find_element_by_accessibility_id("num9Button").click()
self.driver.find_element_by_accessibility_id("multiplyButton").click()
self.driver.find_element_by_accessibility_id("num9Button").click()
self.driver.find_element_by_accessibility_id("equalButton").click()
result = self.driver.find_element_by_accessibility_id("CalculatorResults")
self.assertIn( " 81 ", str(result.text))
def test_subtraction(self):
self.driver.find_element_by_accessibility_id("num9Button").click()
self.driver.find_element_by_accessibility_id("minusButton").click()
self.driver.find_element_by_accessibility_id("num1Button").click()
self.driver.find_element_by_accessibility_id("equalButton").click()
result = self.driver.find_element_by_accessibility_id("CalculatorResults")
self.assertIn( " 8 ", str(result.text))
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(SimpleCalculatorTests)
unittest.TextTestRunner(verbosity=2).run(suite)
Window Application Driverを起動してから、テストを実行してみます。
>python calculatortest.py
test_addition (__main__.SimpleCalculatorTests) ... ok
test_combination (__main__.SimpleCalculatorTests) ... ok
test_division (__main__.SimpleCalculatorTests) ... ok
test_initialize (__main__.SimpleCalculatorTests) ... ok
test_multiplication (__main__.SimpleCalculatorTests) ... ok
test_subtraction (__main__.SimpleCalculatorTests) ... ok
----------------------------------------------------------------------
Ran 6 tests in 11.818s
OK
全部Passしました。
キーワード駆動テスト化してみる
次は同じテストをRobotFrameworkで書いて実行してみます。
AppiumLibraryに用意されているキーワードをそのまま使えます。
使えるキーワードのドキュメントはこちら。
http://serhatbolsu.github.io/robotframework-appiumlibrary/AppiumLibrary.html
各テストケースについてはほとんど説明いらないかと思います。
数字を${SPACE}で囲んでいるところがいまいち感ありますが、そこを除けば、非常に直感的に書けると思います。
Test Setupの、Open Applicationの引数にplatformNameを指定しないと、Click Elementでエラーになってしまったため、明示しています。注意点はそこくらいでしょうか。
(2017/04/22訂正)
http://appium.io/slate/en/master/?python#create-test-project
に、Windows App Automation Sessionのdesired capabilitiesに関して、以下の記載があったので、コードを修正しました。
STARTING A SESSION
Note that you should additionally use these capabilities to ensure you are getting a Windows App automation session:
platformName: Windows deviceName: WindowsPC
公式サンプルは従ってないけどね。。。
*** Settings ***
Library AppiumLibrary
Test Setup Open Application http://127.0.0.1:4723 app=Microsoft.WindowsCalculator_8wekyb3d8bbwe!App platformName=Windows deviceName=WindocwPC
Test Teardown Close Application
*** Test Cases ***
Test Initialization
Click Element accessibility_id=clearButton
Click Element accessibility_id=num7Button
Element Should Contain Text accessibility_id=CalculatorResults ${SPACE}7${SPACE}
Test Addition
Click Element accessibility_id=num1Button
Click Element accessibility_id=plusButton
Click Element accessibility_id=num7Button
Click Element accessibility_id=equalButton
Element Should Contain Text accessibility_id=CalculatorResults ${SPACE}8${SPACE}
Test Combination
Click Element accessibility_id=num7Button
Click Element accessibility_id=multiplyButton
Click Element accessibility_id=num9Button
Click Element accessibility_id=plusButton
Click Element accessibility_id=num1Button
Click Element accessibility_id=equalButton
Click Element accessibility_id=divideButton
Click Element accessibility_id=num8Button
Click Element accessibility_id=equalButton
Element Should Contain Text accessibility_id=CalculatorResults ${SPACE}8${SPACE}
Test Division
Click Element accessibility_id=num8Button
Click Element accessibility_id=num8Button
Click Element accessibility_id=divideButton
Click Element accessibility_id=num1Button
Click Element accessibility_id=num1Button
Click Element accessibility_id=equalButton
Element Should Contain Text accessibility_id=CalculatorResults ${SPACE}8${SPACE}
Test Multiplication
Click Element accessibility_id=num9Button
Click Element accessibility_id=multiplyButton
Click Element accessibility_id=num9Button
Click Element accessibility_id=equalButton
Element Should Contain Text accessibility_id=CalculatorResults ${SPACE}81${SPACE}
Test Substraction
Click Element accessibility_id=num9Button
Click Element accessibility_id=minusButton
Click Element accessibility_id=num1Button
Click Element accessibility_id=equalButton
Element Should Contain Text accessibility_id=CalculatorResults ${SPACE}8${SPACE}
実行してみましょう。全部Passです。
>robot -d result calculatortest.robot
==============================================================================
Calculatortest
==============================================================================
Test Initialization | PASS |
------------------------------------------------------------------------------
Test Addition | PASS |
------------------------------------------------------------------------------
Test Combination | PASS |
------------------------------------------------------------------------------
Test Division | PASS |
------------------------------------------------------------------------------
Test Multiplication | PASS |
------------------------------------------------------------------------------
Test Substraction | PASS |
------------------------------------------------------------------------------
Calculatortest | PASS |
6 critical tests, 6 passed, 0 failed
6 tests total, 6 passed, 0 failed
==============================================================================
Output: D:\Dev\rf_home\result\output.xml
Log: D:\Dev\rf_home\result\log.html
Report: D:\Dev\rf_home\result\report.html
まとめ
- WIndows Application DriverとPythonのAppium関連ライブラリのインストール
- 本家サイトのPythonサンプルテストケース(を修正したもの)の実行
- サンプルテストケースをRobotFrameworkのAppiumLibraryを使ってキーワード駆動型のテストケースに書き直して実行
を試した結果、Windows Application Driverにより、Windowsのデスクトップアプリケーションのテスト自動化がかなり簡単に対応できることがわかりました(行儀よくIDがふられたアプリの単純なボタン操作とかなら、ね)。
いやはや、Windows Application Driverの今後が非常に楽しみですね!