지난 글에서 다룬 GoogleSearch 클래스를 Page Object 를 사용해서 만드는 방법을 알아보겠습니다.
이렇게 Page Object를 사용하는 방법으로 사용하려면 그 기능별로 여러 클래스를 만들어야 합니다.
지난 GoogleSearch 클래스는 한개의 클래스에서 모든 작업이 이루어 졌기 때문에 한개의 JAVA 파일만 보면 됐습니다.
그런데 Page Object를 사용하는 버전에서는 여러개의 클래스 즉 여러개의 JAVA 파일을 봐야합니다.
우선 Page Object 를 사용하는 GoogleSearch 에는 어떤 클래스들이 있는지 알아보겠습니다.
우선 처음에 볼 부분은 GoogleSearch_withPageObject.java 입니다.
/**
* Google search demo class. This class shows how to use page objects.
* Compare with "GoogleSearch.java" class, and see how to use page objects.
*
* @author Chon Chung
*
*/
public class GoogleSearch_withPageObject {
public static void main(String[] args) {
GoogleSearch.testGoogleSearch();
try{
GoogleSearch.testGoogleSuggest();
}catch(Exception e){
System.out.println("Unable to perform testGoogleSuggest() - " +
e.getMessage());
}
}
public static void testGoogleSearch(){
//Create a new instance of GoogleSearch page
GoogleSearchPage googleSearchPage = new GoogleSearchPage(new HtmlUnitDriver());
// go to Google ("http://www.google.com")
googleSearchPage.open();
// Enter something to search for
googleSearchPage.enterSearchForm("Cheese!");
// Now submit the form, and get the next page object
GoogleSearchResultPage googleSearchResultPage = googleSearchPage.submitForm();
// Verify: Check the title of the page
String pageTitle = googleSearchResultPage.getTitle();
System.out.println("Page title is: " + pageTitle);
assertTrue("Got title: " + pageTitle, pageTitle.contains("Cheese!"));
}
public static void testGoogleSuggest() throws Exception {
GoogleSearchSuggestPage googleSuggestPage = new GoogleSearchSuggestPage(new FirefoxDriver());
// Go to the Google Suggest home page: "http://www.google.com/webhp?complete=1&hl=en"
googleSuggestPage.open();
// Enter the query string "Cheese", and get the list the suggestions
List<WebElement> allSuggestions = googleSuggestPage.getSearchSuggestions("Cheese");
for (WebElement suggestion : allSuggestions) {
System.out.println(suggestion.getText());
}
}
}
/**
* Further reading:
* 1. Selenium webdriver page object:
* http://stackoverflow.com/questions/10315894/selenium-webdriver-page-object
* 2. Using Page Objects with Selenium and Web Driver 2.0
* http://www.summa-tech.com/blog/2011/10/10/using-page-objects-with-selenium-and-web-driver-20/
* 3. PageFactory
* http://code.google.com/p/selenium/wiki/PageFactory
* 4. Ben Burton's WebDriver Best Practices
* Video -- http://vimeo.com/44133409
* http://benburton.github.com/presentations/webdriver-best-practices/
*
*/
main() 메소드는 이전의 GoogleSearch 클래스와 똑 같습니다.
testGoogleSearch() 메소드를 보면 GoogleSearch 에서는 먼저 WebDriver 객체를 만들고 그 객체를 사용해서 구글 페이지를 열었는데요.
이번에는 GoogleSearchPage 의 객체를 생성해서 사용합니다.
이 얘기는 GoogleSearchPage라는 클래스가 따로 있고 이 곳에서 WebDriver를 초기화 하는 작업을 한다는 얘기 입니다.
그러면 GoogleSearchPage.java를 볼까요?
/**
* Google Search Page Object.
* @author Chon Chung
*/
public class GoogleSearchPage extends PageBase{
private final static String pageTitle = "Google";
private final static String SEARCH_FIELD_NAME = "q";
/** Constructor */
public GoogleSearchPage(WebDriver driver){
super(driver, pageTitle);
// set the default URL
URL = "http://www.google.com";
}
/** Returns the default URL */
public String getURL(){
return URL;
}
/** Enter the Search Text in the Search form field */
public void enterSearchForm(String searchText){
driver.findElement(By.name(SEARCH_FIELD_NAME)).sendKeys(searchText);
}
/** Submit the form and return the next page object.
* Seperate function should be in a seperate method. */
public GoogleSearchResultPage submitForm(){
driver.findElement(By.name(SEARCH_FIELD_NAME)).submit();
return new GoogleSearchResultPage(driver);
}
}
GoogleSearchPage()라는 생성자가 있죠? 여기에서 super 메소드를 사용합니다.
이 얘기는 이 클래스는 어떤 다른 클래스를 상속 받았다는 얘기입니다.
좀 위에 보니까 PageBase 클래스를 상속 받았네요.
소스 분석은 나중에 하고 오늘은 어떤 클래스들이 Page Object를 위해 사용됐는지 보기로 했으니까 다른 메소드들을 분석하는 것은 다음 글에서 하겠습니다.
그럼 PageBase 클래스를 보죠.
/**
* Page Object base class. It provides the base structure
* and properties for a page object to extend.
*
* @author Chon Chung
*/
public class PageBase {
/** Default URL */
protected String URL;
/** This page's WebDriver */
protected WebDriver driver;
/** Expected Page Title. This will be used in isPageLoad()
* to check if page is loaded. */
protected String pageTitle;
/** Constructor */
public PageBase(WebDriver driver, String pageTitle) {
this.driver = driver;
this.pageTitle = pageTitle;
}
/**
* Check if page is loaded by comparing
* the expected page-title with an actual page-title.
**/
public boolean isPageLoad(){
return (driver.getTitle().contains(pageTitle));
}
/** Open the default page */
public void open(){
driver.get(URL);
}
/** Returns the page title */
public String getTitle() {
return pageTitle;
}
/** Returns the default URL */
public String getURL() {
return URL;
}
/**
* Send text keys to the element that finds by cssSelector.
* It shortens "driver.findElement(By.cssSelector()).sendKeys()".
* @param cssSelector
* @param text
*/
protected void sendText(String cssSelector, String text) {
driver.findElement(By.cssSelector(cssSelector)).sendKeys(text);
}
/** Is the text present in page. */
public boolean isTextPresent(String text){
return driver.getPageSource().contains(text);
}
/** Is the Element in page. */
public boolean isElementPresent(By by) {
try {
driver.findElement(by);//if it does not find the element throw NoSuchElementException, thus returns false.
return true;
} catch (NoSuchElementException e) {
return false;
}
}
/**
* Is the Element present in the DOM.
*
* @param _cssSelector element locater
* @return WebElement
*/
public boolean isElementPresent(String _cssSelector){
try {
driver.findElement(By.cssSelector(_cssSelector));
return true;
} catch (NoSuchElementException e) {
return false;
}
}
/**
* Checks if the elment is in the DOM and displayed.
*
* @param by - selector to find the element
* @return true or false
*/
public boolean isElementPresentAndDisplay(By by) {
try {
return driver.findElement(by).isDisplayed();
} catch (NoSuchElementException e) {
return false;
}
}
/**
* Returns the first WebElement using the given method.
* It shortens "driver.findElement(By)".
* @param by element locater.
* @return the first WebElement
*/
public WebElement getWebElement(By by){
return driver.findElement(by);
}
}
/**
* Further reading:
* 1. Selenium webdriver page object:
* http://stackoverflow.com/questions/10315894/selenium-webdriver-page-object
* 2. Using Page Objects with Selenium and Web Driver 2.0
* http://www.summa-tech.com/blog/2011/10/10/using-page-objects-with-selenium-and-web-driver-20/
* 3. PageFactory
* http://code.google.com/p/selenium/wiki/PageFactory
*/
PageBase() 생성자를 보시면 WebDriver와 pageTitle을 세팅합니다.
이렇게 3개의 클래스만 사용되나요?
아까 봤던 GoogleSearch_withPageObject 클래스의 testGoogleSearch() 메소드를 다시 보겠습니다.
좀 아래로 내려가니까 GoogleSearchResultPage 객체를 만드는 부분이 있습니다.
이 클래스도 따로 있는 것 같습니다.
/**
* Google Search Result Page Object.
* @author Chon Chung
*
*/
public class GoogleSearchResultPage extends PageBase{
private static final String resultStats_id = "resultStats";
private final static String pageTitle = "Google Search";
public GoogleSearchResultPage(WebDriver driver){
super(driver, pageTitle);
}
/** Returns the search ResultStat. */
public String getSearchResultStat(){
return driver.findElement(By.id(resultStats_id)).getText();
}
}
여기서도 PageBase 클래스를 상속하네요.
이 PageBase 클래스는 저 위에 있으니까 다시 볼 필요는 없습니다.
그러면 testGoogleSearch() 메소드는 다 봤고 이어서 testGoogleSuggest() 메소드를 보겠습니다.
여기에서는 GoogleSearchSuggestPage 클래스에 대한 객체를 생성하네요.
이 GoogleSearchSuggestPage.java 파일도 사용됐습니다.
public class GoogleSearchSuggestPage extends PageBase{
private final static String pageTitle = "Google";
private final static String SEARCH_FIELD_NAME = "q";
/** Constructor */
public GoogleSearchSuggestPage(WebDriver driver){
super(driver, pageTitle);
// set the default URL
URL = "http://www.google.com/webhp?complete=1&hl=en";
}
/** Enter the Search Text in the Search form field */
public void enterSearchForm(String searchText){
driver.findElement(By.name(SEARCH_FIELD_NAME)).sendKeys(searchText);
}
/** Submit the form and return the next page object.
* Seperate function should be in a seperate method. */
public GoogleSearchResultPage submitForm(){
driver.findElement(By.name(SEARCH_FIELD_NAME)).submit();
return new GoogleSearchResultPage(driver);
}
/**
* Enter the query string, and get the list of the suggestions
* It use WaitTool to wait for the div (class=gsq_a).
*
* @param searchText the query string to search for
* @return the list of the google search suggestions
*/
public List<WebElement> getSearchSuggestions(String searchText){
// Enter the query string "Cheese"
driver.findElement(By.name(SEARCH_FIELD_NAME)).sendKeys(searchText);
// Wait and get the list of suggestions
List<WebElement> allSuggestions = WaitTool.waitForListElementsPresent(driver, By.className("gsq_a"), 5);
return allSuggestions;
}
}
여기서도 PageBase 클래스가 상속됐습니다. 다시 볼 필요는 없겠죠.
그 다음에 이 파일 안에서 다른 custom 클래스에 대한 객체를 만드는 부분은 없습니다.
다시 GoogleSearch_withPageObject 클래스로 돌아가죠.
testGoogleSuggest() 메소드를 보니까 다른 custom 클래스에 대한 객체를 생성하는 부분은 없습니다.
그러면 지금까지 살펴본 클래스들이 GoogleSearch.java 를 Page Object를 사용하는 버전으로 바꿨을 때 만든 클래스들 입니다.
PageBase.java
GoogleSearchPage.java
GoogleSearchResultPage.java
GoogleSearchSuggestPage.java
GoogleSearch_withPageObject.java
총 이렇게 5개의 파일이 사용됐습니다.
지난번 GoogleSearch.java에서는 단 한개의 파일만 사용했는데 똑 같은 일을 하는 Page Object를 만들기 위해 이렇게 파일을 5개로 쪼개서 기능을 부여 했네요.
다음 글에서는 각 클래스별로 어떤 일을 하고 전체적으로 어떻게 연관을 맺고 실행이 되는지를 알아보겠습니다.
'TDD Project > Selenium Web Driver' 카테고리의 다른 글
Selenium WebDriver CSS Selector Tip - List<WebElement> (0) | 2013.12.04 |
---|---|
Selenium WebDriver 에서 JavascriptExecutor 사용할 때 유념해야 될 상황 (0) | 2013.12.02 |
Page Objects in Selenium 2 (Web Driver) 소스 분석 (with Page Objects) 04 (0) | 2013.10.30 |
Page Objects in Selenium 2 (Web Driver) 소스 분석 (with Page Objects) 03 (0) | 2013.10.27 |
Page Objects in Selenium 2 (Web Driver) 소스 분석 (with Page Objects) 02 (0) | 2013.10.25 |
Page Objects in Selenium 2 (Web Driver) 소스 분석 (without Page Objects) (0) | 2013.10.25 |
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 |