Taming Robot Framework Yasushi Masuda
TamingRobot Framework
Yasushi Masuda
Yasushi Masuda( @whosaysni )
MonotaRO Co., LTD.株式会社モノタロウ IT 部門
Pythonista since 2001 (2.0 〜 )• elaphe (barcode library)• oikami.py (老神 .py )• PyCon JP founder
Japanese Translation works
←new!
Robot Framework
Test Automation Framework for ATDD
Originally Developed in Nokia Networks
OSS (Apache License 2.0)
Keyword driven
powered
http://robotframework.org/
What's good• Text-based (VCS friendly, End-user friendly)• Any language is allowed 日本語も OK• Simple suite structure - file/directory• Quick - no test compilation• Batteries included - BuiltIn library/keywords• Powerful external libraries (Selenium2, DB,
Appium, etc..)• Runs anywhere on Python, extendable with
Python
ATDD?
Keywords?
Acceptance Test
- from user's point of view
- prior to coding
- what would be checked by a test
Requirements
System Analysis
Software Design
Module Design
Acceptance Test
System Test
Integration Test
Unit Test
Coding
• ウェブサイトで、利用者がアンケートに回答したり、自分の診断結果を表示したりしたい。• ログインしてなかったら、ユーザー ID とパスワードでログイン。• ログインしたら、メニューのページがあって、アンケートに回答するページと、診断結果の表示ページに飛ぶ。
• アンケートに回答してなかったら、診断結果のページには行けない。• アンケートに回答していたら、アンケートのページには行けない。
• 未ログインでアクセスするとログインページに移動すること• ログイン済でアクセスするとメニューページに移動すること• ログインページにユーザ ID 欄とパスワード欄、ログインボタンがあること• 正しいユーザ ID とパスワードを入力してログインボタンを押すとログインしてメニューのページに移動すること• ユーザ ID やパスワードが正しくないか、空欄のときは「ユーザ ID かパスワードが正しくありません」と表示すること• アンケート未回答のとき、メニューにはアンケートへのリンクが表示され、診断結果のリンクが表示されないこと• アンケート回答済のとき、メニューにアンケートへのリンクが表示されず、診断結果へのリンクが表示されること
Keywords
combination of actions
• 正しいユーザ ID とパスワードを入力してログインボタンを押すとログインしてメニューのページに移動すること• ユーザ ID やパスワードが正しくないか、空欄のときは「ユーザ ID かパスワードが正しくありません」と表示すること
• ログイン成功のテスト• ユーザ ID に「 ${ 正しい ID} 」を入力する• パスワードに「 ${ 正しいパスワード } 」を入力する• ログインボタンをクリックする• 遷移先が「 ${ メニューのページ } 」か検証する
• ログイン失敗のテスト• ユーザ ID に「 ${ 正しい ID} 」を入力する• パスワードに「 ${ 不正なパスワード } 」を入力する• ログインボタンをクリックする• 遷移先が「 ${ ログインページ } 」か検証する• 画面に「ユーザ ID かパスワードが正しくありません」と表示されているか検証する
in an example
Python https://www.python.org/downloads/
$ pip install robotframework
$ pip install robotframework-selenium2library※ WebDriver http://www.seleniumhq.org/projects/webdriver/
also supported:PyPy, Jython, IronPython
Installation in seconds
*** settings ***Library Selenium2Library
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To http://192.168.240.86:8000/ Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
minimal test case
*** settings ***Library Selenium2Library
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To http://192.168.240.86:8000/ Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
sections
*** settings ***Library Selenium2Library
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To http://192.168.240.86:8000/ Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
header
test case(s)
*** settings ***Library Selenium2Library
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To http://192.168.240.86:8000/ Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
Name
Actions
*** settings ***Library Selenium2Library
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To http://192.168.240.86:8000/ Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
Keyword Arguments
*** settings ***Library Selenium2Library
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To http://192.168.240.86:8000/ Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
variables
*** settings ***Library Selenium2Library
*** variables ***${SITE_ROOT} = http://192.168.240.86:8000/
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To ${SITE_ROOT} Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
*** settings ***Library Selenium2Library
*** variables ***${SITE_ROOT} = http://192.168.240.86:8000/
*** test cases ***My First Test Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480 Go To ${SITE_ROOT} Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
Reuse actions by user-defined keywords
*** settings ***Library Selenium2Library
*** variables ***${SITE_ROOT} = http://192.168.240.86:8000/
*** test cases ***My First Test ブラウザウィンドウを準備する Go To ${SITE_ROOT} Title Should Be Login Page Should Contain Please Log In. Capture Page Screenshot Screenshot.png Close All Browsers
*** keywords ***ブラウザウィンドウを準備する Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480
日本語 OK!
User Keyword
Setup/Teardown*** settings ***Library Selenium2Library
*** variables ***${SITE_ROOT} = http://192.168.240.86:8000/
*** test cases ***My First Test [Setup] ブラウザウィンドウを準備する Go To ${SITE_ROOT} Title Should Be Login Page Should Contain Please Log In. [Teardown] スクリーンショットを取ってブラウザを閉じる*** keywords ***ブラウザウィンドウを準備する Open Browser about: browser=chrome Set Window Position 100 100 Set Window Size 640 480
スクリーンショットを撮ってブラウザを閉じる Capture Page Screenshot Screenshot.png Close All Browsers
Structured tests
*** settings ***Library Selenium2Library
*** variables ***${SITE_ROOT} = http://192.168.240.86:8000/
*** test cases ***ログイン画面は「ログインしてください」と表示する トップページに行く 「ログインしてください」と表示する正しいログイン情報でログインできる トップページに行く ログインフォームが表示されている ユーザ ID 欄に「 ${VALID_ID} 」を入力する パスワード欄に「 ${VALID_PW} 」を入力する ログインボタンを押す メニュー画面に遷移する不正なログイン情報でログインできない トップページに行く ログインフォームが表示されている ユーザ ID 欄に「 ${VALID_ID} 」を入力する パスワード欄に「 ${INVALID_PW} 」を入力する ログインボタンを押す ログイン画面に遷移する 「 ID またはパスワードが違います」と表示する
test case
test case
test case
A file => A suite test suite
test suite
test suite
test suite
test suite
test suitetest suite
test suitetest suite
─ tests ├ test_webui │ ├ test_login.robot │ ├ test_dashboard.robot │ └ test_logout.robot └ test_api ├ test_auth.robot └ test_stat.robot
Bunch of files (suites) in a directory => suitesBunch of suite dirs => suite
*** settings ***Resources resources/common_resources.txt
*** keywords ***...
*** variables ***...
× Test cases aren't allowed
Resource files:Share keywords/variables among suites
*** settings ***Variables sut_variables.py ${HOME}
VAR1 = [...]VAR2 = "..."
def get_variables(*args): from os.path import abspath, join home = abspath(args[0]) return { 'DESKTOP': join(home, 'Desktop'), 'DOWNLOAD': join(home, 'Download') }
Variable files:Defined in Python, allowing dynamic/parametric
variable definitions
Running tests
$ robot mytest.robot==============================================================================Test Library==============================================================================My First Test | PASS |------------------------------------------------------------------------------Test Library | PASS |1 critical test, 1 passed, 0 failed1 test total, 1 passed, 0 failed==============================================================================Output: /path/to/test/output.xmlLog: /path/to/test/log.htmlReport: /path/to/test/report.html
HTML report
Log
<?xml version="1.0" encoding="UTF-8"?><robot generated="20160721 21:25:48.239" generator="Robot 3.0 (Python 2.7.10 on darwin)"> <suite source="/Users/ymasuda/Desktop/test_demo/10_login.robot" id="s1" name="10 Login"> <kw type="setup" name="Open Browser" library="Selenium2Library"> <doc>Opens a new browser instance to given URL.</doc> <arguments> <arg>about:</arg> <arg>browser=chrome</arg> </arguments> <msg timestamp="20160721 21:25:48.346" level="INFO"> Opening browser 'chrome' to base url 'about:' </msg> <status status="PASS" endtime="20160721 21:25:50.512" starttime="20160721 21:25:48.346"></status> </kw> <test id="s1-t1" name=" ログイン前に管理ページに行くとログインにリダイレクトする "> <kw type="setup" name=" テストケース準備 "> <kw name="Delete All Cookies" library="Selenium2Library"> ...
XML Output:Individual test/suite results, keywords as well
robot
test suite
HTML output Log
XML Output
Custom Report
CI
Screenshots
Xunit OutputBuild Tools
XSLT
Drone, Jenkins, etc.
Advanced Features
Template: Data-driven testsGherkin style: Behaviour-driven tests
Page Object Pattern
*** test cases ***不正なデータのときエラーメッセージを出す [template] ログインに失敗してエラーメッセージを表示する ${EMPTY} ${EMPTY} ユーザー ID を入力してください ${EMPTY} BADPASS ユーザー ID を入力してください TESTUSER ${EMPTY} パスワードを入力してください TESTUSER BADPASS ID またはパスワードが違います TEST BADPASS ID は半角英数で入力してください T01234567890123456 BADPASS ユーザ ID が長すぎます*** keywords ***ログインに失敗してエラーメッセージを表示する [arguments] ${user_id} ${password} ${err_msg} 「 ${user_id} 」と「 ${password} 」でログインする ログイン画面から遷移しない エラーメッセージに「 ${err_msg} 」と表示する
Templates
*** test cases ***Login success for valid user/password Given user is looged out Given at login page When enter "${VALID_ID" in ID, "${VALID_PW}" in Password And click login button Then user is redirected to menu page
GherkinGherkin prefixes are ignored automatically
from robotpageobjects import Page
class LoginPage(Page):
selectors = { 'user id': 'id=user_id', 'password': 'id=passwd' }
def login(self, uid, pw): self.input_text('user id', uid) self.input_text('password', pw) self.click_button(...)
Page Object Pattern(robotframework-pageobject by NCBI)
*** settings ***Library mysite.LoginPage
*** test cases ***Test Login Page Go To Login Page Login Page Url Should Be /login Login ${VALID_ID} ${VALID_PW}
Ecosystem
System Under Test
Interface
Test Library
Robot Framework
Test cases / User Keywords Text Files
Python + Robot Framework
Python package
Test tools:WebDriver,
DB driver, etc.
def should_be_prime(x): """Fails if x is not a prime""" try: ix = int(x) except: raise ValueError('Not a number.') asserts.true(is_prime(x), 'Not a prime.')
*** settings ***Library MyLibrary
*** test cases ***Number should be prime Should Be Prime 41
Define new keyword in a library
Built-in librariesOS(child process), XML, Telnet, Dialog
External librariesDatabase, MongoDB, ElasticSearch...
SSH, HTTP, FTP, SUDS, MQTT...Swing, Calabash, Appium, Django...
Serial ← New!
Beyond E2E
Requirements
System Analysis
Software Design
Module Design
Acceptance Test
System Test
Integration Test
Unit Test
Coding
Extending coverages
Tweaking internal states
Login state: session cookiesInternal DB status: SQL fixtures
Config/server status: commands via ssh
Be a good test trainer• Start with minimal essential E2E• Add regression for every failure detection• Reorganize test keywords/structures
(reuse, modular, configurable)• Run test as many time as possible
(culture, process, automation)
Docs
Online Docsrobotframework.org
http://robotframework.org/#documentation
日本語ドキュメント集(和訳)http://robotframework-ja.readthedocs.io/
Books"Robot Framework Test Automation"https://www.amazon.co.jp/dp/B00G8YAWH8
MLrobotframework-users@googlegroup ( 英語 )
rfw-users-jp@googlegroup ( 日本語 )
Thanks!