├── README.md ├── azure-pipelines.yml ├── pom.xml └── src └── test ├── java ├── pages │ ├── CommonPage.java │ ├── EcommerceMainPage.java │ └── EcommerceMainPageElementMap.java ├── steps │ ├── CommonSteps.java │ └── EcommerceMainSteps.java ├── tests │ └── RunTest.java └── util │ ├── TestRule.java │ └── Utils.java └── resources ├── drivers └── READ.txt └── features └── Pesquisa.feature /README.md: -------------------------------------------------------------------------------- 1 | # Projeto Base Automação Web - Selenium, Java & Cucumber 2 | 3 | ## Ferramentas utilizadas: 4 | - [Maven](https://maven.apache.org/ "Maven") 5 | - [Java](https://www.java.com/pt_BR/ "Java") 6 | - [JUnit](https://junit.org/junit4/ "JUnit") 7 | - [Selenium](https://www.seleniumhq.org/ "Selenium") 8 | - [ChromeDriver](https://chromedriver.chromium.org/downloads "ChromeDriver") 9 | - [Cucumber](https://cucumber.io/ "Cucumber") 10 | - [PageFactory](https://github.com/SeleniumHQ/selenium/wiki/PageFactory "PageFactory") 11 | - [PageObject (pattern)](https://martinfowler.com/bliki/PageObject.html "PageObject") 12 | 13 | ## Arquitetura: 14 | 15 | ``` 16 | ├── README.md 17 | ├── pom.xml 18 | └── src 19 | ├── main 20 | │   ├── java 21 | │   └── resources 22 | └── test 23 | ├── java 24 | │   ├── pages 25 | │   │   ├── CommonPage.java 26 | │   │   ├── EcommerceMainPage.java 27 | │   │   └── EcommerceMainPageElementMap.java 28 | │   ├── steps 29 | │   │   ├── CommonSteps.java 30 | │   │   └── EcommerceMainSteps.java 31 | │   ├── tests 32 | │   │   └── RunTest.java 33 | │   └── util 34 | │   ├── TestRule.java 35 | │   └── Utils.java 36 | └── resources 37 | ├── drivers 38 | │   └── READ.txt 39 | └── features 40 | └── Pesquisa.feature 41 | ``` 42 | 43 | 44 | ### Arquitetura - Bibliotecas utilizadas 45 | 46 | Neste projeto foram utilizadas 4 bibliotecas: 47 | - [selenium-java](https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java "selenium-java") 48 | - [junit](https://mvnrepository.com/artifact/junit/junit "junit") 49 | - [cucumber-java](https://mvnrepository.com/artifact/info.cukes/cucumber-java "cucumber-java") 50 | - [cucumber-junit](https://mvnrepository.com/artifact/info.cukes/cucumber-junit "cucumber-junit") 51 | 52 | A biblioteca selenium-java possui as implementações de: *WebDriver, DesiredCaps, ChromeDriver, ExpectedConditions, WebDriverWait, Actions, WebElement, FindBy, PageFactory*, utilizadas no projeto. 53 | 54 | A biblioteca junit possui as implementações de: *TestWatcher, Description, ClassRule, RunWith, Assert*, utilizadas no projeto. 55 | 56 | A biblioteca cucumber-java possui as implementações de: *Scenario, Before, After, Dado, E, Entao, CucumberOptions*, utilizadas no projeto. 57 | 58 | A biblioteca cucumber-junit possui a implementação da classe *Cucumber.class*, utilizada da classe RunTest como ferramenta de execução. 59 | 60 | ### Arquitetura - Mapeamento dos elementos 61 | Para mapear os elementos utilizamos a biblioteca do selenium PageFactory, responsável por abstrair os elementos para uma classe única e para facilitar a escrita e manutenção. Por padrão os elementos são armazenados nas classes com o padrão PageElementMap. Detalhes da implementação e exemplos: 62 | - WebElement - responsável por identificar os elementos como Web; 63 | - FindBy - responsável por mapear, através de anotações, os seletores dos WebElements 64 | - CommonPage - responsável por abstrair ações comuns a todas as classes de Page e PageElementMap 65 | 66 | Após mapeados, é necessário "inicializar" os elementos na classe em que serão utilizadas. Por padrão, os elementos são utilizados nas classe Page correspondentes. Para inicializar os elementos, siga o exemplo abaixo: 67 | 68 | `PageFactory.initElements(driver, classe)` 69 | 70 | ### Arquitetura - Interação com elementos da página 71 | Para interagir com elementos da página, conforme o padrão Page Objects, criamos uma classe de Page para cada página ou grupo de páginas do sistema. Abaixo detalhes da implementação e exemplos: 72 | - PageFactory: responsável pela inicialização dos elementos na página 73 | - TestRule: responsável por gerenciar a execução do teste como um todo. Neste caso, captura qual o driver que está sendo utilizado. 74 | - Utils: responsável por armazenar funções úteis para criação e execução dos testes. 75 | 76 | ### Arquitetura - Classe Base (CommonPage) 77 | Nesta classe são definidas ações comuns a todas a outras Pages que serão criadas no projeto, como: 78 | - captura de screenshots 79 | - logs 80 | - waits (estáticos e explícitos) 81 | 82 | ### Arquitetura - Cucumber e Definições de steps 83 | Para criação dos testes, o passo a passo é definido em arquivos .feature, dentro do diretório resources/features. Estes arquivos contém o detalhamento do teste que será executado. Para isso utilizamos o Cucumber. 84 | Para cada passo utilizado neste arquivo, deve ser criada uma definição de Steps 85 | correspondente. Os arquivos de steps serão criados no diretório steps. 86 | 87 | ### Arquitetura - Execução dos testes 88 | Para execução dos testes, utilizamos classe JUnit, em conjunto com anotações do CucumberOptions para facilitar a criação de suítes de testes com diferentes configurações. 89 | 90 | Para executar o teste, basta clicar com o botão direito sobre a classe, e selecionar "Run ". É possível executar com maven também, através do comando: `mvn test -Dtest=NomeDaClasseDeExecucao` 91 | 92 | ### Arquitetura - Utilitários e TestRule 93 | Para configuração do ciclo de vida do teste, geração de relatórios e criação de métodos auxiliares, utilizamos as classes TestRule e Utils, respectivamente. Alguns dos métodos mais importantes são: 94 | **TestRule** 95 | - ***starting, beforeCenario e afterCenario*** - métodos que definem os comportamentos antes, durante e após a execução dos testes em geral e de cada cenário. 96 | - ***abrirNavegador*** - método responsável por um abrir um navegador Chrome. 97 | 98 | **Utils** 99 | - ***setDriverByOS*** - método para definir o driver de acordo com o sistema operacional. 100 | 101 | ### Arquitetura - ChromeDriver 102 | 103 | Por conveniência, faça o download do chromedriver adequado para o seu sistema operacional e adicione no diretório resources/drivers. 104 | Local para download: https://chromedriver.chromium.org/downloads 105 | 106 | 107 | ------------ 108 | 109 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Maven 2 | # Build your Java project and run tests with Apache Maven. 3 | # Add steps that analyze code, save build artifacts, deploy, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/java 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'ubuntu-latest' 11 | 12 | steps: 13 | - task: Maven@3 14 | inputs: 15 | mavenPomFile: 'pom.xml' 16 | mavenOptions: '-Xmx3072m' 17 | javaHomeOption: 'JDKVersion' 18 | jdkVersionOption: '1.8' 19 | jdkArchitectureOption: 'x64' 20 | publishJUnitResults: true 21 | testResultsFiles: '**/surefire-reports/TEST-*.xml' 22 | goals: 'package' 23 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | selenium-java-cucumber 8 | selenium-java-cucumber-structure 9 | 1.0-SNAPSHOT 10 | 11 | 12 | UTF-8 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | org.seleniumhq.selenium 22 | selenium-java 23 | 3.12.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | junit 31 | junit 32 | RELEASE 33 | test 34 | 35 | 36 | 37 | 38 | 39 | 40 | info.cukes 41 | cucumber-java 42 | 1.2.5 43 | 44 | 45 | 46 | 47 | info.cukes 48 | cucumber-junit 49 | 1.2.5 50 | test 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/test/java/pages/CommonPage.java: -------------------------------------------------------------------------------- 1 | package pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.interactions.Actions; 6 | import org.openqa.selenium.support.ui.ExpectedConditions; 7 | import org.openqa.selenium.support.ui.WebDriverWait; 8 | import util.TestRule; 9 | 10 | public class CommonPage { 11 | 12 | protected WebDriver driver = TestRule.getDriver(); 13 | 14 | public CommonPage(){} 15 | 16 | //actions example 17 | protected void moveToElement(WebElement element){ 18 | Actions action = new Actions(driver); 19 | action.moveToElement(element).build().perform(); 20 | } 21 | 22 | //explicit wait example 23 | protected void waitVisibilityOf(WebElement element){ 24 | WebDriverWait wait = new WebDriverWait(driver, 30); 25 | wait.until(ExpectedConditions.visibilityOf(element)); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/pages/EcommerceMainPage.java: -------------------------------------------------------------------------------- 1 | package pages; 2 | 3 | import org.openqa.selenium.support.PageFactory; 4 | 5 | public class EcommerceMainPage extends EcommerceMainPageElementMap { 6 | 7 | public EcommerceMainPage(){ 8 | PageFactory.initElements(driver, this); 9 | } 10 | 11 | public void pesquisarProduto(String produto){ 12 | txtPesquisarProduto.sendKeys(produto); 13 | btnPesquisarProduto.click(); 14 | } 15 | 16 | public boolean isPesquisaRetornouResultados(){ 17 | return !lblQtdResultadosEncontrados.getText().contains("0"); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/pages/EcommerceMainPageElementMap.java: -------------------------------------------------------------------------------- 1 | package pages; 2 | 3 | import org.openqa.selenium.WebElement; 4 | import org.openqa.selenium.support.FindBy; 5 | 6 | public class EcommerceMainPageElementMap extends CommonPage { 7 | 8 | @FindBy(id = "search_query_top") 9 | protected WebElement txtPesquisarProduto; 10 | 11 | @FindBy(name = "submit_search") 12 | protected WebElement btnPesquisarProduto; 13 | 14 | @FindBy(css = ".heading-counter") 15 | protected WebElement lblQtdResultadosEncontrados; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/steps/CommonSteps.java: -------------------------------------------------------------------------------- 1 | package steps; 2 | 3 | import cucumber.api.java.pt.Dado; 4 | import util.TestRule; 5 | 6 | public class CommonSteps { 7 | 8 | @Dado("que acesso o ecommerce") 9 | public void acessarEcommerce(){ 10 | String ecommerceUrl = "http://automationpractice.com"; 11 | TestRule.abrirNavegador(ecommerceUrl); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/steps/EcommerceMainSteps.java: -------------------------------------------------------------------------------- 1 | package steps; 2 | 3 | import cucumber.api.java.pt.E; 4 | import cucumber.api.java.pt.Entao; 5 | import org.junit.Assert; 6 | import pages.EcommerceMainPage; 7 | 8 | public class EcommerceMainSteps { 9 | 10 | @E("pesquiso o produto \"(.*)\"") 11 | public void pesquisarProduto(String produto){ 12 | EcommerceMainPage ecommerceMainPage = new EcommerceMainPage(); 13 | ecommerceMainPage.pesquisarProduto(produto); 14 | } 15 | 16 | @Entao("a pesquisa deve retornar resultados") 17 | public void validarQuePesquisaRetornouResultados(){ 18 | EcommerceMainPage ecommerceMainPage = new EcommerceMainPage(); 19 | Assert.assertTrue("O resultado da pesquisa está vazio.", ecommerceMainPage.isPesquisaRetornouResultados()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/tests/RunTest.java: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import cucumber.api.CucumberOptions; 4 | import cucumber.api.junit.Cucumber; 5 | import org.junit.ClassRule; 6 | import org.junit.runner.RunWith; 7 | import util.TestRule; 8 | 9 | @RunWith(Cucumber.class) 10 | @CucumberOptions( 11 | features = "classpath:features", 12 | tags = "@run", 13 | glue = {""} 14 | ) 15 | public class RunTest { 16 | 17 | @ClassRule 18 | public static TestRule testRule = new TestRule(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/util/TestRule.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import cucumber.api.Scenario; 4 | import cucumber.api.java.After; 5 | import cucumber.api.java.Before; 6 | import org.junit.rules.TestWatcher; 7 | import org.junit.runner.Description; 8 | import org.openqa.selenium.WebDriver; 9 | import org.openqa.selenium.chrome.ChromeDriver; 10 | import org.openqa.selenium.chrome.ChromeOptions; 11 | 12 | public class TestRule extends TestWatcher { 13 | 14 | private static WebDriver driver; 15 | 16 | public TestRule(){ 17 | super(); 18 | } 19 | 20 | @Override 21 | protected void starting(Description description){} 22 | 23 | @Before 24 | public void beforeScenario(Scenario scenario){} 25 | 26 | @After 27 | public void afterScenario(){ 28 | if(driver != null){ 29 | driver.close(); 30 | driver.quit(); 31 | driver = null; 32 | } 33 | } 34 | 35 | protected void finished(Description description){ 36 | super.finished(description); 37 | } 38 | 39 | public static WebDriver getDriver(){ 40 | return driver; 41 | } 42 | 43 | public static void abrirNavegador(String url){ 44 | ChromeOptions chromeOpts = new ChromeOptions(); 45 | chromeOpts.addArguments("start-maximized"); 46 | Utils.setDriverByOS(); 47 | 48 | driver = new ChromeDriver(chromeOpts); 49 | driver.manage().window().maximize(); 50 | driver.navigate().to(url); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/util/Utils.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class Utils { 4 | 5 | protected static void setDriverByOS(){ 6 | String driverPath = "src/test/resources/drivers/"; 7 | if(System.getProperty("os.name").contains("Windows")){ 8 | driverPath = driverPath + "chromedriver.exe"; 9 | }else{ 10 | driverPath = driverPath + "chromedriver"; 11 | } 12 | System.setProperty("webdriver.chrome.driver", driverPath); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/drivers/READ.txt: -------------------------------------------------------------------------------- 1 | Por conveniência, faça o download do chromedriver adequado para o seu sistema operacional e adicione neste diretório. 2 | Local para download: https://chromedriver.chromium.org/downloads -------------------------------------------------------------------------------- /src/test/resources/features/Pesquisa.feature: -------------------------------------------------------------------------------- 1 | #language: pt 2 | #encoding: utf-8 3 | #@run 4 | Funcionalidade: Pesquisa 5 | 6 | Contexto: 7 | Dado que acesso o ecommerce 8 | 9 | @run 10 | Cenario: Pesquisar produto 11 | Quando pesquiso o produto "t-shirt" 12 | Entao a pesquisa deve retornar resultados 13 | 14 | Esquema do Cenario: Pesquisar produtos 15 | Quando pesquiso o produto "" 16 | Entao a pesquisa deve retornar resultados 17 | Exemplos: 18 | | nome_produto | 19 | | t-shirt | 20 | | short | 21 | | shoes | --------------------------------------------------------------------------------