码迷,mamicode.com
首页 > 其他好文 > 详细

pytest复习

时间:2021-06-15 17:44:52      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:数据   append   获取数据   ali   nal   cal   app   collect   sse   

复习补充

 

 

目前,一部分公司使用unittest,一部分使用pytest。但是,pytest明显具有优势。



unittest框架

unittest框架是系Python自带的测试框架。在使用unittest是时,需要继承Unittest.TestCase.

同时,需要注意:unittest框架中的测试类运行,需要补充上:

if __name__ == __main__:

unittest.main()

 

使用unittest时,产生测试报告:unittest+HTMLTestRunner


python3.5以后,有一个类型提示Type hints

"""我们期待a是int型,b是int型,同时该方法的返回值也是int"""
def add(self, a:int, b:int) ->int:
    return a + b

 

Python的入口:if __name__ == ‘__main__‘:


pytest运行规则

pytest 收集所有以test*.py文件,Test开头的类,和以test开头的函数和方法,都能识别成测试用例

常用参数:

  • -k : 满足表达式的都会执行

    pytest -k ‘add‘ 执行包含add的测试用例

    pytest -k ‘add‘ or ‘div‘ 执行包含add和div的测试用例

  • --collect-only : 只负责收集测试用例

    pytest --collect-only pytest_Terminal.py 收集pytest_Terminal.py文件中的测试用例

    pytest --collect-only 收集当前目录下的测试用例

  • -m: 加标签。 执行前为用例加@pytest.mark.标签名

  
import pytest
?
from python.demo import Calc
?
?
class TestClac1:
    #统一放在setup里面初始化
    def setup(self):
        self.calc = Calc()
?
    @pytest.mark.add
    def test_add(self):
        result = self.calc.add(1,2)
        print(result)
        assert 3 == result
?
    @pytest.mark.add
    def test_add_1(self):
        result = self.calc.add(1,1)
        print(result)
        assert 2==result
?
    def test_div(self):
        result = self.calc.div(2,1)
        print(result)
        assert 2==result
 pytest -m add -v -s pytest_Terminal.py 执行mark标记为add的测试用例

 

  • --junit-xml: 生成一个执行结果为xml的文件

  pytest --junit-xml ./result pytest_Terminal.py

创建一个result.xml文件,将执行pytest_Terminal.py文件产生的结果放在其中


pytest-ordering插件

我们一般在做自动化测试时,用例设计之间应该是可以相互独立执行的,没有一定的前后依赖关系的,如果我们真的有前后依赖,想指定用例的先后顺序,可以用到pytest-ordering插件解决这个问题

@pytest.mark.run(order=序号)
@pytest.mark.run(order=2)
def test_div(self):
    result = self.calc.div(2,2)
    print(result)
    assert 1==result

 

 

pytest .ini文件【待补充】

可以改变pytest的运行行为


导出依赖包

  • pip freeze 导出依赖包

    pip freeze > requirements.txt 导出依赖包到requirements.txt中

  • 安装导出的依赖包 pip install -r requirements.txt

浮点型的精度问题 Decimal( )

Decimal()方法的参数必须得是一个字符串,计算完以后的结果还是一个Decimal对象,直接用float()转为和字符串内容相等的浮点数

float(Decimal(‘6.6‘))

yaml用法

将数据存到add.yml文件中,读取文件从而获取数据
import yaml
import pytest
?
from python.demo import Calc
?
?
class TestCal:
?
    # 统一放在setup里面初始化
    def setup(self):
        self.calc = Calc()
?
    # @pytest.mark.parametrize("case1_a,case1_b",[
    #     [1,2],
    #     [0.1,0.2],
    #     [0,1]
    # ])
    """将数据存到add.yml文件中,读取文件从而获取数据"""
    @pytest.mark.parametrize("case1_a,case1_b,except_data",
                             yaml.safe_load(open("D:/workspace/pycharm_station/python测试框架实战/datas/add.yml")))
    def test_case1_add(self,case1_a,case1_b,except_data):
        result = self.calc.add(case1_a,case1_b)
        print(result)
        assert except_data==result
?
 
?
    # 除法
    @pytest.mark.parametrize("case2_a,case2_b,except_data2",)
    def test_case2_div(self,case2_a,case2_b,except_data2):
        result = self.calc.div(case2_a,case2_b)
        print(result)
        # assert except_data2 == result

 

 

add.yml文件

- [1,2,3]
- [2,3,5]
- [0.1,0.3,0.4]
- [-2,-3,-5]
- [0,0,0]

 

 
将方法名封装在steps.yml中,读取文件内容。

如果是‘add‘则执行‘add( )‘方法;如果读取的内容==‘add1‘,则执行‘add1( )‘方法

steps.yml文件

- add
- add1

 

 

pyhton测试文件

#import sys
?
import yaml
import pytest
?
from python.demo import Calc
?
# sys.path.append(‘..‘)
?
?
#读取封装方法名的steps.yml文件,读取的内容是列表格式,以列表格式返回
def steps():
    with open(D:/workspace/pycharm_station/python测试框架实战/datas/steps.yml) as f:
        return yaml.safe_load(f)
?
?
class TestCal:
?
    # 统一放在setup里面初始化
    def setup(self):
        self.calc = Calc()
?
?
    #    """将数据存到add.yml文件中,读取文件从而获取数据"""
    @pytest.mark.parametrize("case1_a,case1_b,except_data",
                             yaml.safe_load(open("D:/workspace/pycharm_station/python测试框架实战/datas/add.yml")))
    def test_case1_add(self, case1_a, case1_b, except_data):
        steps1 = steps()
        for step in steps1:
            if step == add:
                result = self.calc.add(case1_a,case1_b)
            elif step == add1:
                result = self.calc.add1(case1_a,case1_b)
?
            print(f\n{step} answer is: {result} )
            

 


           
           
           
#运行结果
?
============================= test session starts =============================
collecting ... collected 5 items
?
test_pytest_yaml.py::TestCal::test_case1_add[1-2-3] PASSED               [ 20%]
add answer is: 3
?
add1 answer is: 5
?
test_pytest_yaml.py::TestCal::test_case1_add[2-3-5] PASSED               [ 40%]
add answer is: 5
?
add1 answer is: 7
?
test_pytest_yaml.py::TestCal::test_case1_add[0.1-0.3-0.4] PASSED         [ 60%]
add answer is: 0.4
?
add1 answer is: 2.4
?
test_pytest_yaml.py::TestCal::test_case1_add[-2--3--5] PASSED            [ 80%]
add answer is: -5
?
add1 answer is: -3
?
test_pytest_yaml.py::TestCal::test_case1_add[0-0-0] PASSED               [100%]
add answer is: 0
?
add1 answer is: 2
?
?
============================== 5 passed in 0.08s ==============================
?
Process finished with exit code 0

 


?

pytest.fixture用法

  • 什么是fixture?

    1. fixture是在测试函数运行前后,由朋友test执行的外壳函数

    2. 它的作用是将一些非核心测试逻辑从测试函数中分离出来,以便于其他测试函数使用,同时保持这些逻辑的一致性;

    3. fixture的代码可以进行定制,满足多变的测试需求,包括:定义传入测试的数据集,配置测试前系统的初始状态,为批量测试提供数据源等····

      总之,fixture是pytest用户将测试前后进行预备、清理工作的代码分离出核心测试逻辑的一种机制。

  • fixture函数放在哪里合适?

    1. 可以放在单独的测试文件中

    2. 如果希望多个测试文件共享fixture,可以放在某个公共目录下创建的conftest.py文件【一般,conftest.py文件与测试文件同级目录】

    3. 使用fixture传递数据(参数化)

fixture非常适合存放测试数据,并且他可以返回任何数据

 

import pytest
?
@pytest.fixture()
def some_data():
    return 42
?
def test_some_data(some_data):
    assert some_data == 42

#@pytest.fixture() 装饰器用于声明函数是一个fixture

如果测试函数的参数列表中包含fixture名字,那么pytest会检测到,

检测顺序是:优先搜索该测试所在的模块,然后搜索conftest.py

并在测试函数运行之前执行该fixture,

pytest --setup-show example1.py 可以完整显示每个用例的fixture 调用顺序

  • fixture参数化

    pytest.fixture( ): 在fixture级别的function处参数化

    @pytest.mark.parametrize: 允许在function或者class级别的参数化,为特定的测试函数或者类提供了多个argument设置


fixture中重要的:yield关键字

  • yield一般结合fixture使用:fixture通过scope参数控制setup级别,既然有setup作为用例之前的操作,用例执行完之后肯定也有teardown操作。而fixture的teardown操作并不是独立的函数,用yield关键字呼唤teardown操作

import pytest
?
?
@pytest.fixture(scope="module")
def open():
    print("打开浏览器,并且打开百度首页")
?
    yield
    print("执行teardown!")
    print("最后关闭浏览器")
?
def test_s1(open):
    print("用例1:搜索python-1")
?
def test_s2(open):
    print("用例2:搜索python-2")
?
def test_s3(open):
    print("用例3:搜索python-3")
?
if __name__ == "__main__":
    pytest.main(["-s", "test_f1.py"])

 

 
  • yield + 函数 ==生成器
  • yield 和return的区别:

  共同点:return和yield都用来返回值,在一次性的返回所有值的场景中return和yield的作用是一样的。

  不同点: 如果要返回的数据是通过for等循环生成的迭代器类型数据(如列表、元组),return只能在循环外部一次性的返回;yield则可以在循环内部逐个元素返回。

  测试return:

class TestReturn:
    def gen_iterator(self):
        result_list = []
        for j in range(3):
            print(fgen_iterator--{j})
            result_list.append(j)
        #return在循环外部,只有当变量完全生成后一次性返回;如果在循环体内部,则只会返回第一个数据
        return  result_list
?
    def call_gen_iterator(self):
        # 获取gen_iterator方法返回的list结果
        result_list = self.gen_iterator()
        for i in result_list:
            print(fcall_gen_iterator--{i})
?
if __name__ == __main__:
    obj = TestReturn()
    obj.call_gen_iterator()
    
#运行结果
gen_iterator--0
gen_iterator--1
gen_iterator--2
call_gen_iterator--0
call_gen_iterator--1
call_gen_iterator--2

结果分析:次性执行完下层函数,生成完整的迭代器类型返回值result_list,一次性返回给上层函数

 

测试yield

class TestYield:
    def gen_iterator(self):
        for j in range(3):
            print(f"do_something-{j}")
            # yield在for循环内部
            yield j
?
    def call_gen_iterator(self):
        # yield并不是直接返回[0,1,2],执行下边这句后result_list什么值都没有
        result_list = self.gen_iterator()
        # i每请求一个数据,才会触发gen_iterator生成一个数据
        for i in result_list:
            print(f"call_gen_iterator-{i}")
?
if __name__ == "__main__":
    obj = TestYield()
    obj.call_gen_iterator()
    
#运行结果
do_something-0
call_gen_iterator-0
do_something-1
call_gen_iterator-1
do_something-2
call_gen_iterator-2

结果:上下层函数是交替进行的,即上层函数请求迭代一个值下层函数才生成一个值并立即返回这个值

  • 如果在setup就异常了,那么是不会去执行yield后面的teardown内容了



pytest复习

标签:数据   append   获取数据   ali   nal   cal   app   collect   sse   

原文地址:https://www.cnblogs.com/wangm-hoshi/p/14883121.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!