Web测试示例¶
场景分析¶
Web测试是一种 有状态测试 , 步骤之间往往有着巨大的依赖性和影响里,所以一个Web测试通常包含大量的测试步骤;
再加上Web测试通常使用Selenium或Playwright进行浏览器控制, 由于浏览器功能繁多,无法像requests那样的 统一传参接口 , 所以在执行测试步骤时,需要根据实时状态调用不同的方法、传递不同的参数;
此外,对浏览器进行自动化操作之后,其结果并不会进行返回,而是作用在Web页面的上, 所以不能直接对操作进行断言,而是需要再一次主动 从页面中获取结果 ,然后再进行断言,
由此可见,Web自动化测试的显著特点有:
步骤数量多
参数变化大
断言不直接
备注
在实际项目中通常会对Selenium或Playwright进行二次封装, 以减少步骤和参数,从而降低一定难度。 但是受限于Web项目自身的特点,封装后的效率和难度依旧无法和API测试相比。
安装依赖¶
下面以Selenium为例
pip install selenium
Selenium 现在即可以自动下载驱动,又能够进行浏览器控制,所以只需要安装他一个即可。
设计用例¶
鉴于web测试的复杂度,可以先用python写出测试用例,然后再改写为yaml。
# test_web.py
from selenium import webdriver
def test_web():
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('https://www.baidu.com')
driver.find_element('xpath','//*[@id="kw"]').send_keys("大红灯笼高高挂")
driver.find_element('xpath','//*[@id="su"]').click()
driver.get_screenshot_as_file('page.png')
driver.quit()
(为了降低难度,该用例没有使用断言)
从Python用例可以看出,web测试用例步骤大致可分为3类:
外部函数
driver中的成员方法
find_element返回值中的成员方法
参数类型也可分为3类:
无参数
位置参数
关键字参数
根据python版本web测试用例,设计yaml版Web测试用例如下:
name: 使用百度搜索
steps:
- get_webdriver:
- implicitly_wait: 10
- get: https://www.baidu.com
- find_element:
by: xpath
value: '//*[@id="kw"]'
action: # 此非selenium原生参数,需要二次处理
send_keys: '大红灯笼高高挂'
- find_element:
by: xpath
value: '//*[@id="su"]'
action: # 此非selenium原生参数,需要二次处理
click:
- get_screenshot_as_file: page.png
- quit:
实现钩子¶
接下来根据用例内容,实现hook,使得每个步骤都能够正确的执行
# conftest.py
from selenium import webdriver
from pytest_yaml import YamlItem
def pytest_yaml_run_step(item: YamlItem):
step = item.current_step # 从参数值中取出字典格式的测试步骤
step_type = list(step.keys())[0] # 从字典的key即为类型
step_data = list(step.values())[0] # 从字典的value即为步骤内容
print(f"测试步骤:{item.current_step_no}, 步骤类型: {step_type}, 步骤内容: {step_data} ...", end="")
action =None
match step_type: # 根据不同的步骤类型,匹配不同的测试动作
case 'get_webdriver':
# 启动浏览器,并将响应保存到item中,以便后续hook进行处理
item.driver = webdriver.Chrome()
print(f'浏览器启动成功!')
return True
case 'find_element':
action = step_data.pop('action', None)
func = getattr(item.driver, step_type)
if not step_data:
el =func()
elif isinstance(step_data, dict):
el = func(**step_data)
else:
el = func(step_data)
if action and el:
for action_name,action_args in action.items():
action_func = getattr(el,action_name)
if action_args:
action_func(action_args)
else:
action_func()
return True
执行结果如下
(.venv) C:\demo\pytest-yaml-demo>pytest
====================================== test session starts ======================================
platform win32 -- Python 3.12.0, pytest-8.3.4, pluggy-1.5.0
rootdir: C:\demo\pytest-yaml-demo
configfile: pytest.ini
plugins: yaml-1.1.0
collected 1 item
Web测试\test_web.yaml
DevTools listening on ws://127.0.0.1:60519/devtools/browser/363b32ff-33fa-428f-92f2-892a43376601
[6952:18404:1216/195012.865:ERROR:ssl_client_socket_impl.cc(879)] handshake failed; returned -1, SSL error code 1, net_error -101
. [100%]
======================================= 1 passed in 5.03s =======================================
小结¶
至此,用于Web测试的yaml用例已成功实现。