pytest测试笔记

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,接口自动化测试中

  1. 测试步骤的数据驱动
  2. 测试数据的数据驱动
  3. 配置的数据驱动

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