반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

지난 글 'Page Objects in Selenium 2 (Web Driver)' 맨 마지막에 아래와 같이 샘플 소스 코드들이 있었습니다.


이 샘플 코드들을 한번 분석해 보겠습니다.


* Here are the source codes


Project Home: https://github.com/ChonC/wtbox
wiki: https://github.com/ChonC/wtbox/wiki
PageBase source code
Page Objects test example


샘플을 보면 구글 페이지에서 검색하는 기능을 Selenium으로 테스트하는 소스들이 있습니다.


Page Objects를 사용하지 않은 버전과 Page Objects를 사용한 버전이 있습니다.


우선 Page Objects를 사용하지 않은 버전을 보겠습니다.



/**
* Testing Google search. This class does not use Page Object pattern.
* Compare it with “GoogleSearch_withPageObject.java” class, which uses Page Object pattern.
*
* This example is from
* "The 5 Minute Getting Started Guide
* (http://code.google.com/p/selenium/wiki/GettingStarted)."
*
*/
public class GoogleSearch {

         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 the html unit driver
         WebDriver driver = new HtmlUnitDriver();

         // And now use this to visit Google
         driver.get("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();
       
         //*** return the next page object

         // Check the title of the page
         String pageTitle = driver.getTitle();
         System.out.println("Page title is: " + pageTitle);
         assertTrue("Got title: " + pageTitle, pageTitle.contains("Cheese!"));
         }
       
         public static void testGoogleSuggest() throws Exception {
                       
         // The Firefox driver supports javascript
         WebDriver driver = new FirefoxDriver();
       
         // Go to the Google Suggest home page
         driver.get("http://www.google.com/webhp?complete=1&hl=en");
       
         // Enter the query string "Cheese"
         WebElement query = driver.findElement(By.name("q"));
         query.sendKeys("Cheese");

         // Sleep until the div we want is visible or 5 seconds is over
         long end = System.currentTimeMillis() + 5000;
         while (System.currentTimeMillis() < end) {
         WebElement resultsDiv = driver.findElement(By.className("gsq_a"));

         // If results have been returned, the results are displayed in a drop down.
         if (resultsDiv.isDisplayed()) {
         break;
         }
         }

         // And now list the suggestions
         List<WebElement> allSuggestions = driver.findElements(By.className("gsq_a"));
       
         for (WebElement suggestion : allSuggestions) {
         System.out.println(suggestion.getText());
         }
         }
}


/**
* References:
* 1. http://stackoverflow.com/questions/10315894/selenium-webdriver-page-object
*/

맨 먼저 main() 메소드를 봐야 합니다.


가장 먼저 하는 일은 GoogleSearch에 있는 testGoogleSearch() 메소드를 호출하는 겁니다.

GoogleSearch는 이 클래스 이름이니까 이 클래스 내에 있는 testGoogleSearch() 메소드를 가장 먼저 시작하는 겁니다.


testGoogleSearch() 메소드를 보죠.


먼저 WebDriver로 HtmlUnitDreiver() 를 초기화를 하고 get() 메소드를 사용해서 http://www.google.com 으로 갑니다.

그리고 name 이 q 인 element를 찾아서 element 라는 WebElement 객체를 만들구요. 

이 element 객체에 Cheese!라고 입력을 합니다.

그리고 이 form 에 대한 submit() 을 실행합니다.


그러면 Cheese!로 검색한 페이지로 가게 되겠죠.

이 페이지의 title을 pageTitle이라는 String 객체에 담습니다.


그리고 이 pageTitle을 콘솔에 출력합니다.


그러면 콘솔에 아래와 같이 출력 됩니다.




출력하고 난 다음에는 assertTrue라는 jUnit 메소드를 사용해서 해당 페이지에 Cheese!라는 글자가 포함돼 있는지 테스트 합니다.


여기까지 하면 한가지 테스트가 완료 됐네요.


다시 main()메소드를 보면 그 다음에 testGoogleSuggest() 라는 메소드를 또 호출하는 것을 볼 수 있습니다.


이제 이 메소드가 실행될 텐데요. 한번 보겠습니다.


여기서는 WebDriver 에 FirefoxDriver() 를 세팅합니다.

여기까지 실행하면 Firefox가 오픈됩니다. (화면은 비어있구요.)

get() 메소드를 사용해서 http://www.google.com/webhp?complete=1&hl=en 로 이동합니다.



그리고 name이 q 인 Element를 찾아서 query라는 객체에 이 WebElement를 담습니다.

그리고 이 query 에 Cheese 를 입력합니다.


그러면 여기까지 진행이 됩니다.


그 다음에는 현재 시간 + 5초를 해서 end 라는 long 객체에 담네요.

그리고 while 문을 사용해서 이 5초동안 기다리게 하고 나서 className이 gsq_a 인 WebElement를 resultsDiv라는 객체에 담습니다.


이건 아마 원격으로 처리되다 보면 Ajax call 로 Auto Complete 기능을 실행하는데 시간이 걸리니까 이렇게 했나 봅니다.

이 while 문 안쪽을 보니까 resultsDiv 가 display 되면은 더이상 while 문을 돌지 않고 빠져 나가도록 break를 했네요.


그 다음을 보면 다시 className이 gsq_a 인 Element들을 List 객체인 allSuggestions 에 담습니다.

위 페이지를 Firebugs로 보면은 Auto complete으로 나온 cheesecake factory, cheesecake factory san diego, cheesecake recipe, cheese 이런 것들이 gsq_a 라는 클래스에 속해 있는걸 보실 수 있을 겁니다.




다음에는 이 allSuggestions List 객체에 대해서 for 문을 돌려서 콘솔에 출력하네요.



그러면 아래와 같이 Auto Complete 에 있었던 Suggestion들이 콘솔에 출력 됩니다.


여기까지가 GoogleSearch 클래스가 하는 일 입니다.


샘플 소스를 보면은 이 작업을 Page Objects를 사용해서 만든 샘플도 있습니다.

이름이 GoogleSearch_withPageObject 라는 클래스인데요.

위 GoogleSearch 클래스를 Page Object를 사용해서 어떻게 만드는지 잘 보여주고 있습니다.


이 클래스는 다음 글에서 정리 하겠습니다.


반응형


반응형

Selenium 2 Web Driver 의 Page Objects 에 대해 잘 정리하고 좋은 소스코드도 있는 곳을 찾아서 그 내용을 정리해 둡니다.


Page Objects in Selenium 2 (WebDriver)





참조



This project is inspired by:
Ben Burton's WebDriver Best Practices
Dave Justin’s page object post
James Cox's Using Page Objects



* Why Page Objects pattern?


반복되는 코드를 줄이기 위해.
single page object로 페이지의 internal state를 캡슐화 하기 위해
UI 의 변화는 실제 테스트 코드가 아닌 오직 single page object에만 영향을 미친다.
Code re-use : 여러 테스트 케이스에서 같은 page object를 사용할 수 있도록 한다.



* Step 1 : Page Object base class


Page Base 클래스는 extend 하기 위해 base structure와 page object의 property들을 제공한다.




* Step 2 : Extends PageBase






* Step 3 : Navigation from Page to Page


1. 사용자가 새로운 URL을 브라우저의 URL 바에 입력하는 것을 시뮬레이팅 할 때, 필요한 page object를 생성하는 것은 test case가 해야할 일 입니다.





2. 페이지에서 어떤 일은 브라우저에서 다른 페이지로 넘어가도록 만듭니다. 예를 들어 링크를 클릭하거나 form 을 submit 하는 경우가 있겠죠. 이럴 경우 다음 page object를 return 하는 것은 page object가 해야할 일입니다.


* Step 4 : Tests with Page Objects




* Here are the source codes


Project Home: https://github.com/ChonC/wtbox
wiki: https://github.com/ChonC/wtbox/wiki
PageBase source code
Page Objects test example

Thank you!

Chon Chung - @chon_chung


반응형


반응형

Selenium 2/WebDriver Quick Tips: Page Object Navigation Strategies
   
   


automated web testing (테스트 자동화) 에서 Page Object는 애플리케이션의 웹 페이지를 나타내는 클래스 혹은 객체를 말합니다. Page Object는 개발자가 웹페이지와 상호작용하는 기술적이고 상세한 내용들을 따로 떼어내서 다루기 때문에 좀 더 가독성 있고 실제 구현해야 할 비지니스에 집중할 수 있는 개발환경을 제공합니다.
  

두가지 장점으로 정리하자면 아래와 같습니다.

    * 가독성 높은 테스트 코드
    * 한 장소에 page access logic을 따로 만들어서 사용해 유지보수에도 훨씬 유리하다.



이 Page Object를 사용하지 않을 경우의 테스트는 아래와 같습니다.


    @Test
    public void shouldBeAbleToSearchForCats() {

        driver.get("http://www.trademe.co.nz");
        driver.findElement(By.id("searchString"))
                 .sendKeys("cats");
        driver.findElement(
                  By.cssSelector("button[value='Search']"))
                  .click();

        assertThat(driver.getTitle())
                         .contains("cats for sale");
        List titleElements
           = driver.findElements(
                        By.cssSelector(".listingTitle"));
        List adTitles = Lists.newArrayList();
        for(WebElement titleElement : titleElements) {
            adTitles.add(titleElement.getText());
        }

        assertThat(adTitles).isNotEmpty();
        for(String title : adTitles) {
            assertThat(title)
                 .containsIgnoringCase("cats");
        }
    }


이것을 Page Object를 사용해서 만들면 아래처럼 만들 수 있습니다.
   


    SearchPage searchPage;
    ResultsPage resultsPage;
           
    @Test
    public void shouldBeAbleToSearchForCats() {
        searchPage.open();
        searchPage.searchFor("cats");
        resultsPage.shouldDisplayTitlesWith("cats");
    }



이 경우 SearchPage 클래스는 아래와 같이 Thucydides 를 사용할 겁니다.



@DefaultUrl("http://www.trademe.co.nz")
public class SearchPage extends PageObject {

    @FindBy(id = "searchString")
    WebElement searchField;

    @FindBy(css = "button[value='Search']")
    WebElement searchButton;

    @FindBy(id = "main-box-categories")
    WebElement categoriesList;

    public SearchPage(WebDriver driver) {
        super(driver);
    }

    public void searchFor(String searchTerms) {
        searchField.sendKeys(searchTerms);
        searchButton.click();
    }

    public void selectsCategory(String category) {
        categoriesList.findElement(
            By.linkText(category)).click();
    }
}


Page Object를 가지고 navigation을 해야 될 때 사용되는 일반적인 방법은 새로운 페이지로 navigate 하고 이 page에 대한 Page Object를 return 하는 메소드를 만드는 것입니다. 예를 들어 serchFor 메소드 리스트는 아래와 같이 작성되어야 할 겁니다.


   

public void searchFor(String searchTerms) {
        searchField.sendKeys(searchTerms);
        searchButton.click();
        return switchTo(ResultsPage.class);
    }



만약 operation이 새로운 페이지로 navigate 하지 않는다면 이 Page Object 는 간단히 자기 자신을 return 하면 됩니다.


   

public SearchPage selectsCategory(String category) {
        categoriesList.findElement(
            By.linkText(category)).click();
        return this;
    }



이 접근법은 두가지 장점이 있습니다. 첫번째로 테스트의 가독성이 좀 더 편하게 됩니다.


   

SearchPage searchPage;
    ResultsPage resultsPage;
           
    @Test
    public void shouldBeAbleToSearchForCats() {
        searchPage.open();
        searchPage.searchFor("cats")
                  .selectsCategory("Pets & Animals")
                  .shouldDisplayTitlesWith("cats");
    }



또한 이 Page Objects 의 내용을 잘 몰라도 그냥 이것을 extend 해서 사용하면 됩니다. IDE 가 각 action 이후에 어떤 operation이 가능한지 그 리스트를 보여줄 겁니다.



이 접근법은 page navigation이 분명하게 정의되고 변화없이 안정적인 어플리케이션의 경우 아주 유용하게 사용될 수 있습니다. 어떤 어플리케이션들에서는 navigation이 분명하지 않은 경우가 있습니다. non-trivial navigation logic 에 따라 여러 다른 screen으로 이동하거나 (GWT 같은 AJAX-heavy 프레임워크를 사용하는 어플리케이션의 경우)가 그렇습니다.
위의 경우 return 된 Page Object를 사용해서 navigating 하는 방법은 효율적입니다. 테스트 코드에 page navigation 에 대한 내장된 로직을 넣게 되니까요. 만약에 이 로직이 non-trivial 이라면 이렇게 코딩을 하면 나중에 유지보수상의 문제가 생길겁니다. 그러면 Page Object 로부터 얻는 잇점 대신 그로인해 생기는 단점이 더 클 수도 있습니다.

반응형

Selenium WebDriver - PageFactory

2013. 10. 20. 18:14 | Posted by 솔웅


반응형

The PageFactory



PageObject 패턴을 지원하기 위해 Webdriver가 지원하는 라이브러리에는 factory 클래스가 포함돼 있습니다.



A Simple Example


PageFactory를 사용하기 위해 우선 WebElements나 List<WebElement>인 PageObject의 필드들을 정의해야 합니다.


예제를 보겠습니다.




package org.openqa.selenium.example;

import org.openqa.selenium.WebElement;

public class GoogleSearchPage {
    // Here's the element
    private WebElement q;

    public void searchFor(String text) {
        // And here we use it. Note that it looks like we've
        // not properly instantiated it yet....
        q.sendKeys(text);
        q.submit();
    }
}

이 코드가 제대로 작동되도록 하려면 q field를 제대로 초기화 시켜줘야 합니다.
여기서 우리는 PageObject를 초기화 해 줄 필요가 있습니다.

package org.openqa.selenium.example;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.support.PageFactory;

public class UsingGoogleSearchPage {
    public static void main(String[] args) {
        // Create a new instance of a driver
        WebDriver driver = new HtmlUnitDriver();

        // Navigate to the right place
        driver.get("http://www.google.com/");

        // Create a new instance of the search page class
        // and initialise any WebElement fields in it.
        GoogleSearchPage page = PageFactory.initElements(driver, GoogleSearchPage.class);

        // And now do the search.
        page.searchFor("Cheese");
    }
}


Explanation

The PageFactory relies on using sensible defaults: the name of the field in the Java class is assumed to be the "id" or "name" of the element on the HTML page. That is, in the example above, the line:


   q.sendKeys(text);



is equivalent to:


    driver.findElement(By.id("q")).sendKeys(text);



저기에서 사용된 driver 인스턴스는 PageFactory의 initElement 메소드에 전달된 그 인스턴스 입니다.


위 예제에서 우리는 PageFactory를 PageObject 인스턴스를 초기화 하는데 사용했습니다. 이렇게 함으로서 첫번째로 인수로 (public SomePage(WebDriver driver) {) WebDriver를 받는 생성자를 찾습니다. 만약에 그 생성자가 없으면 디폴트 생성자가 호출됩니다. 어떤 경우에는 PageObject는 WebDriver interface의 인스턴스말고도 다른것들을 필요로 합니다. 이미 생성된 객체의 element를 초기화하기 위해 PageFactory 가 사용 될 수도 있습니다.



ComplexPageObject page = new ComplexPageObject("expected title", driver);

// Note, we still need to pass in an instance of driver for the
// initialised elements to use
PageFactory.initElements(driver, page);



Making the Example Work Using Annotations



예제를 돌리면 PageFactory는 해당 페이지에서 이 클래스에 있는 WebElement의 필드 이름과 match 되는 element를 찾을 겁니다. 일단 ID 속성과 일치하는 element를 찾겠죠. 만약 찾지 못하면 PageFactory는 다시 뒤로 가서 그 name 속성의 value로 element를 찾을 겁니다.


이 코드가 작동 되더라도 Google 홈페이지의 소스코드를 잘 몰라서 field 의 이름이 q 라는 것을 모를겁니다. 다행히 우리는 annotation을 사용해서 이에 대해 알릴 수 있습니다..



package org.openqa.selenium.example;

import org.openqa.selenium.By;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.WebElement;

public class GoogleSearchPage {
    // The element is now looked up using the name attribute
    @FindBy(how = How.NAME, using = "q")
    private WebElement searchBox;

    public void searchFor(String text) {
        // We continue using the element just as before
        searchBox.sendKeys(text);
        searchBox.submit();
    }
}



한가지 걸리는 부분은 WebElement에 대해 메소드를 호출할 때마다 driver 가 현재 페이지에서 다시 그것을 찾을 거라는 겁니다. AJAX-heavy 어플리케이션에서 이것은 당연히 일어나는 일로 생각 될 수도 있습니다. 하지만 Google search 페이지에서는 그 element가 항상 거기에 있고 변하지 않을 거라는 것을 알고 있습니다. 그리고 우리는 해당 페이지이외의 페이지에서 작업하지 않을거라는 것도 알고 있구요. (같은 이름의 다른 element가 없을 거라는 것을 알고 있다는 얘기죠. 우리가 한번 찾아본 것은 그 element를 캐쉬에 넣어두면 더 유용할 겁니다.



package org.openqa.selenium.example;

import org.openqa.selenium.By;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.WebElement;

public class GoogleSearchPage {
    // The element is now looked up using the name attribute,
    // and we never look it up once it has been used the first time
    @FindBy(how = How.NAME, using = "q")
    @CacheLookup
    private WebElement searchBox;

    public void searchFor(String text) {
        // We continue using the element just as before
        searchBox.sendKeys(text);
        searchBox.submit();
    }
}


Reducing Verbosity



위의 예제는 아직도 좀 너무 복잡한거 같습니다. annotating을 약간 바꿔서 더 간단하게 만들겠습니다.



public class GoogleSearchPage {
  @FindBy(name = "q")
  private WebElement searchBox;

  // The rest of the class is unchanged.
}



Notes

    PageFactory를 사용하면 필드들이 초기화 됐다라고 가정하실 수 있습니다. 만약 PageFactory를 사용하지 않는다면 field들이 초기화 됐다고 가정하게 되면 NullPointerExceptions 가 발생할 겁니다.
    List<WebElement> 필드는 @FindBy 나 @FindBys annotation 이 있을 경우에 사용합니다. 디폴트 검색 strategy는 by id 나 by name 입니다. 한 페이지 내에 같은 아이디나 name을 가지는 엘리먼트들이 여러개 존재하는 경우는 드물기 때문에 WebElement 필드는 list로 사용하기 적합합니다.
    WebElements are evaluated lazily. 만약 PageObject에서 WebElement를 전혀 사용하지 않는다면 findElement를 호출하는 일은 없을 겁니다.
    The functionality works using dynamic proxies. 이 의미는 특정 subclass로서 WebElement를 기대해서는 안된다는 것입니다. 설사 여러분이 driver의 type을 알고 있더라도요. 예를 들어 HtmlUnitDriver를 사용하신다면 HtmlUnitWebElement의 인스턴스와 함께 WebElement 필드가 초기화 되기를 기대하시면 안 됩니다.

반응형

Selenium WebDriver - PageObjects

2013. 10. 20. 02:53 | Posted by 솔웅


반응형

PageObjects는 Selenium WebDriver 테스트에서 권장하는 디자인 패턴입니다.

반복되는 코드를 패턴화 해서 하나로 만들어 놓고 활용하는 방법입니다.

제가 충분히 이해를 못 했는지 원문이 해석하기 무척 힘드네요. 일단 Tutorial 을 한번 대강 해석해 놓고 나중에 소스를 좀 분석해 보겠습니다.


==================================

PageObjects 



Page Object 패턴은 객체들의 시리즈로서 여러분의 웹앱 화면들을 represent 합니다.


WebDriver



Updated Mar 31, 2013




Page Objects

웹앱 UI에서 어떤 테스트해야할 부분이 있습니다. Page Object는 이러한 테스트해야할 부분들을 테스트 코드내에서 한 객체로서 간단하게 다룹니다. 이것은 반복되는 코드를 줄이고 ,UI가 바뀌었을 때 한 부분만 고치면 되도록 만듭니다.


Implementation Notes

PageObject는 동시에 두가지 방향을 생각하게 할 수 있습니다. 우선 한 방향은 테스트를 하는 개발자에게 향하는 것입니다. 특정 페이지에 의해 제공되는 서비스가 됩니다. 두번째는 개발자로부터 나오는 방향입니다. HTML 페이지의 구조에 대한 깊은 이해가 있어야 합니다. Page Object는 페이지가 요구하는 그런 서비스의요구로서 생각됩니다. 예를 들어 웹베이스 이메일 시스템의 inbox를 생각해 봅시다. 여기서 제공하는 기능들은 편지를 쓰거나 어떤 이메일을 읽거나 inbox 내 이메일들의 리스트를 보여주는 겁니다. 이러한 것들이 테스트를 하는데 있어서 어떻게 implement 될까요.



우리는 개발자에게 implementation 하는것 보다 interaction 하는 그런 서비스들에 대해 좀 더 생각하도록 해야하기 때문에 PageObject는 WebDriver 인스턴스의 기본적인 부분들 같은 것들을 그렇게 드러내지 않습니다. 이것을 구현하기 위해 PageObject의 메소드들은 다른 PageObject를 return 해야 합니다. 이 의미는 우리 어플리케이션을 통해 유저의 사용경험들을 효과적으로 모델화 할 수 있다는 겁니다. It also means that should the way that pages relate to one another change (like when the login page asks the user to change their password the first time they log into a service, when it previously didn't do that) simply changing the appropriate method's signature will cause the tests to fail to compile. Put another way, we can tell which tests would fail without needing to run them when we change the relationship between pages and reflect this in the PageObjects.



이 접근법의 결과로는 성공적인 로그인과 성공적이지 않은 로그인 보두에 대한 모델링이 필요하다는 겁니다. 혹은 앱의 상황에 따라서 click 의 결과가 다르게 나올 수 있다는 것이구요. PageObject에 여러 메소드들을 갖는것은 일반적인 것입니다.



public class LoginPage {
    public HomePage loginAs(String username, String password) {
        // ... clever magic happens here
    }
   
    public LoginPage loginAsExpectingError(String username, String password) {
        //  ... failed login here, maybe because one or both of the username and password are wrong
    }
   
    public String getErrorMessage() {
        // So we can verify that the correct error is shown
    }
}



위의 코드를 보면 아주 중요한 부분이 있습니다. 이 테스트들은 PageObjects가 아닙니다. 페이지의 상태에 대한 assertion들을 만들어야 합니다. 예를 들어



public void testMessagesAreReadOrUnread() {
    Inbox inbox = new Inbox(driver);
    inbox.assertMessageWithSubjectIsUnread("I like cheese");
    inbox.assertMessageWithSubjectIsNotUnread("I'm not fond of tofu");
}



이 코드는 아래와 같이 재 작성해야 합니다.



public void testMessagesAreReadOrUnread() {
    Inbox inbox = new Inbox(driver);
    assertTrue(inbox.isMessageWithSubjectIsUnread("I like cheese"));
    assertFalse(inbox.isMessageWithSubjectIsUnread("I'm not fond of tofu"));
}




물론 모든 guideline에는 예외가 있습니다. 그중에 PageObjects에서 흔히 볼 수 있는 것이 우리가 PageObject를 초기화 할 때 맞는 페이지에서 WebDriver가 있는지에 대해 체크하는 것입니다. 이 작업은 아래 예제에서와 같이 처리하시면 됩니다.


마지막으로 PageObject는 모든 페이지를 represent 할 필요는 없습니다. PageObjects는 그 사이트나 페이지 내에서 여러번 반복되는 부분을 represent 하면 됩니다. 여기서 핵심은 특정 페이지의 HTML 구조에 대한 지식을 기반으로 여러분의 test suite 내에서 한 부분에서 이것을 만들어 두면 된다는 겁니다.


Summary

    The public methods represent the services that the page offers
    페이지에서 요구되는 서비스들을 represent 하는 public methods
    Try not to expose the internals of the page
    페이지의 내부적인 부분을 표현하려고 하지 않는다.
    Generally don't make assertions
    일반적으로 assertion들을 만들지 않는다.
    Methods return other PageObjects
    다른 PageObjects를 return 한다.
    Need not represent an entire page
    전체 페이지를 represent 할 필요는 없다.
    Different results for the same action are modelled as different methods
    같은 action에 대한 다른 결과들을 위해 다른 메소드들로 모델링 한다.




Example



public class LoginPage {
    private final WebDriver driver;

    public LoginPage(WebDriver driver) {
        this.driver = driver;

        // Check that we're on the right page.
        if (!"Login".equals(driver.getTitle())) {
            // Alternatively, we could navigate to the login page, perhaps logging out first
            throw new IllegalStateException("This is not the login page");
        }
    }

    // The login page contains several HTML elements that will be represented as WebElements.
    // The locators for these elements should only be defined once.
        By usernameLocator = By.id("username");
        By passwordLocator = By.id("passwd");
        By loginButtonLocator = By.id("login");

    // The login page allows the user to type their username into the username field
    public LoginPage typeUsername(String username) {
        // This is the only place that "knows" how to enter a username
        driver.findElement(usernameLocator).sendKeys(username);

        // Return the current page object as this action doesn't navigate to a page represented by another PageObject
        return this;   
    }

    // The login page allows the user to type their password into the password field
    public LoginPage typePassword(String password) {
        // This is the only place that "knows" how to enter a password
        driver.findElement(passwordLocator).sendKeys(password);

        // Return the current page object as this action doesn't navigate to a page represented by another PageObject
        return this;   
    }

    // The login page allows the user to submit the login form
    public HomePage submitLogin() {
        // This is the only place that submits the login form and expects the destination to be the home page.
        // A seperate method should be created for the instance of clicking login whilst expecting a login failure.
        driver.findElement(loginButtonLocator).submit();

        // Return a new page object representing the destination. Should the login page ever
        // go somewhere else (for example, a legal disclaimer) then changing the method signature
        // for this method will mean that all tests that rely on this behaviour won't compile.
        return new HomePage(driver);   
    }

    // The login page allows the user to submit the login form knowing that an invalid username and / or password were entered
    public LoginPage submitLoginExpectingFailure() {
        // This is the only place that submits the login form and expects the destination to be the login page due to login failure.
        driver.findElement(loginButtonLocator).submit();

        // Return a new page object representing the destination. Should the user ever be navigated to the home page after submiting a login with credentials
        // expected to fail login, the script will fail when it attempts to instantiate the LoginPage PageObject.
        return new LoginPage(driver);  
    }

    // Conceptually, the login page offers the user the service of being able to "log into"
    // the application using a user name and password.
    public HomePage loginAs(String username, String password) {
        // The PageObject methods that enter username, password & submit login have already defined and should not be repeated here.
        typeUsername(username);
        typePassword(password);
        return submitLogin();
    }
}


Support in WebDriver

이 패턴을 지원하는 패키지로 PageFactory 가 있습니다. 이것은 PageObjects에서 boiler-plate 코드를 동시에 remove 하는 것을 도와 줍니다.


=================================================


사실 이 글을 읽고는 무엇인지 확실히 이해를 잘 못하겠구요. 그나마 저 소스코드를 보니까 대강 알 수 있을 것 같습니다.


이 LoginPage 클래스에서는 우선 생성자에서 여기가 login 페이지가 맞는지 확인하고 해당 페이지가 아니면 예외를 발생 시키네요.

이 클래스는 로그인 페이지를 위한 클래스 입니다.


그리고 By type의 객체 세개를 만들었는데 각각 id로 유저명, 비밀번호 그리고 login 버튼을 찾는 객체들입니다.


첫번째 메소드는 typeUsername 인데요. 여기서는 LoginPage를 return 하네요.

PageObjects는 다른 PageObjects를 return 한다던데 이것을 말하나 봅니다.

그 안에는 by id 로 유저명을 찾아서 거기다가 전달 받은 파라미터를 type 해 넣습니다.


두번째 메소드인 typePassword도 똑 같습니다. 여기는 비밀번호를 쳐 넣는겁니다.


그 다음 메소드인 submitLogin 이 나오는데요. 

여기서는 HomePage를 return 하네요.

메소드 내에서는 login button을 클릭하는 일을 하구요.


id하고 비밀번호를 입력하고 login 버튼을 클릭하게 되겠죠.


그 다음 메소드는 이전 메소드와 완전히 똑 같습니다. 단지 이름이 submitLoginExpectingFailure() 인걸로 봐서 fail이 예상될 때 호출하는 메소드 인가 봅니다.


그 다음 loginAs() 메소드가 실제 실행할 때 호출하는 메소드인데요.

username과 password를 파라미터로 받아서 typeUsername()과 typePassword() 를 호출해서 아이디와 비밀번호를 타입하고 return submitLogin() 함으로서 로그인 버튼을 클릭하고 성공한 페이지를 return 하는 일을 합니다.

이렇게 하면 로그인 기능은 어디서든지 불러서 사용할 수 있겠네요.


그러면 이 부분에 대한 반복되는 코딩을 막을 수 있구요.


아이디, 비밀번호 이외에 다른 정보가 들어가는 걸로 바뀌거나 아이디에 대한 룰이 바뀌거나 하면 이 부분만 바꿔주면 되구요.


이 패턴을 지원하는 패키지가 PageFactory 라고 하니까 다음 글에서는 이걸 한번 배워봐야겠습니다.


반응형

Selenium WebDriver Tutorial 03

2013. 10. 19. 02:44 | Posted by 솔웅


반응형

이 글은 Selenium WebDriver 튜토리얼을 3번에 걸쳐 번역한 글 중 하나입니다.

원본은 여기에 있습니다.



Driver Specifics and Tradeoffs



Selenium-WebDriver’s Drivers



WebDriver는 작성되어야 할 테스트에 대한 key interface 이름입니다. 여기에는 몇개의 implementation들이 있습니다. 그것들을 살펴보겠습니다.



HtmlUnit Driver

이것이 현재 가장 빠르고 가장 가벼운 implemeatation 입니다. 이것은 HtmlUnit에 기초하고 있습니다. HtmlUnit은 GUI 가 없는 WebBrowser의 자바 베이스 implementation입니다. 자바 이외의 언어는 이 드라이버를 사용하기 위해 Selemium Server를 binding 해야 합니다.


Usage


WebDriver driver = new HtmlUnitDriver();


장점

    WebDriver를 가장 빨리 implementation 함
    pure Java solution으로 플랫폼 독립적이다.
    자바스크립트를 지원함


단점

    다른 브라우저의 자바스크립트 behaviour 를 Emulate 해야 한다.

   



JavaScript in the HtmlUnit Driver


주요 브라우저들은 HtmlUnit (Rhino)에 의해 사용되는 자바스크립트 엔진을 사용하지 않습니다. HtmlUnit을 사용하는 자바스크립트를 테스트 한다면 이 브라우저들에서는 그 결과가 다르게 나올 겁니다.


우리가 자바스크립트라고 말할 때 실제 이 의미는 자바스크립트와 DOM을 말하는 겁니다. DOM 이 W3C에 의해 정의 됐음에도 불구하고 각 브라우저들은 이 DOM의 implementation과 관련해서 자기들만의 방법을 사용하고 있습니다. 그래서 그에 따라 자바스크립트가 어떻게 작동하는지도 서로 다릅니다. HtmlUnit은 DOM을 implementation 하는 아주 확실한 방법입니다. 그리고 자바스크립트를 사용하기 위한 좋은 방법을 지원하고 있습니다. 하지만 다른 브라우저들도 그렇기는 합니다. W3C 표준과 여러 주요 브라우저들의 implementation들은 서로 다릅니다.


WebDriver와 관련해서 우리는 선택을 해야 합니다. HtmlUnit의 자바스크립트를 사용해서 팀원들이 실행할 때 생길 수 있는 위험성을 감수해야 할지 아니면 자바스크립트를 disable 해야 하는지요. 디폴트로는 HtmlUnit을 사용할 때 자바스크립트를 default로 함으로서 피해를 줄일수도 있겠죠. WebDriver와 HtmlUnit 모두를 release 하는데 있어 우리는 특정 부분에서 HtmlUnit의 디폴트로 자바스크립트를 enable 로 하기를 바랍니다.


Enabling JavaScript


그때까지 기다리기 힘드시면 자바스크립트를 enable 하도록 만드는것은 굉장히 쉽습니다.


HtmlUnitDriver driver = new HtmlUnitDriver(true);


이렇게 하면 HtmlUnit Driver에서 디폴트로 파이어폭스 3.6 버전의 자바스크립트를 emulate 합니다.



Firefox Driver

Firefox 플러그인을 사용해서 파이어폭스 브라우저를 사용할 수 있습니다. 사용되는 Firefox 프로파일은 Selenium WebDriver.xpi (플러그인)을 포함합니다. A few settings are also changed by default ((see the source to see which ones) ) Firefox Driver는 윈도우, 맥, 리눅스에서 실행하고 테스트할 수 있습니다.


Usage


WebDriver driver = new FirefoxDriver();


장점

    실제 브라우저에서 실행하고 자바스크립트를 지원함
    인터넷 익스플로러 Driver 보다 빠르다.

단점

    HtmlUnit Driver 보다 느리다.

   


Modifying the Firefox Profile


user agent string을 수정할 수도 있습니다. 그러려면 여러 유용한 extension들을 포함하고 있는 파이어폭스 프로파일을 trick out 해야 합니다. 이 프로파일을 obtain하는데는 두가지 방법이 있습니다. Firefox의 프로파일 매니저에 의해 프로파일이 생성됐다고 가정하고 아래 코드를 보겠습니다. (firefox -ProfileManager):


ProfilesIni allProfiles = new ProfilesIni();
FirefoxProfile profile = allProfiles.getProfile("WebDriver");
profile.setPreferences("foo.bar", 23);
WebDriver driver = new FirefoxDriver(profile);


프로파일이 Firefox로 register 되지 않았을 경우는 이렇게 합니다.


File profileDir = new File("path/to/top/level/of/profile");
FirefoxProfile profile = new FirefoxProfile(profileDir);
profile.addAdditionalPreferences(extraPrefs);
WebDriver driver = new FirefoxDriver(profile);


리눅스에서 Firefox에 native event들이 디폴트로 disable되어 있다면 다음과 같이 enable 되게 할 수 있습니다.


FirefoxProfile profile = new FirefoxProfile();
profile.setEnableNativeEvents(true);
WebDriver driver = new FirefoxDriver(profile);


Info


See the Firefox section in the wiki page for the most up to date info.


Internet Explorer Driver


이 driver는 .dll에 의해 콘트롤 됩니다. 이것은 Windows OS에서만 사용 가능합니다. Selenium 은 XP 의 버전 6,7,8 과 Windows7 상의 버전 9 에 맞게 만들었습니다.


Usage


WebDriver driver = new InternetExplorerDriver();


Pros

    실제 브라우저에서 실행되고 IE가 지원하는 자바스크립트를 지원한다.


Cons

    IE는 윈도우즈에서만 작동한다.
    비교적 느리다.
    대부분의 버전에서 native 하게 XPath를 지원하지 않는다. 다른 브라우저보다 느린 Sizzle이 자동적으로 inject 된다. 어떤 브라우저에서는 CSS selector와 비교할 때 더 느리다.
    버전 6,7에서는 CSS 가 native 적으로 지원하지 않는다. 대신 Sizzle이 inject 된다.
    IE 8,9에서 CSS selector는 native 이다. 하지만 그 브라우저에서는 CSS3를 완전히 지원하지 않는다.


Info

See the Internet Explorer section of the wiki page for the most up to date info. Please take special note of the Required Configuration section.



Chrome Driver


Chrome Driver는 Chromium project에 의해 유지되고 지원됩니다. WebDriver는 chromedriver binary를 통해서 Chrome과 함께 작동됩니다. (found on the chromium project’s download page). 이것을 사용하려면 chromedriver와 인스톨 된 chrome browser가 모두 있어야 합니다. chromedriver는 여러분 컴퓨터 내의 어딘가에 있어야 합니다. 그리고 그 경로를 세팅해서 WebDriver가 자동적으로 찾을 수 있도록 해야 합니다. Chrome browser는 chromedriver에 의해 인스톨된 경로를 자동으로 찾을 겁니다. 이런 것들은 환경변수로 overridden 할 수 있습니다. Please refer to the wiki for more information.


Usage


WebDriver driver = new ChromeDriver();



Pros

    실제 브라우저에서 동작되고 자바스크립트를 지원한다.
    Chrome이 Webkit-based 브라우저이기 때문에 Chrome Driver는 Safari에서 동작하는 것들에 대해서도 verify할 수 있습니다. Chrome은 V8 자바스크립트 엔진을 사용하고Safari는 Nitro 엔진을 사용합니다. 그러니까 JavaScript가 실행되는 것이 서로 다를 수도 있습니다.



Cons

    HtmlUnit Driver 보다 느리다.



Info


See our wiki for the most up to date info. More info can also be found on the downloads page



Getting running with Chrome Driver

Download the Chrome Driver executable and follow the other instructions on the wiki page



Opera Driver

See the Opera Driver wiki article in the Selenium Wiki for information on using the Opera Driver.

iPhone Driver

See the iPhone Driver wiki article in the Selenium Wiki for information on using the Mac iOS Driver.

Android Driver

See the Android Driver wiki article in the Selenium Wiki for information on using the Android Driver.




Alternative Back-Ends: Mixing WebDriver and RC Technologies



WebDriver-Backed Selenium-RC



자바버전의 WebDriver는 Selenium-RC API의 implementation을 제공합니다. 이 의미는 여러분이 Selenium-RC API에 있는 기능들을 WebDriver에서도 사용할 수 있다는 겁니다. 즉 이전 버전의 기능들도 모두 사용할 수 있다는 것이죠. 이미 Selenium-RC API를 사용한 테스트 suite들을 가지고 있는 분들이 WebDriver의 기능들을 사용해야 하는 분들에게 좋은 소식이죠. 이것을 Selenium-WebDriver로 migration을 쉽게 해 줍니다. 또한 두 API 모두를 한번에 사용할 수도 있습니다.


Selenium-WebDriver is used like this:


// You may use any WebDriver implementation. Firefox is used here as an example
WebDriver driver = new FirefoxDriver();

// A "base url", used by selenium to resolve relative URLs
 String baseUrl = "http://www.google.com";

// Create the Selenium implementation
Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl);

// Perform actions with selenium

selenium.open("http://www.google.com");
selenium.type("name=q", "cheese");
selenium.click("name=btnG");

// Get the underlying WebDriver implementation back. This will refer to the
// same WebDriver instance as the "driver" variable above.
WebDriver driverInstance = ((WebDriverBackedSelenium) selenium).getWrappedDriver();

//Finally, close the browser. Call stop on the WebDriverBackedSelenium instance
//instead of calling driver.quit(). Otherwise, the JVM will continue running after
//the browser has been closed.
selenium.stop();


Pros

    WebDriver와 Selenium API를 함께 사용할 수 있다.
    Selenium RC API에서 WebDriver API로 migration 하는 간단한 방법을 제공한다.
    실행하기 위해 Selenium RC server를 필요로 하지 않는다.


Cons

    Does not implement every method
    모든 메소드를 implement 하지는 않는다.
    좀 더 advanced 한 Selenium 사용기능이 제대로 작동하지 않는다. (using “browserbot” or other built-in JavaScript methods from Selenium Core)
    어떤 메소드는 서로 다른 implementation으로 인해 느려질 수 있다.


   
Backing WebDriver with Selenium


WebDriver는 Selenium RC 보다 적은 브라우저들을 지원합니다. 그래서 Selenium RC 버전을 WebDriver API 버전으로 사용하려면 SeleneseCommandExecutor를 사용할 수 있습니다.



Safari는 이와 같은 방법으로 지원되는데요. 다음과 같이 코딩하면 됩니다. (be sure to disable pop-up blocking):


DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setBrowserName("safari");
CommandExecutor executor = new SeleneseCommandExecutor(new URL("http://localhost:4444/"), new URL("http://www.google.com/"), capabilities);
WebDriver driver = new RemoteWebDriver(executor, capabilities);


이렇게 접근하는 방법에는 중요한 몇가지 제한이 있습니다. findElements가 원하는대로 작동 안될 수도 있습니다. 또한 Selenium Core를 사용하기 때문에 자바스크립트 sandbox도 제한이 있습니다.


Running Standalone Selenium Server for use with RemoteDrivers


Selenium’s Download page에서 download selenium-server-standalone-<version>.jar 를 다운받으시고 옵션으로 IEDriverServer도 다운 받습니다. Chrome을 사용하려면 Google Code에서 다운 받으세요.


IEDriverServer와 chromedriver를 unpack 하고 이것을 $PATH / %PATH% 에 넣으세요. 그러면 추가적인 수정없이 IE와 Chrome 을 사용하실 수 있습니다.


Start the server on the command line with


java -jar <path_to>/selenium-server-standalone-<version>.jar


If you want to use native events functionality, indicate this on the command line with the option


-Dwebdriver.enable.native.events=1


For other command line options, execute


java -jar <path_to>/selenium-server-standalone-<version>.jar -help


In order to function properly, the following ports should be allowed incoming TCP connections: 4444, 7054-5 (or twice as many ports as the number of concurrent instances you plan to run). Under Windows, you may need to unblock the applications as well.



Additional Resources


WebDriver에 대해 좀 더 많은 것을 아시려면 WebDriver’s wiki를 보세요.


그리고 인터넷에서 Selenium-WebDriver’s drivers를 포함해서 Selenium과 관련된 여러 정보를 찾아보세요. Selenium과 관련한 여러 블로그와 포럼들이 있을 겁니다. 참고로 Selenium 사용자 그룹에도 정보가 아주 많습니다. http://groups.google.com/group/selenium-users



Next Steps.


이글은 WebDriver를 high level로 간단히 훑어 본 겁니다. 일단 Selenium-WebDriver API에 익숙해 지면 그 다음에는 어떻게 test suite들을 만드는지에 대해 궁금하실 겁니다. 요즈음 Selenium 전문가들이 접근하는 방법은 Page Factory를 사용해서 Page Object Design Pattern을 사용해서 테스트 코드를 디자인 하는 겁니다. Selenium-WebDriver는 자바와 C#에서 PageFactory 를 지원합니다. 이것은 next chapter에서  advanced topic을 다루는 글에서 다뤄집니다. 이 기술과 관련한 high-level description에 대해서는 Test Design Considerations chapter에서 다뤄 집니다. 이 두 글들은 여러분의 테스트 코드를 좀 더 유지보수하기 쉽도록 작성하는 방법을 알려 줍니다.

반응형


반응형

Selenium WebDriver 와 TestNG 를 같이 사용하는 방법을 정리하겠습니다. 그리고 xml을 이용해서 parallel 하게 같은 테스트를 여러 브라우저에서 같이 테스트 하는 방법도 알아보구요.


우선 실제 Test를 하는 클래스부터 봅니다.


public class WebDriverTest extends SelTestCase {
    @Test
    public void testWiki() {
        driver.get("http://www.wikipedia.org/");
        driver.findElement(By.id("searchInput")).sendKeys("Selenium Software");
        driver.findElement(By.name("go")).click();
        driver.findElement(By.cssSelector(".mw-search-results li:nth-of-type(1) a")).click();
        Assert.assertTrue(
                driver.findElement(
                        By.cssSelector("img[src='//upload.wikimedia.org/wikipedia/en/5/5c/Seleniumlogo.png']")).
                        isDisplayed());
        Reporter.log("My test Passed");
    }
}


이 WebDriverTest는 SelTestCase를 extends 했습니다. 이 SelTestCase는 나중에 보고 이 소스부터 분석하겠습니다.

@Test 는 annotation 인데요. jUnit 이랑 똑같습니다. 그런데 여기서는 TestNG를 사용할 거니까 TestNG를 import 해야 합니다.


import org.testng.annotations.Test;


다음은 testWiki()라는 테스트 메소드를 만듭니다.

여기서는 wikipedia.org 페이지를 열고 id 가 searchInput 인 element를 찾아서 거기에 Selenium Software 를 입력합니다. 아마 이 element는 textfield나 textarea 일 겁니다.

그 다음엔 name 이 go 인 엘리먼트를 click 합니다.

그 다음엔 cssSelector를 사용하는데요. class 가 mw-search-results 인것을 찾고 그 안에 li 인 것 중에 가장 첫번째 li에 있는 a 링크를 찾아서 그 링크를 클릭합니다.

그 다음에 테스트 문이 들어가는데요. 링크를 클릭해서 나온 페이지에 해당 이미지가 있으면 테스트가 Success 될 것이고 이 이미지가 없으면 fail 될 겁니다.

그 다음에는 TestNG에서 자동으로 생성해 주는 Report 에 log가 찍히도록 해 줍니다.


그런데 여기서 driver라는 객체가 있는데 이 객체를 선언해 주는 부분이 없습니다.

이 driver 객체는 상속받은 SelTestCase 클래스에서 선언해 주었을 겁니다.


public class SelTestCase {
    WebDriver driver;
   
    @BeforeMethod()
    @Parameters("browser")
    public void launchBrowser(String browser) {
        String path = System.getProperty("user.dir"); // current path of project

        if(browser.equalsIgnoreCase("FF")){
            driver = new FirefoxDriver();
        }else if(browser.equalsIgnoreCase("Chrome")){
            System.setProperty("webdriver.chrome.driver",path + "\\chromedrive\\chromedriver.exe");
            driver = new ChromeDriver();
        }else if (browser.equalsIgnoreCase("IE")) {
            System.setProperty("webdriver.ie.driver",path + "\\iedrive\\IEDriverServer.exe");
            driver = new InternetExplorerDriver();
        }
    }
   
    @AfterMethod
    public void closeBrowser() {
        driver.close();
        driver.quit();
    }
}

이 SelTestCase 클래스에서는 맨 먼저 WebDriver 를 초기화 시킵니다. 여기서 초기화 


그 다음에 @BeforeMethod() annotation이 있는데요. 이것은 테스트 메소드가 실행되기 전에 실행하라는 의미 입니다.

그러니까 WebDriverTest 클래스에 있는 testWiki() 라는 테스트 메소드가 시작되기 전에 이 메소드가 시작 됩니다.


그 다음에 있는 annotation은 파라미터로서 browser를 받겠다는 건데요. 이 파라미터는 다음에 볼 xml 파일에서 던져 줄 겁니다.


해당 메소드를 보면은요. launchBrowser() 라는 메소드인데요 스트링을 input 파라미터로 받습니다.

그 안을 보면 path라는 스트링에 이 프로젝트의 현재 위치를 대입합니다.


그리고 if 문이 나오는데요. input 파라미터가 FF 이면 FirefoxDriver() 를 driver 객체에 대입하고 Chrome인 경우는 ChromeDriver()를 그리고 IE인 경우에는 인터넷 익스플로러 드라이버를 drive 객체에 대입합니다.


그러니까 저 위에 있는 WebDriverTest 클래스의 testWiki() 테스트 메소드가 시작되기 전에 조건에 맞게 driver 객체를 세팅한 후 그 테스트 메소드가 실행될 겁니다.


다음에 나오는 건 @AfterMethod 가 있는 걸로 봐서 저 testWiki() 테스트 메소드가 실행되고 난 다음에 실행되는 메소드 입니다.

이름이 closeBrower() 이고 그 안에는 브라우저를 close하고 메모리로부터 driver 객체를 완전히 없애는 quit을 해주는 메소드 입니다.


이 두 클래스에서는 TestNG와 Selenium WebDriver를 같이 사용하고 있습니다.


여기에서 이 한개의 테스트를 여러 웹 브라우저에서 테스트할 수 있도록 하는 작업을 하겠습니다.

그러면 해당 프로젝트에 xml 파일을 만들어야 합니다.


testng.xml 이라는 파일을 아래와 같이 만듭니다.


<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Widipedia Test" verbose="3" parallel="methods">
    <test name="Wiki in FF">
    <parameter name="browser" value="FF"></parameter>
        <classes>
            <class name="WebDriverTest"/>
        </classes>
    </test>
   
    <test name="Wiki in Chrome">
    <parameter name="browser" value="Chrome"></parameter>
        <classes>
            <class name="WebDriverTest"/>
        </classes>
    </test>
    <!--
    <test name="Wiki in IE">
    <parameter name="browser" value="IE"></parameter>
        <classes>
            <class name="WebDriverTest"/>
        </classes>
    </test>   
     -->
</suite>

<suite> 태그를 써서 여러 테스트를 한개의 suite에 담겠다는 것을 알립니다.

그리고 <test> 태그 안에 각각의 테스트들을 정의 합니다.

첫번째는 <parameter> 태그안에 name 이 browser이고 value 는 FF 를 설정합니다.

이 것이 SelTestCase 클래스에 있는 launchBrowser()메소드에 전달될 파라미터 입니다.

그 다음에 <classes> 태그 안에는 name 에  WebDriverTest 를 넣습니다.

이 클래스를 run 하라는 겁니다.


그 다음에는 Chrome 과 IE 에 대한 <test> 태그들을 같은 방식으로 만듭니다.


여기서 IE는 주석처리를 했습니다.

제가 해 보니까 에러가 나더라구요.

혹시 이 IE는 왜 에러가 나는지 아시는 분은 좀 알려 주세요.


이 test suite를 실행하려면 Run-run configurations 를 선택합니다.




여기서 보시다시피 프로젝트를 선택하고 Suite를 선택한 다음에 아까 만들었던 xml 을 세팅합니다.


그러면 이 xml에서 정의된 대로 테스트가 여러 브라우저에서 실행될 겁니다.



반응형

Selenium WebDriver Tutorial 02

2013. 10. 18. 05:20 | Posted by 솔웅


반응형

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();



반응형

Selenium WebDriver Tutorial 01

2013. 10. 17. 17:25 | Posted by 솔웅


반응형

Selenium WebDriver

NOTE: We’re currently working on documenting these sections. We believe the information here is accurate, however be aware we are also still working on this chapter. Additional information will be provided as we go which should make this chapter more solid.



Introducing WebDriver



Selenium 2.0 의 새 기능중 중요한 부분은 WebDriver API 를 통합했다는 겁니다. WebDriver는 Selenium-RC API 의 한계를 극복하기 위한 기능들이 추가 된 것으로 프로그래밍을 좀 더 간단하고 간결하게 할 수 있도록 도와 줍니다. Selenium-WebDriver는 페이지가 reload 되지 않고도 페이지의 element들이 바뀌는 dynamic web page를 좀 더 제대로 지원하기 위해 만들었습니다. WebDriver의 목표는 현재 Web-App의 문제점들을 제대로 해결하기 위해 만들어진 잘 디자인된 객체 지향 API 입니다.



How Does WebDriver ‘Drive’ the Browser Compared to Selenium-RC?



Selenium-WebDriver는 자동화를 위해 각 브라우저 고유의 기능들을 지원함으로서 브라우저에 직접 호출하는 기능을 지원합니다. 어떻게 이렇게 직접 호출을 할 수 있고 어떤 기능들을 지원하느냐는 여러분이 사용하는 브라우저에 따라 다릅니다. 각 browser driver에 대한 정보는 나중에 살펴 보겠습니다.



Selenium-RC에 익숙하신 분들에게는 이 부분이 여러분이 사용하시던 부분과 좀 다를 겁니다. Selenium-RC는 각 브라우저에 대해 같은 방법으로 작독했습니다. 브라우저가 로드 되면 그 브라우저에 자바스크립트를 inject 하고 그 브라우저 안에서 AUT를 drive 하기 위해 그 자바스크립트를 사용합니다. WebDriver는 이와 같이 작동하지 않습니다. WebDriver는 automation을 위해 지원하는 브라우저의 고유 기능을 direct 하게 사용합니다.


WebDriver and the Selenium-Server



이 Selenium-WebDriver를 어떻게 사용할 것인가에 따라 Selenium Server가 필요할 수도 있고 그렇지 않을 수도 있습니다. 만약 WebDriver API 만을 사용할 거라면 Selenium-Server는 필요하지 않습니다. 만약 여러분의 브라우저와 테스트들이 같은 machine 에서 작동하고 여러분의 테스트가 WebDriver API만을 사용한다면 Selenium-Server가 필요하지 않습니다. WebDriver가 곧바로 그 브라우저를 실행시킬 겁니다.



Selenium-WebDriver와 함께 Selenium-Server를 사용하는데는 몇가지 이유가 있습니다.

       

- 여러분의 tests를 여러 machine들이나 virtual machines(VMs)에서 사용하기 위해 Selenium-Grid를 사용하는 경우.
      

- 여러분의 machine에 있지 않는 브라우저 버전을 갖고 있는 다른 machine에 remote로 접근해야 할 경우.
       

- Java bindings (Python,C#,Ruby 같은) 을 사용하지 않고 HtmlUnit Driver를 사용 할 경우.



Setting Up a Selenium-WebDriver Project



Selenium 을 인스톨한다는 의미는 development에 project를 셋업한다는 얘기입니다. 그렇게 되면 Selenium을 사용해서 프로그래밍 할 수 있게 되는거죠. 이것을 프로그래밍 언오와 개발환경에 따라 어떻게 할까요.





JAVA



Selenium 2.0 Java 프로젝트를 셋업하는 가장 쉬운 방법은 Maven을 이용하는 겁니다. Maven 은 java binding들 (Selenium 2.0 java client library)와 모든 dependency들을 다운로드 하고 프로젝트를 생성할 겁니다. 메이븐의 pom.xml (project configuration) 파일을 사용해서 이러한 일을 하시면 됩니다. 이 작업이 완료 되면 여러분은 maven 프로젝트를 여러분이 사용하시는 IDE (IntelliJ IDEA 나 이클립스)에 import 하실 수 있습니다.



첫번째로 Selenium project 파일들이 들어갈 폴더를 생성합니다. Maven을 사용하려면 pom.xml 파일이 필요합니다. 이 파일은 텍스트 에디터로 만들 수 있습니다. 이 pom.xml 파일이나 메이븐에 대한 자세한 부분은 다루지 않겠습니다. 아마 pom.xml은 아래와 같을 겁니다. 여러분 프로젝트를 위해 만든 폴더에 이 파일을 생성해 넣으세요.



<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>MySel20Proj</groupId>
        <artifactId>MySel20Proj</artifactId>
        <version>1.0</version>
        <dependencies>
            <dependency>
                <groupId>org.seleniumhq.selenium</groupId>
                <artifactId>selenium-java</artifactId>
                <version>2.35.0</version>
            </dependency>
            <dependency>
                <groupId>com.opera</groupId>
                <artifactId>operadriver</artifactId>
            </dependency>
        </dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>com.opera</groupId>
                    <artifactId>operadriver</artifactId>
                    <version>1.5</version>
                    <exclusions>
                        <exclusion>
                            <groupId>org.seleniumhq.selenium</groupId>
                            <artifactId>selenium-remote-driver</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
            </dependencies>
        </dependencyManagement>
</project>



이 때 최신 버전을 사용하세요. 위 코드 내의 버전들은이 글을 쓸 당시의 최종 버전들입니다. Maven download page를 체크하셔서 위의 코드 중 버전이 바뀐 경우 바꿔주세요.



이제 command-line에서 cd 로 해당 프로젝트 디렉토리로 가셔서 아래처럼 maven을 run 해 주세요.



mvn clean install



이렇게 하면 Selenium과 다른 dependency들을 다운받아 프로젝트에 추가할 겁니다.



마지막으로 이 프로젝트를 개발환경에 import 하시면 됩니다. 이 방법을 자세히 아시려면 아래 링크를 따라 가서 참고하시면 도움이 될 겁니다.



Importing a maven project into IntelliJ IDEA. Importing a maven project into Eclipse.



C#



As of Selenium 2.2.0, the C# bindings are distributed as a set of signed dlls along with other dependency dlls. Prior to 2.2.0, all Selenium dll’s were unsigned. To include Selenium in your project, simply download the latest selenium-dotnet zip file from https://code.google.com/p/selenium/downloads/list. If you are using Windows Vista or above, you should unblock the zip file before unzipping it: Right click on the zip file, click “Properties”, click “Unblock” and click “OK”.



Unzip the contents of the zip file, and add a reference to each of the unzipped dlls to your project in Visual Studio (or your IDE of choice).



Official NuGet Packages: RC WebDriver WebDriverBackedSelenium Support


Python



If you are using Python for test automation then you probably are already familiar with developing in Python. To add Selenium to your Python environment run the following command from a command-line.



pip install selenium



Pip requires pip to be installed, pip also has a dependency on setuptools.



Teaching Python development itself is beyond the scope of this document, however there are many resources on Python and likely developers in your organization can help you get up to speed.
Ruby



If you are using Ruby for test automation then you probably are already familiar with developing in Ruby. To add Selenium to your Ruby environment run the following command from a command-line.



gem install selenium-webdriver



Teaching Ruby development itself is beyond the scope of this document, however there are many resources on Ruby and likely developers in your organization can help you get up to speed.



Perl



Perl bindings are provided by a third party, please refer to any of their documentation on how to install / get started. There is one known Perl binding as of this writing.



PHP



PHP bindings are provided by a third party, please refer to any of their documentation on how to install / get started. There are three known bindings at this time: By Chibimagic By Lukasz Kolczynski and By the Facebook

반응형


반응형

오늘은 Selenium WebDriver를 이용한 예제를 하나 공부했습니다.


클래스를 실행 시키면 Firefox 브라우저를 켜서 gmail로 가고 아이디 입력과 비밀번호 입력 그리고 Log in 버튼을 누르는 것까지 실행하는 예제입니다.


import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class WebDriver_Ex {
    public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        driver.get("http://gmail.com");
//        WebElement username = driver.findElement(By.id("Email"));
        WebElement username = driver.findElement(By.xpath("//*[@id=\"Email\"]"));
        username.sendKeys("아이디");
        WebElement password  = driver.findElement(By.id("Passwd"));
        password.sendKeys("비밀번호");
       
        WebElement signInBtn = driver.findElement(By.id("signIn"));
        signInBtn.click();
    }
}



이 소스를 실행시키면 Firefox를 실행시키고 사용자 이름과 비밀번호를 주어진 값으로 채워 넣습니다.

그리고 로그인 버튼을 클릭하는 이벤트를 발생시켜서 gmail로 로그인을 합니다.


소스를 보면요.

먼저 WebDriver 인터페이스에 있는 FirefoxDriver()의 객체를 만듭니다.

다음에 get() 메소드를 사용해서 gmail 로 접속을 합니다.

여기까지 하면 파이어폭스 브라우저에 gmail.com 페이지가 뜹니다.


그 다음에는 gmail 페이지의 태그를 알아야 하는데요. 사용자 이름을 넣는 텍스트필드에 값을 넣어야 하는데 이때 사용할 수 있는 방법이 id로 하는 방법과 xpath 로 하는 방법이 있습니다.


이 페이지의 소스를 보려면 firebug 플러그인을 firefox 브라우저에 인스톨해서 사용하시면 편합니다.

xpath를 아시려면 firepath 를 인스톨 하시면 되구요.


자세한 방법은 검색하셔서 관련 글을 보시면 됩니다. 관련된 글이 많이 있을 겁니다.


이 Firebug를 통해서 보면 gmail 의 로그인 페이지에서 아이디를 넣는 텍스트 필드의 id 가 Email 인 것을 알 수 있습니다.

여기까지 알면 WebElement 를 사용해서 해당 텍스트 필드의 객체를 생성합니다.


WebElement username = driver.findElement(By.id("Email"));


혹은 Firepath 를 사용해서 xpath 를 알 수도 있습니다.

xpath 에는 절대경로(Absolute xpath,complete xpath)와 상대경로(partial xpath) 가 있는데요.

여기서는 상대경로를 사용합니다.

WebElement username = driver.findElement(By.xpath("//*[@id=\"Email\"]"));


이렇게 하면 아이디를 넣는 텍스트 필드의 WebElement 객체를 만들었습니다.


이러면 이 엘리먼트를 마음대로 다룰 수가 있게 됩니다.


아이디를 넣어야 하니까 이럴때눈 sendKeys() 메소드를 사용하시면 됩니다.

비밀번호두 마찬가지로 진행합니다.

그리고 로그인 버튼도 WebElement 객체를 만들어서 click() 메소드를 사용해서 클릭하도록 합니다.


이제 이 소스를 실행하면 gmail로 가서 아이디와 비밀번호를 입력하고 로그인 버튼을 눌러서 접속하는것까지 실행합니다.


Selenium 은 테스팅 툴입니다.


여기서는 그 다음페이지의 title을 받아서 원래 설계된 페이지로 제대로 왔는지 안 왔는지 여부를 테스트 할 수 있겠네요.


일단 오늘은 Selenium 을 사용해서 웹페이지에 있는 WebElement들을 control 하는 방법을 정리했습니다.


반응형
이전 1 ··· 3 4 5 6 7 8 9 다음