在前面的课程我们已经学习完成appium入门了,新来的同学可以从此跳转学习 appium入门
下面我们来学习如何使用代码来编写,将实现自动化测试和生成测试报告
Appium 是一个开源的移动端自动化测试工具,支持 Android 和 iOS 平台。结合 Java 语言,可以实现高效的自动化测试脚本编写。以下是具体实现步骤。
Java JDK(1.8 或更高版本)和 Maven。 maven下载教程
安装 Node.js 以运行 Appium 服务器。
配置 Android 环境变量(如 ANDROID_HOME
)并确保 adb
工具可用
在pom.xml配置文件中使用 Maven 添加 Appium 和 TestNG 依赖到项目中:
io.appium
java-client
9.4.0
org.testng
testng
7.8.0
test
下面我们进入我们测试目录 project>src>test>java>org.example
我们创建一个demoTest,代码如下:
package org.example;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import org.example.util.WelcomeUtil;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URL;
public class demoTest {
private AppiumDriver driver;
@BeforeTest
public void setUp() throws MalformedURLException {
//建立连接
UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformVersion("13");
options.setDeviceName("192.168.10.104:5555");
options.setAutomationName("UiAutomator2");
options.setAppPackage("com.fqcx.welcome");
options.setAppActivity("com.fqcx.welcome.activity.MainActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), options);
}
@Test
public void test(){
//测试内容
}
@AfterTest
public void tearDown(){
//断开连接
driver.quit();
}
}
这段 Java 代码是一个基于 TestNG 和 Appium 的简单自动化测试框架模板,用于对移动应用进行自动化测试。我会从代码结构、各部分功能和需要补充完善的内容来为你讲解:
1.首先定义一个AppiumDriver对象
2.在@BeforeTest注解下的方法建立连接,信息需要填写自己设备的版面,名字和测试应用包名,启动页面
PlatformVersion 安卓版本,获取命令:adb shell getprop ro.build.version.release
DeviceName 设备名称,获取命令:adb devices
AppPackage和AppActivity可根据adb命令获取: adb shell dumpsys activity top | grep ACTIVITY
后面是Appium Server 的监听地址,127.0.0.1是本地环回地址。告诉驱动去哪里找 Appium Server,以便发送自动化命令
3.在@Test注解下写测试内容,稍候具体讲解
4.@AfterTest注解的tearDown方法:在当前类的所有测试方法执行完毕后运行,主要用于清理和释放资源。代码中 driver.quit(); 语句用于关闭AppiumDriver实列,断开与移动设备的连接,确保测试结束后资源被正确释放,避免占用系统资源。
我们将测试一个如图计算器APP,下面我们来正式开始
1.首先我们拿到测试设备名称,版本号。以及测试APP的包名和启动页面
包名为:com.rp.calculator
启动页面为:com.rp.calculator.MainActivity
@BeforeTest
public void setUp() throws MalformedURLException {
//建立连接
UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformVersion("13");
options.setDeviceName("192.168.10.104:5555");
options.setAutomationName("UiAutomator2");
options.setAppPackage("com.rp.calculator");
options.setAppActivity("com.rp.calculator.MainActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), options);
}
2.现在我们先编写两条测试用例实例:
用例编号 | 用例名称 | 操作步骤 | 预期结果 |
Test_01 | 输入溢出,测试超长数字时是否截断或报错 | 1.点击7个9 2.点击* 3.点击10个9 4.点击= |
9999999*9999999 =99999980000001 |
Test_02 | 零值处理,0参与的加减乘除 | 1. 0+983= 2. 0-983= 3. 983-0= 4. 0*3= 5. 12/0= 6. 0/12= |
1. 983 2. -983 3. 983 4. 0 5. ∞ 6. 0 |
下面我们用代码实现。我们发现,需要点击一个button很多次,我们可以把他写成一个方法。我们传入需要点击的数字就好,根据传入的数字不同,获取不同的xpath点击。
// 通用点击方法(带等待)
private void clickElement(By locator) {
wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
}
// 输入数字
public void inputNumber(String number) {
for (char c : number.toCharArray()) {
String digit = String.valueOf(c);
/* if (digit.equals(".")) {
clickElement(By.id("com.rp.calculator:id/dec"));
}*/
clickElement(By.xpath("//android.widget.Button[@text=\"" + digit + "\"]"));
}
}
//测试代码
@Test(priority = 1)
public void test1() {
//最大值
for (int i = 0; i < 7; i++) {
inputNumber("9");
}
driver.findElement(By.xpath("//android.widget.Button[@resource-id=\"com.rp.calculator:id/signButton\"]")).click();
for (int i = 0; i < 9; i++) {
inputNumber("9");
}
driver.findElement(By.id("com.rp.calculator:id/eql")).click();
String expressionText = driver.findElement(By.id("com.rp.calculator:id/qusTv")).getText();
String resultText = driver.findElement(By.id("com.rp.calculator:id/ansTv")).getText();
Assert.assertEquals(expressionText,"9999999*9999999","输入值不符合");
Assert.assertEquals(resultText,"99999980000001","输出结果不符合");
}
上面为第一条用例的测试代码。我们可以给测试用例编priority=1。 我们已知输入框最大输入15个字符。 我们使用xpath元素定位到9,首先输入7个9,再点击*。最后输入9个9,如果有长度限制,实际只输入了7个9,再点击等于。
最后我们可以断言判断:
拿到输入框的文本,判断是否是9999999*9999999。如果是则PASS,否则提示输入值不符合
拿到输出结果文本,判断是否是99999980000001。如果是则PASS,否则提示输出结果不符合
下面我们来编写第二条测试用例,零值处理
我们看到用例有很多数据,可以创建一个参数化测试数据源,为测试方法提供多组输入数据和预期结果,从而实现一个测试方法自动执行多次不同的测试场景。
// 数据提供者:生成多个测试用例
@DataProvider(name = "calculationData3")
public Object[][] provideCalculations() {
return new Object[][]{
{"0", "+", "983", "983"},
{"0", "-", "983", "-983"},
{"983", "-", "0", "983"},
{"0", "×", "3", "0"},
{"12", "÷", "0", "∞"},
{"0", "÷", "2", "0"},
};
}
经过后面优化,发现加减乘除点击次数也比较多,我们也可以写成一个方法:
// 输入运算符
public void inputOperator(String operator) {
String xpath;
switch (operator) {
case "+":
xpath = "//android.widget.Button[@text=\"+\"]";
break;
case "-":
xpath = "//android.widget.Button[@text=\"-\"]";
break;
case "×":
xpath = "//android.widget.Button[@text=\"×\"]";
break;
case "÷":
xpath = "//android.widget.Button[@text=\"÷\"]";
break;
default:
throw new IllegalArgumentException("不支持的运算符: " + operator);
}
clickElement(By.xpath(xpath));
}
最后编写我们的测试代码:
@Test(dataProvider = "calculationData3", priority = 2)
public void test3(String num1, String operator, String num2, String expectedResult) {
inputNumber(num1);
inputOperator(operator);
inputNumber(num2);
driver.findElement(By.id("com.rp.calculator:id/eql")).click();
String expressionText = driver.findElement(By.id("com.rp.calculator:id/qusTv")).getText();
String resultText = driver.findElement(By.id("com.rp.calculator:id/ansTv")).getText();
Assert.assertEquals(expressionText,expectedResult,"输入值不符合");
Assert.assertEquals(resultText,expectedResult,"输出结果不符合");
}
现在我们的自动化测试用例编写完毕了,总共写了两条,后续同学们也可以自己再完善,下面附上完整的源码和测试结果。
package org.example;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import org.example.util.CalculatorUtil;
import org.example.util.WelcomeUtil;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
public class demoTest {
private AppiumDriver driver;
private static final int TIMEOUT = 10; // 等待超时时间(秒)
private WebDriverWait wait;
@BeforeTest
public void setUp() throws MalformedURLException {
//建立连接
UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformVersion("13");
options.setDeviceName("192.168.10.104:5555");
options.setAutomationName("UiAutomator2");
options.setAppPackage("com.rp.calculator");
options.setAppActivity("com.rp.calculator.MainActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), options);
wait = new WebDriverWait(driver, Duration.ofSeconds(TIMEOUT));
}
// 通用点击方法(带等待)
private void clickElement(By locator) {
wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
}
public void inputNumber(String number) {
for (char c : number.toCharArray()) {
String digit = String.valueOf(c);
/* if (digit.equals(".")) {
clickElement(By.id("com.rp.calculator:id/dec"));
}*/
clickElement(By.xpath("//android.widget.Button[@text=\"" + digit + "\"]"));
}
}
@Test(priority = 1)
public void test1() {
//最大值
for (int i = 0; i < 7; i++) {
inputNumber("9");
}
driver.findElement(By.xpath("//android.widget.Button[@resource-id=\"com.rp.calculator:id/signButton\"]")).click();
for (int i = 0; i < 9; i++) {
inputNumber("9");
}
driver.findElement(By.id("com.rp.calculator:id/eql")).click();
String expressionText = driver.findElement(By.id("com.rp.calculator:id/qusTv")).getText();
String resultText = driver.findElement(By.id("com.rp.calculator:id/ansTv")).getText();
Assert.assertEquals(expressionText, "9999999×9999999", "输入值不符合");
Assert.assertEquals(resultText, "99999980000001", "输出结果不符合");
}
// 输入运算符
public void inputOperator(String operator) {
String xpath;
switch (operator) {
case "+":
xpath = "//android.widget.Button[@text=\"+\"]";
break;
case "-":
xpath = "//android.widget.Button[@text=\"-\"]";
break;
case "×":
xpath = "//android.widget.Button[@text=\"×\"]";
break;
case "÷":
xpath = "//android.widget.Button[@text=\"÷\"]";
break;
default:
throw new IllegalArgumentException("不支持的运算符: " + operator);
}
clickElement(By.xpath(xpath));
}
// 数据提供者:生成多个测试用例
@DataProvider(name = "calculationData3")
public Object[][] provideCalculations() {
return new Object[][]{
{"0", "+", "983", "983"},
{"0", "-", "983", "-983"},
{"983", "-", "0", "983"},
{"0", "×", "3", "0"},
{"12", "÷", "0", "∞"},
{"0", "÷", "2", "0"},
};
}
@Test(dataProvider = "calculationData3", priority = 2)
public void test3(String num1, String operator, String num2, String expectedResult) {
inputNumber(num1);
inputOperator(operator);
inputNumber(num2);
driver.findElement(By.id("com.rp.calculator:id/eql")).click();
String expressionText = driver.findElement(By.id("com.rp.calculator:id/qusTv")).getText();
String resultText = driver.findElement(By.id("com.rp.calculator:id/ansTv")).getText();
Assert.assertEquals(resultText, expectedResult, "输出结果不符合");
}
@AfterTest
public void tearDown() {
//断开连接
driver.quit();
}
}
上面就是Appium+Java的实战例子了。我们从环境搭建--->认识基本框架--->编写测试用例--->实现自动化测试脚本。相信大家有了个基础的了解。但是这些还是不够的,后面我还会讲解生成测试报告,滑动操作等。