2016-11-04 2 views
3

У меня проблема с пониманием этого шаблона. Сначала я хочу протестировать логин на своей странице, для которого у меня есть LoginPage, который расширяет мой объект PageObject после успешной аутентификации, он возвращает LoginPageReceipt. Теперь, когда у меня есть loginPageReceipt, я хочу сохранить это для своей второй страницы. Вторая проблема, о которой я думаю, заключается в том, что если сначала я тестирую логин, то я хочу протестировать следующий модуль, но мне нужно войти в систему. Как мне это сделать? Мой второй тест не должен использовать результат первого теста, и я не должен дублировать код. Вот мои занятия. Как я это сделал.Page Object Pattern понимание

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

Одна из замечательных особенностей объектной модели страницы заключается в том, что это общая рекомендация, а не жесткая система. У каждого есть предпочтения в отношении того, как они моделируют свои проекты селена.

Чтобы ответить на ваши прямые вопросы, вполне допустимо использовать метод объекта страницы, который запускает новую страницу для загрузки в браузере, чтобы вернуть новый объект страницы, представляющий эту страницу.

С точки зрения каждого отдельного теста, если вы не пытаетесь сохранить информацию о состоянии в веб-приложении по одному тесту другому (что для меня, как правило, плохое), то да, вам понадобится каждый тест, чтобы повторить это логин. Но он не должен быть дублированным кодом, инкапсулировать эту процедуру в методе, который каждый тест может вызывать как бизнес первого порядка. Кроме того, выполнение процедуры - это не то же самое, что тестирование процедуры, ваш тест на странице входа в систему должен утверждать, что все правильно, дополнительные тесты, требующие входа в качестве промежуточного шага, должны пропустить эти утверждения.

Для объектов страницы дополнительно не требуется инкапсулировать целую страницу. Вы хотите задуматься о своем дизайне относительно приложения, которое вы тестируете. Не все приложения автоматизированы одинаково, поэтому проекты селена также не должны быть универсальными.

Если ваше приложение представляет собой коллекцию статических страниц, которые не меняются с явным изменением, вам может понадобиться один объект страницы на веб-страницу. Но что, если у вас есть одностраничное приложение, которое представляет собой не что иное, как javascript, что большие регионы страницы появляются и исчезают очень часто ... Возможно, ваши объекты страницы лучше инкапсулируют регионы этой единственной страницы, представляя компоненты или кадры, которые приходят и уходят, но сами по себе непротиворечивы.

С концептуальной точки зрения вы хотите, чтобы объекты вашей страницы спрятали весь необработанный селен, чтобы ваши тесты не нуждались в знаниях или заботе и не предоставляли сжатый публичный API, который ваши тесты могут вызывать для выполнения действий на этой странице ,

Независимо от того, применяют ли методы вашего объекта страницы небольшие действия на странице, такие как отдельные методы для каждого поля в форме или большие рабочие процессы, такие как или один метод для заполнения всей формы и отправки ее вам. Это решение должно быть сделано с учетом дизайна приложения, и ваша цель - сделать что-то, что не только надежное, но и легко создать новый контент и легко поддерживать существующий контент.

Edit:

Вот пример теоретического объекта Логин страницы:

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

И если вы точно знаете, где вы будете перенаправлены, ваши методы submit и performLogin могут возвращать экземпляр вашего следующего объекта страницы.

0

Другой ответ хорош и уточняет ваш вопрос. Я хотел бы предложить структуру в этом ответе.

enter image description here

Ваш тестовый класс не должен ничего о селене знать. Он должен взаимодействовать только с объектами страницы. Объекты страницы взаимодействуют с браузером через фрагменты страницы. Фрагменты страниц связаны с webdriver.

Как вы используете селен + java, взгляните на Arquillian - Graphene. Это набор libs, который поможет вам создать лучшую структуру в 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, например.

Смежные вопросы