作业讲解
雪球 app 搜索功能自动化测试实战
需求分析
- 被测应用:雪球 App,请在应用商店直接安装。
- 雪球 App 介绍
- 雪球 app 是一款免费版,非常实用的股票平台,提供热点资讯内容和实时行情,提供了证券交流交易,公募、理财服务 - 雪球 app 功能包括搜索股票,查看行情,交易,浏览热门文章,发帖,登录,注册,等功能
- 测试场景:搜索股票
用例设计
- 打开【雪球】应用首页
- 点击搜索框(点击之前,判断搜索框的是否可用,并查看搜索框 name 属性值,并获取搜索框坐标,以及它的宽高)
- 向搜索框输入:alibaba
- 判断【阿里巴巴】是否可见
- 如果可见,打印 “搜索成功” - 如果不可见,打印 “搜索失败”
用例编写思路
- pytest 测试框架编写
- 添加隐式等待
- 添加测试装置
- 添加断言
步骤拆解
- 使用 setup_class 函数创建 driver 建立连接并打开【雪球】应用首页
因为雪球应用需要登录才能进入首页,看到搜索框元素。所以 capability 中需要设置不清空缓存信息。
这样执行测试时,就可以提前打开雪球 app,先完成登录操作,进入首页后,再运行代码完成用例执行。
Python 示例:
class TestXueqiu:
def setup_class(self):
'''
完成 capability 设置
初始化 driver
:return:
'''
# 设置 cpability
caps = {
# 设置 app 安装的平台(Android,iOS)
"platformName": "Android",
# 设置 appium 驱动
"appium:automationName": "uiautomator2",
# 设置设备名称
"appium:deviceName": "emulator-5554",
# 设置被测 app 的包名
"appium:appPackage": "com.xueqiu.android",
# 设置被测 app 启动页面的 Activity
"appium:appActivity": ".view.WelcomeActivityAlias",
# 不清空缓存信息,保存登录信息
"appium:noReset": True,
# 强制app重启,整个测试运行之前重启 app
"appium:forceAppLaunch": True,
# 跳过安装,权限设置等操作
"appium:skipDeviceInitialization": True
}
# 初始化 driver
self.driver = webdriver.Remote(
"http://127.0.0.1:4723",
options=UiAutomator2Options().load_capabilities(caps)
)
# 隐式等待
self.driver.implicitly_wait(20)
Java 示例:
public class TestXueqiu {
private static AndroidDriver driver;
@BeforeAll
public static void setUp() throws MalformedURLException {
// 初始化capability
DesiredCapabilities caps = new DesiredCapabilities();
// 设置 app 安装的平台(Android、iOS)
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
// 设置 appium 驱动
caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2");
// 设置设备名称
caps.setCapability(MobileCapabilityType.DEVICE_NAME, "emulator-5554");
// 设置 app 的包名
caps.setCapability("appPackage", "com.xueqiu.android");
// 设置 app 的启动页
caps.setCapability("appActivity", ".view.WelcomeActivityAlias");
// 设置 app 不清空缓存
caps.setCapability("appium:noReset", true);
// 设置 app 不重启
caps.setCapability("appium:shouldTerminateApp", true);
// 设置启动url
URL remoteUrl = new URL("http://127.0.0.1:4723");
// 初始化driver
driver = new AndroidDriver(remoteUrl, caps);
// 隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
}
- 点击搜索框(点击之前,判断搜索框的是否可用,并查看搜索框 name 属性值,并获取搜索框坐标,以及它的宽高)
Python 示例:
def test_search(self):
# 定义搜索关键词
search_key = "alibaba"
## 定位到搜索框
searchbox_ele = self.driver.find_element(
AppiumBy.ID, "com.xueqiu.android:id/home_search"
)
# 先判断一下搜索框是否可用
if searchbox_ele.is_enabled():
# 1. 查看搜索框属性
searchbox_text = searchbox_ele.text
print(f"首页搜索框的 text:{searchbox_text}")
searchbox_location = searchbox_ele.location
print(f"首页搜索框的 location坐标为:{searchbox_location}")
searchbox_size = searchbox_ele.size
print(f"首页搜索框的 size 宽高:{searchbox_size}")
# 2. 点击搜索框
searchbox_ele.click()
Java 示例:
@Test
public void testSearch() {
String searchKey = "alibaba";
WebElement searchBox = driver.findElement(AppiumBy.id("com.xueqiu.android:id/home_search"));
if (searchBox.isEnabled()) {
String searchBoxTest = searchBox.getText();
System.out.println("首页搜索框的 text:" + searchBoxTest);
org.openqa.selenium.Point searchboxLocation = searchBox.getLocation();
System.out.println("首页搜索框的 location坐标为:" + searchboxLocation);
org.openqa.selenium.Dimension searchboxSize = searchBox.getSize();
System.out.println("首页搜索框的 size 宽高:" + searchboxSize);
searchBox.click();
}
}
- 如果搜索框可用,向搜索框输入:alibaba
Python 示例:
# 3. 向搜索框输入:alibaba
self.driver.find_element(
AppiumBy.ID,
"com.xueqiu.android:id/search_input_text"
).send_keys(search_key)
Java 示例:
// 3. 向搜索框输入关键词:alibaba
WebElement searchInputEle = driver.findElement(AppiumBy.id("com.xueqiu.android:id/search_input_text"));
searchInputEle.sendKeys(searchKey);
- 判断【阿里巴巴】是否可见,如果可见打印搜索,断言 result 为 true
- 向输入框传入
alibaba
后,搜索结果如图所示 - 同时也注意到这个列表下方还有一个阿里巴巴,使用 Xpath 定位,会同时定位到两个元素,因为我们需要定位的是第一个元素,使用find_element
会在找到第一个元素就将该元素返回,所以是可以正常定位到的。如果需要定位到页面下方的另一个阿里巴巴
可以使用find_elements
定位到多个元素再进行选择。
Python 示例:
# 4. 判断【阿里巴巴】是否可见
alibaba_element = self.driver.find_element(
AppiumBy.XPATH,
"//*[@text='阿里巴巴']"
)
result = alibaba_element.is_displayed()
print(result)
# 如果可见,打印“搜索成功”
if result == True:
print("搜索成功")
# 如果不可见,打印“搜索失败
else:
print("搜索失败")
assert result == True
Java 示例:
// 4. 判断【阿里巴巴】是否可见
WebElement alibabaElement = driver.findElement(AppiumBy.xpath("//*[@text='阿里巴巴']"));
boolean result = alibabaElement.isDisplayed();
System.out.println(result);
// 如果可见,打印“搜索成功”
if (result) {
System.out.println("搜索成功");
} else {
// 如果不可见,打印“搜索失败”
System.out.println("搜索失败");
}
// 断言结果是否为真
assert result;
完整代码示例
Python 示例:
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
class TestXueqiu:
def setup_class(self):
'''
完成 capability 设置
初始化 driver
:return:
'''
# 设置 cpability
caps = {
# 设置 app 安装的平台(Android,iOS)
"platformName": "Android",
# 设置 appium 驱动
"appium:automationName": "uiautomator2",
# 设置设备名称
"appium:deviceName": "emulator-5554",
# 设置被测 app 的包名
"appium:appPackage": "com.xueqiu.android",
# 设置被测 app 启动页面的 Activity
"appium:appActivity": ".view.WelcomeActivityAlias",
# 不清空缓存信息,保存登录信息
"appium:noReset": True,
# 强制app重启,整个测试运行之前重启 app
"appium:forceAppLaunch": True,
# 跳过安装,权限设置等操作
"appium:skipDeviceInitialization": True
}
# 初始化 driver
self.driver = webdriver.Remote(
"http://127.0.0.1:4723",
options=UiAutomator2Options().load_capabilities(caps)
)
# 隐式等待
self.driver.implicitly_wait(20)
def teardown_class(self):
'''
关闭 driver
:return:
'''
self.driver.quit()
def test_search(self):
"""
1. 判断搜索框的是否可用
并查看搜索框 name 属性值,并获取搜索框坐标,以及它的宽高
2. 点击搜索框
3. 向搜索框输入:alibaba
4. 判断【阿里巴巴】是否可见
如果可见,打印“搜索成功”
如果不可见,打印“搜索失败
:return:
"""
# 1. 判断搜索框的是否可用,并查看搜索框 name 属性值,并获取搜索框坐标,以及它的宽高
search_key = "alibaba"
searchbox_ele = self.driver.find_element(
AppiumBy.ID, "com.xueqiu.android:id/home_search"
)
# 先判断一下搜索框是否可用
if searchbox_ele.is_enabled():
# 1. 查看搜索框属性
searchbox_text = searchbox_ele.text
print(f"首页搜索框的 text:{searchbox_text}")
searchbox_location = searchbox_ele.location
print(f"首页搜索框的 location坐标为:{searchbox_location}")
searchbox_size = searchbox_ele.size
print(f"首页搜索框的 size 宽高:{searchbox_size}")
# 2. 点击搜索框
searchbox_ele.click()
# 3. 向搜索框输入:alibaba
self.driver.find_element(
AppiumBy.ID,
"com.xueqiu.android:id/search_input_text"
).send_keys(search_key)
# 4. 判断【阿里巴巴】是否可见
alibaba_element = self.driver.find_element(
AppiumBy.XPATH,
"//*[@text='阿里巴巴']"
)
result = alibaba_element.is_displayed()
print(result)
# 如果可见,打印“搜索成功”
if result == True:
print("搜索成功")
# 如果不可见,打印“搜索失败
else:
print("搜索失败")
assert result == True
else:
print("搜索框不可用")
assert False
import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
public class TestXueqiu {
private static AndroidDriver driver;
@BeforeAll
public static void setUp() throws MalformedURLException {
// 初始化capability
DesiredCapabilities caps = new DesiredCapabilities();
// 设置 app 安装的平台(Android、iOS)
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
// 设置 appium 驱动
caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2");
// 设置设备名称
caps.setCapability(MobileCapabilityType.DEVICE_NAME, "emulator-5554");
// 设置 app 的包名
caps.setCapability("appPackage", "com.xueqiu.android");
// 设置 app 的启动页
caps.setCapability("appActivity", ".view.WelcomeActivityAlias");
// 设置 app 不清空缓存
caps.setCapability("appium:noReset", true);
// 设置 app 不重启
caps.setCapability("appium:shouldTerminateApp", true);
// 设置启动url
URL remoteUrl = new URL("http://127.0.0.1:4723");
// 初始化driver
driver = new AndroidDriver(remoteUrl, caps);
// 隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
}
@AfterAll
public static void tearDown() {
if (driver != null) {
driver.quit();
}
}
@Test
public void testSearch() {
// 1. 判断搜索框的是否可用,并查看搜索框 name 属性值,并获取搜索框坐标,以及它的宽高
String searchKey = "alibaba";
WebElement searchBox = driver.findElement(AppiumBy.id("com.xueqiu.android:id/home_search"));
// 先判断一下搜索框是否可用
if (searchBox.isEnabled()) {
// 1. 查看搜索框属性
String searchBoxTest = searchBox.getText();
System.out.println("首页搜索框的 text:" + searchBoxTest);
org.openqa.selenium.Point searchboxLocation = searchBox.getLocation();
System.out.println("首页搜索框的 location坐标为:" + searchboxLocation);
org.openqa.selenium.Dimension searchboxSize = searchBox.getSize();
System.out.println("首页搜索框的 size 宽高:" + searchboxSize);
// 2. 点击搜索框
searchBox.click();
// 3. 向搜索框输入:alibaba
WebElement searchInputEle = driver.findElement(AppiumBy.id("com.xueqiu.android:id/search_input_text"));
searchInputEle.sendKeys(searchKey);
// 4. 判断【阿里巴巴】是否可见
WebElement alibabaElement = driver.findElement(AppiumBy.xpath("//*[@text='阿里巴巴']"));
boolean result = alibabaElement.isDisplayed();
System.out.println(result);
// 如果可见,打印“搜索成功”
if (result) {
System.out.println("搜索成功");
} else {
// 如果不可见,打印“搜索失败”
System.out.println("搜索失败");
}
// 断言结果是否为真
assert result;
} else {
System.out.println("搜索框不可用");
assert false;
}
}
}
总结
- App 自动化测试用例编写