自动化测试用例
自动化测试用例¶
这里根据手工测试用例从 P0,P1,P2 级别的用例中选择一部分实现自动化测试。
目标¶
-
提升测试效率:自动化测试可以显著加快测试进程,尤其在大量重复测试和回归测试的情况下。
-
增强测试可靠性:自动化测试可以避免人为疏忽和错误,一旦设定测试脚本,测试过程和结果会变得可预测和一致。
-
扩大测试覆盖范围:自动化测试引擎可以在有限的时间内执行大量的测试,包括一些人工测试难以完成的大规模和复杂场景的测试,大大增强了测试的广度和深度。
-
灵活的测试时机:自动化测试可以在任何合适的时间,如休息时间、夜间进行,而非只能在人力资源允许的时间框内进行测试。
步骤¶
-
确定测试范围:明确需要自动化的测试内容和目标,通常是频繁进行的重复性测试、时间消耗大的测试、需要大量数据输入的测试。
-
选择合适的自动化测试工具:根据测试需求、应用特性、团队技能等因素,选择适合的测试框架和工具。
-
设计并编写测试脚本:根据测试需求为应用编写自动化测试脚本,需要考虑测试的完整性和扩展性,编写完成后需要对脚本进行调试和验证。
-
运行与调整测试:运行测试脚本,获取测试结果,根据结果调整和优化测试脚本,形成测试与优化的循环。
-
报告和分析测试结果:通过自动化测试工具产生详细的测试报告,分析测试结果,提供优化应用的方向和依据。
-
持续优化和维护测试脚本:随着应用的更新和迭代,测试脚本也需要持续优化和维护,以适应新的测试需求。
参考示例¶
import os
import sys
import allure
import pytest
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.common.touch_action import TouchAction
dir_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(dir_path)
from log_utils import logger
@allure.epic("ApiDemo")
class TestAppDemo:
def setup(self):
# 创建一个字典,desirecapbility
caps = {}
caps["platformName"] = "Android"
# Android 包名和页面名,获取命令:
# mac/linux: adb logcat ActivityManager:I | grep "cmp"
# windows: adb logcat ActivityManager:I | findstr "cmp"
caps["appPackage"] = "io.appium.android.apis"
caps["appActivity"] = ".ApiDemos"
caps["deviceName"] = "emulator-5554"
caps["noReset"] = "true"
# 创建driver ,与appium server建立连接,返回一个 session
# driver 变成self.driver 由局部变量变成实例变量,就可以在其它的方法中引用这个实例变量了
self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
self.driver.implicitly_wait(5)
logger.info(f"启动包名:{caps['appPackage']},启动页面:{caps['appActivity']}")
def teardown(self):
logger.info("保存当面页面截图tmp.png")
self.driver.save_screenshot("tmp.png")
logger.info("将截图添加到报告中")
allure.attach.file("tmp.png", name="页面截图",
attachment_type=allure.attachment_type.PNG)
self.driver.quit()
@pytest.mark.P0
@allure.feature("滑动验证")
def test_seeking(self):
"""
打开 demo.apk
1. 点击 Animation 进入下个页面
2. 点击 Seeking 进入下个页面
3. 查看【RUN】按钮是否显示/是否可点击
4. 查看【滑动条】是否显示/是否可用/是否可点击
5. 获取【滑动条】长度
6. 点击【滑动条】中心位置
:return:
"""
with allure.step("1.点击 Animation 进入下个页面"):
logger.info("点击 Animation")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Animation").click()
with allure.step("2.点击 Seeking 进入下个页面"):
logger.info("点击 Seeking")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Seeking").click()
with allure.step("3. 查看【RUN】按钮是否显示/是否可点击"):
run_element = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Run")
run_is_displayed = run_element.is_displayed()
run_is_clickable = run_element.get_attribute("clickable")
logger.info(f"【run】按钮是否可见:{run_is_displayed},是否可点击:{run_is_clickable}")
with allure.step("4. 查看【滑动条】是否显示/是否可用/是否可点击"):
seekbar_element = self.driver.find_element(AppiumBy.ID, "io.appium.android.apis:id/seekBar")
seekbar_displayed = seekbar_element.is_displayed()
seekbar_enabled = seekbar_element.is_enabled()
seekbar_clickable = seekbar_element.get_attribute("clickable")
logger.info(f"seekbar 滑动条 是否可见:{seekbar_displayed},"
f"是否可用:{seekbar_enabled},"
f"是否可点击:{seekbar_clickable}")
with allure.step("5.获取【滑动条】长度"):
seekbar_size = seekbar_element.size
width = seekbar_size.get("width")
logger.info(f"seekbar 的长度:{width}")
seekbar_location = seekbar_element.location
x = seekbar_location.get("x")
y = seekbar_location.get("y")
with allure.step("6.点击【滑动条】中心位置 移动到滑动条中心位置,y轴坐标不变,x轴坐标变化"):
seekbar_centerx = x + width / 2
seekbar_centery = y
# driver.tap 用于在特定的位置进行点击操作。它可以模拟用户在屏幕上进行的轻触动作。
# 使用 driver.tap 方法需要提供被点击的坐标位置。可以通过传递 x 和 y 坐标参数给 driver.tap 方法来指定点击的位置。
self.driver.tap([(seekbar_centerx, seekbar_centery)])
assert seekbar_clickable
assert run_is_clickable
@pytest.mark.P0
@allure.feature("toast弹窗验证")
@pytest.mark.parametrize('operate', ['Search', 'Add'])
def test_toast(self, operate):
with allure.step("点击 Views 进入下个页面"):
logger.info("点击 Views")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Views").click()
with allure.step("从页面的五分之三处滑动到五分之一处,即向上滑动"):
action = TouchAction(self.driver)
window_rect = self.driver.get_window_rect() # 获取当前窗口的x,y轴信息。高度以及宽度
width = window_rect['width']
height = window_rect['height']
x = int(width / 2)
y_end = int(height * 1 / 5)
y_start = int(height * 3 / 5)
# press点击 wait设置等待时长,单位mm move_to滑动的最终位置 release释放 perform执行
action.press(x=x, y=y_start).wait(2000).move_to(x=x, y=y_end).release().perform()
logger.info(f"滑动距离从{y_start}-{y_end}")
with allure.step("点击 Popup Menu 进入下个页面"):
logger.info("点击 Popup Menu")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Popup Menu").click()
with allure.step("定位到Make a Popup!按钮并点击"):
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Make a Popup!").click()
with allure.step("消息框类型选择search"):
self.driver.find_element(AppiumBy.XPATH, f"//*[@text='{operate}']").click()
with allure.step("定位toast消息框"):
toast = self.driver.find_element(AppiumBy.XPATH, "//*[contains(@text, 'Clicked popup')]").text
logger.info(f"提示信息为:{toast}")
assert operate in toast
def test_search(self):
with allure.step("点击 OS 进入下个页面"):
logger.info("点击 OS")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "OS").click()
with allure.step("点击 Morse Code 进入下个页面"):
logger.info("点击 Morse Code")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Morse Code").click()
with allure.step("点击输入框,输入内容"):
logger.info("输入搜索内容")
self.driver.find_element(AppiumBy.ID, "io.appium.android.apis:id/text").send_keys("aaaa")
result = self.driver.find_element(AppiumBy.ID, "io.appium.android.apis:id/text").text
assert result == "aaaa"
def test_check(self):
with allure.step("点击 Preference 进入下个页面"):
logger.info("点击 Preference")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Preference").click()
with allure.step("点击 9. Switch 进入下个页面"):
logger.info("点击 9. Switch")
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "9. Switch").click()
with allure.step("点击复选框"):
logger.info("点击复选框")
self.driver.find_element(AppiumBy.ID, "android:id/checkbox").click()
result = self.driver.find_element(AppiumBy.ID, "android:id/checkbox").get_attribute('checked')
assert result