2016-11-04 4 views
3

이 패턴을 이해하는 데 문제가 있습니다. 먼저 인증에 성공한 후 내 PageObject를 확장하는 LoginPage가있는 내 페이지에서 로그인을 테스트하려면 LoginPageReceipt를 반환합니다. 이제 loginPageReceipt가 있는데, 두 번째 페이지에서이 값을 유지하려고합니다. 두 번째 문제는 내가 생각하기에 처음으로 로그인을 테스트하면 다음 모듈을 테스트하려고하지만 로그인해야합니다. 어떻게해야합니까? 두 번째 테스트는 첫 번째 테스트의 결과를 사용하지 않아야하며 코드를 복제해서는 안됩니다. 여기 수업이 있습니다. 내가 어떻게 그랬어. 페이지의 개체 모델에 대한 중대한 것의페이지 개체 패턴 이해

package Init; 

import org.junit.After; 
import org.junit.AfterClass; 
import org.junit.BeforeClass; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.chrome.ChromeDriver; 
import org.openqa.selenium.chrome.ChromeOptions; 

import java.util.concurrent.TimeUnit; 

public class FunctionalTest { 
    protected static WebDriver driver; 
// private static WebDriverWait driverWait; 

    @BeforeClass 
    public static void setUp() { 
     ChromeOptions options = new ChromeOptions(); 
     options.addArguments("--start-maximized"); 
     System.setProperty("webdriver.chrome.driver", "src\\main\\resources\\chromedriver.exe"); 
     driver = new ChromeDriver(options); 
     driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 
//  driverWait = new WebDriverWait(driver, 10); 
    } 

    @After 
    public void cleanUp() { 
     driver.manage().deleteAllCookies(); 
    } 

    @AfterClass 
    public static void tearDown() { 
     driver.close(); 
    } 
} 

package Init; 

import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.support.PageFactory; 

public class PageObject { 

    protected WebDriver driver; 

    public PageObject(WebDriver driver) { 
     this.driver = driver; 
     PageFactory.initElements(driver, this); 
    } 

} 
package Login; 

import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.FindBy; 
import Init.PageObject; 

import static org.junit.Assert.assertTrue; 

public class LoginPage extends PageObject { 

    @FindBy(id = "UserName") 
    private WebElement userName; 

    @FindBy(id = "Password") 
    private WebElement password; 

    @FindBy(id = "loginButton") 
    private WebElement loginButton; 

    public LoginPage(WebDriver driver) { 
     super(driver); 
     assertTrue(userName.isDisplayed()); 
     assertTrue(password.isDisplayed()); 
     assertTrue(loginButton.isDisplayed()); 
    } 

    public void enterUserName(String userName) { 
     this.userName.clear(); 
     this.userName.sendKeys(userName); 
    } 

    public void enterUserPassword(String password) { 
     this.password.clear(); 
     this.password.sendKeys(password); 
    } 

    public LoginPageReceipt login() { 
     loginButton.click(); 
     return new LoginPageReceipt(driver); 
    } 
} 

package Contractor; 

import Init.PageObject; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.FindBy; 

import static org.junit.Assert.assertTrue; 

public class ContractorPage extends PageObject { 

    @FindBy(id = "moduleContent") 
    private WebElement moduleContent; 

    public ContractorPage(WebDriver driver) { 
     super(driver); 
     assertTrue(moduleContent.isDisplayed()); 
    } 
} 

package Login; 

import Contractor.ContractorPage; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.FindBy; 
import Init.PageObject; 

public class LoginPageReceipt extends PageObject { 

    @FindBy(xpath = "//*[@id=\"loginPartial\"]/span[5]") 
    private WebElement userNamePanel; 

    @FindBy(id = "contractors-menuitem") 
    private WebElement goToContractorPage; 

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

    public String loginConfirmation() { 
     return userNamePanel.getText(); 
    } 

    public ContractorPage contractorPage() { 
     goToContractorPage.click(); 
     return new ContractorPage(driver); 
    } 
} 

package Tests; 

import Login.LoginPage; 
import Login.LoginPageReceipt; 
import org.junit.Test; 
import Init.FunctionalTest; 

import static org.junit.Assert.assertEquals; 

public class LoginTest extends FunctionalTest { 

    private static final String USER_NAME = "xxx"; 
    private static final String PASSWORD = "xxx"; 

    @Test 
    public void login() { 
     FunctionalTest.driver.get("xxx"); 

     LoginPage loginPage = new LoginPage(FunctionalTest.driver); 
     loginPage.enterUserName(USER_NAME); 
     loginPage.enterUserPassword(PASSWORD); 
     LoginPageReceipt loginPageReceipt = loginPage.login(); 

     assertEquals("Użytkownik: " + USER_NAME + " | Wyloguj", loginPageReceipt.loginConfirmation()); 
    } 

} 

package Tests; 

import Contractor.ContractorPage; 
import Init.FunctionalTest; 
import Login.LoginPage; 
import Login.LoginPageReceipt; 
import org.junit.Test; 

import static org.junit.Assert.assertEquals; 

public class ContractorTest extends FunctionalTest { 

    private static final String USER_NAME = "xxx"; 
    private static final String PASSWORD = "xxx"; 

    @Test 
    public void contractorPageTest() { 
     FunctionalTest.driver.get("xxx"); 

     LoginPage loginPage = new LoginPage(FunctionalTest.driver); 
     loginPage.enterUserName(USER_NAME); 
     loginPage.enterUserPassword(PASSWORD); 
     LoginPageReceipt loginPageReceipt = loginPage.login(); 

     assertEquals("Użytkownik: " + USER_NAME + " | Wyloguj", loginPageReceipt.loginConfirmation()); 

     ContractorPage contractorPage = loginPageReceipt.contractorPage(); 
    } 
} 

답변

1

하나는 일반적인 지침이 아니라 엄격한 시스템이다. 누구나 자신의 셀렌 프로젝트를 모델링하는 방법에 대해 선호합니다.

직접적인 질문에 답하려면 브라우저에 새 페이지를로드하고 해당 페이지를 나타내는 새 페이지 객체를 반환하는 페이지 객체의 메소드가 있어야 유효합니다.

각 개별 테스트 측면에서 웹 앱의 상태 정보를 한 테스트에서 다른 테스트로 보지 않는 한 (나에게 일반적으로 나쁜 생각), 그렇다면 모든 테스트를 반복해야합니다. 로그인 절차. 그러나 중복 코드 일 필요는 없으며 각 테스트가 비즈니스의 첫 번째 주문으로 호출 할 수있는 방법으로 루틴을 캡슐화합니다. 또한 프로 시저를 수행하는 것은 프로 시저를 테스트하는 것과 같지 않습니다. 로그인 페이지의 테스트가 올바른지 주장해야합니다. 중개 단계로 로그인해야하는 추가 테스트는 이러한 주장을 건너 뛰어야합니다.

페이지 개체는 각각 전체 페이지를 캡슐화 할 필요가 없습니다. 테스트중인 앱과 관련하여 디자인에 대해 신중하게 생각하고 싶습니다. 모든 앱이 동등한 자동화 기능을 제공하는 것은 아니므로 셀레늄 프로젝트가 보편화 될 것으로 예상해서는 안됩니다.

앱이 상태를 많이 변경하지 않는 정적 페이지 모음 인 경우 웹 페이지 당 하나의 페이지 개체가 필요할 수 있습니다. 그러나 당신이 페이지의 큰 영역을 만들고 사라지게하는 자바 스크립트 만있는 단일 페이지 응용 프로그램이 있다면 어떨까요 ... 아마도 페이지 개체는 출현하는 구성 요소 나 프레임을 나타내는 단일 페이지의 영역을 더 잘 캡슐화합니다. 일관성이있다.

개념적 관점에서 보면 페이지 개체가 모든 원시 셀렌을 숨겨서 테스트가 알 필요가 없거나 신경 쓸 필요가 없으며 테스트가 해당 페이지에서 작업을 수행하기 위해 호출 할 수있는 간결한 공개 API를 제공해야합니다. .

페이지 개체의 메서드가 양식의 각 필드에 대해 별도의 메서드와 같이 페이지에 작은 크기의 작업을 캡슐화하는지 여부와 같은 전체 워크 플로를 채우고 제출하는 방법은 사용자가 결정합니다. 이 결정은 앱 디자인을 염두에두고 이루어져야하며 목표는 신뢰할 수있을뿐만 아니라 기존 콘텐츠를 유지하면서 새 콘텐츠를 쉽게 만들 수 있도록하는 것입니다.

편집 : 테스트처럼 뭔가를 할 수

public class LoginPage { 
    private final WebDriver driver; 

    private final String emailField = "#email"; 
    private final String passwordField = "#password"; 
    private final String submitButton = "#submit"; 

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

    // These are our bite sized methods right here 
    public LoginPage enterEmail(String email) { 
     driver.findElement(By.cssSelector(emailField)).sendKeys(email); 
     return this; 
    } 

    public LoginPage enterPassword(String password) { 
     driver.findElement(By.cssSelector(passwordField)).sendKeys(password); 
     return this; 
    } 

    public void submit() { 
     driver.findElement(By.cssSelector(submitButton)).click(); 
    } 

    // This method represents an entire workflow, 
    // containing multiple bite-sized chunks. 
    public void performLogin(String email, String password) { 
     enterEmail(email); 
     enterPassword(password); 
     submit(); 
    } 
} 

사용하려면 : 여기

는 이론적 로그인 페이지 객체의 예 당신이 알고있는 경우

WebDriver driver = new ChromeDriver(options); 
LoginPage loginPage = new LoginPage(driver); 

//One way: 
loginPage.enterEmail("[email protected]").enterPassword("12345").submit(); 

// Another way: 
loginPage.performLogin("[email protected]", "12345"); 

그리고 정확히 어디에 리디렉션 될 때 submitperformLogin 메서드는 다음 페이지 객체의 인스턴스를 반환 할 수 있습니다.

0

다른 답변은 유용하며 질문이 명확 해집니다. 이 답변에서 프레임 워크를 제안하고 싶습니다.

enter image description here

테스트 클래스는 셀레늄에 대해 아무것도 몰라한다. 페이지 객체와 만 상호 작용해야합니다. 페이지 객체는 페이지 조각을 통해 브라우저와 상호 작용합니다. 페이지 조각은 webdriver를 다룹니다.

셀렌 + 자바를 사용하고 있으므로 Arquillian - Graphene을 살펴보십시오. Java + Selenium에서 더 나은 프레임 워크를 만드는 데 도움이되는 일련의 라이브러리입니다. 당신은 libs를 추가 할 수 있습니다 & 단순히 사용하지 않도록 선택합니다. 기본적으로 기존 스크립트를 망치지 않습니다.

장점 :

  • 당신은 페이지 공장이 필요하지 않습니다. 모든 것이 런타임에 주입됩니다. 드라이버 포함.
  • AJAX 처리
  • JQuery와 선택기
  • AngularJS와 선택

는 더 많은있다. 예를 들어

: 귀하의 경우,

public class LoginPage { 
... 
... 
... 
} 


public class LoginPageReceipt { 
... 
... 
... 
} 



public class ContractorPage { 
... 
... 
... 
} 

테스트 클래스

public class LoginTest{ 

    @Page 
    LoginPage loginPage; 

    @Page 
    LoginPageReceipt loginPageReceipt; 

    @Test 
    public void login() { 
     loginPage.enterUserName(USER_NAME); 
     loginPage.enterUserPassword(PASSWORD); 
     loginPage.login(); 
     assertEquals("Użytkownik: " + USER_NAME + " | Wyloguj", loginPageReceipt.loginConfirmation()); 
    } 

} 

확인 here 예를 들어.