selenium webdriver使ってみようず

56
わわわわわわ わわわわわ #48 SeleniumWebDriver わわわわわわわ 2012/04/07 わ わ

Upload: oda-shinsuke

Post on 20-Aug-2015

13.255 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

SeleniumWebDriver使ってみようず

2012/04/07 お だ

Page 2: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

自己紹介

• 織田 信亮 ( おだ しんすけ )• 大阪で開発者しています• SQLWorld 代表 (http://sqlworld.org)

• http://d.hatena.ne.jp/odashinsuke/• Twitter:@shinsukeoda

Page 3: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

~基本~

Page 4: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Selenium ってなに?

• Web アプリケーション用のテストツール• ブラウザを使って Web アプリケーショ

ンの動作確認等を行う• ブラウザの操作を Selenium が行ってく

れる

Page 5: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Selenium WebDriver ってなに?

http://seleniumhq.org/docs/03_webdriver.html• Selenium が WebDriver と統合された• Selenium 1.0 だと JavaScript/HTML で

記述がメイン• WebDriver は、 Selenium ではセキュリ

ティで制限されていたものが回避出来る• Selenium 2.0 で統合!

Page 6: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

API が提供されている言語

• Java• C#• Python• Ruby• PHP• Perl

Page 7: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

提供されている WebDriver

• HtmlUnit Driver• Firefox Driver• Internet Explorer Driver• Chrome Driver• Opera Driver• iPhone Driver• Android Driver

言語によっては、提供されていない Driver もある!

Page 8: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

API の基本

• ドライバー– IWebDriver (WebDriver)

• エレメント– IWebElement(WebElement)

• ロケーター– By

Page 9: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

using System; using OpenQA.Selenium.IE; using OpenQA.Selenium;

class Program {   static void Main(string[] args) {     IWebDriver driver = new InternetExplorerDriver();     Console.ReadKey();     driver.Quit();   } }

とりあえず、ブラウザ起動してみる

Page 10: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

ドライバー の API

• ページのタイトル取得• 要素の検索

– ISearchContext を実装• FindElement, FindElements

• ページ遷移– INavigation を保持

• GoToUrl, Back, Forward

• コンテキストの切り替え– ITargetLocator を保持

• Alert, Frame, Window

Page 11: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

using System; using OpenQA.Selenium.IE; using OpenQA.Selenium;

class Program {   static void Main(string[] args) {     IWebDriver driver = new InternetExplorerDriver();     driver.Navigate().GoToUrl("http://www.bing.com"); Console.WriteLine(driver.Title);     Console.ReadKey();     driver.Quit();   } }

Bing にいってみる

Page 12: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

using System; using OpenQA.Selenium.IE; using OpenQA.Selenium;

class Program {   static void Main(string[] args) {     IWebDriver driver = new InternetExplorerDriver();     driver.Navigate().GoToUrl("http://www.bing.com");     IWebElement element = driver.FindElement(By.Name("q"));     element.SendKeys(" セレニウム ウェブドライバー ");     Console.ReadKey();     driver.Quit();   } }

テキストボックスに文字を入力

Page 13: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Page 14: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

ロケーターには何がある?

• Id• Name• TagName• ClassName• CssSelector• LinkText• PartialLinkText• XPath

Page 15: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

using System; using OpenQA.Selenium.IE; using OpenQA.Selenium;

class Program {   static void Main(string[] args) {     IWebDriver driver = new InternetExplorerDriver();     driver.Navigate().GoToUrl("http://www.bing.com");     IWebElement elementByName = driver.FindElement(By.Name("q"));     elementByName.SendKeys(" セレニウム ウェブドライバー ");     IWebElement elementById = driver.FindElement(By.Id("sb_form_q"));     elementById.SendKeys(" ID  で取ったお ");     IWebElement elementByCss = driver.FindElement( By.CssSelector("input.sw_qbox"));     elementByCss.Clear();     elementByCss.SendKeys("CssSelector  で ");      Console.ReadKey();     driver.Quit();   }}

色んな取り方をしてみる

Page 16: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

エレメント の メソッド

• SendKeys• Clear• Click• GetAttribute

– input タグの入力値はこれで取得する • GetCssValue• Submit• 要素の検索 (ISearchContext を実装 )

Page 17: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

エレメント の プロパティ

基本 get だけ• Displayed• Enabled• Location• Selected

– チェックボックスや Select の Option• Size• TagName• Text

– タグに挟まれたテキストのこと– テキストボックスの値じゃない!

Page 18: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

~実践~

Page 19: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

みんな大好き IE Driver を使う

• 前準備– IE がインストールされている– ツール => インターネット オプション =>

セキュリティ タブ => 全てのゾーンで「保護モードを有効にする」チェック値を統一

Page 20: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Chrome Driver を使う

• 前準備– Chrome がインストールされている– ChromeDriver.exe をダウンロードするhttp://code.google.com/p/chromedriver/downloads/list

Page 21: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

C# で

• Visual Web Developer 2010 Express (VWD2010)

• 拡張機能マネージャーから NuGet インストール

• Package Manage Console(NuGet) から

– Support は便利だからいれてます

Install-Package Selenium.WebDriverInstall-Package Selenium.Support

ここでは、以下のライブラリも利用していますNunit 、 ChainingAssertion.NUnit

Page 22: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

[Test]public void 検索 () { var driver = new InternetExplorerDriver(); try { driver.Navigate().GoToUrl("http://www.bing.com"); var txt 条件 = driver.FindElementByName("q"); txt 条件 .SendKeys("Microsoft"); txt 条件 .Submit(); Thread.Sleep(3000); // 次の画面に遷移するまで待つ var lbl 件数 = driver.FindElementById("count"); Regex.Match(lbl 件数 .Text, "(?<=of ).*(?= results)").Value.Is("527,000,000"); } finally { driver.Quit(); }}

Page 23: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

便利なやつ その 1

• IWait(Wait)– Selenium.Support に含まれている

• OpenQA.Selenium.Support.UI.IWait

– Thread.Sleep はもう古い!– 指定条件を満たすまで待機する– タイムアウト指定することで、異常時には例

外で終了する

Page 24: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Wait

• WebDriverWait が良く使われる• コンストラクタでタイムアウト時間指定• Until メソッドに Func を渡し条件指定• Func は、既定の実装が幾つかある

– ExpectedConditions

• Func を自前で実装も可wait.Until(d => d.Title == "Microsoft - Bing");

IWait<IWebDriver> wait = new WebDriverWait(driver, new TimeSpan(0, 0,10));wait.Until(ExpectedConditions.TitleIs("Microsoft - Bing"));

Page 25: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

[Test]public void 検索 () { var driver = new InternetExplorerDriver(); try { driver.Navigate().GoToUrl("http://www.bing.com"); var txt 条件 = driver.FindElementByName("q"); txt 条件 .SendKeys("Microsoft"); txt 条件 .Submit(); var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 10)); wait.Until(ExpectedConditions.TitleIs("Microsoft - Bing")); var lbl 件数 = driver.FindElementById("count"); Regex.Match(lbl 件数 .Text, "(?<=of ).*(?= results)").Value.Is("527,000,000"); } finally { driver.Quit(); }}

Page 26: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

PageObject パターン

• 一つの HTML の操作は一つの場所で• 一つのページを一つのオブジェクトとし

て扱い、カプセル化• メソッドは実行する機能を表現する

(DOM の操作ではない )http://memolog.org/2010/11/page_objects.php

http://code.google.com/p/selenium/wiki/PageObjects

Page 27: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

[TestFixture]public class カプセル化 { [Test] public void 検索 () { var driver = new InternetExplorerDriver(); try { var instance = BingSearch.Create(driver); instance.Input 検索条件 ("Microsoft"); instance.Submit 検索 (); instance.Get 検索結果件数 ().Is("527,000,000"); } finally { driver.Quit(); } }}

Page 28: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

public class BingSearch { public static BingSearch Create(RemoteWebDriver driver) { var instance = new BingSearch(driver); driver.Url = "http://www.bing.com"; return instance; } private readonly RemoteWebDriver driver; private BingSearch(RemoteWebDriver driver) { this.driver = driver; } private IWebElement txt 条件 { get { return driver.FindElementByName("q"); } } private IWebElement lbl 件数 { get { return driver.FindElementById("count"); } }

Page 29: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

public void Input 検索条件 (string 条件 ) { this.txt 条件 .Clear(); this.txt 条件 .SendKeys( 条件 ); } public void Submit 検索 () { this.txt 条件 .Submit(); var wait = new WebDriverWait(this.driver, new TimeSpan(0, 0, 10)); wait.Until(ExpectedConditions.TitleIs( "Microsoft - Bing")); } public string Get 検索結果件数 () { return Regex.Match(this.lbl 件数 .Text, "(?<=of ).*(?= results)").Value; }}

Page 30: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Java (Maven) で

• selenium-java

• ie-driver や support もついてくる

<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.20.0</version></dependency>

Page 31: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

@Testpublic void 検索 () { RemoteWebDriver driver = new InternetExplorerDriver(); try { driver.navigate().to("http://www.bing.com"); WebElement txt 条件 = driver.findElementByName("q"); txt 条件 .sendKeys("Microsoft"); txt 条件 .submit(); Wait<WebDriver> wait = new WebDriverWait(driver, 10); wait.until(titleIs("Microsoft - Bing")); WebElement lbl 件数 = driver.findElementById("count"); assertThat(lbl 件数 .getText().replaceAll( "(.*of )(.*)( results)", "$2"), is("527,000,000")); } finally { driver.quit(); }}

Page 32: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

@Testpublic void カプセル化 () { RemoteWebDriver driver = new InternetExplorerDriver(); try { BingSearch instance = BingSearch.create(driver); instance.input 検索条件 ("Microsoft"); instance.submit 検索 (); assertThat(instance.get 検索結果件数 (), is("527,000,000")); } finally { driver.quit(); }}

Page 33: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

public class BingSearch { private final RemoteWebDriver driver; public static BingSearch create(RemoteWebDriver driver) { BingSearch instance = new BingSearch(driver); driver.navigate().to("http://www.bing.com"); return instance; } private BingSearch(RemoteWebDriver driver) { this.driver = driver; } private WebElement txt 条件 () { return driver.findElementByName("q"); } private WebElement lbl 件数 () { return driver.findElementById("count"); }

Page 34: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

public void input 検索条件 (String 条件 ) { this.txt 条件 ().clear(); this.txt 条件 ().sendKeys( 条件 ); } public void submit 検索 () { this.txt 条件 ().submit(); Wait<WebDriver> wait = new WebDriverWait(driver, 10); wait.until(titleIs("Microsoft - Bing")); } public String get 検索結果件数 () { return this.lbl 件数 ().getText().replaceAll( "(.*of )(.*)( results)", "$2"); }}

Java だとプロパティ(getter) の

括弧 が鬱陶しい!

Page 35: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

便利なやつ ( その2 )

• PageFactory– PageObject の実装を少し楽にしてくれる– アノテーション / 属性 ベースで、要素と

フィールドのマッピング• WebElement 型の フィールド

– キャッシュも可能• ページ遷移 / リロードを行った場合は、キャッ

シュを取り直す必要あり– PageFactory.initElements で初期化を行う

Page 36: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

public class Top { public static Top create(WebDriver driver) { driver.navigate().to("http://www.bing.com"); Top instance = new Top(driver); PageFactory.initElements(driver, instance); return instance; } private final WebDriver driver; private Top(WebDriver driver) { this.driver = driver; }

@FindBy(name = "q") @CacheLookup private WebElement txt 条件 ;

Page 37: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

public Result search(String 条件 ) { this.txt 条件 .clear(); this.txt 条件 .sendKeys( 条件 ); this.txt 条件 .submit(); Wait<WebDriver> wait = new WebDriverWait(driver, 10); wait.until(titleIs( 条件 + " - Bing"));

return Result.create(driver); }}

Page 38: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

public class Result { public static Result create(WebDriver driver) { return PageFactory.initElements(driver, Result.class); } private final WebDriver driver; public Result(WebDriver driver) { this.driver = driver; }

@FindBy(id="count") private WebElement lbl 件数 ;

public String 検索結果件数 () { return lbl 件数 .getText() .replaceAll("(.*of )(.*)( results)", "$2"); }}

Page 39: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

便利なやつ ( その3 )

• Select– input type=“select” な WebElement のラッ

パー– Option の選択や取得を容易にしてくれる– PageFactory には対応していない

Page 40: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

WebElement select = ~ ;List<WebElement> options = select.findElements(By.tagName("option"));for (WebElement option : options) { option.click(); // 選択させる if (option.isSelected()) { // 選択していたら }}Select wrapper = new Select(select);// 選択させるwrapper.selectByIndex(0);wrapper.selectByValue("hoge");wrapper.selectByVisibleText(" フヒヒ ");// 選択されているもの取得wrapper.getFirstSelectedOption();wrapper.getAllSelectedOptions();

Select

Page 41: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

よく使いそうな操作

• Table 表示のデータ取得• スクリーンショットの取得• input type=“file” へのパス指定• Alert/Confirm ダイアログ• 新しい Window

Page 42: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Table 表示のデータ取得

• Java だとこんな感じ…– 1 行を表すデータ型作成– <tr> 単位でループし、コレクションの取得

• PageFactory 等を使用しインスタンス生成–比較処理

• .NET だと…

Page 43: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

[Test]public void Table() { var driver = new ChromeDriver(@"c:\work"); try { driver.Url = "http://nabewebdriver.apphb.com/"; var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 10)); wait.Until(d => d.Title == " メニュー "); driver.FindElementByPartialLinkText(" 検索画面 ").Click(); wait.Until(d => d.Title == "Search"); driver.FindElementByXPath("//input[@type='submit' and @value=' 検索 ']").Click(); wait.Until(ExpectedConditions.ElementIsVisible(By.Id("results"))); driver.FindElementsById("roop").Select(e => new { Name = e.FindElement(By.Id("resultName")).Text, Birthday = e.FindElement(By.Id("resultBirthday")).Text, Money = e.FindElement(By.Id("resultMoney")).Text }).Is( new { Name = "名前 1", Birthday = "1970/12/04", Money = "10,000" }, new { Name = "名前 2", Birthday = "1980/10/15", Money = "15,000" }, new { Name = "名前 3", Birthday = "1979/06/23", Money = "20,000" }, new { Name = "名前 4", Birthday = "1990/08/06", Money = "25,000" }, new { Name = "名前 5", Birthday = "2000/07/04", Money = "30,000" } ); } finally { driver.Quit(); }}

Page 44: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

driver.FindElementsById("roop").Select(e => new { Name = e.FindElement(By.Id("resultName")).Text, Birthday = e.FindElement(By.Id("resultBirthday")).Text, Money = e.FindElement(By.Id("resultMoney")).Text}).Is( new { Name = "名前 1", Birthday = "1970/12/04", Money = "10,000" }, new { Name = "名前 2", Birthday = "1980/10/15", Money = "15,000" }, new { Name = "名前 3", Birthday = "1979/06/23", Money = "20,000" }, new { Name = "名前 4", Birthday = "1990/08/06", Money = "25,000" }, new { Name = "名前 5", Birthday = "2000/07/04", Money = "30,000" } );

Page 45: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

スクリーンショットの取得

• TakesScreenshot を実装している Driver が対象–殆どの Driver は実装している

• Java だと…

• NET だと…

FileUtils.copyFile( driver.getScreenshotAs(OutputType.FILE), new File("c:/work/hoge.png"));

driver.GetScreenshot().SaveAsFile( @"c:\work\hoge.png", ImageFormat.Png);

Page 46: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

input type=“file” へのパス指定

• WebElement を取得し、 sendKeys でフルパスを渡す。

• Java だと…

• NET だと…

driver.findElement(By.id("fileupload")) .sendKeys("c:/work/result.jpg");

driver.FindElement(By.Id("fileupload")) .SendKeys(@"c:\work\result.jpg");

Page 47: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Alert/Confirm ダイアログ

• WebDriver から TargetLocator を取得し、alert を呼ぶ。

• Java だと…

• NET だと…Alert dialog = driver.switchTo().alert();

var dialog = driver.SwitchTo().Alert();

Page 48: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Alert インターフェース

• getText– 表示しているテキストを取得

• accept– OK ボタンクリック

• dismiss– キャンセル ボタンクリック

• sendKeys

Page 49: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Alert/Confirm ダイアログ 注意点

• ダイアログが表示されている間は他の操作は出来ない– Driver や Element の操作

• accept/dismiss した後に Alert を操作 –閉じている Dialog は操作出来ない

• Alert を取得する際は、念のため Wait を使う

Page 50: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

エラーになるケース

HTML<input type="button" id="btn" value="hoge“ onclick="alert('hoge');" /><input type="text" id="txt" />

C# コードvar text = driver.FindElementById("txt");driver.FindElementById("btn").Click();// text.SendKeys("hoge"); // Error// driver.FindElementById("button"); // Errorvar dialog = driver.SwitchTo().Alert();dialog.Accept();var dialogText = dialog.Text; // Error

Page 51: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

Alert 取得時の Wait

• Java だと…

• NET だと…

Wait<WebDriver> wait = new WebDriverWait(driver, 10);Alert dialog = wait.until(alertIsPresent());

var wait = new WebDriverWait( driver, new TimeSpan(0, 0, 10));var dialog = wait.Until(d => { try { return d.SwitchTo().Alert(); } catch (Exception) { return null;}});

Page 52: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

新しい Window

• WebDriver から TargetLocator を取得し、window を呼ぶ。–戻り値は WebDriver で呼び出し元と同じイ

ンスタンス• Java だと…

• NET だと…driver.switchTo().window("name or handler");

driver.SwitchTo().Window("name"); // 一応 handler でも OK

Page 53: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

WindowHandler の取得

• Java だと…

• NET だと…

String current = driver.getWindowHandle();Set<String> all = driver.getWindowHandles();

var current = driver.CurrentWindowHandle;var all = driver.WindowHandles;

Page 54: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

新しい Window 切替時の Wait

• Java だと…

• NET だと…

Wait<WebDriver> wait = new WebDriverWait(driver, 10);wait.until(new Function<WebDriver, WebDriver>() { public WebDriver apply(WebDriver arg0) { try { return arg0.switchTo().window("windowName"); } catch (Exception e) { return null; } }});

var wait = new WebDriverWait( driver, new TimeSpan(0, 0, 10));wait.Until(d => { try { return d.SwitchTo().Window("windowName"); } catch (Exception) { return null;}});

Page 55: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

~まとめ~

Page 56: Selenium webdriver使ってみようず

わんくま同盟 大阪勉強会 #48

まとめ• 複数の言語 / ブラウザに対応している

– Java が API が充実してそう• 大概のことは出来ます

–今回説明省いたきましたが、 Interactions を使えば、 Drag&Drop みたいな事も

http://code.google.com/p/selenium/wiki/AdvancedUserInteractions#Mouse_interactions

• Wait 超大事!• 当然テスト以外でも使えます

– ブラウザ操作の自動化