美文网首页
第九章 测试代码

第九章 测试代码

作者: 永不熄灭的火焰_e306 | 来源:发表于2019-09-26 10:53 被阅读0次

    10.1 测试函数

    10.1.1 单元测试和测试用例

    单元测试用于核实函数的某个方面没有问题;测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。

    10.1.2 可通过的测试

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

    example:

    import unittest 
    from name_function import get_formatted_name 
    
     class NamesTestCase(unittest.TestCase):        #编写类继承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')        一个断言方法
            
    unittest.main()     #代码行unittest.main()让Python运行这个文件中的测试
    

    我们运行test_name_function.py时,所有以test_打头的方法都将自动运行

    代码行self.assertEqual(formatted_name, 'Janis Joplin')的意思是说:

    “将formatted_name的值同字符串'Janis Joplin'进行比较,如果它们相等,就万事大吉,如果它

    们不相等,跟我说一声!”

    10.1.3 不能通过的测试

    代码行unittest.main()让Python运行这个文件中的测试

    def get_formatted_name(first, middle, last): 
        """生成整洁的姓名"""
        full_name = first + ' ' + middle + ' ' + last 
        return full_name.title()
    
    #结果:
     E 
    ====================================================================== 
    ERROR: test_first_last_name (__main__.NamesTestCase) 
    ---------------------------------------------------------------------- 
     Traceback (most recent call last): 
     File "test_name_function.py", line 8, 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)
    

    ​ 第1行输出只有一个字母E(见Ø),它指出测试用例中有一个单元测试导致了错误。接下来,我们看到

    NamesTestCase中的test_first_last_name()导致了错误(见)。测试用例包含众多单元测试时,

    知道哪个测试未通过至关重要。在处,我们看到了一个标准的traceback,它指出函数调用

    get_formatted_name('janis', 'joplin')有问题,因为它缺少一个必不可少的位置实参。

    ​ 我们还看到运行了一个单元测试(见)。最后,还看到了一条消息,它指出整个测试用例

    都未通过,因为运行该测试用例时发生了一个错误(见)。这条消息位于输出末尾,让你一眼

    就能看到——你可不希望为获悉有多少测试未通过而翻阅长长的输出。

    10.1.4 测试未通过时怎么办

    根据测试结果修改原有的函数

    example:10.1.3中将中间名设置为可选的

    def get_formatted_name(first, last, middle=''): 
         """生成整洁的姓名""" 
        if middle: 
            full_name = first + ' ' + middle + ' ' + last 
        else: 
            full_name = first + ' ' + last 
        return full_name.title()
    
    #结果:
    . 
    ---------------------------------------------------------------------- 
    Ran 1 test in 0.000s 
    OK
    

    10.1.5 添加新的测试

    import unittest 
    from name_function 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()
    

    们将这个方法命名为test_first_last_middle_name()。方法名必须以test_打头,这样它才

    会在我们运行test_name_function.py时自动运行。

    10.2 测试类

    10.2.1 6中常用的断言方法

    方法 用途
    assertEqual(a,b) 核实a == b
    assertNotEqual(a,b) 核实a!=b
    assertTrue(x) 核实x为True
    assertFalse(x) 核实x为False
    assertIn(item, list) 核实item在list中
    assertNotIn(item, list) 核实item不在list中

    10.2.2 一个要测试的类

    survey.py

    class AnonymousSurvey(): 
        """收集匿名调查问卷的答案""" 
        
        def __init__(self, question): 
            """存储一个问题,并为存储答案做准备""" 
            self.question = question 
            self.responses = [] 
            
        def show_question(self): 
            """显示调查问卷""" 
            print(question) 
            
        def store_response(self, new_response): 
            """存储单份调查答卷""" 
            self.responses.append(new_response) 
            
         def show_results(self): 
            """显示收集到的所有答卷""" 
            print("Survey results:") 
            for response in responses: 
                print('- ' + response)
    

    language_survey.py

    from survey import AnonymousSurvey 
    
    #定义一个问题,并创建一个表示调查的AnonymousSurvey对象
    question = "What language did you first learn to speak?" 
    my_survey = AnonymousSurvey(question) 
    
    #显示问题并存储答案
    my_survey.show_question() 
    print("Enter 'q' at any time to quit.\n") 
    while True: 
        response = input("Language: ") 
        if response == 'q':
            break 
        my_survey.store_response(response) 
        
    # 显示调查结果
    print("\nThank you to everyone who participated in the survey!") 
    my_survey.show_results()
    

    输出结果:

    What language did you first learn to speak? 
    Enter 'q' at any time to quit. 
    Language: English
    Language: Spanish
    Language: English
    Language: Mandarin
    Language: q
    Thank you to everyone who participated in the survey! 
    Survey results: 
    - English 
    - Spanish 
    - English 
    - Mandarin
    

    10.2.3 测试AnonymousSurvery

    test_survey.py

    import unittest 
    from survey import AnonymousSurvey 
    
     class TestAnonmyousSurvey(unittest.TestCase):
            """针对AnonymousSurvey类的测试""" 
            
     def test_store_single_response(self): 
            """测试单个答案会被妥善地存储""" 
             question = "What language did you first learn to speak?" 
             my_survey = AnonymousSurvey(question) 
             my_survey.store_response('English')
             
            self.assertIn('English', my_survey.responses)
            
    unittest.main()
    

    要测试类的行为,需要创建其实例

    结果:

    . 
    ---------------------------------------------------------------------- 
    Ran 1 test in 0.001s 
    OK
    

    核实用户提供三个答案时,它们也将被妥善地存储。为此,我们在TestAnonymousSurvey中再添加一个方法:

    import unittest 
    from survey import AnonymousSurvey 
    
    class TestAnonymousSurvey(unittest.TestCase): 
        """针对AnonymousSurvey类的测试""" 
        
        def test_store_single_response(self): 
            """测试单个答案会被妥善地存储""" 
             --snip-- 
             
        def test_store_three_responses(self): 
            """测试三个答案会被妥善地存储""" 
            question = "What language did you first learn to speak?" 
            my_survey = AnonymousSurvey(question) 
            responses = ['English', 'Spanish', 'Mandarin'] 
            for response in responses:
                my_survey.store_response(response) 
                
            for response in responses: 
                self.assertIn(response, my_survey.responses) 
                
    unittest.main()
    

    10.2.4 方法setUp()

    如果你在TestCase类中包含了方法setUp(),Python将先运行 它,再运行各个以test_打头的方法。这样,在你编写的每个测试方法中都可使用在方法setUp() 中创建的对象了。

    测试自己编写的类时,方法setUp()让测试方法编写起来更容易:可在setUp()方法中创建一

    系列实例并设置它们的属性,再在测试方法中直接使用这些实例。相比于在每个测试方法中都创

    建实例并设置其属性,这要容易得多。

    import unittest 
    from survey import AnonymousSurvey 
    
    class TestAnonymousSurvey(unittest.TestCase): 
        """针对AnonymousSurvey类的测试""" 
        
        def setUp(self): 
            """ 
            创建一个调查对象和一组答案,供使用的测试方法使用
             """ 
            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): 
            """测试单个答案会被妥善地存储""" 
            self.my_survey.store_response(self.responses[0]) 
             self.assertIn(self.responses[0], self.my_survey.responses) 
     
        def test_store_three_responses(self): 
            """测试三个答案会被妥善地存储""" 
            for response in self.responses: 
                 self.my_survey.store_response(response) 
            for response in self.responses: 
                self.assertIn(response, self.my_survey.responses) 
    
    unittest.main()
    

    注意: 运行测试用例时,每完成一个单元测试,Python都打印一个字符:测试通过时打印一个

    句点;测试引发错误时打印一个E;测试导致断言失败时打印一个F。

    相关文章

      网友评论

          本文标题:第九章 测试代码

          本文链接:https://www.haomeiwen.com/subject/pqthyctx.html