View
1.017
Download
6
Category
Preview:
Citation preview
テスト自動化の闇と向き合う新日鉄住金ソリューションズ
石川 真也
(Selenium歴 9ヶ月)
Copyright © 2015 NS Solutions Corporation, All rights reserved. 1
ブラウザテスト
Copyright © 2015 NS Solutions Corporation, All rights reserved. 2
Copyright © 2015 NS Solutions Corporation, All rights reserved. 3
Internet Explorer 7
Internet Explorer 8
Internet Explorer 9
Internet Explorer 10
Internet Explorer 11
Microsoft Edge
Firefox
Google Chrome
Safari
Safari(iOS)
Google Chrome(Android)
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
・アプリにアクセス・ログイン・カートに商品を追加・配送先を選択・支払い方法を選択・注文の確認・購入完了
自動化したい
テスト自動化
Copyright © 2015 NS Solutions Corporation, All rights reserved. 4
Copyright © 2015 NS Solutions Corporation, All rights reserved. 5
Selenium
Selenium-特徴
OSS(Apache2.0)
様々なブラウザに対応
豊富な言語バインディング Java, C#, Python, Ruby, JavaScript etc.
豊富な支援ツール Selenium grid:並列実行
Selenium IDE:画面操作の記録
Appium:iOS, Androidのテスト
Microsoft Edgeにも!
Copyright © 2015 NS Solutions Corporation, All rights reserved. 6
→間口の広さ
Selenium-コード例public class Example {
public static void main(String[] args) {
WebDriver driver = new HtmlUnitDriver();
driver.get("http://www.google.com");
WebElement element = driver.findElement(By.name("q"));
element.sendKeys("Cheese!");
element.submit();
System.out.println("Page title is: " + driver.getTitle());
driver.quit();
}
}
フォーム操作
ページリクエスト
値の取得
Copyright © 2015 NS Solutions Corporation, All rights reserved. 7
テスト自動化の闇
Copyright © 2015 NS Solutions Corporation, All rights reserved. 8
の闇スクリプト保守
Copyright © 2015 NS Solutions Corporation, All rights reserved. 9
Selenium IDEを使えば
ブラウザ操作を記録できて便利!
Copyright © 2015 NS Solutions Corporation, All rights reserved. 10
どんどんテストスクリプトを
作ろう!
Copyright © 2015 NS Solutions Corporation, All rights reserved. 11
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController
driver.findElement(By._id")).clear();
driver.findElement(By._id")).sendKeys("01");
driver.findElement(By.MenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle
Copyright © 2015 NS Solutions Corporation, All rights reserved. 12
「ここのフォームの配置
変えといたから」
Copyright © 2015 NS Solutions Corporation, All rights reserved. 13
えっ
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController
driver.findElement(By._id")).clear();
driver.findElement(By._id")).sendKeys("01");
driver.findElement(By.MenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle
Copyright © 2015 NS Solutions Corporation, All rights reserved. 14
Selenium IDEが吐くコードの例WebElement element = driver.findElement(
By.cssSelector("#content > table > tbody > tr:nth-child(4) > td:nth-child(2)“));
↑Idがcontentの要素の中の↑table要素の中の
↑tbody要素の中の↑4番めのtr要素の中の
↑2番めのtd要素
Copyright © 2015 NS Solutions Corporation, All rights reserved. 15
DOM要素の配置が変わると台無し
DOMツリー上の位置で操作する要素を特定
えっこれ全部修正ですか?
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
driver.get(baseUrl + "/myVideoRental/FrontController
driver.findElement(By._id")).clear();
driver.findElement(By._id")).sendKeys("01");
driver.findElement(By.MenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle
Copyright © 2015 NS Solutions Corporation, All rights reserved. 16
orz
Copyright © 2015 NS Solutions Corporation, All rights reserved. 17
スクリプト保守の闇と向き合う
• テストを意識した設計• 要素のクラス、id体系
• テストスクリプトで工夫• PageObjectパターン• ページごとの操作を抽象化
Copyright © 2015 NS Solutions Corporation, All rights reserved. 18
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
Copyright © 2015 NS Solutions Corporation, All rights reserved. 19
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
LoginPage.class
void login(user, passwd)void logout()boolean isLoggedIn()
PageObjectパターン
の闇「たまに失敗」
Copyright © 2015 NS Solutions Corporation, All rights reserved. 20
スクリプトも完成したし、今やこのテストは完全に
自動化された!
Copyright © 2015 NS Solutions Corporation, All rights reserved. 21
ほらね、ちゃんと動いてる!driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
Copyright © 2015 NS Solutions Corporation, All rights reserved. 22
あれ、このテスト…
たまに失敗してる…?driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
driver.findElement(By.id("DisplayMenuLogic")).click();
assertEquals("貸出・返却メニュー画面", driver.getTitle());
Copyright © 2015 NS Solutions Corporation, All rights reserved. 23
Copyright © 2015 NS Solutions Corporation, All rights reserved. 24
たまに失敗するのはなぜ?
• クリックしようとした要素が不可視状態だった
• ネットワークが遅くてタイムアウト
• ブラウザのキャッシュがのこっていた
• DBの状態がかわっていた
• 信仰心がたりない
• etc. etc. etc.
Copyright © 2015 NS Solutions Corporation, All rights reserved. 25
「このテストが失敗するのはよくあることだから大丈夫」
Copyright © 2015 NS Solutions Corporation, All rights reserved. 26
driver.get(baseUrl + "/myVideoRental/FrontController");
driver.findElement(By.name("shop_id")).clear();
driver.findElement(By.name("shop_id")).sendKeys("01");
(大丈夫じゃない)
orz
Copyright © 2015 NS Solutions Corporation, All rights reserved. 27
たまに失敗の闇と向き合う
• 同じ条件ならいつでも失敗 or いつでも成功するテストがよいテスト!
• 事前条件をそろえる• AP, DB, ブラウザ状態の初期化
• 適切にwaitする• PageObjectパターンとの組み合わせも◎
Copyright © 2015 NS Solutions Corporation, All rights reserved. 28
の闇ブラウザ依存
Copyright © 2015 NS Solutions Corporation, All rights reserved. 29
ページのレイアウト崩れが無いか
確認したい…
Copyright © 2015 NS Solutions Corporation, All rights reserved. 30
スクリーンショットを撮ろう!
Copyright © 2015 NS Solutions Corporation, All rights reserved. 31
File screenshotFile = ((Screenshot)driver).getScreenshotAs(file);
Copyright © 2015 NS Solutions Corporation, All rights reserved. 32
可視範囲のみ
いろんなバー映り込む
Copyright © 2015 NS Solutions Corporation, All rights reserved. 33
Internet Explorer Google Chrome Safari(iOS)
TakesScreenshot interfaceFor WebDriver extending TakesScreenshot, this makes a best effort depending on the browser to return the following in order of preference:
• Entire page
• Current window
• Visible portion of the current frame
• The screenshot of the entire display containing the browser
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/TakesScreenshot.htmlCopyright © 2015 NS Solutions Corporation, All rights reserved. 34
TakesScreenshot interface(意訳)実装するときは下記の順でどれか返してくれればいいよ。ブラウザによってベストエフォートで実装してね。
• ページ全体
• 現在のウインドウ
• 現在のフレームの可視範囲
• ブラウザも含むディスプレイ全体
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/TakesScreenshot.htmlCopyright © 2015 NS Solutions Corporation, All rights reserved. 35
orz
Copyright © 2015 NS Solutions Corporation, All rights reserved. 36
ブラウザ依存の闇と向き合う
世にある便利ツールを使おう!
(他力本願)
Copyright © 2015 NS Solutions Corporation, All rights reserved. 37
Seleniumベースのツール・サービス
• ラッパ /DSL• SeleniumのAPIを使いやすくしてくれたり、自然言語に近い形でテストを書けたりする
• クラウドサービス• 色々なブラウザの実行環境が使えたり、スクショや動画キャプチャ撮ってくれたりする
Copyright © 2015 NS Solutions Corporation, All rights reserved. 38
参考:Seleniumテストの自動化を推し進めるクラウドサービスまとめ
http://blog.htmlhifive.com/2014/12/09/selenium-cloud-services/
宣伝:弊社も作ってます
Pitalium
Copyright © 2015 NS Solutions Corporation, All rights reserved. 39
ピ タ リ ウ ム
by
OSS(Apache2.0)
Copyright © 2015 NS Solutions Corporation, All rights reserved. 40
IE
Safari
Chrome
Pitalium
テスト自動化の闇テスト自動化の闇と向き合う
Copyright © 2015 NS Solutions Corporation, All rights reserved. 41
テスト自動化の闇と向き合うには
• テストしやすい設計
• テストスクリプトに一手間
• 便利ツール・サービスを使う
Copyright © 2015 NS Solutions Corporation, All rights reserved. 42
そして深まる闇
闇トークしたい方
hifiveブースへお越しください!
Copyright © 2015 NS Solutions Corporation, All rights reserved. 43
・ NS Solutions、NS(ロゴ)、NSSOLは、新日鉄住金ソリューションズ株式会社の登録商標です。
・ hifive、hifive(ロゴ)は、新日鉄住金ソリューションズ株式会社の登録商標です。
・ Pitaliumは、新日鉄住金ソリューションズ株式会社の商標です。
・ Javaは、米国ORACLE Corp.の登録商標です。
・ HTML5 Logo by W3C
・ その他本文記載の会社名及び製品名は、それぞれ各社の商標又は登録商標です。
Recommended