Mais conteúdo relacionado Semelhante a Selenium webdriver使ってみようず (20) Mais de Oda Shinsuke (20) Selenium webdriver使ってみようず2. 自己紹介
• 織田 信亮(おだ しんすけ)
• 大阪で開発者しています
• SQLWorld 代表 (http://sqlworld.org)
• http://d.hatena.ne.jp/odashinsuke/
• Twitter:@shinsukeoda
わんくま同盟 大阪勉強会 #48
4. Selenium ってなに?
• Web アプリケーション用のテストツール
• ブラウザを使って Web アプリケーション
の動作確認等を行う
• ブラウザの操作を Selenium が行ってくれ
る
わんくま同盟 大阪勉強会 #48
7. 提供されている WebDriver
• HtmlUnit Driver
• Firefox Driver
• Internet Explorer Driver
• Chrome Driver
• Opera Driver
• iPhone Driver
• Android Driver
言語によっては、提供されていない Driver もあ
る!
わんくま同盟 大阪勉強会 #48
8. API の基本
• ドライバー
– IWebDriver (WebDriver)
• エレメント
– IWebElement(WebElement)
• ロケーター
– By
わんくま同盟 大阪勉強会 #48
10. ドライバー の API
• ページのタイトル取得
• 要素の検索
– ISearchContext を実装
• FindElement, FindElements
• ページ遷移
– INavigation を保持
• GoToUrl, Back, Forward
• コンテキストの切り替え
– ITargetLocator を保持
• Alert, Frame, Window
わんくま同盟 大阪勉強会 #48
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. テキストボックスに文字を入力
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
14. ロケーターには何がある?
• Id
• Name
• TagName
• ClassName
• CssSelector
• LinkText
• PartialLinkText
• XPath
わんくま同盟 大阪勉強会 #48
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. エレメント の メソッド
• SendKeys
• Clear
• Click
• GetAttribute
– input タグの入力値はこれで取得する
• GetCssValue
• Submit
• 要素の検索 (ISearchContext を実装)
わんくま同盟 大阪勉強会 #48
17. エレメント の プロパティ
基本 get だけ
• Displayed
• Enabled
• Location
• Selected
– チェックボックスや Select の Option
• Size
• TagName
• Text
– タグに挟まれたテキストのこと
– テキストボックスの値じゃない!
わんくま同盟 大阪勉強会 #48
19. みんな大好き IE Driver を使う
• 前準備
– IE がインストールされている
– ツール => インターネット オプション => セ
キュリティ タブ => 全てのゾーンで「保護
モードを有効にする」チェック値を統一
わんくま同盟 大阪勉強会 #48
20. Chrome Driver を使う
• 前準備
– Chrome がインストールされている
– ChromeDriver.exe をダウンロードする
http://code.google.com/p/chromedriver/downloads/list
わんくま同盟 大阪勉強会 #48
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. [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. 便利なやつ その1
• IWait(Wait)
– Selenium.Support に含まれている
• OpenQA.Selenium.Support.UI.IWait
– Thread.Sleep はもう古い!
– 指定条件を満たすまで待機する
– タイムアウト指定することで、異常時には例
外で終了する
わんくま同盟 大阪勉強会 #48
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. [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. PageObject パターン
• 一つの HTML の操作は一つの場所で
• 一つのページを一つのオブジェクトとして
扱い、カプセル化
• メソッドは実行する機能を表現する(DOM
の操作ではない)
http://memolog.org/2010/11/page_objects.php
http://code.google.com/p/selenium/wiki/PageObjects
わんくま同盟 大阪勉強会 #48
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. 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. 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. 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. @Test
public 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. @Test
public 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. 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. 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. 便利なやつ (その2)
• PageFactory
– PageObject の実装を少し楽にしてくれる
– アノテーション/属性 ベースで、要素とフィー
ルドのマッピング
• WebElement 型の フィールド
– キャッシュも可能
• ページ遷移/リロードを行った場合は、キャッシュ
を取り直す必要あり
– PageFactory.initElements で初期化を行う
わんくま同盟 大阪勉強会 #48
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. 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. 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. 便利なやつ(その3)
• Select
– input type=“select” な WebElement のラッ
パー
– Option の選択や取得を容易にしてくれる
– PageFactory には対応していない
わんくま同盟 大阪勉強会 #48
40. Select
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();
わんくま同盟 大阪勉強会 #48
41. よく使いそうな操作
• Table 表示のデータ取得
• スクリーンショットの取得
• input type=“file” へのパス指定
• Alert/Confirm ダイアログ
• 新しい Window
わんくま同盟 大阪勉強会 #48
42. Table 表示のデータ取得
• Java だとこんな感じ…
– 1行を表すデータ型作成
– <tr> 単位でループし、コレクションの取得
• PageFactory 等を使用しインスタンス生成
– 比較処理
• .NET だと…
わんくま同盟 大阪勉強会 #48
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. 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. スクリーンショットの取得
• 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. 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. Alert/Confirm ダイアログ
• WebDriver から TargetLocator を取得し、
alert を呼ぶ。
• Java だと…
Alert dialog = driver.switchTo().alert();
• NET だと…
var dialog = driver.SwitchTo().Alert();
わんくま同盟 大阪勉強会 #48
48. Alert インターフェース
• getText
– 表示しているテキストを取得
• accept
– OK ボタンクリック
• dismiss
– キャンセル ボタンクリック
• sendKeys
わんくま同盟 大阪勉強会 #48
49. Alert/Confirm ダイアログ 注意点
• ダイアログが表示されている間は他の操作
は出来ない
– Driver や Element の操作
• accept/dismiss した後に Alert を操作
– 閉じている Dialog は操作出来ない
• Alert を取得する際は、念のため Wait を使
う
わんくま同盟 大阪勉強会 #48
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"); // Error
var dialog = driver.SwitchTo().Alert();
dialog.Accept();
var dialogText = dialog.Text; // Error
わんくま同盟 大阪勉強会 #48
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. 新しい Window
• WebDriver から TargetLocator を取得し、
window を呼ぶ。
– 戻り値は WebDriver で呼び出し元と同じイン
スタンス
• Java だと…
driver.switchTo().window("name or handler");
• NET だと…
driver.SwitchTo().Window("name");
// 一応 handler でもOK
わんくま同盟 大阪勉強会 #48
53. WindowHandler の取得
• Java だと…
String current = driver.getWindowHandle();
Set<String> all = driver.getWindowHandles();
• NET だと…
var current = driver.CurrentWindowHandle;
var all = driver.WindowHandles;
わんくま同盟 大阪勉強会 #48
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
56. まとめ
• 複数の言語/ブラウザに対応している
– Java が API が充実してそう
• 大概のことは出来ます
– 今回説明省いたきましたが、Interactions を使
えば、Drag&Drop みたいな事も
http://code.google.com/p/selenium/wiki/AdvancedUserInteractions#
Mouse_interactions
• Wait 超大事!
• 当然テスト以外でも使えます
– ブラウザ操作の自動化
わんくま同盟 大阪勉強会 #48