Pytest+Allure(详细)
Allure是当今比较主流的开源的免费的自动化测试报告,支持Java,Python,我们来看看如何使用Pytest与Allure整合,输出漂亮的测试报告。
一、Pytest
1、什么是pytest
pytest是一款单元测试框架,在编程过程中,单元主要指的是代码中最小的组成部分,例如函数或类,在面向对象中,最小的单元就是类下面的方法。
当我们编写好一段程序后,会对这些函数和方法进行检测,是否出现程序错误,这种对程序的函数和方法进行测试的过程,就叫做单元测试。
pytest的测试框架类似于unittest框架相似,但pytest的测试框架比unittest更加简洁、高效。
2、pytest的优势
a、pytest能够兼容unittest,如果之前用例是unittest编写的,可以使用pytest直接进行使用
b、pytest的断言直接使用assert断言,并非使用self.assertEqual等语法语句以及其他各式各样的断言方式
c、pytest对于失败的测试用例会提供非常详细的错误信息
d、pytest可以自动发现并收集测试用例
e、pytest有非常灵活的fixture管理
f、pytest有mark标记机制,可以标记某些用例为冒烟测试用例
g、pytest提供了非常丰富的插件系统
h、pytest不需要写类,unittest是需要写类并继承的,这里pytest更加简洁
3、使用pytest
pip install pytest
pytest编写测试用例的规则如下:
a、模块名称以test_开头
b、测试用例函数以test_开头
c、可以不定义测试用例类(非必须)
4、运行pytest
a、直接通过代码左侧的三角进行运行(pycharm)
b、命令行 例如
pytest --alluredir=reports -m smoke
c、创建run.py 内容为
pytest.main(['--alluredir=reports', '-m', 'smoke'])
5、pytest高级特性
a、用例筛选
我们都做过冒烟测试,也知道冒烟测试用例,pytest支持用例筛选,你可以在想要的用例上进行标记,以此来表示这是一个冒烟测试用例
import pytest
# 格式为:@pytest.mark.自定义标记名
@pytest.mark.smoke
def test_True()
assert True
@pytest.mark.smoke
def test_False()
assert False
这样运行用例会有警告信息,通常为了方便分类管理测试用例,我们会对测试用例类型进行注册
新建一个pyproject.toml
[tool.pytest.ini_options]
markers = [
"smoke: 冒烟测试用例",
"serial",
]
可能你会疑惑:不是使用pytest.ini来管理吗?pytest.ini固然可以,但是无法输入中文,为了对各种测试用例进行清晰的分类说明,这里使用pyproject.toml。
注册完成后我们需要运行,在命令行输入pytest -m "smoke",这样就可以运行刚刚标记过的测试用例了,值得一提的是,如果这个标记是在函数上,那么就代表着函数属于标记的筛选用例,如果标记在类上,那么整个类下的所有函数都属于筛选用例。
如果运行多个标记那么可以继续在函数或类上再次进行新的标记,例如login标记,意味着我只想要执行登录模块的冒烟测试用例里,那么再次进行注册并运行即可,运行使用pytest -m "smoke and login",如果是冒烟测试用例和登录模块用例满足一个即可,那么就可以使用or即可,两者选其一,满足即可运行。
b、数据驱动
使用@pytest.mark.parametrize("case_info", cases_list),cases_list为测试用例的列表
@pytest.mark.smoke
@pytest.mark.login
@pytest.mark.parametrize("case_info", ["hello", "world"])
def test_add(case_info):
assert case_info.startswith('h')
运行这个测试用例,结果如下
c、fixture夹具
fixture夹具可以说是pytest的灵魂所在,下面说说具体用法
我们知道在unittest中可以使用setUp/tearDown以及setUpClass/tearDownClass分别来表示函数级别和类级别的前后置,相对比较死板,在pytest中可以灵活设置fixture
首先我们将所有夹具都整理在conftest.py中,这样在编写测试用例函数的时候,无需导入,直接可以使用夹具
d、代码
conftest.py
这里我结合selenium的web自动化的浏览器前后置操作进行举例
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
@pytest.fixture(scope="function")
# scope定义该夹具的有效级别,可以理解成fixture的作用域,默认不写:function,还有class、module、package、session四个【常用】
def browser():
"""管理浏览器的启动和停止"""
# 先设置一下浏览器的加载策略属性
capabilities = Options().to_capabilities()
capabilities["pageLoadStrategy"] = "eager"
# 得到一个浏览器对象
driver = webdriver.Chrome(desired_capabilities=capabilities)
# 隐性等待
driver.implicitly_wait(8)
driver.maximize_window()
yield driver # yield上面的为前置操作,下面的为后置操作,yield后面的driver是返回值(对象),可以直接传入测试用例函数里
driver.quit()
test_login.py
def test_login(browser):# 无需导入夹具browser,可直接当作参数传入
url = 'http://xxxxxxxxx'
username = '123'
password = '321'
expected = '登陆失败'
driver = browser # 使用夹具名可以直接获得夹具browser返回的driver浏览器对象
# 2、访问测试网页
driver.get(url)
# 3、点击登录按钮
login_el = driver.find_element('xpath', "//a[text()='登录']")
login_el.click()
# 4、定位用户名输入框,并输入用户名
username_el = driver.find_element('xpath', "//input[@placeholder='请输入手机号/用户名']")
username_el.send_keys(username)
# 5、定位密码输入框,并输入密码
password_el = driver.find_element('xpath', "//input[@placeholder='请输入密码']")
password_el.send_keys(password)
# 6、点击登录
login_btn = driver.find_element('xpath', "//a[@class='xxxx']")
login_btn.click()
# 7、断言
actual = driver.find_element('xpath', "//div[@class='xxxxx']")
assert expected == actual.text
run.py
import pytest
pytest.main()
ps:通过夹具返回浏览器对象是web自动化很实用的一个技巧
二、Allure
windows:下载,解压,并配置bin文件夹下allure.bat加入到Path环境变量:https://github.com/allure-framework/allure2/releases
mac:brew install allure
1、安装Python依赖
pip install allure-pytest
这将安装Allure-pytest和Allure-python-commons包,以生成与Allure 2兼容的报告数据。
2、基本用法
Allure监听器在测试执行期间会收集结果,只需添加alluredir选项,并选择输出的文件路径即可。
run.py:
import pytest
pytest.main(['--alluredir=reports', '-m', 'smoke'])
运行后,reports文件包下会生成json格式文件,执行如下命令以生成allure测试报告
allure serve reports
3、allure注解说明
每种注解的具体用法在此就不一一赘述,重点说一下以下两点:
1、添加错误截图 allure.attach()
def save_error_screenshot(self, screenshot_name=f'{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}.png'):
"""错误用例截图"""
# 对当前页web页面进行截图
f = self.driver.get_screenshot_as_png()
# 将截图保存到allure报告中
allure.attach(f, screenshot_name, allure.attachment_type.PNG)
2、 参数化的用例中动态设置测试用例名称 allure.dynamic.title
# 用例数据
casedatas = [
{'title': '用例1','data':"xxx"},
{'title': '用例2','data':"xxx"},
{'title': '用例3','data':"xxx"}
]
class TestLogin:
@pytest.mark.parametrize('item',casedatas)
def test_demo(self, item):
# 动态设置报告中的用例名称
allure.dynamic.title(item['title'])
4、allure的命令行参数
pytest.main(['--alluredir=reports', '-m', 'smoke'])中也可以使用allure的命令参数进行测试用例的指定和执行。
--allure-severities=SEVERITIES_SET
Comma-separated list of severity names. Tests only
with these severities will be run. Possible values
are: blocker, critical, normal, minor, trivial.
--allure-epics=EPICS_SET
Comma-separated list of epic names. Run tests that
have at least one of the specified feature labels.
--allure-features=FEATURES_SET
Comma-separated list of feature names. Run tests that
have at least one of the specified feature labels.
--allure-stories=STORIES_SET
Comma-separated list of story names. Run tests that
have at least one of the specified story labels.
--allure-link-pattern=LINK_TYPE:LINK_PATTERN
Url pattern for link type. Allows short links in test,
like 'issue-1'. Text will be formatted to full url
with python str.format().
比如:
pytest.main(['--alluredir=reports', '--allure-features=xxxfeature测试用例', '-sv'])