📅 2024年11月18日

📘 读《Python入门到实践》

📦 Python3.8.6

🏆 测试代码

本章节使用 pytest来测试 python代码,需要通过 pip来下载

 python -m pip install --user pytest
 Successfully installed colorama-0.4.6 exceptiongroup-1.2.2 iniconfig-2.0.0 packaging-24.2 pluggy-1.5.0 pytest-8.3.3 tomli-2.1.0

✏️ 编写测试函数

先编写一个测试用例,这个函数的意思是输入你的名和姓,返回你的名字

## 测试用例
def get_formatted_name(first_name, last_name):
    full_name = f"{first_name} {last_name}"
    return full_name.title()

编写一个基础的单元测试,使用 assert断言,断⾔(assertion)就是声称满⾜特定的条件,有点像Go语言里面 Example测试,比如下面的意思就是这个如果 formatted_name和的自己写的这个输出是一模一样的就表示测试成功

第⼀,测试函数必须以 test_ 打头。 在测试过程中,pytest 将找出并运⾏所有以 test_ 打头的函数。

第⼆, 测试函数的名称应该⽐典型的函数名更⻓,更具描述性

from name_function import get_formatted_name

def test_get_formatted_name():
    formatted_name  = get_formatted_name('Tan','chang')
    assert formatted_name == 'Tan Chang'

在pycharm中可以直接运行,或者通过终端运行 pytest,运行结果如下

===================================================== test session starts ===================================================== 
platform win32 -- Python 3.8.6, pytest-8.3.3, pluggy-1.5.0
rootdir: D:\learnCode\python\PythonStu\pythonProject1\Testing
collected 1 item                                                                                                            

test_first_laster_name.py .                                                                                              [100%] 

====================================================== 1 passed in 0.01s ====================================================== 

可见运行通过了

✏️ 测试类

编写针对类的测试

1️⃣ 各种断言

在编写测试时,可做出任何可表⽰为条件语句的断⾔。如果该条件确实成 ⽴,你对程序⾏为的假设就得到了确认,可以确信其中没有错误。如果你 认为应该满⾜的条件实际上并不满⾜,测试就不能通过,让你知道代码存 在需要解决的问题。这里只是一个示例,但是在实际中比这个要多的多,也可以自己组建

assert a == b 断⾔两个值相等 
assert a != b 断⾔两个值不等 
assert a 断⾔ a 的布尔求值为 
True assert not a 断⾔ a 的布尔求值为 
False assert element in list 断⾔元素在列表中 
assert element not in list 断⾔元素不在列表中

2️⃣ 编写一个要被测试的类

如下是一个匿名调查类,他有2个变量,有3个方法

class AnonymousSurvey:
    def __init__(self,question):
        self.question = question
        self.response = []

    def show_question(self):
        """显示问卷调查"""
        print(self.question)

    def add_response(self, new_response):
        """添加调查结果"""
        self.response.append(new_response)

    def show_results(self):
        """显示调查结果"""
        print("Survey result")
        for response in self.response:
            print(f"- {response}")

编写一个测试它的测试函数,这里我编写了两个测试函数,在测试函数内都创建一个另一个调查对象,并各自操作调查对象

from name_function import AnonymousSurvey


def test_get_survey_question_one():
    question = "你觉得哪个语言最好用?"
    survey = AnonymousSurvey(question)
    survey.add_response("python")
    """查看是否存到匿名调查内去了"""
    assert "go" in survey.response


def test_get_survey_question_two():
    question = "你觉得哪个语言最好用?"
    survey = AnonymousSurvey(question)
    response = ['go', 'php', 'java', 'python']
    """将列表语言添加进匿名调查的response"""
    for re in response:
        survey.add_response(re)
    """遍历查看是否存储到匿名调查内"""
    for re in response:
        assert re in survey.response

测试结果

##第一个肯定是测试失败的
============================= test session starts =============================
collecting ... collected 1 item

test_first_laster_name.py::test_get_survey_question_one FAILED           [100%]
test_first_laster_name.py:9 (test_get_survey_question_one)
'go' != ['python']

预期:['python']
实际:'go'
<点击以查看差异>

def test_get_survey_question_one():
        question = "你觉得哪个语言最好用?"
        survey = AnonymousSurvey(question)
        survey.add_response("python")
        """查看是否存到匿名调查内去了"""
>       assert "go" in survey.response
E       AssertionError: assert 'go' in ['python']
E        +  where ['python'] = <name_function.AnonymousSurvey object at 0x000001A25009C190>.response

test_first_laster_name.py:15: AssertionError


============================== 1 failed in 0.13s ==============================

第二个

============================= test session starts =============================
collecting ... collected 1 item

test_first_laster_name.py::test_get_survey_question_two PASSED           [100%]

============================== 1 passed in 0.01s ==============================

3️⃣ fixture

如上代码比较繁琐,在每个测试函数内都创建了一个匿名调查对象,在少量的测试还好,但是如果在大量的测试创建这么多类型就会有大问题了,使用 fixture可以减少对象的创建,也就是可以创建好一个对象供多个测试函数使用

创建 fixture,需要使用到装饰器,装饰器(decorator)是放在函数定义 前⾯的指令。在运⾏函数前,Python 将该指令应⽤于函数,以修改函数代 码的行为,

当测试函数的⼀个形参与应用了装饰器 @pytest.fixture 的函数(夹具)同名时,将自动运行 fixture,并将 fixture返回的值传递给测试函数。

也就是为后面的测试函数提供一个对象

##创建fixtrue
@pytest.fixturedd()
def survey():
    question = "你觉得哪个语言最好用?"
    survey = AnonymousSurvey(question)
    return survey


def test_get_survey_question_one(survey):
    survey.add_response("python")
    """查看是否存到匿名调查内去了"""
    assert "python" in survey.response


def test_get_survey_question_two(suvey):
    response = ['go', 'php', 'java', 'python']
    """将列表语言添加进匿名调查的response"""
    for re in response:
        survey.add_response(re)
    """遍历查看是否存储到匿名调查内"""
    for re in response:
        assert re in survey.response