Python从入门到实践——第十一章 测试代码

第十一章 测试代码

1.测试函数

文件一name_function_test1

# name_function_test_1.py

def get_formatted_name(first, last, middle=''):

    """生成整洁的姓名"""

    if middle:

        full_name = f"{first} {middle} {last}"

    else:

        full_name = f"{first} {last}"

    return full_name.title()

文件二 name_function_test

【名字test结尾

import unittest

from name_function_test_1 import get_formatted_name




class NamesTestCase(unittest.TestCase):

    """测试name_function.py """

    def test_first_last_name(self):

        """能够正确地处理像Janis Joplin这样的姓名吗?"""

        formatted_name = get_formatted_name('janis', 'joplin')

        self.assertEqual(formatted_name, 'Janis Joplin')



    def test_first_last_middle_name(self):

        """能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗?"""

        formatted_name = get_formatted_name(

            'wolfgang', 'mozart', 'amadeus')

        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')





# unittest.main()

【断言】 self.assert

测试目的:这段代码是一个简单的单元测试,用于测试名字格式化函数 `get_formatted_name` 是否能够正确地处理不同情况下的姓名。

测试类和方法: 通过 `unittest.TestCase` 创建了一个测试类 `NamesTestCase`,其中包含了两个测试方法。每个测试方法都以 `test_` 开头,是为了让 unittest 能够自动识别和执行这些方法。

第一个测试方法 (`test_first_last_name`):测试函数调用 `get_formatted_name` 函数,将 'janis' 和 'joplin' 作为参数传递给它。然后,使用 `self.assertEqual` 断言来验证函数的返回值是否等于期望的结果 'Janis Joplin'。

第二个测试方法 (`test_first_last_middle_name`): 同样地,这个方法测试 `get_formatted_name` 函数,但这次使用了包含中间名 'amadeus' 的完整名字 'wolfgang mozart amadeus'。通过断言验证函数的返回值是否等于'Wolfgang Amadeus Mozart'。

注释和文档字符串: 注释和文档字符串用于解释代码的目的和各个部分的功能。注释解释了整个测试类的目的,而文档字符串则解释了每个测试方法的具体测试目标。

注释掉的 `unittest.main()`:在最后,`unittest.main()` 这一行是注释掉的。这是因为在讲解代码时,你可能只想解释测试的内容而不直接执行测试。如果需要执行测试,可以取消注释这一行。

【练习】

11-1 城市和国家:编写一个函数,它接受两个形参:一个城市名和一个国家名。这个函数返回一个格式为City,Country的字符串,如Santiago,Chile。将这个函数存储在一个名为city_functions.py的模块中。

# city_functions.py

def format_city_country(city, country):

    """格式化城市和国家的字符串"""

    formatted_string = f"{city.title()}, {country.title()}"

    return formatted_string

创建一个名为test_cities.py的程序,对刚编写的函数进行测试(别忘了,你需要导入模块unittest以及要测试的函数)。编写一个名为test_city_country()的方法,核实使用类似于'santiago'和'chile'这样的值来调用前述函数时,得到的字符串是正确的。运行test_cities.py,确认测试test_city_country()通过了。

import unittest

from city_functions import format_city_country

class TestCities(unittest.TestCase):

    '''test city_functions.py模块'''



    def test_city_country(self):

        formatted_result=format_city_country('santiago','chile')

        self.assertEqual(formatted_result,'Santiago, Chile')

if __name__ == '__main__': #这是主程序入口

    unittest.main()

11-2 人口数量:修改前面的函数,使其包含第三个必不可少的形参population,并返回一个格式为City, Country-populationxxx的字符串,如Santiago,Chile-population 5000000。运行test_cities.py,确认测试test_city_country()未通过。修改上述函数,将形参population设置为可选的。再次运行test_cities.py,确认测试test_city_country()又通过了。

# city_functions.py

def format_city_country(city, country,population=None):

    """格式化城市和国家的字符串"""

    if population:

        formatted_string = f"{city.title()}, {country.title()},{population}"

    else:

        formatted_string = f"{city.title()}, {country.title()}"

    return formatted_string

再编写一个名为test_city_country_population()的测试,核实可以使用类似于'santiago'、'chile'和'population=5000000'这样的值来调用这个函数。再次运行test_cities.py,确认测试test_city_country_population()通过了

import unittest

from city_functions import format_city_country

class TestCities(unittest.TestCase):

    '''test city_functions.py模块'''



    def test_city_country(self):

        formatted_result=format_city_country('santiago','chile')

        self.assertEqual(formatted_result,'Santiago, Chile')



    def test_city_population(self):

        formatted_result= format_city_country('santiago','chile', 500000)

if __name__ == '__main__': #这是主程序入口

    unittest.main()

2. 测试类

雇员:编写一个名为Employee的类,其方法__init__()接受名、姓和年薪,并将它们都存储在属性中。编写一个名为give_raise()的方法,它默认将年薪增加5000美元,但也能够接受其他的年薪增加量。

为Employee编写一个测试用例,其中包含两个测试方法:test_give_default_raise()和test_give_custom_raise()。使用方法setUp(),以免在每个测试方法中都创建新的雇员实例。运行这个测试用例,确认两个测试都通过了。

import unittest



class Employee:

    def __init__(self, first_name, last_name, salary):

        self.first_name = first_name

        self.last_name = last_name

        self.salary = salary



    def give_raise(self, amount=5000):

        self.salary += amount



class TestEmployee(unittest.TestCase):

    def setUp(self):

        self.employee = Employee("John", "Doe", 50000)



    def test_give_default_raise(self):

        self.employee.give_raise()

        self.assertEqual(self.employee.salary, 55000)



    def test_give_custom_raise(self):

        self.employee.give_raise(10000)

        self.assertEqual(self.employee.salary, 60000)



if __name__ == '__main__':

    unittest.main()

3. 小结

在本章中,你学习了:如何使用模块unittest中的工具来为函数和类编写测试;如何编写继承unittest.TestCase的类,以及如何编写测试方法,以核实函数和类的行为符合预期;如何使用方法setUp()来根据类高效地创建实例并设置其属性,以便在类的所有测试方法中都可使用它们。测试是很多初学者都不熟悉的主题。作为初学者,并非必须为你尝试的所有项目编写测试;但参与工作量较大的项目时,你应对自己编写的函数和类的重要行为进行测试。这样你就能够更加确定自己所做的工作不会破坏项目的其他部分,你就能够随心所欲地改进既有代码了。

你可能感兴趣的:(python,开发语言)