Python测试代码unittest简单使用笔记。

学习Python有段时间了,关于测试的部分基本没咋学过,初学的时候看不懂,现在都2018年了,回头再来学习下,要不然一点不了解说不过去。

首先参考的是入门初级《Python编程从入门到实践》第11章,测试代码。

Python标准库中的模块unittest提供了代码测试工具。单元测试用于何时函数的某个方法没有问题;

测试用例是一组单元测试,这些单元测试一起核实函数在各种情况下的行为都符合要求。

良好的测试用例考虑到了函数可能收到的各种输入,包含针对目标情形的测试。

全覆盖测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖很难。

通常,最初只要针对代码的重要行为编写测试既可,等项目被广泛使用时再考虑全覆盖。

首先编写一个测试函数

def get_formatted_name(first, last):
    full_name = first + ' ' + last
    return full_name.title()

 然后编写一个测试该函数的类

import unittest
from name_function import get_formatted_name

# 编写一个测时类继承unittest.TestCase
class NamesTestCase(unittest.TestCase):

    # 定义一个测试的方法,方法名字要以test开头,这样在unittest.main()执行的时候会自动执行
    def test_first_last_name(self):
        # 调用被测试的函数,输入参数,并通过变量接收
        formatted_name = get_formatted_name('janis', 'joplin')
        # 通过assertEqual判断测试函数返回的,与实际正确的结果是否一致。
        self.assertEqual(formatted_name, 'Janis Joplin')

if __name__ == '__main__':
    unittest.main()

 执行该脚本

shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_name_function.py 
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

 一个点表示一个测试方法通过了,第二个是花费的时间,第三个参数为所有的测试方法都通过了。

故意搞错了试试。

def get_formatted_name(first, middle, last):
    full_name = first + ' ' + middle + ' ' + last
    return full_name.title()

 把函数改成三个参数输入的。

运行测试的输出

shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_name_function.py 
E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_name_function.py", line 10, in test_first_last_name
    formatted_name = get_formatted_name('janis', 'joplin')
TypeError: get_formatted_name() missing 1 required positional argument: 'last'

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

测试没通过,就要新办法去修改你的函数,让其通过

def get_formatted_name(first, last, middle=''):
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' +last
return full_name.title()

改成这样就又可以通过了。

因为这个函数可以接收三个参数,所以原来的测试类上面添加一个测试的方法。

import unittest
from name_function import get_formatted_name

# 编写一个测时类继承unittest.TestCase
class NamesTestCase(unittest.TestCase):

    # 定义一个测试的方法,方法名字要以test开头,这样在unittest.main()执行的时候会自动执行
    def test_first_last_name(self):
        # 调用被测试的函数,输入参数,并通过变量接收
        formatted_name = get_formatted_name('janis', 'joplin')
        # 通过assertEqual判断测试函数返回的,与实际正确的结果是否一致。
        self.assertEqual(formatted_name, 'Janis Joplin')
        
    def test_first_last_middle_name(self):
        formatted_name = get_formatted_name(
            'wolfgang', 'mozart', 'amadeus'
        )
        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')

if __name__ == '__main__':
    unittest.main()

 返回的结果

shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_name_function.py 
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

作业不写了,基本跟书上的一模一样,只不过把名字改成了城市。

测试类。

各种断言方法

self.assertEqual(a,b)    核实 a == b

self.assertNotEqual(a, b)    核实 a != b

assertTrue(x)           核实x为True

assertFalse(x)          核实x为False

assertIn(item, list)    核实item在list中

assertNotIn(item, list)  核实item不在list中

看了一下,其实跟测试函数差不多。

先些测试准备被测试的类

class AnonymousSurvey:

    def __init__(self, question):
        self.question = question
        self.responses = []

    def show_question(self):
        print(self.question)

    def store_response(self, new_response):
        self.responses.append(new_response)

    def show_results(self):
        print('Survey result:')
        for response in self.responses:
            print('- ' + response)

 在写一个脚本使用这个类

from survey import AnonymousSurvey

question = "What language did you first learn to spaek?"
my_survey = AnonymousSurvey(question)


my_survey.show_question()
print('Enter "q" at any time to quit.
')
while True:
    response = input("Language: ")
    if response == 'q':
        break
    my_survey.store_response(response)

print('
Thank you to everyone who participated in the survey!')
my_survey.show_results()

 运行脚本显示的情况

/usr/local/bin/python3.7 /Users/shijianzhong/study/测试/Python从入门到实践/language_survey.py
What language did you first learn to spaek?
Enter "q" at any time to quit.

Language: python
Language: java
Language: js
Language: q

Thank you to everyone who participated in the survey!
Survey result:
- python
- java
- js

编写测试 AnonymousSurvey的类,因为每添加一门语言,在实例的responses属性里面都会多一门,所以测试的时候用了AssertIn()

import unittest
from survey import AnonymousSurvey

# 创建测试类
class TestAnonymousSurvey(unittest.TestCase):

    # 首先针对只输入了一门语言的情况
    def test_store_single_response(self):
        question = "What language did you first learn to spaek?"
        my_survey = AnonymousSurvey(question)
        # 保存一门语言
        my_survey.store_response('English')

        # 准备测试,这么语言是否在对象的responses属性里面
        self.assertIn('English', my_survey.responses)

if __name__ == '__main__':
    unittest.main()
shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_survey.py 
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

后面写测试三个答案时候,是否也能妥善保管

import unittest
from survey import AnonymousSurvey

# 创建测试类
class TestAnonymousSurvey(unittest.TestCase):

    # 首先针对只输入了一门语言的情况
    def test_store_single_response(self):
        question = "What language did you first learn to spaek?"
        my_survey = AnonymousSurvey(question)
        # 保存一门语言
        my_survey.store_response('English')

        # 准备测试,这么语言是否在对象的responses属性里面
        self.assertIn('English', my_survey.responses)

    def test_store_three_responses(self):
        question = "What language did you first learn to spaek?"
        my_survey = AnonymousSurvey(question)
        # 答案列表
        responses = ['English', 'Spanish', 'Mandarin']
        for response in responses:
            # 把答案先存起来
            my_survey.store_response(response)

        for response in responses:
            # 测试所有的答案到底在不在实例的responses里面
            self.assertIn(response, my_survey.responses)


if __name__ == '__main__':
    unittest.main()
shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_survey.py 
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

方法setUp()

前面的测试,每次测试都要在测试方法中实例化对象,很蛮烦,所以有了setUp方法,就好比普通类里面的__init__,在每次执行的时候,该方法内的逻辑会先执行。

import unittest
from survey import AnonymousSurvey

# 创建测试类
class TestAnonymousSurvey(unittest.TestCase):

    def setUp(self) -> None:
        question = "What language did you first learn to spaek?"
        # 对象变成实例属性,后面大家可以用
        self.survey = AnonymousSurvey(question)
        # 答案列表
        self.responses = ['English', 'Spanish', 'Mandarin']



    # 首先针对只输入了一门语言的情况
    def test_store_single_response(self):
        # 从答案列表拿一个元素出来,进行存储操作
        self.survey.store_response(self.responses[0])
        # 准备测试,这么语言是否在对象的responses属性里面
        self.assertIn(self.responses[0], self.survey.responses)

    def test_store_three_responses(self):
        for response in self.responses:
            # 把答案先存起来
            self.survey.store_response(response)

        for response in self.responses:
            # 测试所有的答案到底在不在实例的responses里面
            self.assertIn(response, self.survey.responses)


if __name__ == '__main__':
    unittest.main()

 运行结果是一样的。这本书中的学习结束,作业不做了,这个书中的作业太简单了。

从另外一本书上看到,说写函数或者方法之前应该先写测试,这个感觉。。。。。。好苛刻啊。。。。。。

原文地址:https://www.cnblogs.com/sidianok/p/12689050.html