编写函数或类时,还可为其编写测试,通过测试,就可确定面对各种输入都能按照要求那样工作。测试让你信心满满,即使有更多的人使用你的程序,它可以正常工作。

​ python中有模块unittest中的工具测试代码

测试代码

​ 先准备一个将要测试的代码

##编写要测试的代码
###function_test.py
def user_name(first,last):
    """接受用户传递的名字"""
    uesrname = first+last
    return uesrname.title()
##调用函数
from function_test import user_name


print("please enter you name as required:")


##定义一个循环让用户循环输入
# status = True
while True:
    first = input("enter you first name:")
    if first == 'q':
        # status = False
        break
    last = input("enter you last name: ")
    if last == 'q':
        # status = False
        break
    formatted_name = user_name(first,last)
    print(formatted_name)
    
##执行
please enter you name as required:
enter you first name:tan
enter you last name: chang
Tanchang
enter you first name:q

想上面这样我写了一段代码,要去测试它的话就要一个一个的去测试它,这样就会特别麻烦

单元测试和

​ python标准库中的模块unittest提供了代码测试工具。单元测试用于核实函数的某个方面没有问题;

可通过的测试

​ 要为函数编写测试用例,可先导入模块unittest以及要测试的函数,再创建有个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。

###检查function_test.py能否正常运行
###test_name_function.py
from function_test import user_name
import unittest


class TestnameCase(unittest.TestCase):
    """测试function_test.py"""

    def test_name(self):
        """是否可以正确的处理谭 畅这样用户名"""
        """调用user_name函数传递实参,然后传给name变量"""
        name = user_name('谭', '畅')
        """这是一个断言方法,用来测试得到的结果进行比较然后得出是否和自己期望的值是一样的,这里就是比较"""
        self.assertEqual(name, '谭畅')
##执行
"""表示测试运行了0.001秒"""
Ran 1 test in 0.001s

OK

不能通过的测试

​ 现在来看一下没有通过的时候是什么样子,修改function_name.py文件

##编写要测试的代码
"""加上中间名"""
def user_name(first,middle,last):
    """接受用户传递的名字"""
    uesrname = first+middle+last
    return uesrname.title()
##再去用上面的测试语句来测试运行
##test_name_function.py
##执行
Ran 1 test in 0.003s

FAILED (errors=1)
Launching unittests with arguments python -m unittest test_name_function.TestnameCase.test_name in C:\Users\tanchang\Desktop\python\code
Error
Traceback (most recent call last):
  File
##这里就是告诉你last这个实参没有
"C:\Users\tanchang\Desktop\python\code\test_name_function.py", line 23, in test_name
    name = user_name('谭', '畅')
TypeError: user_name() missing 1 required positional argument: 'last'

测试未通过时怎么办

​ 当你测试未通过时,应当修改你测试的内容,不应该修改你的测试

###修改function_name.py
def user_name(first,last,middle=''):
    """接受用户传递的名字"""
    """python中字符串为空的都为flase"""
    if middle:
        full_name = first+middle+last
    else:
        full_name = first + last
    return full_name.title()
###让python执行这个测试
unittest.main
###test_name_function.py
##执行
Ran 1 test in 0.001s

OK

添加新的测试

​ 刚刚再function_name.py中添加了一个middle名,现在可以再测试中再添加一个测试,添加middle名是否会成功

from function_test import user_name
import unittest


class TestnameCase(unittest.TestCase):
    """测试function_test.py"""

    def test_name(self):
        """是否可以正确的处理谭 畅这样用户名"""
        """调用user_name函数传递实参,然后传给name变量"""
        name = user_name('谭', '畅')
        """这是一个断言方法,用来测试得到的结果进行比较然后得出是否和自己期望的值是一样的"""
        self.assertEqual(name, '谭畅')

    def test_middle_name(self):
        """测试加入中间名是否会成功"""
        """注意实参的顺序"""
        name = user_name('周','伦','杰')
        self.assertEqual(name,'周杰伦')
unittest.main

##执行
Ran 2 tests in 0.004s

OK


​ 11-1城市和国家:编写一个函数,它接受两个形参:一个城市名和一个国家名。这个函数返回一个格式为City,Country的字符串,如 Santiago,Chile。将这个函数存储在一个名为city_functions.py的模块中。
​ 创建一个名为test_cities.py的程序,对刚编写的函数进行测试(别忘了,你需要导入模块unittest以及要测试的函数)。编写一个名为test_city_country()的方法,核实使用类似于' santiago'和'chile'这样的值来调用前述函数时,得到的字符串是正确的.运行test_cities.py,确认测试test_city_country()通过了。

##city_function.py
def country(City,Country):
    """接受城市,国家名"""
    count = City+','+Country
    return count
##test_cities.py
import unittest
from city_functions import country
class CitytestConutry(unittest.TestCase):
    """测试打印的是不是和期望打印的一样"""
    def test_city_count(self):
        count_name = country('北京','中国')
        self.assertEqual(count_name,'北京,中国')
##执行
Ran 1 test in 0.003s

OK

测试类

各种断言方法

​ python再unittest.TestCase中提供了很多断言方法
image-20211108160416341

一个要测试的类

​ 类的测试与函数的测试相似,你所作的大部分工作都是测试类中的方法行为,但存在一些不同之处。

##创建一个收集用户使用的编程语言的问卷
class survey_username():
    """收集调查用户的名字"""

    def __init__(self, questions):
        self.questions = questions
        self.code_languages = []

    def show_question(self):
        """打印询问"""
        print(self.questions)

    def storage_code(self, new_user):
        """存储用户"""
        self.code_languages.append(new_user)

    def show_result(self):
        print('survey code languages:')
        for i in self.code_languages:
            print('-' + i)


##创建实列
questions = '您好,谢谢您参加我们的调查请在下面输入您的所使用的编程语言:'
my_servey = survey_username(questions)

my_servey.show_question()
print('输入q退出')
while True:
    data = input('输入您使用的编程语言:')
    if data == 'q':
        break
    my_servey.storage_code(data)
print('谢谢配合')
my_servey.show_result()


##执行
您好,谢谢您参加我们的调查请在下面输入您的所使用的编程语言:
输入q退出
输入您使用的编程语言:C
输入您使用的编程语言:PYTHON
输入您使用的编程语言:C++
输入您使用的编程语言:C#
输入您使用的编程语言:q
谢谢配合
survey code languages:
-C
-PYTHON
-C++
-C#

测试类

​ 上面我定义了一个类并执行了它,我现在把后面的实列给注释掉再编写code_language_survey_test.py文件

###code_language_survey_test.py
from code_languages_survey import survey_username
import unittest


class survey(unittest.TestCase):
    """测试调查问卷"""

    def test_code_language_survey(self):
        """测试"""
        question = '你比较喜欢使用哪些编程语言?'
        my_survey = survey_username(question)
        my_survey.storage_code('Python')
        self.assertIn('Python', my_survey.code_languages)
        
        
##测试
"""测试成功j"""
Ran 1 test in 0.002s

OK

方法setUp()

​ 之前需要再每个测试方法都要去创建一个实列,其实可以不用这么麻烦,可以直接使用setup()来实现,直接定义一个setup方法,直接再setUp中创建实列,然后再其他测试方法中就不用创建实列。
​ 如果再unittet.TestCase类中包含了setup(),还有一些其他语句,他就会先执行setUp()语句,再执行其他的test语句

##修改一下code_language_survey_test.py
from code_languages_survey import survey_username
import unittest


class survey(unittest.TestCase):
    """测试调查问卷"""

    def setUp(self):
        """测试"""
        question = '你比较喜欢使用哪些编程语言?'
        self.my_survey = survey_username(question)
        self.my_code_language = ['C','C++','C#','Python','Go']

    def test_code_language_survey_one(self):
        """测试单个数据是否能存储"""
        self.my_survey.storage_code(self.my_code_language[0])
        self.assertIn(self.my_code_language[0],self.my_survey.code_languages[0])

    def test_code_language_survey(self):
        """测试这5个语言是否会正确的存储到里面"""
        for i in self.my_code_language:
            self.my_survey.storage_code(i)
        for i in self.my_code_language:
            self.assertIn(i,self.my_survey.code_languages)


​ 11-3雇员:编写一个名为Employee的类,其方法_init_()接受名、姓和年薪,并将它们都存储在属性中。编写一个名为give_raise()的方法,它默认将年薪增加5000美元.但也能够接受其他的年薪增加量
​ 为Employee 编写一个测试用例,其中包含两个测试方法:test_give_default_raise()和test_give_custom_raise()。使用方法 setUp(),以免在每个测试方法中都创建新的雇员实例。运行这个测试用例,确认两个测试都通过了。

##Employee.py
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,num=5000):
        self.salary += num
##test_Employee.py
    """测试加薪"""

    def setUp(self):
        self.firstname = 'tan'
        self.lastname = 'chang'
        self.salary = 6000
        self.employee_sv = Employee(self.firstname, self.lastname, self.salary)

    def test_give_default_raise(self):
        self.employee_sv.give_raise()
        self.assertEqual(self.salary + 5000, self.employee_sv.salary)

    def test_give_custom_raise(self):
        numeber = 3000
        self.employee_sv.give_raise(num=numeber)
        self.assertEqual(self.salary + numeber, self.employee_sv.salary)