Skip to content

Latest commit

 

History

History
216 lines (172 loc) · 6.42 KB

File metadata and controls

216 lines (172 loc) · 6.42 KB

Organização de Testes

À medida que o projeto cresce, manter os testes organizados e manuteníveis torna-se essencial. Esta aula apresenta boas práticas de organização para projetos Appium de médio e grande porte.

Estrutura Recomendada

src/test/
├── java/
│   ├── base/
│   │   ├── BaseTest.java          # Setup/Teardown do driver
│   │   └── BasePage.java          # Métodos comuns a todas as páginas
│   ├── pages/
│   │   ├── LoginPage.java
│   │   ├── HomePage.java
│   │   ├── PerfilPage.java
│   │   └── CheckoutPage.java
│   ├── tests/
│   │   ├── LoginTest.java
│   │   ├── HomeTest.java
│   │   └── CheckoutTest.java
│   └── utils/
│       ├── DriverFactory.java     # Cria o driver conforme a plataforma
│       ├── WaitHelper.java        # Métodos de espera
│       ├── ScreenshotHelper.java  # Captura de tela em falhas
│       └── TestDataHelper.java    # Geração de dados de teste
└── resources/
    ├── apps/
    │   ├── meuapp.apk
    │   └── meuapp.app
    ├── testdata/
    │   └── usuarios.json
    ├── config.properties
    └── testng.xml

BasePage.java

Centralize métodos comuns a todas as Page Objects:

package base;

import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;

public abstract class BasePage {

    protected final AndroidDriver driver;
    protected final WebDriverWait wait;

    protected BasePage(AndroidDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(15));
    }

    protected WebElement esperarVisivel(By locator) {
        return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
    }

    protected WebElement esperarClicavel(By locator) {
        return wait.until(ExpectedConditions.elementToBeClickable(locator));
    }

    protected void clicar(By locator) {
        esperarClicavel(locator).click();
    }

    protected void digitar(By locator, String texto) {
        WebElement campo = esperarVisivel(locator);
        campo.clear();
        campo.sendKeys(texto);
    }

    protected String obterTexto(By locator) {
        return esperarVisivel(locator).getText();
    }
}

DriverFactory.java

Centralize a criação de drivers para suportar múltiplas plataformas:

package utils;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.ios.options.XCUITestOptions;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

public class DriverFactory {

    public static AppiumDriver createDriver(Properties config) throws MalformedURLException {
        String plataforma = config.getProperty("platform");

        if ("android".equalsIgnoreCase(plataforma)) {
            return createAndroidDriver(config);
        } else if ("ios".equalsIgnoreCase(plataforma)) {
            return createIOSDriver(config);
        }
        throw new IllegalArgumentException("Plataforma não suportada: " + plataforma);
    }

    private static AndroidDriver createAndroidDriver(Properties config) throws MalformedURLException {
        UiAutomator2Options options = new UiAutomator2Options();
        options.setDeviceName(config.getProperty("android.device"));
        options.setApp(config.getProperty("android.app"));
        options.setAutoGrantPermissions(true);
        return new AndroidDriver(new URL(config.getProperty("appium.url")), options);
    }

    private static IOSDriver createIOSDriver(Properties config) throws MalformedURLException {
        XCUITestOptions options = new XCUITestOptions();
        options.setDeviceName(config.getProperty("ios.device"));
        options.setApp(config.getProperty("ios.app"));
        options.setAutoAcceptAlerts(true);
        return new IOSDriver(new URL(config.getProperty("appium.url")), options);
    }
}

ScreenshotHelper.java

Capture screenshots automaticamente quando um teste falhar:

package utils;

import io.appium.java_client.AppiumDriver;
import org.openqa.selenium.OutputType;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class ScreenshotHelper {

    public static void capturar(AppiumDriver driver, String nomeDoTeste) {
        try {
            String timestamp = LocalDateTime.now()
                .format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
            String caminho = "target/screenshots/" + nomeDoTeste + "_" + timestamp + ".png";

            File screenshot = driver.getScreenshotAs(OutputType.FILE);
            FileUtils.copyFile(screenshot, new File(caminho));
            System.out.println("Screenshot salva em: " + caminho);
        } catch (Exception e) {
            System.err.println("Falha ao capturar screenshot: " + e.getMessage());
        }
    }
}

Use no @AfterMethod:

@AfterMethod
public void tearDown(ITestResult result) {
    if (result.getStatus() == ITestResult.FAILURE) {
        ScreenshotHelper.capturar(driver, result.getName());
    }
    driver.quit();
}

Grupos de Testes com TestNG

Organize os testes em grupos para execução seletiva:

@Test(groups = {"smoke", "login"})
public void loginComSucesso() { ... }

@Test(groups = {"regressao", "login"})
public void loginComSenhaErrada() { ... }

Execute apenas o grupo smoke:

<!-- testng.xml -->
<suite name="Suite">
  <test name="Smoke Tests">
    <groups>
      <run>
        <include name="smoke"/>
      </run>
    </groups>
    <classes>
      <class name="tests.LoginTest"/>
    </classes>
  </test>
</suite>

Boas Práticas

  • Mantenha cada @Test independente — não assuma que outro teste rodou antes
  • Use @BeforeMethod para estado limpo: reinstale ou resete o app quando necessário
  • Capture screenshots em falhas para diagnóstico mais fácil
  • Use grupos (smoke, regressao) para facilitar a execução seletiva em CI/CD

Ir para: Testes Paralelos