Esempio di test in Java
Not for use with personal data
Si assicuri di consultare la guida completa all'installazione di Appium con axe DevTools Mobile se è agli inizi, o altri esempi di axe DevTools Mobile per Appium in altre lingue.
Esempio completo con UIAutomator2
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import org.junit.jupiter.api.*;
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.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AndroidDebugTest {
private static AndroidDriver driver;
// The axeSettings object still accepts apiKey and axeServiceUrl but is not required
// if you are going to make one time @BeforeAll annotated call to 'mobile: axeStartSession'
private static Map<String, Object> axeSettings;
private static final String API_KEY = "<YOUR_API_KEY>";
private static final String PROJECT_ID = "<YOUR_DEV_HUB_PROJECT_ID>";
private static final String APP_PACKAGE = "<YOUR_APP_PACKAGE_NAME>";
// It is very important to make a call to 'mobile: axeStartSession' inside @BeforeAll annotated
// method to setup your session for posting to Dev Hub.
@BeforeAll
public static void setUp() throws MalformedURLException {
axeSettings = new HashMap<>();
axeSettings.put("tags", new String[]{"appium", "qa"});
axeSettings.put("uploadToDashboard", true);
axeSettings.put("ignoreRules", new String[]{"ScreenOrientation"});
UiAutomator2Options options = new UiAutomator2Options()
.setPlatformName("Android")
.setDeviceName("Android")
.setAppPackage(APP_PACKAGE)
.setAppActivity(".MainActivity")
.setAutomationName("AxeUiAutomator2")
.setUiautomator2ServerLaunchTimeout(Duration.ofMillis(60000))
.setUiautomator2ServerInstallTimeout(Duration.ofMillis(60000))
.setAdbExecTimeout(Duration.ofMillis(60000))
.setIgnoreHiddenApiPolicyError(true)
.setDisableWindowAnimation(true)
.setCapability("waitForIdle", true)
.setNewCommandTimeout(Duration.ofSeconds(300))
.setNoReset(false)
.setFullReset(false);
driver = new AndroidDriver(new URL("http://localhost:4723/"), options);
// Make one time call to setup your session for posting to Dev Hub.
// This also accepts axeServiceUrl in case of private instance.
Map<String, Object> axeAuthSettings = new HashMap<>();
axeAuthSettings.put("apiKey", API_KEY);
axeAuthSettings.put("projectId", PROJECT_ID);
driver.executeScript("mobile: axeStartSession", axeAuthSettings);
}
@AfterAll
public static void tearDown() {
if (driver != null) {
driver.quit();
}
}
private void dismissSystemUIError() {
try {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
WebElement systemPopup = wait.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//*[contains(@text, 'System UI')]")));
if (systemPopup.isDisplayed()) {
WebElement waitButton = wait.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//*[contains(@text, 'Wait')]")));
waitButton.click();
System.out.println("Dismissed the System UI error popup by clicking 'Wait'.");
}
} catch (Exception e) {
System.out.println("No System UI error popup appeared.");
}
}
private void launchApp() {
try {
driver.terminateApp(APP_PACKAGE);
Thread.sleep(1000); // Give the app time to fully terminate
} catch (Exception e) {
System.out.println("App was not running or failed to terminate: " + e.getMessage());
}
driver.activateApp(APP_PACKAGE);
try {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
wait.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//*[contains(@text, 'Screen Name')]")));
} catch (Exception e) {
dismissSystemUIError();
// Try again after dismissing the error (if not, then fail)
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
wait.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//*[contains(@text, 'Screen Name')]")));
}
}
@BeforeEach
public void beforeEach() {
launchApp();
}
// Now since your session is authenticated you can keep making 'mobile: axeScan' call
// like below in test1 and test2. The scans will be uploaded to the dashboard and also grouped in Dev Hub.
@Test
@Order(1)
public void test1() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//*[contains(@text, 'Screen Name')]")));
System.out.println(element.getText());
Map<String, Object> appiumScanResult = (Map<String, Object>) driver.executeScript("mobile: axeScan", axeSettings);
List<?> results = (List<?>) appiumScanResult.get("axeRuleResults");
System.out.println("debug: Total results: " + results.size());
}
@Test
@Order(2)
public void test2() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//*[contains(@text, 'Screen Name')]")));
element.click();
driver.findElement(By.xpath("//*[contains(@text, 'announced by a screen')]"));
Map<String, Object> appiumScanResult = (Map<String, Object>) driver.executeScript("mobile: axeScan", axeSettings);
List<?> results = (List<?>) appiumScanResult.get("axeRuleResults");
System.out.println("debug: Total results: " + results.size());
}
}
Esempio completo con XCUITest
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.ios.options.XCUITestOptions;
import org.junit.jupiter.api.*;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class IOSMapsDebugTest {
private static IOSDriver driver;
// The axeSettings object still accepts apiKey and axeServiceUrl but is not required
// if you are going to make one time @BeforeAll annotated call to 'mobile: axeStartSession'
private static Map<String, Object> axeSettings;
private static final String API_KEY = "<YOUR_API_KEY>";
private static final String PROJECT_ID = "<YOUR_DEV_HUB_PROJECT_ID>";
private static final String BUNDLE_ID = "com.apple.Maps";
// It is very important to make a call to 'mobile: axeStartSession' inside @BeforeAll annotated
// method to setup your session for posting to Dev Hub.
@BeforeAll
public static void setUp() throws MalformedURLException {
axeSettings = new HashMap<>();
axeSettings.put("tags", new String[]{"appium", "qa", "ios"});
axeSettings.put("uploadToDashboard", true);
axeSettings.put("ignoreRules", new String[]{"ScreenOrientation"});
// Matching the working sample - minimal capabilities
XCUITestOptions options = new XCUITestOptions()
.setPlatformName("iOS")
.setAutomationName("AxeXCUITest")
.setUdid("<YOUR_DEVICE_OR_SIMULATOR_UDID>")
.setBundleId(BUNDLE_ID)
.setWdaLaunchTimeout(Duration.ofMillis(960000)); // 16 minutes like the working sample
// NOT specifying platformVersion - let it auto-detect
driver = new IOSDriver(new URL("http://127.0.0.1:4723/"), options);
// Make one time call to setup your session for posting to Dev Hub.
// This also accepts axeServiceUrl in case of private instance.
Map<String, Object> axeAuthSettings = new HashMap<>();
axeAuthSettings.put("apiKey", API_KEY);
axeAuthSettings.put("projectId", PROJECT_ID);
axeAuthSettings.put("axeServiceUrl", "https://mobile-qa.dequelabs.com");
driver.executeScript("mobile: axeStartSession", axeAuthSettings);
}
@AfterAll
public static void tearDown() {
if (driver != null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
driver.quit();
}
}
private void launchApp() {
driver.activateApp(BUNDLE_ID);
}
@BeforeEach
public void beforeEach() {
launchApp();
}
// Now since your session is authenticated you can keep making 'mobile: axeScan' call
// like below in test1 and test2. The scans will be uploaded to the dashboard and also grouped in Dev Hub.
@Test
@Order(1)
@Timeout(10)
public void test1_scanMainScreen() {
Map<String, Object> appiumScanResult = (Map<String, Object>) driver.executeScript("mobile: axeScan", axeSettings);
List<?> results = (List<?>) appiumScanResult.get("axeRuleResults");
System.out.println("debug: Total results: " + results.size());
}
@Test
@Order(2)
@Timeout(10)
public void test2_clickSearchAndScan() {
Map<String, Object> appiumScanResult = (Map<String, Object>) driver.executeScript("mobile: axeScan", axeSettings);
List<?> results = (List<?>) appiumScanResult.get("axeRuleResults");
System.out.println("debug: Total results: " + results.size());
}
}
note
Utilizzi TestNG? Nessun problema. I nostri driver Appium sono compatibili con questo framework di test. Framework di test.
