Migrating from Selenium 1.0
Selenium 1.0을 사용해서 만든 test suit들을 가지고 계시다면 이것을 어떻게 Selenium 2.0으로 migrate 하는지에 대해 팁을 알려 드리겠습니다. Simon Stewart는 Selenium 2.0 의 lead developer 인데오 Selenium 1.0에서 migrating 하는 방법에 대해 글을 썼습니다. 아래 링크를 참조하세요.
Migrating From Selenium RC to Selenium WebDriver
Introducing the Selenium-WebDriver API by Example
WebDriver는 웹 어플리케이션 테스팅 자동화 툴입니다. 특정 기능이 디자인한대로 제대로 작동하는지를 점검하는 일을 하죠. 이 WebDriver는 Selenium-RC (1.0)API 보더 더 쉽게 접근할 수 있도록 발전시킨 API를 제공합니다. 이것을 통해서 여러분의 테스트들을 읽기 쉽고 유지관리하기 쉽게 도와 줍니다. WebDriver는 다른 테스트 플랫폼에 종속되지 않습니다. 그렇기 때문에 유닛테스팅이나 main 메소드를 통한 테스팅 모두에 사용될 수 있습니다. 이번 글에서는 WebDriver의 API를 소개하고 실제 사용하는 방법에 대해 알아보겠습니다. 아직 WebDriver가 설치되지 않았다면 셋업부터 시작하세요. 이래 링크를 따라가시면 관련 글이 있습니다.
Setting Up a Selenium-WebDriver Project.
일단 프로젝트가 셋업 됐다면 일반 라이브러리를 사용하듯이 WebDriver르르 사용하실 수 있습니다.
Note: additional steps are required to use Chrome Driver, Opera Driver, Android Driver
and iPhone Driver
이제 코딩할 준비가 다 됐는데요. 예제를 통해서 설명하겠습니다. 이 예제는 구글을 통해서 Cheese라는 단어로 검색을 하는 겁니다. 검색 후 다음 페이지의 title을 콘솔에 찍어 보겠습니다.
package org.openqa.selenium.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Selenium2Example {
public static void main(String[] args) {
// Create a new instance of the Firefox driver
// Notice that the remainder of the code relies on the interface,
// not the implementation.
WebDriver driver = new FirefoxDriver();
// And now use this to visit Google
driver.get("http://www.google.com");
// Alternatively the same thing can be done like this
// driver.navigate().to("http://www.google.com");
// Find the text input element by its name
WebElement element = driver.findElement(By.name("q"));
// Enter something to search for
element.sendKeys("Cheese!");
// Now submit the form. WebDriver will find the form for us from the element
element.submit();
// Check the title of the page
System.out.println("Page title is: " + driver.getTitle());
// Google's search is rendered dynamically with JavaScript.
// Wait for the page to load, timeout after 10 seconds
(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.getTitle().toLowerCase().startsWith("cheese!");
}
});
// Should see: "cheese! - Google Search"
System.out.println("Page title is: " + driver.getTitle());
//Close the browser
driver.quit();
}
}
다음 글에서는 WebDriver에 대해 좀 더 많은 것을 배울 겁니다. 예를 들어 브라우저 히스토리에서 navigating forward, backward 하는 방법이나 frame과 window를 사용해 웹 사이트를 테스트하는 방법같은 것들이요.
Selenium-WebDriver API Commands and Operations
Fetching a Page
WebDriver로 할 첫번째 일은 page를 navigate 하는 겁니다. 일반적으로 get() 메소드를 호출함으로서 이 작업을 할 수 있습니다.
driver.get("http://www.google.com");
OS/Browser combination을 포함한 여러 조건에 따라 WebDriver는 페이지를 로드하는 동안 기다리거나 기다리지 않을 수도 있습니다. 특정 환경에서 WebDriver는 페이지가 finish되기 전에 혹은 시작되거나 loading되기 전에 control을 return 할 겁니다. 제대로 된 테스트를 하기 위해 명시적으로 혹은 암시적으로 페이지내에 있는 element들을 기다리는 시간이 필요합니다.
Locating UI Elements (WebElements)
WebDriver에 있는 element들은 WebDriver 인스턴스나 WebElement 에서 처리할 수 있습니다. 이 element를 찾는 명령어들이 있는데요. 이 Find Elements 메소드를 사용하면 우선 WebElement를 return 합니다. 그렇지 않으면 exception이 발생합니다. 그 다음에 WebElements의 리스트가 return 되구요. 이 query 와 DOM element가 맞지 않으면 empty 리스트가 return 될 수 있습니다.
이 Find 메소드는 By라고 하는 query 객체를 사용합니다.
By ID
이것은 element를 찾는데 가장 흔히 사용됩니다. UI를 개발하면서 한 페이지 내에 unique 하지 않은 id가 있을 수 있습니다. 혹은 자동으로 생성된 id가 있을 수 있구요. 두 경우 모두 피하셔야 합니다. id보다 html element에 있는 class 가 자동 생성되도록 하면 좋습니다.
Example of how to find an element that looks like this:
<div id="coolestWidgetEvah">...</div>
WebElement element = driver.findElement(By.id("coolestWidgetEvah"));
By Class Name
이 경우 Class 는 DOM element의 attribute를 참조합니다. 실제 작업을 하다 보면 같은 클래스 이름을 가지고 있는 많은 DOM element들이 있게 됩니다. 그러니까 이 경우 리스트를 사용해서 여러 element를 담도록 할 수 있습니다.
Example of how to find an element that looks like this:
<div class="cheese"><span>Cheddar</span></div><div class="cheese"><span>Gouda</span></div>
List<WebElement> cheeses = driver.findElements(By.className("cheese"));
By Tag Name
The DOM Tag Name of the element.
Example of how to find an element that looks like this:
<iframe src="..."></iframe>
WebElement frame = driver.findElement(By.tagName("iframe"));
By Name
Find the input element with matching name attribute.
Example of how to find an element that looks like this:
<input name="cheese" type="text"/>
WebElement cheese = driver.findElement(By.name("cheese"));
By Link Text
Find the link element with matching visible text.
Example of how to find an element that looks like this:
<a href="http://www.google.com/search?q=cheese">cheese</a>>
WebElement cheese = driver.findElement(By.linkText("cheese"));
By Partial Link Text
Find the link element with partial matching visible text.
Example of how to find an element that looks like this:
<a href="http://www.google.com/search?q=cheese">search for cheese</a>>
WebElement cheese = driver.findElement(By.partialLinkText("cheese"));
By CSS
Like the name implies it is a locator strategy by css.
대개 Native 브라우저는 디폴트로 이것을 사용합니다.
그러니까 일반적으로 사용되는 css selector들에 대한 w3c css selectors <http://www.w3.org/TR/CSS/#selectors> 를 참조하세요.
브라우저가 css query에 대한 native support를 하지 않으면 Sizzle이 사용됩니다. IE 6,7 그리고 파이어폭스 3.0 은 css query engine으로서 Sizzle을 사용합니다.
모든 브라우저가 똑같이 생성되는 것은 아닙니다. 어떤 css는 어떤 버전에서는 작동을 하지만 다른 버전에서는 작동을 안 할 수도 있습니다.
Example of to find the cheese below:
<div id="food"><span class="dairy">milk</span><span class="dairy aged">cheese</span></div>
WebElement cheese = driver.findElement(By.cssSelector("#food span.dairy.aged"));
By XPATH
WebDriver는 브라우저의 native XPath를 사용합니다. 이 native XPath 를 지원하지 않는 브라우저에 대해 우리는 나름대로의 implementation을 제공합니다. 다양한 xpath 엔진의 차이점으로 인해 기대했던 것과는 다른 결과가 나올 수 있습니다.
<table>
This is a little abstract, so for the following piece of HTML:
<input type="text" name="example" />
<INPUT type="text" name="other" />
List<WebElement> inputs = driver.findElements(By.xpath("//input"));
The following number of matches will be found
Driver | Tag and Attribute Name | Attribute Values | Native XPath Support |
---|---|---|---|
HtmlUnit Driver | Lower-cased | As they appear in the HTML | Yes |
Internet Explorer Driver | Lower-cased | As they appear in the HTML | No |
Firefox Driver | Case insensitive | As they appear in the HTML | Yes |
This is a little abstract, so for the following piece of HTML:
<input type="text" name="example" /> <INPUT type="text" name="other" />
List<WebElement> inputs = driver.findElements(By.xpath("//input"));
The following number of matches will be found
XPath expression | HtmlUnit Driver | Firefox Driver | Internet Explorer Driver |
---|---|---|---|
//input | 1 (“example”) | 2 | 2 |
//INPUT | 0 | 2 | 0 |
어떤 HTML element들은 attribute에 대해 디폴트값을 사용한다면 명시적으로 정의할 필요가 없는것들도 있습니다. 예를 들어 input tag같은 경우 디폴트가 text 이기 때문에 이 경우 type attribute를 굳이 넣을 필요가 없습니다. 이 경우 WebDriver의 xpath를 사용한다면 원하는 결과가 안 나올 수도 있습니다.
Using JavaScript
element를 찾기 위해 자바스크립트를 실행할 수도 있습니다.
Simple example on a page that has jQuery loaded:
WebElement element = (WebElement) ((JavascriptExecutor)driver).executeScript("return $('.cheese')[0]");
Finding all the input elements to the every label on a page:
List<WebElement> labels = driver.findElements(By.tagName("label"));
List<WebElement> inputs = (List<WebElement>) ((JavascriptExecutor)driver).executeScript(
"var labels = arguments[0], inputs = []; for (var i=0; i < labels.length; i++){" +
"inputs.push(document.getElementById(labels[i].getAttribute('for'))); } return inputs;", labels);
User Input - Filling In Forms
textarea나 text field에 어떻게 text를 넣는지에 대해서는 이미 보았습니다. 그런데 다른 element들에는 어떻게 할까요. checkbox 같은 경우는 toggle을 할 수 있고 Opthion tag 같은 경우 click을 할 수 있습니다.
WebElement select = driver.findElement(By.tagName("select"));
List<WebElement> allOptions = select.findElements(By.tagName("option"));
for (WebElement option : allOptions) {
System.out.println(String.format("Value is: %s", option.getAttribute("value")));
option.click();
}
이렇게 하면 페이지 내의 첫번째 SELECT element를 찾을 겁니다. 그리고 각 OPTION들을 찾을 거구요. 그 다음에 그 옵션들을 출력할 겁니다. 그런데 이 방법은 그렇게 효율적인 방법이라고 할 수 없습니다. 이럴 경우는 아래와 같이 사용하시면 좀 더 유용하게 사용하실 겁니다.
Select select = new Select(driver.findElement(By.tagName("select")));
select.deselectAll();
select.selectByVisibleText("Edam");
이 경우 첫번째 SELECT의 모든 OPTION들의 선택을 해제하고 Edam이라는 OPTION만 선택할 겁니다.
form을 다 채워 넣으면 이 form 을 submit 해야 합니다. 이 일을 하려면 submit 버튼을 찾아서 이 버튼을 클릭하면 됩니다.
driver.findElement(By.id("submit")).click();
각 element들에 대해 WebDriver는 간편한 submit 메소드 기능을 제공합니다. form 인의 한 element에서 이것을 call 하면 WebDriver는 form이 감싸고 있는 부분을 DOM 에서 찾고 거기에 대해 submit 을 호출합니다. 이 element가 form 안에 있지 않다면 NoSuchElementException이 던져 집니다.
element.submit();
Moving Between Windows and Frames
어떤 웹 어플리케이션은 많은 프레임이나 윈도우들을 갖고 있습니다. WebDriver는 switchTo 메소드를 사용해서 이 프레임이나 윈도우를 이동할 수 있습니다.
driver.switchTo().window("windowName");
이렇게 하면 특정 윈도우 내에서만 작업하게 됩니다. 그런데 이 window의 이름은 어떻게 알까요? 자바스크립트나 이것을 open 한 링크를 보세요.
<a href="somewhere.html" target="windowName">Click here to open a new window</a>
또한 “switchTo().window()” method에 window handle을 전달 할 수도 있습니다. 이 작업은 아래처럼 모든 윈도우에 적용할 수도 있습니다.
for (String handle : driver.getWindowHandles()) {
driver.switchTo().window(handle);
}
frame간에도 이동할 수 있는데요. (iframe도 포함)
driver.switchTo().frame("frameName");
dot(.)으로 구분해서 하위 프레임에 접근할 수도 있습니다. 물론 index를 사용해서 해당 프레임에 접근할 수도 있구요.
driver.switchTo().frame("frameName.0.child");
이렇게 하면 “frameName” 이라는 프레임의 첫번째 하위 프레임 내의 child라는 프레임으로 접근할 겁니다. All frames are evaluated as if from *top*.
Popup Dialogs
Selenium 2.0 beta 1 부터 popup dialog box를 지원하기 시작했습니다. popup을 뛰우면 아래와 같이 alert()을 사용해서 이 팝업에 접근할 수 있습니다.
Alert alert = driver.switchTo().alert();
이렇게 하면 현재 open 된 alert 객체를 return 합니다. 이 객체를 가지고 accept, dismiss 나 해당 contents를 읽고 prompt에 type 하는 작업등을 할 수 있습니다. 이 인터페이스는 alerts, confirms, prompts 에 모두 똑같이 사용됩니다. Refer to the JavaDocs
or RubyDocs for more information.
Navigation: History and Location
이전에 get() 메소드를 사용해서 페이지를 navigating 해 봤었습니다. ( driver.get("http://www.example.com")). to() 메소드를 사용할 수도 있습니다.
driver.navigate().to("http://www.example.com");
navigate().to() 와 get()은 같은 일을 합니다.
이 navigate 인터페이스는 backward와 forward도 지원합니다.
driver.navigate().forward();
driver.navigate().back();
Cookies
이제 쿠키를 어떻게 사용하는지에 대해서도 살펴 보겠습니다. 우선 쿠키가 사용될 도메인에 있어야 합니다.
// Go to the correct domain
driver.get("http://www.example.com");
// Now set the cookie. This one's valid for the entire domain
Cookie cookie = new Cookie("key", "value");
driver.manage().addCookie(cookie);
// And now output all the available cookies for the current URL
Set<Cookie> allCookies = driver.manage().getCookies();
for (Cookie loadedCookie : allCookies) {
System.out.println(String.format("%s -> %s", loadedCookie.getName(), loadedCookie.getValue()));
}
// You can delete cookies in 3 ways
// By name
driver.manage().deleteCookieNamed("CookieName");
// By Cookie
driver.manage().deleteCookie(loadedCookie);
// Or all of them
driver.manage().deleteAllCookies();
Changing the User Agent
파이어폭스에서는 이 User Agent를 바꾸는 작업이 쉽습니다.
FirefoxProfile profile = new FirefoxProfile();
profile.addAdditionalPreference("general.useragent.override", "some UA string");
WebDriver driver = new FirefoxDriver(profile);
Drag And Drop
아래에 drag and drop을 시행할 수 있는 Actions 클래스에 대한 에제가 있습니다.
WebElement element = driver.findElement(By.name("source"));
WebElement target = driver.findElement(By.name("target"));
(new Actions(driver)).dragAndDrop(element, target).perform();
'TDD Project > Selenium Web Driver' 카테고리의 다른 글
Page Objects in Selenium 2 (Web Driver) (0) | 2013.10.24 |
---|---|
Selenium 2/WebDriver Quick Tips: Page Object Navigation Strategies (0) | 2013.10.21 |
Selenium WebDriver - PageFactory (0) | 2013.10.20 |
Selenium WebDriver - PageObjects (0) | 2013.10.20 |
Selenium WebDriver Tutorial 03 (0) | 2013.10.19 |
Selenium WebDriver 와 TestNG 함께 사용하기 (1) | 2013.10.18 |
Selenium WebDriver Tutorial 01 (0) | 2013.10.17 |
Selenium WebDriver - WebElement 다루기 (0) | 2013.10.16 |
Selenium WebDriver - Maven 관련 (0) | 2013.10.15 |
Selenium WebDriver 관련 메모 - 설치 및 브라우저별 WebDriver 세팅 하기 (0) | 2013.10.15 |