pytest 命名要求
方法(类里面的def)
函数(类外面的def)
python 命名规范
模块(modules) 小写加下划线 get_token
包(packages) 小写加下划线 get_token_list
类(class) 驼峰 GetToken
异常(exception) 驼峰 GetTokenError
方法/函数(function) 小写加下划线 get_token_list()
常量(常量是不可改变的量)(class constants)全大写 DEFAULT_TOKEN
变量(class constants)小写加下划线 get_token
pytest的命名规范(只有这么命名才可以通过pytest直接执行)
文件 test_开头,或者_test结尾的.py文件
类 Test开头命名的类
方法/函数 test_开头
ps:测试类中,不可以有构造函数__init__
疑问:如果没有py文件没有类,只有方法会执行吗?
回答:可以执行
pytest用例结构:用例名称,前置条件,断言(assert<表达式>)
表达式 可以用 == ,!= ,in等判断
setup/teardown只能作用于类内的方法,等于setup_method/teardown_method
模块module 理解为.py文件
参数化
@pytest.mark.parametrize("name1,name2,name3",[(name1_value1,name2_value1,name3_value1),(name1_value2,name2_value2,name3_value2)],ids=["testname1","testname2","testname3"])
def test_params("name1,name2,name3")
通过参数化,将参数name1,name2,name3,和参数值name_value传到test_params()里
同时通过ids=[“testname1”]给用例起名,ids的个数与参数的个数必须一致
eval(str(a+b))可以把str转换成 可执行代码
在一个方法上写两个参数化,可以将a和b全组合(笛卡尔积)
@pytest.mark.parametrize("name1",[name1_value1,name1_value2,name1_value3])
@pytest.mark.parametrize("name2",[name2_value1,name2_value2,name2_value3])\
def test_params(name1,name2)
pytest支持标记用例,执行时可以选择标记的用例
使用@pytest.mark.标记,加到class或者de的f上一行
执行时 pytest xxx.py -vs(展示详细日志)-m (选择标记用例) “标记”
直接执行pytest会报warning,需要新建pytest.ini文件
[pytest]
markers = demo
smoke
如何跳过用例
1,使用@pytest.mark.skip
还可以使用@pytest.mark.skip(reason=“跳过原因”)展示跳过原因,可以展示在测试报告中
2,使用pytest.skip,可以在用例执行过程中跳过之后的步骤
def check_login():
return False
def test_getname():
print("start")
if check_login() != True:
pytest.skip("用户未登录,跳过该方法")
print("end")
3,使用@pytest.mark.xfail
用于预期结果是fail的用例,还是会执行用例,
如果成功了会标记为xpass和如果失败了会标记为xfail,仅用于提示,可以专门展示这条用例
还可以通过pytest.xfail()在用例中使用,方法中后面的代码不执行
pytest运行用例
通过命令行执行
pytest -v可以展示哪些测试用例被执行了
输入pytest 执行当前目录下所有符合条件的py文件
输入pytest xx.py 执行xx.py文件里所有的测试用例
输入pytest xx.py::类名(不加括号),执行xx.py文件里某个类的测试用例,也适用类外的方法
输入pytest xx.py::类名::方法名 ,执行某个方法
pytest常用命令行参数
1,–lf(–last–fail)
只执行上次运行失败的用例
如果上次没有失败的用例,那么执行全部所选用例
2,–ff(–first–fail)
先执行上次失败的用例,然后执行全部所选用例
pytest执行方式
1,pycharm可视化,右键执行
2,命令行pytest执行
3,使用python解释器执行
3.1使用main函数
python的模块执行时,name__一定等于__main,当该模块被其他模块导入时,就不是main了
if __name__ == '__main__':
#python test_xx.py执行当前目录下所有用例,这里的当前目录是命令行执行时的目录,不是文件存放的目录
pytest.main()
#执行指定用例模块
pytest.main(['test_mark.py','-vs'])
#执行指定用例模块的某个类
pytest.main(['test_mark.py::TestMark','-vs'])
#执行指定用例模块的某个类
pytest.main(['test_mark.py','-vs','-m','float'])
3.2使用python -m pytest
此时,pytest后面正常加参数使用,不需要加main函数
常用的异常处理方式
这里的异常指的是,程序运行的报错,不是异常场景
1,try catch
try:
a = int(input("输入被除数"))
b = int(input("输入除数"))
c = a / b
print('两数相除结果为{}'.format(c))
except(ValueError, ArithmeticError):
#问题:(ValueError, ArithmeticError)两个参数是哪来的?
print('数据错误')
except():
print("未知错误")
print("程序继续运行")
2,pytest.raise
def test_raise():
with pytest.raises(ValueError):
#单个异常类型
raise ValueError
#raise 是python自带的方法,可以抛出异常
with pytest.raises((ValueError,ZeroDivisionError)):
#多个异常类型
# raise ValueError
raise ZeroDivisionError
def test_raise1():
with pytest.raises((ValueError,ZeroDivisionError)) as Errortype:
# raise ValueError
raise ZeroDivisionError('这是除数为0异常')
assert Errortype.type is ZeroDivisionError
#获取异常类型
assert Errortype.value.args[0] == '这是除数为0异常'
#获取异常参数
pytest yaml 数据驱动
数据驱动的场景:
App,Web,接口自动化测试中
- 测试步骤的数据驱动
- 测试数据的数据驱动
- 配置的数据驱动
allure安装
allure是基于标准xUnit的输出进行分析,每个语言的单测框架
1,需要java 1.8,配置环境变量时不能有;号,不能到bin目录,例如:C:\Program Files\Java\jdk1.8.0_144
2,下载allure压缩包,解压后,配置环境变量 例如 G:\allure-2.13.8\allure-2.13.8\bin
3,验证allure安装成功 allure --version
4,pip install allure-pytest
allure使用
1,用pytest执行:pytest -vs test_allure_title.py --alluredir ./result
test_allure_title.py是文件名,./result是allure生成文件的路径
2,用python执行:python -m pytest -vs test_allure_title.py --alluredir ./result
3,查看报告 allure serve ./result
./result 是allure文件的路径
4,清空alluredir:–clear-alluredir
pytest -vs test_allure_title.py --alluredir ./result --clear-alluredir
allure语法
https://docs.qameta.io/allure/#_pytest
@allure.feature() #模块
@allure.story() #类别,正确场景,失败场景
指定场景执行 --allure-stories
$ pytest tests.py --allure-stories story_1,story_2
指定模块执行 --allure-features
$ pytest tests.py --allure-features feature2 --allure-stories story2
@allure.title() #给用例重新起个中文名称
with allure.step()#给用例加上步骤名称,建议更换一个page就加一个步骤
with allure.step("打开登录"):
print("打开登录页面")
allure支持添加链接,有三种方法,分别是普通链接,bug地址,测试用例地址
LINK_URL
@allure.link(LINK_URL)
@allure.issue(123,“bug信息”)
@allure.testcase(LINK_URL)
其中@allure.issue的地址,通过命令行添加bug地址
pytest directory_with_tests/ --alluredir=/tmp/my_allure_report
–allure-link-pattern=issue:http://www.mytesttracker.com/issue/{}
allure支持用例优先级
@allure.severity(allure.severity_level.TRIVIAL)
def test_with_trivial_severity():
pass
@allure.severity(allure.severity_level.NORMAL)
def test_with_normal_severity():
pass
@allure.severity(allure.severity_level.NORMAL)
class TestClassWithNormalSeverity(object):
def test_inside_the_normal_severity_test_class(self):
pass
@allure.severity(allure.severity_level.CRITICAL)
def test_inside_the_normal_severity_test_class_with_overriding_critical_severity(self):
pass
指定优先级执行–allure-severities
$ pytest tests.py --allure-severities normal,critical