【web自动化】-4-引入pytest测试框架全面封装
一、父类页面BasePage
先接上集的POM设计方法,由于封装的重写定位元素的方法,以及触发显示等待在所有页面类中都可以使用,但所有页面类都需要重新复制优化后的封装代码。
为了让代码清晰简洁减少重复,使用继承的方式让每一个子页面类获取父页面类的方法和属性。
所有的页面类都需要获取:
- 实例属性:驱动
- 实例方法:显示等待,定位元素
BasePage一般在POM模式中当作所有页面的父类(元类)
BasePage一般属于抽象类的范畴,不建议直接实例化其实例对象,不能代表任何的实例对象。
把子类页面中共同需要使用的属性或者方法统一封装到父类中:
类属性,类方法,实例属性,实例方法。
方便调用实现代码的高度复用(将厕所放到公共区域而不是你的卧室 大家都方便去上厕所)
二、pytest封装
1.函数用例为主 格式def test_xxx()

2.执行某个特定的用例:pytest -sk test_xxx

三、Xpath为动态元素的值时总是会改变
此时不能通过简单的复制,要自己手写Xpath:


四、XPath 手写方法指南
XPath是一种用于在 XML/HTML 文档中定位元素的语言,在自动化测试中广泛使用。
1. 基本语法结构
XPath 使用路径表达式来选择节点,基本格式为:
/ - 根节点
// - 任意层级节点
. - 当前节点
.. - 父节点
@ - 属性
2. 绝对路径与相对路径
-
绝对路径:从根节点开始的完整路径(慎用,页面结构变化时易失效)
/html/body/div[1]/div[2]/form/input -
相对路径:从当前节点开始(推荐)
//div[@class="container"]//input
3. 按元素名称定位
//div # 所有div元素
//input # 所有input元素
//button # 所有button元素
4. 按属性定位
//input[@id="username"] # id属性等于"username"的input
//a[@href="https://example.com"] # href属性等于指定值的a标签
//div[@class="content"] # class属性等于"content"的div
5. 按文本内容定位
//button[text()="登录"] # 文本完全等于"登录"的button
//a[contains(text(), "注册")] # 文本包含"注册"的a标签
//p[starts-with(text(), "欢迎")] # 文本以"欢迎"开头的p标签
6. 组合条件(逻辑运算符)
//input[@type="text" and @name="email"] # 同时满足两个条件
//button[@id="submit" or @class="btn"] # 满足任一条件
//div[not(@class="disabled")] # 不满足条件
7. 层级关系定位
//div[@id="parent"]/child::span # 直接子节点span
//div[@id="parent"]//descendant::span # 任意层级子节点span
//span[@id="child"]/parent::div # 父节点div
//input[@id="username"]/following-sibling::button # 下一个兄弟节点button
//button[@id="submit"]/preceding-sibling::input # 前一个兄弟节点input
8. 索引定位(从 1 开始)
//div[@class="item"][1] # 第一个匹配的div
//ul/li[last()] # 最后一个li
//ul/li[position() < 3] # 前两个li
9. 模糊匹配
//input[contains(@id, "user")] # id包含"user"的input
//div[starts-with(@class, "box")] # class以"box"开头的div
//a[ends-with(@href, ".pdf")] # href以".pdf"结尾的a标签(需XPath 2.0支持)
10. 轴(Axes)定位
//div[@id="content"]/ancestor::body # 所有祖先节点(直到根节点)
//input[@id="email"]/following::button # 当前节点之后的所有button
//button[@id="save"]/preceding::input # 当前节点之前的所有input
11. 使用函数
//input[count(//div) > 5] # 满足条件的input(div数量>5)
//div[contains(@class, "active") and string-length(text()) > 10] # 文本长度>10的div
12. 复杂示例
//form[@id="loginForm"]//input[@name="username" and @type="text"]
//table[@class="data"]/tbody/tr[position() mod 2 = 0] # 表格偶数行
//div[contains(@class, "product") and .//span[text()="热门"]] # 包含"热门"标签的产品
五、Fixture 夹具:自动化测试中的「前置准备」与「后置清理」
在自动化测试中,Fixture(夹具)是一种特殊的函数或机制,用于为测试用例提供一致的、可重复的测试环境。它就像是实验室中的实验设备,确保每次实验(测试)都在相同条件下进行。
1. 为什么需要 Fixture?
- 避免重复代码:测试前的初始化(如登录、创建数据)和测试后的清理(如删除数据、关闭连接)逻辑,无需在每个测试用例中重复编写。
- 保证测试独立性:每个测试用例运行前都有干净的环境,避免测试之间相互干扰。
- 提高可维护性:环境配置集中管理,修改时只需更新 Fixture,无需修改所有测试用例。
2. pytest框架中的 Fixture 实现
- Python(pytest 框架)
pytest 使用@pytest.fixture装饰器定义 Fixture。
import pytest
# 定义Fixture
@pytest.fixture
def setup_user():
# 前置操作:创建测试用户
user = {"name": "test", "id": 123}
yield user # 返回数据给测试用例
# 后置操作:清理用户(yield之后的代码)
# 使用Fixture
def test_user_profile(setup_user):
assert setup_user["name"] == "test"
带参数的 Fixture
@pytest.fixture(params=["chrome", "firefox"])
def browser(request):
# 根据参数初始化不同浏览器
if request.param == "chrome":
driver = webdriver.Chrome()
else:
driver = webdriver.Firefox()
yield driver
driver.quit() # 关闭浏览器
3. Fixture 的高级用法
(1)共享 Fixture(pytest)
在conftest.py文件中定义 Fixture,使其可被多个测试文件共享。
# conftest.py
@pytest.fixture(scope="session") # 整个测试会话只执行一次
def database_connection():
conn = create_db_connection()
yield conn
conn.close()
(2)Fixture 嵌套
Fixture 可以依赖其他 Fixture。
@pytest.fixture
def login_user(database_connection):
# 使用database_connection Fixture
user = create_user_in_db(database_connection)
token = login(user)
yield token
delete_user(database_connection, user.id)
(3)参数化 Fixture
通过参数化生成多组测试数据。
@pytest.fixture(params=[1, 2, 3])
def numbers(request):
return request.param
def test_numbers(numbers):
assert numbers > 0
4. Fixture 的作用域(Scope)
Fixture 的作用域决定了它的执行频率,常见作用域包括:
- function(默认):每个测试函数执行一次。
- class:每个测试类执行一次。
- module:每个测试模块执行一次。
- session:整个测试会话执行一次(如数据库连接)。
@pytest.fixture(scope="class")
def shared_resource():
# 类级别的Fixture
resource = setup_resource()
yield resource
cleanup(resource)
5. 最佳实践
- 单一职责:Fixture 应专注于环境准备,避免包含业务逻辑。
- 命名清晰:使用描述性名称(如
setup_database、login_admin)。 - 避免过度依赖:Fixture 之间的依赖应尽量简单,避免复杂的调用链。
- 适当的清理:确保 Fixture 执行后环境恢复原状,避免测试污染。
核心:分离测试逻辑与环境管理。
# web自动化
更多推荐



所有评论(0)