Python Crash Course读书笔记 - 第11章:TESTING YOUR CODE

Unit test定义:

Verifies that one specific aspect of a function’s behavior is correct.

Test case定义:

a collection of unit tests that together prove that a function behaves as it’s supposed to, within the full range of situations you expect it to handle.

一个好的test case至少要包括各类典型的函数输入组合。

测试函数

为函数写test case的步骤:

  1. import unittest 模块
  2. 写一个类,继承unittest.TestCase
  3. 写一系列方法测试函数的各种行为

看一个例子。
首先是待测试的函数:

$ cat name_function.py
def get_formatted_name(first, last, middle=''):
    """Generate a neatly formatted full name."""
    if middle:
        full_name = f"{first} {middle} {last}"
    else:
        full_name = f"{first} {last}"
    return full_name.title()

然后是测试用例:

$ cat test_name_function.py
import unittest

from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
    """Tests for 'name_function.py'."""

    def test_first_last_name(self):
        """Do names like 'Janis Joplin' work?"""
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')

    def test_first_last_middle_name(self):
        """Do names like 'Wolfgang Amadeus Mozart' work?"""
        formatted_name = get_formatted_name(
            'wolfgang', 'mozart', 'amadeus')
        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')

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

这里有些要点:

  1. 待测试的函数需要有输入和输出
  2. 测试类NamesTestCase(名字无所谓)继承了unittest.TestCase
  3. 两个测试用例,方法名都是已test_开头,所有以此开头的方法都会自动运行
  4. assert系列方法会验证输出是否与期望的匹配
  5. if __name__这句是必要的。当某程序作为主程序运行时,__name__等于__main__,当这个文件被import(也就是不是主程序时),__name__等于文件名(例如name_function.py就是name_function
  6. unittest.main()启动测试

运行测试,2表示运行了2个测试用例,OK表示测试成功。两个.表示两个用例测试均通过,用此可以表示进度,如果不成功,可能是EF

$ p3 test_name_function.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

测试类

unittest.TestCase中包含一系列assert方法:

  • assertEqual(a, b)
  • assertNotEqual(a, b)
  • assertTrue(x),x等于True
  • assertFalse(x)
  • assertIn(item, list)
  • assertNotIn(item, list)

测试类和测试函数并无不同,只不过将调用函数改为实例化类并调用对象的方法。

待测试的类如下:

$ cat survey.py
class AnonymousSurvey:
    """Collect anonymous answers to a survey question."""

    def __init__(self, question):
        """Store a question, and prepare to store responses."""
        self.question = question
        self.responses = []

    def show_question(self):
        """Show the survey question."""
        print(self.question)

    def store_response(self, new_response):
        """Store a single response to the survey."""
        self.responses.append(new_response)

    def show_results(self):
        """Show all the responses that have been given."""
        print("Survey results:")
        for response in self.responses:
            print(f"- {response}")

测试用例定义如下:

$ cat test_survey.py
import unittest
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
    """Tests for the class AnonymousSurvey"""

    def setUp(self):
        """
        Create a survey and a set of responses for use in all test methods.
        """
        question = "What language did you first learn to speak?"
        self.my_survey = AnonymousSurvey(question)
        self.responses = ['English', 'Spanish', 'Mandarin']

    def test_store_single_response(self):
        """Test that a single response is stored properly."""
        self.my_survey.store_response(self.responses[0])
        self.assertIn(self.responses[0], self.my_survey.responses)

    def test_store_three_responses(self):
        """Test that three individual responses are stored properly."""
        for response in self.responses:
            self.my_survey.store_response(response)
        for response in self.responses:
            self.assertIn(response, self.my_survey.responses)

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

要点如下:

  1. setUp相当于初始化,可以定义在所有测试用例中需要共享的变量。
  2. 需要调用的测试用例名以test_开头
  3. assertIn测试回答是否在列表之中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值