Testes automatizados com Selenium utilizando o padrão Page Object

Testes automatizados com Selenium utilizando o padrão Page Object

Testes de aceitação automatizados são excelentes ferramentas para manter a qualidade e confiabilidade dos sistemas. No entanto a medida que a suíte de testes cresce a manutenção do código pode se tornar um problema se alguns cuidados não forem tomados desde o início. Neste tutorial vou mostrar como criar um projeto de testes com Selenium 2 utilizado o padrão Page Object que vai nos ajudar a aumentar a velocidade e qualidade dos testes.
A idéia do PageObject é encapsular uma view ou fragmento do nosso sistema em uma api a qual possamos interagir de uma forma mais semântica e menos repetitiva.

Por exemplo  este poderia ser o código para realizar login no sistema:

WebElement inputLogin = driver.findElement(By.id("login"));
inputLogin.sendKeys("usuario");
WebElement inputSenha = driver.findElement(By.id("senha"));
inputSenha.sendKeys("senha");
WebElement btnLogin = driver.findElement(By.id("btn-login"));
btnLogin.click();

Em vez de repetir este código ao longo de nossa suíte de testes podemos encapsular esta ação em um objeto PageLogin com o método:

paginaLogin.autenticar("usuario", "senha");

Dessa forma temos um ganho em muito grande em legibilidade e reutilização.

Criando o projeto

Vamos primeiro criar um projeto básico do maven com o comando:

mvn archetype:generate -DgroupId=[GROUP-ID-DO-PROJETO] -DartifactId=[NOME-PROJETO-TESTES] -DarchetypeArtifactId=maven-archetype-quickstart

output

Vamos editar o arquivo pom.xml e adicionar as dependências do Selenium. Este template também vem com uma versão desatualizada do JUnit vamos trocar para as seguintes versões:

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.50.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

Vamos criar nossos testes para o google chrome. Então precisamos baixar o driver de acordo com nosso sistema operacional no site http://chromedriver.storage.googleapis.com/index.html?path=2.20/ descompactar e copiar para a pasta: /src/main/resources/drivers

chromedriver

Criando Testes

Esta é classe base para todos os nossos PageObjects ela recebe em seu construtor o Webdriver.

package com.ricardomurad.pages;

import org.openqa.selenium.WebDriver;

public abstract class Page {

    private WebDriver webDriver;

    public Page(WebDriver webDriver) {
        this.webDriver = webDriver;
    }

    public String getTitle() {
        return this.webDriver.getTitle();
    }

    public abstract String getPath();

}

Também vamos criar uma classe base para os testes com métodos para inicializar o webDriver.

public abstract class SeleniumBaseTest {

    protected  WebDriver webDriver;
    protected String baseUrl;

    @Before
    public void initDriver() {
        System.setProperty("webdriver.chrome.driver", loadProperty("chrome.driver.path"));
        webDriver = new ChromeDriver();
        webDriver.manage().timeouts().implicitlyWait(parseInt(loadProperty("test.timeout")), TimeUnit.SECONDS);
        baseUrl = loadProperty("base.url");
        this.initPage();
    }

    @After
    public void tearDown() {
        if(this.webDriver != null) {
           webDriver.manage().deleteAllCookies();
            webDriver.close();

        }
    }

    protected abstract void initPage();
}

Criando o teste

Vamos fazer um teste simples que verifica se o site https://github.com/join mostra uma mensagem de validação quando insiro um nome de usuário e email que já estão cadastrados. Na GitHubJoinPage criei 3 métodos: setUsername, setEmail, isErrorMessageVisible(final String message). Estes métodos poderão ser reaproveitados posteriormente para testar o fluxo de login por exemplo.

Repare que na classe GitHubJoinPage.class declarei dois atributos do tipo WebElement e adicionei a anotação @FindBy. Quando chamarmos o método PageFactory.initElements(webDriver, GitHubJoinPage.class) o selenium vai fazer o trabalho de injetar esses WebElements.

Como a mensagem de validação é adicionada a tela a partir de uma requisição ajax criei para fins de demonstração explicitamente um WebDriverWait que aguarda esses elementos aparecem na tela por 5 segundos. Você pode usar esse recurso variando o tempo de acordo com a necessidade do seu sistema.

public class GitHubJoinPage extends Page {

    @FindBy(id = "user_login")
    private WebElement userNameInput;

    @FindBy(id = "user_email")
    private  WebElement userEmailInput;


    public GitHubJoinPage(WebDriver webDriver) {
        super(webDriver);
    }

    @Override
    public String getPath() {
        return "/join";
    }

    public void setUsername(String username) {
        userNameInput.sendKeys(username);
    }

    public void setEmail(String email) {
        userEmailInput.sendKeys(email);
    }

    public Boolean isErrorMessageVisible(final String message) {
        WebDriverWait wait = new WebDriverWait(webDriver, 5);
        wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//dd[@class='error' and text()='" + message + "']")));
        return true;
    }

}

Com o page object criado basta chamar os métodos a partir da classe de teste.

out%02d

Considerações finais

1 – Considere usar também um framework de BDD como o cucumber ou spock. O modelo de BBD se encaixa bem em testes de aceitação.
2 – Para tornar os testes isolados seria ideal instanciar um webdriver e autenticar a cada teste. O ideal é que um teste não influencie em nada na execução do outro.

O projeto completo pode ser acessado no link https://github.com/RicardoMurad/tutorialPageObject

abcs

Leave a Comment

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *