PageObject пару вопросов

Посмотрел видео Михаила Поляруша про Page Object.

 

@Test
    public void testSearch(){
        HomePage home = new HomePage(driver);
        ResultPage result = home.search("Самолёт");
        assertTrue(result.getFirstLink().contains("Самолёт"));
    }

 

@Test
    public void testClickSearch(){
        HomePage home = new HomePage(driver);
        home.testClickSearch();
    }

 

Пример. Есть 2 тесткейса - см. выше. Первый вводит в инпут-поля гугла слово "самолет", жмет кнопку "Найти". И проверяет, что в первой ссылке есть слово "Самолет"

. Впринципе все понятно.

Вопрос номер 1:

Я хочу создать второй тескейс, который заходит на сайт гугла и   жмет кнопку ENTER.   Т.е. мы остаемся на остаемся на главной странице. Т.е. в классе HomePage

я создаю метод testClickSearch который ничего не возвращает. Верно ли я делаю ?

public void testClickSearch() {
        driver.findElement(By.id("gbqfq")).sendKeys(Keys.ENTER);
    }

Вопрос номер 2:

Мне не нравится, что постоянно надо создавать объект экземляр класса home класса HomePage. Т.е. если допустим будет 100 кейсов (типо зайти на гугл и кликнуть кнопку "Мне повезет", "Зайти на гугл и кликнуть какой-нибудь линк", "Зайти на гугл и кликнуть на гугл переводчик" и т.п. ), т.е. мне 100 раз придется писать

HomePage home = new HomePage(driver);   - что явно не есть хорошо. Как постпают в таком случае ?

 

Вопрос номер 3:

Куда выносят  методы setUp и tearDown. Чтобы оставить только тесткейсы, без этих двух методов ???

Создают отдельный класс ? или еще как-нибудь. Желательно с примерами кода

 

 

 

 

 

 

1) да вы делаете правильно, поскольку страница остается та же то ненужно возвращать никакого значения, тоесть void метод есть правильным решением.

 

2) где-то на форуме было обсуждение подобного вопроса, к сожалению ссылку не скажу. я с такими вещами смирился, у меня в классе тестов описываются заранее все страницы как null, и уже в процессе по мере необходимости я их инициализирую, например:

private LoginPage loginPage = null;
    private SystemMonitorPage smPage = null;
    private SettingsPage settingPage = null;

@Test

public void test(){

loginPage =new LoginPage(driver,serverUrl);
        smPage = loginPage.loginAsDefaultAdmin();
        settingPage=smPage.getHeader().gotoSettingsTab();

}

как с этим боротся, можно воспользоватся Фабрикой(паттерн проектирования) но я не пробовал такое делать.

 

3) методы init и teardown можно вынести в класс предок и все тест кейсы наследовать от них. эти методы сделать с аннотациями @Before @After:

к примеру:

public abstract class BasicTestFrame {

public WebDriver driver;

public Selenium selenium;

    @BeforeClass
    public void startSelenium() {

        driver = WebDriverFactory.getFirefoxDriver();
        selenium= new WebDriverBackedSelenium(driver, ConfigProperties.getProperty("server.url").trim());
        driver.manage().timeouts().implicitlyWait(Long.parseLong(ConfigProperties.getProperty("imp.wait")), TimeUnit.SECONDS);

    }

    @AfterClass
    public void stopSelenium() {
        if(driver instanceof ChromeDriver)
            driver.quit();
        else driver.close();
    }

и классы тест кейсов будут начинатся следующим образом:

public class GoogleSearchTest extends BasicTestFrame{}

ну и далее вы сможете безопасно пользоватся вебдрайвером инициализированым в ините, поскольку класс кейса наследует БейсикТестФрейм.

 

методы init и teardown можно вынести в класс предок и все тест кейсы наследовать от них. эти методы сделать с аннотациями @Before @After:

Я так и делал, но что-то не получается ((

Создал отдельный класс

public abstract class SetUpteatDown {

private WebDriver driver;
@Before
public void setUp(){
System.setProperty("webdriver.chrome.driver", "E:\\chromedriver.exe");
   driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
 
driver.get("http://google.ru");
}
 
@After
public void teatDown(){
driver.close();
}
}
 
Теперь в классе GoogleTestPage указываю extends SetUpteatDown{
 
public class GoogleTestPage extends SetUpteatDown{
private WebDriver driver;
 
@Test
public void testSearch(){
HomePage home = new HomePage(driver);
ResultPage result = home.search("Самолёт");
assertTrue(result.getFirstLink().contains("Самолёт"));
}
 
@Test
public void testClickSearch(){
HomePage home = new HomePage(driver);
home.testClickSearch();
 
}
}
Когда запускаю на выполнение - срабатывает метод setUp, но не работает метод @Test
public void testSearch() - ошибка "java.lang.NullPointerException"
Что-то я не догоняю почему ((
 
2)По поводу второго вопроса, что надо постоянно писать в каждом методе HomePage home = new HomePage(driver); - кто-нубудь знает решение ??

 

обьявите вебдрайвер в тестфрейме как public, а в тест кейсе(гуглпейджтест) уберите его вовсе.

 

аннотации лучше ставить @BeforeClass @AfterClass из testNG.

спасибо большое

Я бы предложил совершенно другую структуру. Все тесты будут наследоваться от абстрактного класса, допустим, BaseTest. Внутри класса будет инициализироваться / закрываться драйвер. Там же можно сделать метод получения первой страницы для всех тестов, который будет возвращать Page Object HomePage:

public abstract class BaseTest {

protected RemoteWebDriver driver;

// ...

@BeforeClass(alwaysRun = true)
    public void start() {
        if (driver == null) {
            driver = initDriver();
            driver.manage().timeouts().implicitlyWait(
                    Long.valueOf(Context.timeout), TimeUnit.MILLISECONDS);
        }
    }

    @AfterClass
    public void stop() {
        if (driver != null) {
            driver.close();
            driver.quit();
        }
    }

// ...

protected HomePage getHomePage() {
        String url = "get it from somewhere";

        driver.navigate().to(url);

        return new HomePage(driver);
    }

// ...

}

Все Page Objects будут наследоваться от родителя в виде абстрактного класса-обертки для всех методов работы с Selenium.

public class AbstractPage {

// ...
    protected RemoteWebDriver remoteWebDriver;

public AbstractPage(RemoteWebDriver remoteWebDriver) {
        this.remoteWebDriver = remoteWebDriver;
    }

// ...

}

Ну а дальше, для HomePage, в случае отсутствия перехода на другую страницу, достаточно методу возвращать this.

public class HomePage extends AbstractPage {

public HomePage(RemoteWebDriver remoteWebDriver) {
        super(remoteWebDriver);
    }

/* Вызываемые методы-обертки описаны в AbstractPage. В качестве параметров используются By элементы, описанные внутри HomePage. */

public HomePage testSearch(String text) {
        setText(searchInput, text);

        clickAndWait(searchButton);


        return this;
    }

}

Сам тест внутри класса, наследуемого от BaseTest, будет выглядеть приблизительно так:

@Test

public void search() {

        getHomePage().testSearch("google");

// asserts

}

Код правился на ходу. Возможно где-то что-то не то. Но сама суть, думаю, ясна.

в принципе я исповедую такой же стиль, просто давал быстрый ответ на вопрос, не вдавался в глубокие подробности=)

да ви тут целий фреймворк виложили)

кстати хороший подход когда много разних поп-апов итд в структуре функционала, можна обертки разние абстрактние писать в паралеле с пейдж обджектами.