• pytest单侧模块_入门汇总


    Pytest简单介绍

    (pytest是python的一个测试框架,主要是用来进行一些小的测试)

    • 安装:pip install -U pytest
    • 查看是否安装成功:pytest --version
    • 运行:在当前文件所在目录下执行pytest,会寻找当前目录以及子目录下以test开头的py文件或者以test结尾的py文件,找到文件后,在文件中找到以test开头函数并执行。(或者执行pytest 文件名--这样可以指定某个文件进行pytest的测试  或者  python -m pytest xxx.py)

    在执行pytest xxx.py时,若增加参数:pytest -v -s xxx.py   (-v:显示运行的函数;-s:显示内部的打印信息)

    • 编写pytest测试样例的规则:
      1. 测试文件以test_开头
      2. 测试类以Test开头,并且不能带有init方法
      3. 测试函数以test_开头
      4. 断言使用基本的assert即可
    • 断言--正常
    assert value == 0
    • 断言--异常(pytest.raise方法):
     1 #断言1除以0,将产生一个ZeroDivisionError类型的异常。
     2 import pytest  
     3 def test_zero_division():  
     4     with pytest.raises(ZeroDivisionError):  
     5         1 / 0       
     6         
     7 #有的时候,我们可能需要在测试中用到产生的异常中的某些信息,比如异常的类型type,异常的值value等等。下面我们修改下上面的测试:
     8 import pytest  
     9 def test_recursion_depth():  
    10     with pytest.raises(ZeroDivisionError) as excinfo:  
    11     1/0  
    12     assert excinfo.type == 'RuntimeError'  
    13 #因为该测试断言产生的异常类型是RuntimeError,而实际上产生的异常类型是ZeroDivisionError,所以测试失败了。在测试结果中,可以看到assert子表达式excinfo.type的值。
    • 在test前,可以通过增加skip或xfail进行跳过(失败)测试案例
    1 import pytest
    2 
    3 # @pytest.mark.skipif()   跳过
    4 # @pytest.mark.skip()    跳过
    5 # @pytest.mark.xfail()     若出错跳过,pass也跳过,但会显示pass
    6 def test_123():
    7     # pytest.skip()    也可以实现'跳过'目的
    8     assert 1 == 0
    • 简单例子:
    1 # coding:utf-8
    2 import pytest
    3 
    4 def fun(x):
    5     return x + 1
    6 
    7 def test_fun():
    8     assert fun(2) == 3

    结果:

    (venvX) F:	est_jiaxin>pytest test_para1.py
    ============================= test session starts =============================
    platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1
    rootdir: F:	est_jiaxin, inifile:
    plugins: allure-adaptor-1.7.10
    collected 1 item                                                               
    
    test_para1.py .                                                          [100%]
    
    ========================== 1 passed in 0.09 seconds ===========================

    pytest之feature-scope

    • function:每个test都运行,默认是function的scope.
    • class:每个class的所有test只运行一次.
    • module:每个module的所有test只运行一次.
    • session:每个session只运行一次.

    比如你的所有test都需要连接同一个数据库,那可以设置为module,只需要连接一次数据库,对于module内的所有test,这样可以极大的提高运行效率。

    代码:

    1 @pytest.fixture(scope="module")
    2     def hero_backup_policy(self, acmp_cfg):
    3         return AcloudBackupPolicy(acmp_cfg)
    4 
    5 @pytest.fixture(scope="function")
    6     def hero_acloud_backup_policy(self, acmp_cfg):
    7         return Server(acmp_cfg)

    pytest的参数化方式

    • pytest.fixture()方式进行参数化,fixture装饰的函数可以作为参数传入其他函数

    • conftest.py 文件中存放参数化函数,可作用于模块内的所有测试用例

    • pytest.mark.parametrize()方式进行参数化

    待测试代码片段:(is_leap_year.py)

     1 # coding:utf-8
     2 def is_leap_year(year):
     3     # 先判断year是不是整型
     4     if isinstance(year, int) is not True:
     5         raise TypeError("传入的参数不是整数")
     6     elif year == 0:
     7         raise ValueError("公元元年是从公元一年开始!!")
     8     elif abs(year) != year:
     9         raise ValueError("传入的参数不是正整数")
    10     elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
    11         print"%d年是闰年" % year
    12         return True
    13     else:
    14         print"%d年不是闰年" % year
    15         return False
    • pytest.fixture()

    1. pytest.fixture()中传入的参数为list,用例执行时,遍历list中的值,每传入一次值,则相当于执行一次用例。

    2. @pytest.fixture()装饰的函数中,传入了一个参数为request。

    3. 这里的测试数据是直接存在list中的,能否存入json文件或者xml文件再进行读取转换为list呢?

    代码:

     1 # coding:utf-8
     2 import is_leap_year
     3 import pytest
     4 
     5 class TestPara():
     6     is_leap = [4, 40, 400, 800, 1996, 2996]
     7     is_not_leap = [1, 100, 500, 1000, 1999, 3000]
     8     is_valueerror = [0, -4, -100, -400, -1996, -2000]
     9     is_typeerror = ['-4', '4', '100', 'ins', '**', '中文']
    10 
    11     @pytest.fixture(params=is_leap)
    12     def is_leap(self, request):
    13         return request.param
    14 
    15     @pytest.fixture(params=is_typeerror)
    16     def is_typeerror(self, request):
    17         return request.param
    18 
    19     def test_is_leap(self, is_leap):
    20         assert is_leap_year.is_leap_year(is_leap) == True
    21 
    22     def test_is_typeerror(self, is_typeerror):
    23         with pytest.raises(TypeError):
    24             is_leap_year.is_leap_year(is_typeerror)
    • conftest.py 文件 -- 测试数据与用例分离

    1. 采用conftest.py文件存储参数化数据和函数,模块下的用例执行时,会自动读取conftest.py文件中的数据。

    代码:

     conftest.py文件
    1
    # coding:utf-8 2 import pytest 3 4 is_leap = [4, 40, 400, 800, 1996, 2996] 5 is_not_leap = [1, 100, 500, 1000, 1999, 3000] 6 is_valueerror = [0, -4, -100, -400, -1996, -2000] 7 is_typeerror = ['-4', '4', '100', 'ins', '**', '中文'] 8 9 @pytest.fixture(params=is_leap) 10 def is_leap(request): 11 return request.param 12 13 @pytest.fixture(params=is_typeerror) 14 def is_typeerror(request): 15 return request.param
     test_para.py文件
    1
    # coding:utf-8 2 3 import is_leap_year 4 import pytest 5 6 class TestPara(): 7 def test_is_leap(self, is_leap): 8 assert is_leap_year.is_leap_year(is_leap) == True 9 10 def test_is_typeerror(self, is_typeerror): 11 with pytest.raises(TypeError): 12 is_leap_year.is_leap_year(is_typeerror)
    • pytest.mark.parametrize() -- 进行参数化

    1. 采用标记函数参数化,传入单个参数,pytest.mark.parametrize("参数名",lists)。
    2. 采用标记函数传入多个参数,如pytest.mark.parametrize("para1, para2", [(p1_data_0, p2_data_0), (p1_data_1, p2_data_1),...]。
    3. 这里:测试用例中传入2个参数,year和期望结果,使输入数据与预期结果对应,构造了2组会失败的数据,在执行结果中,可以看到失败原因。

    代码:

     1 # coding:utf-8
     2 import is_leap_year
     3 import pytest
     4 
     5 class TestPara():
     6     # 参数传入year中
     7     @pytest.mark.parametrize('year, expected', [(1, False), (4,True), (100, False), (400, True), (500, True)])
     8     def test_is_leap(self, year, expected):
     9         assert is_leap_year.is_leap_year(year) == expected
    10 
    11     @pytest.mark.parametrize('year, expected', [(0, ValueError),('-4', TypeError), (-4, ValueError), ('ss', TypeError), (100.0, ValueError)])
    12     def test_is_typeerror(self, year, expected):
    13         if expected == ValueError:
    14             with pytest.raises(ValueError) as excinfo:
    15                 is_leap_year.is_leap_year(year)
    16                 assert excinfo.type == expected
    17         else:
    18             with pytest.raises(TypeError) as excinfo:
    19                 is_leap_year.is_leap_year(year)
    20                 assert excinfo.type == expected

    参考链接:https://blog.csdn.net/zhusongziye/article/details/79902772

    pytest-fixture扩展内容

    1.  把一个函数定义为Fixture很简单,只能在函数声明之前加上“@pytest.fixture”。其他函数要来调用这个Fixture,只用把它当做一个输入的参数即可。

     1 import pytest
     2 
     3 @pytest.fixture()
     4 def before():
     5     print '
    before each test'
     6 
     7 def test_1(before):
     8     print 'test_1()'
     9 
    10 def test_2(before):
    11     print 'test_2()'

    result:

    (venvX) F:	est_jiaxin>pytest -v -s test_compute.py
    ============================= test session starts =============================
    platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1 -- f:projectssandomvenvxscriptspython.exe
    cachedir: .pytest_cache
    rootdir: F:	est_jiaxin, inifile:
    plugins: allure-adaptor-1.7.10
    collected 2 items                                                              
    
    test_compute.py::test_1
    before each test
    test_1()
    PASSED
    test_compute.py::test_2
    before each test
    test_2()
    PASSED
    
    ========================== 2 passed in 0.17 seconds ===========================
    

    2.  进行封装

     1 import pytest
     2 
     3 @pytest.fixture()
     4 def before():
     5     print '
    before each test'
     6 
     7 # 每个函数前声明
     8 @pytest.mark.usefixtures("before")
     9 def test_1():
    10     print 'test_1()'
    11 @pytest.mark.usefixtures("before")
    12 def test_2():
    13     print 'test_2()'
    14 
    15 #封装在类里,类里的每个成员函数声明
    16 class Test1:
    17     @pytest.mark.usefixtures("before")
    18     def test_3(self):
    19         print 'test_1()'
    20     @pytest.mark.usefixtures("before")
    21     def test_4(self):
    22         print 'test_2()'
    23 
    24 #封装在类里在前声明
    25 @pytest.mark.usefixtures("before")
    26 class Test2:
    27     def test_5(self):
    28         print 'test_1()'
    29     def test_6(self):
    30         print 'test_2()'

    result:

    (venvX) F:	est_jiaxin>pytest -v -s test_compute.py
    ============================= test session starts =============================
    platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1 -- f:projectssandomvenvxscriptspython.exe
    cachedir: .pytest_cache
    rootdir: F:	est_jiaxin, inifile:
    plugins: allure-adaptor-1.7.10
    collected 6 items                                                              
    
    test_compute.py::test_1
    before each test
    test_1()
    PASSED
    test_compute.py::test_2
    before each test
    test_2()
    PASSED
    test_compute.py::Test1::test_3
    before each test
    test_1()
    PASSED
    test_compute.py::Test1::test_4
    before each test
    test_2()
    PASSED
    test_compute.py::Test2::test_5
    before each test
    test_1()
    PASSED
    test_compute.py::Test2::test_6
    before each test
    test_2()
    PASSED
    
    ========================== 6 passed in 0.11 seconds ===========================
    

    3.  fixture还可以带参数,可以把参数赋值给params,默认是None。对于param里面的每个值,fixture都会去调用执行一次,就像执行for循环一样把params里的值遍历一次。

    1 import pytest
    2 
    3 @pytest.fixture(params=[1, 2, 3])
    4 def test_data(request):
    5     return request.param
    6 
    7 def test_not_2(test_data):
    8     print('test_data: %s' % test_data)
    9     assert test_data != 2

    result:

    (venvX) F:	est_jiaxin>pytest -v -s test_compute.py
    ============================= test session starts =============================
    platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1 -- f:projectssandomvenvxscriptspython.exe
    cachedir: .pytest_cache
    rootdir: F:	est_jiaxin, inifile:
    plugins: allure-adaptor-1.7.10
    collected 3 items                                                              
    
    test_compute.py::test_not_2[1] test_data: 1
    PASSED
    test_compute.py::test_not_2[2] test_data: 2
    FAILED
    test_compute.py::test_not_2[3] test_data: 3
    PASSED
    
    ================================== FAILURES ===================================
    ________________________________ test_not_2[2] ________________________________
    
    test_data = 2
    
        def test_not_2(test_data):
            print('test_data: %s' % test_data)
    >       assert test_data != 2
    E       assert 2 != 2
    
    test_compute.py:64: AssertionError
    ===================== 1 failed, 2 passed in 0.12 seconds ======================
    
  • 相关阅读:
    LaTeX公式编辑器
    早期和东京,京都大学高考试题
    猎犬追狐狸试题
    矩阵方程的计算求解(Matlab实现)
    高考压轴题
    何天成:从高联到IMO金牌,超详细数学竞赛学习方法
    几个精彩的数论问题
    高考试题网站
    泛函分析有什么好的教材?
    ifndef系列
  • 原文地址:https://www.cnblogs.com/sunshine-blog/p/9468399.html
Copyright © 2020-2023  润新知