Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Selenium webdriver使ってみようず

16,153 views

Published on

2012/04/07 わんくま大阪#48

Published in: Technology, Business

Selenium webdriver使ってみようず

  1. 1. SeleniumWebDriver 使ってみようず 2012/04/07 お だ わんくま同盟 大阪勉強会 #48
  2. 2. 自己紹介• 織田 信亮(おだ しんすけ)• 大阪で開発者しています• SQLWorld 代表 (http://sqlworld.org)• http://d.hatena.ne.jp/odashinsuke/• Twitter:@shinsukeoda わんくま同盟 大阪勉強会 #48
  3. 3. ~基本~わんくま同盟 大阪勉強会 #48
  4. 4. Selenium ってなに?• Web アプリケーション用のテストツール• ブラウザを使って Web アプリケーション の動作確認等を行う• ブラウザの操作を Selenium が行ってくれ る わんくま同盟 大阪勉強会 #48
  5. 5. Selenium WebDriver ってなに?http://seleniumhq.org/docs/03_webdriver.html• Selenium が WebDriver と統合された• Selenium 1.0 だと JavaScript/HTML で記 述がメイン• WebDriver は、Selenium ではセキュリ ティで制限されていたものが回避出来る• Selenium 2.0 で統合! わんくま同盟 大阪勉強会 #48
  6. 6. API が提供されている言語• Java• C#• Python• Ruby• PHP• Perl わんくま同盟 大阪勉強会 #48
  7. 7. 提供されている WebDriver• HtmlUnit Driver• Firefox Driver• Internet Explorer Driver• Chrome Driver• Opera Driver• iPhone Driver• Android Driver 言語によっては、提供されていない Driver もあ る! わんくま同盟 大阪勉強会 #48
  8. 8. API の基本• ドライバー – IWebDriver (WebDriver)• エレメント – IWebElement(WebElement)• ロケーター – By わんくま同盟 大阪勉強会 #48
  9. 9. とりあえず、ブラウザ起動してみるusing System;using OpenQA.Selenium.IE;using OpenQA.Selenium;class Program { static void Main(string[] args) { IWebDriver driver = new InternetExplorerDriver(); Console.ReadKey(); driver.Quit(); }} わんくま同盟 大阪勉強会 #48
  10. 10. ドライバー の API• ページのタイトル取得• 要素の検索 – ISearchContext を実装 • FindElement, FindElements• ページ遷移 – INavigation を保持 • GoToUrl, Back, Forward• コンテキストの切り替え – ITargetLocator を保持 • Alert, Frame, Window わんくま同盟 大阪勉強会 #48
  11. 11. Bing にいってみる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(); }} わんくま同盟 大阪勉強会 #48
  12. 12. テキストボックスに文字を入力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(); }} わんくま同盟 大阪勉強会 #48
  13. 13. わんくま同盟 大阪勉強会 #48
  14. 14. ロケーターには何がある?• Id• Name• TagName• ClassName• CssSelector• LinkText• PartialLinkText• XPath わんくま同盟 大阪勉強会 #48
  15. 15. 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(); }} わんくま同盟 大阪勉強会 #48
  16. 16. エレメント の メソッド• SendKeys• Clear• Click• GetAttribute – input タグの入力値はこれで取得する• GetCssValue• Submit• 要素の検索 (ISearchContext を実装) わんくま同盟 大阪勉強会 #48
  17. 17. エレメント の プロパティ基本 get だけ• Displayed• Enabled• Location• Selected – チェックボックスや Select の Option• Size• TagName• Text – タグに挟まれたテキストのこと – テキストボックスの値じゃない! わんくま同盟 大阪勉強会 #48
  18. 18. ~実践~わんくま同盟 大阪勉強会 #48
  19. 19. みんな大好き IE Driver を使う• 前準備 – IE がインストールされている – ツール => インターネット オプション => セ キュリティ タブ => 全てのゾーンで「保護 モードを有効にする」チェック値を統一 わんくま同盟 大阪勉強会 #48
  20. 20. Chrome Driver を使う• 前準備 – Chrome がインストールされている – ChromeDriver.exe をダウンロードする http://code.google.com/p/chromedriver/downloads/list わんくま同盟 大阪勉強会 #48
  21. 21. C# で• Visual Web Developer 2010 Express (VWD2010)• 拡張機能マネージャーから NuGet インス トール• Package Manage Console(NuGet) から Install-Package Selenium.WebDriver Install-Package Selenium.Support – Support は便利だからいれてます ここでは、以下のライブラリも利用しています Nunit、ChainingAssertion.NUnit わんくま同盟 大阪勉強会 #48
  22. 22. [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(); }} わんくま同盟 大阪勉強会 #48
  23. 23. 便利なやつ その1• IWait(Wait) – Selenium.Support に含まれている • OpenQA.Selenium.Support.UI.IWait – Thread.Sleep はもう古い! – 指定条件を満たすまで待機する – タイムアウト指定することで、異常時には例 外で終了する わんくま同盟 大阪勉強会 #48
  24. 24. Wait• WebDriverWait が良く使われる• コンストラクタでタイムアウト時間指定• Until メソッドに Func を渡し条件指定• Func は、既定の実装が幾つかある – ExpectedConditions IWait<IWebDriver> wait = new WebDriverWait(driver, new TimeSpan(0, 0,10)); wait.Until(ExpectedConditions.TitleIs("Microsoft - Bing"));• Func を自前で実装も可 wait.Until(d => d.Title == "Microsoft - Bing"); わんくま同盟 大阪勉強会 #48
  25. 25. [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(); }} わんくま同盟 大阪勉強会 #48
  26. 26. PageObject パターン• 一つの HTML の操作は一つの場所で• 一つのページを一つのオブジェクトとして 扱い、カプセル化• メソッドは実行する機能を表現する(DOM の操作ではない) http://memolog.org/2010/11/page_objects.php http://code.google.com/p/selenium/wiki/PageObjects わんくま同盟 大阪勉強会 #48
  27. 27. [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(); } }} わんくま同盟 大阪勉強会 #48
  28. 28. 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"); } } わんくま同盟 大阪勉強会 #48
  29. 29. 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; }} わんくま同盟 大阪勉強会 #48
  30. 30. Java (Maven) で• selenium-java <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.20.0</version> </dependency>• ie-driver や support もついてくる わんくま同盟 大阪勉強会 #48
  31. 31. @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(); }} わんくま同盟 大阪勉強会 #48
  32. 32. @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(); }} わんくま同盟 大阪勉強会 #48
  33. 33. 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"); } わんくま同盟 大阪勉強会 #48
  34. 34. 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) の 括弧 が鬱陶しい! わんくま同盟 大阪勉強会 #48
  35. 35. 便利なやつ (その2)• PageFactory – PageObject の実装を少し楽にしてくれる – アノテーション/属性 ベースで、要素とフィー ルドのマッピング • WebElement 型の フィールド – キャッシュも可能 • ページ遷移/リロードを行った場合は、キャッシュ を取り直す必要あり – PageFactory.initElements で初期化を行う わんくま同盟 大阪勉強会 #48
  36. 36. 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条件; わんくま同盟 大阪勉強会 #48
  37. 37. 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); }} わんくま同盟 大阪勉強会 #48
  38. 38. 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"); }} わんくま同盟 大阪勉強会 #48
  39. 39. 便利なやつ(その3)• Select – input type=“select” な WebElement のラッ パー – Option の選択や取得を容易にしてくれる – PageFactory には対応していない わんくま同盟 大阪勉強会 #48
  40. 40. SelectWebElement 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(); わんくま同盟 大阪勉強会 #48
  41. 41. よく使いそうな操作• Table 表示のデータ取得• スクリーンショットの取得• input type=“file” へのパス指定• Alert/Confirm ダイアログ• 新しい Window わんくま同盟 大阪勉強会 #48
  42. 42. Table 表示のデータ取得• Java だとこんな感じ… – 1行を表すデータ型作成 – <tr> 単位でループし、コレクションの取得 • PageFactory 等を使用しインスタンス生成 – 比較処理• .NET だと… わんくま同盟 大阪勉強会 #48
  43. 43. [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(); }} わんくま同盟 大阪勉強会 #48
  44. 44. 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" }); わんくま同盟 大阪勉強会 #48
  45. 45. スクリーンショットの取得• TakesScreenshot を実装している Driver が対象 – 殆どの Driver は実装している• Java だと… FileUtils.copyFile( driver.getScreenshotAs(OutputType.FILE), new File("c:/work/hoge.png") );• NET だと… driver.GetScreenshot().SaveAsFile( @"c:workhoge.png", ImageFormat.Png); わんくま同盟 大阪勉強会 #48
  46. 46. input type=“file” へのパス指定• WebElement を取得し、sendKeys でフル パスを渡す。• Java だと… driver.findElement(By.id("fileupload")) .sendKeys("c:/work/result.jpg");• NET だと… driver.FindElement(By.Id("fileupload")) .SendKeys(@"c:workresult.jpg"); わんくま同盟 大阪勉強会 #48
  47. 47. Alert/Confirm ダイアログ• WebDriver から TargetLocator を取得し、 alert を呼ぶ。• Java だと… Alert dialog = driver.switchTo().alert();• NET だと… var dialog = driver.SwitchTo().Alert(); わんくま同盟 大阪勉強会 #48
  48. 48. Alert インターフェース• getText – 表示しているテキストを取得• accept – OK ボタンクリック• dismiss – キャンセル ボタンクリック• sendKeys わんくま同盟 大阪勉強会 #48
  49. 49. Alert/Confirm ダイアログ 注意点• ダイアログが表示されている間は他の操作 は出来ない – Driver や Element の操作• accept/dismiss した後に Alert を操作 – 閉じている Dialog は操作出来ない• Alert を取得する際は、念のため Wait を使 う わんくま同盟 大阪勉強会 #48
  50. 50. エラーになるケース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 わんくま同盟 大阪勉強会 #48
  51. 51. Alert 取得時の Wait• Java だと… Wait<WebDriver> wait = new WebDriverWait(driver, 10); Alert dialog = wait.until(alertIsPresent());• NET だと… var wait = new WebDriverWait( driver, new TimeSpan(0, 0, 10)); var dialog = wait.Until(d => { try { return d.SwitchTo().Alert(); } catch (Exception) { return null;} }); わんくま同盟 大阪勉強会 #48
  52. 52. 新しい Window• WebDriver から TargetLocator を取得し、 window を呼ぶ。 – 戻り値は WebDriver で呼び出し元と同じイン スタンス• Java だと… driver.switchTo().window("name or handler");• NET だと… driver.SwitchTo().Window("name"); // 一応 handler でもOK わんくま同盟 大阪勉強会 #48
  53. 53. WindowHandler の取得• Java だと… String current = driver.getWindowHandle(); Set<String> all = driver.getWindowHandles();• NET だと… var current = driver.CurrentWindowHandle; var all = driver.WindowHandles; わんくま同盟 大阪勉強会 #48
  54. 54. 新しい Window 切替時の Wait• Java だと… 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; } } });• NET だと… var wait = new WebDriverWait( driver, new TimeSpan(0, 0, 10)); wait.Until(d => { try { return d.SwitchTo().Window("windowName"); } catch (Exception) { return null;} }); わんくま同盟 大阪勉強会 #48
  55. 55. ~まとめ~わんくま同盟 大阪勉強会 #48
  56. 56. まとめ• 複数の言語/ブラウザに対応している – Java が API が充実してそう• 大概のことは出来ます – 今回説明省いたきましたが、Interactions を使 えば、Drag&Drop みたいな事も http://code.google.com/p/selenium/wiki/AdvancedUserInteractions# Mouse_interactions• Wait 超大事!• 当然テスト以外でも使えます – ブラウザ操作の自動化 わんくま同盟 大阪勉強会 #48

×