pytest测试框架(一)

一、pytest安装

pip install pytest

二、pytest的编写规则

1.测试文件以test_开头(以_test结尾也可以)
2.测试类以Test开头,并且不能带有 init 方法
3.测试函数以test_开头
4.断言使用基本的assert即可

 三、pytest的运行方式--运行指定的case

1、主函数模式

if __name__ == '__main__':
    pytest.main(['s'])  #s 表示输出调试信息,包括print打印的信息

2、命令行模式

示例代码如下:

import pytest


class TestDemo_1(object):

    def test_01(self):
        x = 'hell'
        assert 'h' in x

    def test_02(self):
        sum = 4-2
        assert 2 == sum


class TestDemo_2(object):

    def test_add_01(self):
        print('add user 01')
        assert 1 == 2

    def test_add_02(self):
        print('add user 02')
        assert 3 != 6

运行test_num.py文件中的全部用例:通过nodeld

命令窗口输入
pytest test_num.py

运行TestDemo_2类下的两个用例:

pytest test_num.py::TestDemo_2

运行TestDemo_1类下面的test_02用例

pytest test_num.py::TestDemo_1::test_02

3、通过读取pytest.ini配置文件运行(***企业自动化推荐使用)

pytest.ini是单元测试框架的核心配置文件(文件名必须是pytest.ini)

  1、位置:一般放置于项目的根目录

  2、编码:必须是ANSI

  3、作用:改变pytest的默认行为

  4、运行规则:不管是主函数的模式运行,命令行运行,都会去读取这个配置文件

pytest.ini配置文件范例

 1 [pytest]
 2 # 命令行参数,多个参数用空格分隔
 3 addopts = -vs --html ./report/report.html
 4 
 5 # 测试用例文件夹,可自己配置(测试用例路径)
 6 testpaths = ./testcase
 7 
 8 # 配置测试搜索的模块文件名称
 9 python_files = test_*.py
10 
11 # 配置测试搜索的类名
12 python_classes = Test*
13 
14 # 配置测试搜索的测试函数名
15 python_functions = test
16 
17 #分组执行
18 markes =
19     smock:冒烟用例
20     productmanger:产品管理

命令行:pytest -vs ./testcase

参数详解:

1 -s 表示输出调试信息,包括print打印信息
2 -v 显示更详细的信息
3 -vs 两个参数一起使用
4 -n 支持多进程或多分布式运行测试用例,例:pytest -vs test_pro.py -n 5
5 --reruns NUM 失败用例重跑
6 -x 表示只要一个用例报错,那么测试停止
7 --maxfail=2 出现两个用例失败就停止
8 -k 指定运行测试用例(??)
9 --html 生成HTML的测试报告

四、多进程运行

在我们做接口自动化测试时,当测试用例很多时,就需要用到多进程运行

首先需要安装内置库

pip install -U pytest -xdist

运行

pytest test_num.py -n Num

# Num表示要运行的进程数

pytest test_num.py -n 5

五、重试运行--失败用例重跑

当做接口自动化测试,遇到网络波动或503时导致case运行失败,这并不是测试失败,这时需要重试运行

首先也是需要安装内置库

pip install -U pytest-rerunfailures

运行

pytest test_se.py --reruns NUM 

# NUM表示重试的次数

pytest test_num.py --reruns 5

 六、pytest的执行测试用例的顺序

unittest:通过ascll码的大小来绝对的执行顺序

pytest:1.从上到下

      2.改变默认的执行顺序,通过装饰器方式来控制用例执行顺序,@pytest.mark.run(order=1)

 1 import pytest
 2 
 3 sum = 2
 4 
 5 
 6 class TestOrder(object):
 7 
 8     @pytest.mark.run(order=2)
 9     def test_02(self):
10         print('我是02')
11         assert 'h' in 'hello'
12 
13     @pytest.mark.run(order=1)
14     def test_01(self):
15         print('我是01')
16         assert 2 == sum
17 
18     @pytest.mark.run(order=4)
19     def test_05(self):
20         print('我是05')
21 
22     @pytest.mark.run(order=3)
23     def test_03(self):
24         print('我是03')
25 
26 
27 if __name__ == '__main__':
28     pytest.main(['vs'])

 七、如何分组执行

smock:冒烟测试,测试用例分布在各个模块中

分模块执行:同样在pytest.ini配置文件配置markers即可,在分组执行的测试用例前加上@pytest.mark.smock(smock可以自定义)

  

命令行执行:pytest -m "smock"

同时执行多个分组:pytest -m "smock or productmanager"

八、跳过测试用例

(1)无条件跳过

@pytest.mark.skip

(2)有条件跳过

@pytest.mark.skipif(sum>2,reason='不满足')

 九、生成HTML报告

安装pytest -html插件

pip install pytest-html
--html ./report/report.html

十、pytest框架实现前后置的处理(常用三种)

第一种:类似于unittest的前后置,setup/teardown/setup_class/teardown_class

class SetupDemo(object):

    # 这个在所有的测试用例之前只运行一次
    def setup_class(self):
        print('在每个类执行前的初始化操作,如数据库的链接,创建日志对象')

    # 每个测试用例执行前都会执行
    def setup(self):
        print('在每个测试用例执行之前运行,如打开网页')

    def test_add(self):
        print('this is add')

    def test_delete(self):
        print('this is delete')

    def test_update(self):
        print('this is update')

    # 在每个类执行完后只执行一次
    def teardown_class(self):
        print('在每个类执行后的操作,如数据库的关闭,销毁日志对象')

    # 每个测试用例执行后都会执行
    def teardown(self):
        print('在每个测试用例执行之后运行')

 第二种(*****):pytest的核心,通过装饰器@pytest.fixtrue方式来实现部分用例的前后置和所有用例前后置。

格式和结构:

1 @pytest.fixture(scope="function", params="", autouse=False, ids="", name="")
2 def fixture_test():
3     print('测试fixture处理用例的前后置')

1、scope(******):表示被@pytest.fixture标记的方法作用域,它有四个值--->function(默认)、class、module、package/session

2、params(****):参数化(支持的格式:list、tuple、字典列表[{},{},{}],字典元组({},{},{}) )

3、autouse(*****):自动使用,默认为False

4、ids(*):当使用params参数化时,给每一个值设置一个变量,意义不大

5、name(**):表示给@pytest.fixture标记的方法取一个别名

代码实践使用详细范例介绍

一)、scope

1)scope="function"-->作用域函数,yield分隔,使用后置

 1 import pytest
 2 
 3 
 4 @pytest.fixture(scope="function")
 5 def fixture_test():
 6     print('测试fixture处理用例的前置')
 7     yield
 8     print('测试fixture处理用例的后置')
 9 
10 
11 class TestDemo(object):
12 
13     def test_add(self,fixture_test):
14         print('this is add')
15 
16     def test_delete(self):
17         print('this is delete')

如果类下面的两个方法都需要使用fixture_test前后置,可以直接加上autouse=True参数即可。--》@pytest.fixture(scope="function",autouse=True)

2)scope="class"-->作用域是类,类似于setup_class和teardown_class,只在类开始之前、结束之后执行一次

 1 import pytest
 2 
 3 @pytest.fixture(scope="class",autouse=True)
 4 def fixture_test():
 5     print('测试fixture处理用例的前置')
 6     yield
 7     print('测试fixture处理用例的后置')
 8 
 9 class TestDemo(object):
10 
11     def test_add(self):
12         print('this is add')

3)scope="module"--->作用域是模块,一个文件中有多个类,也会只执行一次前置和后置

 1 import pytest
 2 
 3 
 4 @pytest.fixture(scope="module",autouse=True)
 5 def fixture_test():
 6     print('测试fixture处理用例的前置')
 7     yield
 8     print('测试fixture处理用例的后置')
 9 
10 
11 class TestDemo(object):
12 
13     def test_add(self):
14         print('this is add')
15 
16     def test_delete(self):
17         print('this is delete')
18 
19 
20 class TestDemo2:
21 
22     def test_update(self):
23         print('this is update')
24 
25     def test_query(self):
26         print('this is query')

二)、params-->参数化

 1 import pytest
 2 
 3 data = ['成都', '大理', '西安', '北京', '南昌']
 4 
 5 @pytest.fixture(scope="function", params=data)
 6 def fixture_test(request):
 7     # 注意:这里返回的param不用s,否则会报错,request也是固定写法
 8     print('测试前置')
 9     yield request.param
10     print('测试后置')
11 
12 class TestDemo(object):
13 
14     def test_add(self, fixture_test):
15         print('this is add')
16         print('获取测试用例前置的参数:%s' % fixture_test)
17 
18     def test_delete(self):
19         print('this is delete')

三)、ids--->给参数化值设置变量

不设置的情况,执行结果显示的是Unicode值,如下:

设置以后,展示如下:

@pytest.fixture(scope="function", params=data, ids=['CD', 'DL', 'XA'])

四)、name-->给被fixture标记的方法修改别名

 

posted on 2021-05-16 17:31  丿adhere  阅读(172)  评论(0编辑  收藏  举报