您的位置:澳门新葡萄京最大平台 > 最大平台 > 测试代码

测试代码

发布时间:2019-11-23 16:23编辑:最大平台浏览(150)

    测试代码

      介绍如何使用Python模块unittest 中的工具来测试代码。

     

    1.  测试函数

      在Python中,测试函数是用于自动化测试,使用python模块中的unittest中的工具来进行测试。

      例如,创建一个函数max_function()接受两个数字,求其最大值,再创建一个函数number_function()提示用户输入两个数

      代码1:

    1 def get_max_number(x,y):
    2     """求两个数中的最大值"""
    3     if x > y :
    4         max_number = x
    5     else:
    6         max_number = y
    7     return max_number
    

     

      代码2:

     1 from max_function import get_max_number
     2 
     3 print("Enter 'q' at any time to quit.")
     4 while True:
     5     x = input("Please enter x:")
     6     if x == 'q':
     7         break
     8     y = input("Please enter y:")
     9     if y == 'q':
    10         break
    11     max_number = get_max_number(x,y)
    12     print("The max is :",max_number,".")
    

     

      运行结果:

    1 Enter 'q' at any time to quit.
    2 Please enter x:12
    3 Please enter y:23
    4 The max is : 23 .
    5 Please enter x:66
    6 Please enter y:99
    7 The max is : 99 .
    8 Please enter x:q
    

     

    1.1  单元测试和测试用例

      Python标准库中的模块 unittest 提供了代码测试工具。单元测试用于核实函数的某个方面没有问题;测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。全覆盖式测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。

     

    1.2 可通过的测试

      创建测试用例的语法需要一段时间才能习惯,但测试用例创建后,再添加针对函数的单元测试就很简单了。要为函数编写测试用例,可先导入模块 unittest 以及要测试的函数,再创建一个继承 unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。

      例如,创建一个包含一个方法的测试用例,它检查函数get_max_number()在给定x、y值时,是否能正确求出最大值。

      代码:

     1 import  unittest
     2 
     3 from max_function import get_max_number
     4 
     5 class TestMaxCase(unittest.TestCase):
     6     """测试max_function.py"""
     7 
     8     def test_x_y(self):
     9         """能够处理x,y这样的数字"""
    10         max_number = get_max_number(20,18)
    11         self.assertEqual(max_number,20)
    12 
    13 unittest.main
    

      说明:

      第1行,导入一个模块unittest。

      第2行,从模块max_function中导入函数get_max_number()。

      第5行,创建了一个名为TestMaxCase的类,用于包含一系列针对 get_max_number() 的单元测试。

      第8行,定义一个方法test_x_y()。

      第10行,调用函数get_max_number()求出最大值,并赋值给变量max_number 。

      第11行,调用 unittest 的方法 assertEqual() ,并向它传递 max_number 和 20代码行self.assertEqual(max_number,20)的意思是说:“将 max_number的值同字数字20进行比较,如果它们相等,就万事大吉,如果它们不相等,跟我说一声!”

      第13行,调用unittest的main方法。

     

      运行结果:

    1 Ran 1 test in 0.001s
    2 
    3 OK
    

       从第1行可知,测试了一个函数,花费了0.001s;第3行,说明测试OK,通过测试。

     

    1.3 不能通过的测试

      例如,我们创建的一个求三个数的最大值的函数,但是只给其提供两个值。

      代码1:

     1 def get_max_number(x,y,z):
     2     """求三个数中的最大值"""
     3     if x > y  and  x > z:
     4         max_number = x
     5     elif y > z:
     6         max_number = y
     7     else:
     8         max_number = z
     9 
    10     return max_number
    

     

      代码2:

     1 import  unittest
     2 
     3 from max_function1 import get_max_number
     4 
     5 class TestMaxCase(unittest.TestCase):
     6     """测试max_function.py"""
     7 
     8     def test_x_y(self):
     9         """能够处理x,y这样的数字"""
    10         max_number = get_max_number(20,18)
    11         self.assertEqual(max_number,20)
    12 
    13 unittest.main
    

     

      代码2的运行结果如下:

     1  Ran 1 test in 0.000s
     2 
     3 FAILED (errors=1)
     4 Launching unittests with arguments python -m unittest test_max_function1.TestMaxCase in F:PyProjects14exercisechapter_eleven
     5 
     6 Error
    7 Traceback (most recent call last):
    8   File "D:PythonPython36libunittestcase.py", line 59, in testPartExecutor
    9     yield
    10   File "D:PythonPython36libunittestcase.py", line 601, in run
    11     testMethod()
    12   File "F:PyProjects14exercisechapter_eleventest_max_function1.py", line 12, in test_x_y
    13     max_number = get_max_number(20,18)
    14 TypeError: get_max_number() missing 1 required positional argument: 'z'
    

      从以上运行结果可知,由于取最大值的函数需要三个位置实参,但是只给其传了两个,少了一个,由于报错。

     

    1.4 测试未通过时怎么办

      当测试不通过时,我们不要测试区修改用于测试的函数,而应该去修改被测试的函数,使其通过测试。

      例如,对1.3中测试未通过的函数进行完善。

      代码1:

     1 def get_max_number(x=0,y=0,z=0):
     2     """求三个数中的最大值"""
     3     if x > y  and  x > z:
     4         max_number = x
     5     elif y > z:
     6         max_number = y
     7     else:
     8         max_number = z
     9 
    10     return max_number
    

      说明:

      第1行,为了在用户不提供任何参数而调用求最大值的函数时不报错,我们给每个形参都赋予一个默认值0。

      

      代码2:

     1 import  unittest
     2 
     3 from max_function2 import get_max_number
     4 
     5 class TestMaxCase(unittest.TestCase):
     6     """测试max_function.py"""
     7 
     8     def test_x_y(self):
     9         """能够处理x,y这样的数字"""
    10         max_number = get_max_number(20,18)
    11         self.assertEqual(max_number,20)
    12 
    13 unittest.main
    

     

      运行结果:

    1 Ran 1 test in 0.000s
    2 
    3 OK
    

      从以上运行结果可知,测试已通过。

      

    1.5 添加新测试

      例如,我们在以上求最大的模块中,增加一个求最小值的函数。

      代码1:

     1 def get_max_number(x=0,y=0,z=0):
     2     """求三个数中的最大值"""
     3     if x > y  and  x > z:
     4         max_number = x
     5     elif y > z:
     6         max_number = y
     7     else:
     8         max_number = z
     9 
    10     return max_number
    11 
    12 def get_min_number(x=0,y=0,z=0):
    13     """求三个数中的最小值"""
    14     if x < y and x < z :
    15         min_number = x
    16     elif y < z :
    17         min_number = y
    18     else:
    19         min_number = z
    20 
    21     return min_number
    

     

      代码2:

     1 import  unittest
     2 
     3 from max_min_function import get_max_number
     4 from max_min_function import get_min_number
     5 
     6 class TestMaxCase(unittest.TestCase):
     7     """测试max_function.py"""
     8 
     9     def test_max_number(self):
    10         """能够处理x,y这样的数字"""
    11         max_number = get_max_number(20,18)
    12         self.assertEqual(max_number,20)
    13 
    14     def test_min_number(self):
    15         """能否处理x、y、z这样的数字"""
    16         min_number = get_min_number(1,13,18)
    17         self.assertEqual(min_number,1)
    18 
    19 
    20 unittest.main
    

     

      运行结果:

    1 Ran 2 test in 0.001s
    2 
    3 OK
    

      从以上结果可知,两测试都已通过,耗时0.001s。

     

    2. 测试类

      测试类就是针对类来编写测试,验证类是否能想我没期待的那样。如果针对类的测试通过了,我没就能确信对类所做的改进没有意外地破坏其原有的行为。

     

    2.1 各种断言方法

      Python在 unittest.TestCase 类中提供了很多断言方法。断言方法检查我没认为应该满足的条件是否确实满足。如果该条件确实满足,我们对程序行为的假设就得到了确认,我们就可以确信其中没有错误。如果我们认为应该满足的条件实际上并不满足,Python将引发异常。

      常用的断言方法有:

      (1)assertEqual(a, b),核实 a == b。

    *  (2)*assertNotEqual(a, b),核实 a != b。

      (3)assertTrue(x),核实 x 为 True。

      (4)assertFalse(x),核实 x 为 False。

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

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

     

    2.2  测试类

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

      例如,我们创建一个管理匿名调查问卷的类AnonymousSurvey,并将其存于模块survey中,然后测试它。

      (1)创建类AnonymousSurvey

      代码1:

     1 class AnonymousSurvey():
     2     """收集匿名调查问卷的答案"""
     3 
     4     def __init__(self,question):
     5         """存储一个问题,并为存储答案做准备"""
     6         self.question = question
     7         self.responses = []
     8 
     9     def show_question(self):
    10         """显示调查问卷"""
    11         print(self.question)
    12 
    13     def store_response(self,new_response):
    14         """存储单份调查问卷"""
    15         self.responses.append(new_response)
    16 
    17     def show_results(self):
    18         """显示收集到的所有答案"""
    19         print("Survey results:")
    20         for reponse in  self.responses:
    21             print(('-' + reponse))
    

      说明:

      第4~7行,存储了一个指定的调查问题,并创建了一个空列表response,用于存储答案。

      第9~11行,创建一个函数show_question(),用于显示调查问卷。

      第13~15行,创建一个函数store_response(),用于存储单份调查问卷,即使用append()方法往答案列表中添加新答案。

      第17~21行,创建一个函数show_response(),用于显示收集到的所有答案,其中使用for循环遍历答案列表response。

     

      代码2:

     1 from survey import AnonymousSurvey
     2 
     3 # 定义一个问题,并创建一个表示调查的AnonymousSurvey对象
     4 question = "What language did you first learn to speak?"
     5 my_survey = AnonymousSurvey(question)
     6 
     7 # 显示问题并存储答案
     8 my_survey.show_question()
     9 print("Enter 'q' at time to quit.n")
    10 while True:
    11     response = input("language:")
    12     if response == 'q':
    13         break
    14     my_survey.store_response(response)
    15 
    16 # 显示调查结果
    17 print("nThank you to everyone who participated in the survey!")
    18 my_survey.show_results()
    

      说明:

      第1行,从模块survey中导入一个类AnonymousSurvey。

      第4~5行,定义一个问题,并应用该问题创建一个表示调查的AnonymousSurvey对象。

      第8~14行,调用 show_question() 来显示问题,并提示用户输入答案。收到每个答案的同时将其存储起来。用户输入所有答案(输入 q 要求退出)

    后。

      第17~18行,显示调查结果,即调用 show_results() 来打印调查结果。

     

      运行结果:

     1 What language did you first learn to speak?
     2 Enter 'q' at time to quit.
     3 
     4 language:English
     5 language:Spanish
     6 language:English
     7 language:Chinese
     8 language:Mandarin
     9 language:q
    10 
    11 Thank you to everyone who participated in the survey!
    12 Survey results:
    13 -English
    14 -Spanish
    15 -English
    16 -Chinese
    17 -Mandarin
    

     

    最大平台,  (2)测试 AnonymousSurvey 类

    • 测试单个答案

      代码1:

     1 import unittest
     2 from survey import AnonymousSurvey
     3 
     4 class TestAnonmyousSurvey(unittest.TestCase):
     5     """针对AnonymousSurvey类的测试"""
     6 
     7     def test_store_single_response(self):
     8         """测试单个答案会被妥善地存储"""
     9         question = "What language did you first learn to speak?"
    10         my_survey = AnonymousSurvey(question)
    11         my_survey.store_response('English')
    12         self.assertIn('English', my_survey.responses)
    13 
    14     unittest.main
    

      说明:

      第1行,导入测试模块unittest。

      第2行,从模块survey中导入类AnonymousSurvey。

      第4行,继承模块unittest中的类TestCase创建一个测试类TestAnonmyousSurvey。

      第7~12行,创建一个方法test_store_single_response来测试单个答案会被妥善地存储。

      第14行,调用模块unittest中的main方法来执行测试。

     

      运行结果:

    1 Ran 1 test in 0.000s
    2 
    3 OK
    

     

      

    • 测试多个答案

      代码2:

     1 import unittest
     2 from survey import AnonymousSurvey
     3 
     4 class TestAnonmyousSurvey(unittest.TestCase):
     5     """针对AnonymousSurvey类的测试"""
     6 
     7     def test_store_single_response(self):
     8         """测试单个答案会被妥善地存储"""
     9         question = "What language did you first learn to speak?"
    10         my_survey = AnonymousSurvey(question)
    11         my_survey.store_response('English')
    12         self.assertIn('English', my_survey.responses)
    13 
    14     def test_store_three_responses(self):
    15         """测试三个答案会被妥善地存储"""
    16         question = "What language did you first learn to speak?"
    17         my_survey = AnonymousSurvey(question)
    18         responses = ['English', 'Spanish', 'Mandarin']
    19         for response in responses:
    20             my_survey.store_response(response)
    21 
    22         for response in responses:
    23             self.assertIn(response, my_survey.responses)
    24 
    25     unittest.main
    

     

      运行结果:

    1 Ran 2 tests in 0.000s2 
    3 OK
    

     

    2.3 方法 setUp()的使用

      在前面的test_survey.py中,我们在每个测试方法中都创建了一个 AnonymousSurvey 实例,并在每个方法中都创建了答案。 unittest.TestCase 类包含方法 setUp() ,让我们只需创建这些对象一次,并在每个测试方法中使用它们。如果你在 TestCase 类中包含了方法 setUp() ,Python将先运行它,再运行各个以test_打头的方法。这样,在我们编写的每个测试方法中都可使用在方法 setUp()中创建的对象了。

       例如,使用 setUp() 来创建一个调查对象和一组答案,供方法 test_store_single_response() 和test_store_three_responses() 使用。

      代码:

     1 import unittest
     2 from survey import AnonymousSurvey
     3 
     4 class TestAnonymousSurvey(unittest.TestCase):
     5     """针对AnonymousSurvey类的测试"""
     6     def setUp(self):
     7         """
     8         创建一个调查对象和一组答案,供使用的测试方法使用
     9         """
    10         question = "What language did you first learn to speak?"
    11         self.my_survey = AnonymousSurvey(question)
    12         self.responses = ['English', 'Spanish', 'Mandarin']
    13 
    14     def test_store_single_response(self):
    15         """测试单个答案会被妥善地存储"""
    16         self.my_survey.store_response(self.responses[0])
    17         self.assertIn(self.responses[0], self.my_survey.responses)
    18 
    19     def test_store_three_responses(self):
    20         """测试三个答案会被妥善地存储"""
    21         for response in self.responses:
    22             self.my_survey.store_response(response)
    23         for response in self.responses:
    24             self.assertIn(response, self.my_survey.responses)
    25 
    26     unittest.main
    

      说明:

      第11行,创建一个调查对象。

      第12行,创建一个答案列表。

     

      运行结果:

    1 Ran 1 test in 0.000s
    2 
    3 OK
    

      

      测试自己编写的类时,方法 setUp() 让测试方法编写起来更容易:可在 setUp() 方法中创建一系列实例并设置它们的属性,再在测试方法中直接使用这些实例。相比于在每个测试方法中都创建实例并设置其属性,这要容易得多。  

      运行测试用例时,每完成一个单元测试,Python都打印一个字符:测试通过时打印一个句点;测试引发错误时打印一个 E ;测试导致断言失败时打印一个 F 。这就是你运行测试用例时,在输出的第一行中看到的句点和字符数量各不相同的原因。如果测试用例包含很多单元测试,需要运行很长时间,就可通过观察这些结果来获悉有多少个测试通过了。

     

    本文由澳门新葡萄京最大平台发布于最大平台,转载请注明出处:测试代码

    关键词:

上一篇:没有了

下一篇:设计模式外观模式