2022.4.10 Python Pytest 实战训练营

from pythonCode.calculator import Calculator
import pytest


class TestCalculator:

    def teardown_class(self):
        print("结束测试")

    def setup_method(self):
        print("开始计算")

    def teardown_method(self):
        print("结束计算")

    @pytest.mark.parametrize("first, second, excepted", [
        pytest.param(1, 1, 2, marks=pytest.mark.p0),
        pytest.param(-0.01, 0.02, 0.01, marks=pytest.mark.p0),
        pytest.param(10, 0.02, 10.02, marks=pytest.mark.p0),
        pytest.param(98.99, 99, 197.99, marks=pytest.mark.p1),
        pytest.param(99, 98.99, 197.99, marks=pytest.mark.p1),
        pytest.param(-98.99, -99, -197.99, marks=pytest.mark.p1),
        pytest.param(-99, -98.99, -197.99, marks=pytest.mark.p1),
        pytest.param(99.01, 0, "参数大小超出范围", marks=pytest.mark.p1),
    ], ids=["整数+整数", "负浮点数+正浮点数", "正整数+浮点数", "浮点数+整数", "整数+浮点数", "负浮点数+负整数", "负整数+负浮点数", "参数超出范围"])
    def test_add(self, first, second, excepted):
        calc = Calculator()
        assert calc.add(first, second) == excepted

在此处键入或粘贴代码

练习1:
被测试代码为:
class Calculator:
def add(self, a, b):

    if a > 99 or a < -99 or b > 99 or b < -99:
        print("请输入范围为【-99, 99】的整数或浮点数")
        return "参数大小超出范围"

    return a + b

def div(self, a, b):
    if a > 99 or a < -99 or b > 99 or b < -99:
        print("请输入范围为【-99, 99】的整数或浮点数")
        return "参数大小超出范围"

    return a / b

用例设计为:
from pythoncode.calculator import Calculator
import pytest

class TestCalculator:
def setup_class(self):
print(‘创建实例化Calculator对象’)
self.calc = Calculator()

def setup(self):
    print('开始计算')

def teardown(self):
    print('结束计算')

def teardown_class(self):
    print('测试结束')
#冒烟测试用例
@pytest.mark.parametrize('a,b,expected',[[1,1,2],[-0.01,0.02,0.01],[10,0.02,10.02]],ids=['整数相加','浮点数相加','整数和浮点数相加'])
@pytest.mark.p0
def test_add0(self,a,b,expected):

    result = self.calc.add(a, b)
    print(result)
    assert result == expected

#有效边界值和无效边界值
@pytest.mark.parametrize('a,b,expected', [[98.99, 99, 197.99], [99, 98.99, 197.99], [-98.99,-99,-197.99],[-99,-98.99,-197.99],[99.01,0,'参数大小超出范围'],[-99.01,-1,'参数大小超出范围'],[2,99.01,'参数大小超出范围'],[1,-99.01,'参数大小超出范围']],

                         ids=['有效边界值1','有效边界值2','有效边界值3','有效边界值4','参数大小超出范围1','参数大小超出范围2','参数大小超出范围3','参数大小超出范围4'])
@pytest.mark.p1
def test_add1(self,a,b,expected):
    result=self.calc.add(a,b)
    print(result)
    assert result==expected



# def test_add2(self):
#     try:
#         result=self.calc.add('中',9.3)
#     except TypeError as e:
#         print('异常信息:')
#         print(e)

# def test_add2(self):
#         with pytest.raises(TypeError) as e:
#             result = self.calc.add('中', 9.3)
#         print('异常信息:')
#         print(e)     #为什么需要对齐with才可以打印呢?---放在with里面是执行try里面的代码,print(e)应该是在捕获了之后才能打印

#异常情况的处理
@pytest.mark.parametrize('a,b,excepted',[['中',9.3,TypeError],['9.3','文',TypeError]],ids=['中文1','中文2'])
@pytest.mark.p2
def test_add2(self,a,b,excepted):
        with pytest.raises(excepted) as e:
            result = self.calc.add(a, b)
            assert result==excepted

-- coding: utf-8 --

@Time : 2022-04-11 10:45

@File : test_aa.py

import yaml
import pytest

from pythoncode.Calculator import Calculator

def get_data():
‘’‘获取yaml中的测试数据’’’
with open(’./data.yaml’,‘r’,encoding=‘utf-8’) as f:
datas = yaml.safe_load(f)
print(datas)
return datas

class TestCalculator():
def setup(self):
print(“开始计算”)
def teardown(self):
print(“结束计算”)
def setup_class(self):
self.call = Calculator()
def teardown_class(self):
print(“结束测试”)
@pytest.mark.P0
@pytest.mark.parametrize(‘a,b,expect’,get_data().get(“P0”).get(“data”),
ids=get_data().get(“P0”).get(“ids”))
def test_add00(self,a,b,expect):
res = self.call.add(a,b)
assert res == expect
@pytest.mark.P1
@pytest.mark.parametrize(‘a,b,expect’,get_data().get(“P1”).get(“data”),ids=get_data().get(“P1”).get(“ids”))
def test_add01(self,a,b,expect):
res = self.call.add(a,b)
assert res == expect
@pytest.mark.P2
@pytest.mark.parametrize(‘a,b,expect’,get_data().get(“P2”).get(“data”),ids=get_data().get(“P2”).get(“ids”))
def test_add02(self,a,b,expect):
with pytest.raises(eval(expect)) as e:
res = self.call.add(a,b)
assert res == expect

练习2:
from pythoncode.calculator import Calculator
import pytest
import yaml
def get_datas(level):
with open(’./datas.yml’,encoding=‘utf-8’) as f:
result=yaml.safe_load(f)
print(result)
add_datas=result.get(‘add’).get(level).get(‘datas’)
add_ids = result.get(‘add’).get(level).get(‘ids’)
print(f"{level}级别的datas为: {add_datas}")
print(f"{level}级别的ids为: {add_ids}")
return[add_datas,add_ids]

class TestCalculator:
add_p0_datas=get_datas(‘P0’)[0]
add_p0_ids=get_datas(‘P0’)[1]
print(add_p0_datas)
add_p1_datas = get_datas(‘P1’)[0]
add_p1_ids = get_datas(‘P1’)[1]
add_p2_datas = get_datas(‘P2’)[0]
add_p2_ids = get_datas(‘P2’)[1]
def setup_class(self):
print(‘创建实例化Calculator对象’)
self.calc = Calculator()

def setup(self):
    print('开始计算')

def teardown(self):
    print('结束计算')

def teardown_class(self):
    print('测试结束')
#冒烟测试用例
@pytest.mark.parametrize('a,b,expected',add_p0_datas,ids=add_p0_ids)
@pytest.mark.p0
def test_add0(self,a,b,expected):

    result = self.calc.add(a, b)
    print(result)
    assert result == expected

#有效边界值和无效边界值
@pytest.mark.parametrize('a,b,expected', add_p1_datas,
                         ids=add_p1_ids)
@pytest.mark.p1
def test_add1(self,a,b,expected):
    result=self.calc.add(a,b)
    print(result)
    assert result==expected

#异常情况的处理
@pytest.mark.parametrize('a,b,excepted',add_p2_datas,ids=add_p2_ids)
@pytest.mark.p2
def test_add2(self,a,b,excepted):
        with pytest.raises(eval(excepted)) as e:#eval让字符串变成一个表达式,完成运算,把它转成了一个类型
            result = self.calc.add(a, b)
            assert result==excepted

思路:
使用参数化来实现计算器相加功能测试
*并没有完整写完,但思路和写法类似
1.先把case分类,下面分为几类:
P0(基础相加功能case),P1-1(有效值相加),P1-2(无效值相加:超出数值范围)
2.上面每个分类对应一个test case方法,如下:
test_Ca_add_P0
test_Ca_add_P1_1
test_Ca_add_P1_2

3.每个方法里面验证方式基本一致
通过调用原calculator add方法进行测试

4.add方法需要传参两个加数,另外我们还要传期望结果,所以总共传三个参数x,y,except

5.每个测试方法添加修饰器来进行传参@pytest.mark.parametrize
6.编写yaml文件,把测试数据写入
7.编写get_data方法来获取对应参数(test_func.py),注意这里我把对应等级priority作为参数传入这个方法

test_cal.py

import allure
import pytest
import yaml


from code.caculator import Calculator
from test import test_func

@allure.feature("计算器功能")
class TestCalculator:
    def setup_class(self):
        self.cal = Calculator()
    def setup(self):
        print("开始计算")
    def teardown(self):
        print("结束计算")
    # @pytest.skip
    @pytest.mark.P0
    # @pytest.mark.run(order=3)
    @allure.story("相加基本用例")
    @pytest.mark.parametrize("x,y,expected",test_func.get_data("P0")[0],
                             ids=test_func.get_data("P0")[1])
    def test_Ca_add_P0(self,x,y,expected):
        result = self.cal.add(x,y)
        assert result == expected

    @pytest.mark.P1
    # @pytest.mark.run(order = 1)
    @allure.story("有效值相加")
    @pytest.mark.parametrize("x,y,expected",test_func.get_data("P1-1")[0],
                             ids=test_func.get_data("P1-1")[1])
    def test_Ca_add_P1_1(self,x,y,expected):
        result = self.cal.add(x,y)
        assert result == expected


    @pytest.mark.P1
    # @pytest.mark.run(order=2)
    @allure.story("无效边界值相加")
    @pytest.mark.parametrize("x,y,expected",test_func.get_data("P1-2")[0],
                             ids=test_func.get_data("P1-2")[1])
    def test_Ca_add_P1_2(self,x,y,expected):
        try:
            result = self.cal.add(x,y)
            assert result == expected
        except TypeError as e:
            print(f"输入有问题,输入值为{x,y},抛出异常:{e}")

test_data.yml

add:
  P0:
    Ca_add_001:
      - 1
      - 1
      - 2
    Ca_add_002:
      - -0.01
      - 0.02
      - 0.01

test_func.py

def get_data(priority="P0"):
    data = yaml.safe_load(open("../data/test_data.yml",encoding = 'utf-8'))
    data = data.get("add")
    result = []
    # print(type(data))
    # print(f"data is {data}")
    # print(type(data["P0"]),data["P0"])
    for item in data[priority].values():
        result.append(item)
    print(result)
    return [result,data[priority].keys()]