登陆

章鱼世界官网-Python中的单元测试!

admin 2019-05-18 224人围观 ,发现0个评论

Python学习沟通群:1004391443,这里是python学习者聚集地,有大牛答疑,有资源共享!小编也预备了一份python学习材料,有想学习python编程的,或是转行,或是大学生,还有作业中想提高自己才能的,正在学习的小伙伴欢迎参加学习。

  • 来历 | 愿码(ChainDesk.CN) 内容修改
  • 愿码Slogan | 衔接每个程序员的故事
  • 网站 | http://chaindesk.cn
  • 愿码愿景 | 打造全学科IT体系免费课程,助力小白用户、初级工程师0本钱免费体系学习、低本钱进阶,协助BAT一线资深工程师生长并运用本身优势发明睡后收入。
  • 官方大众号 | 愿码 | 愿码服务号 | 区块链部落
  • 免费参加愿码全思想工程师社群 | 任一大众号回复“愿码”两个字获取入群二维码

本文阅览时长:11min

根本单元测验

在咱们开端评论新的概念和功用之前,让咱们来看看怎么运用unittest来表达咱们现已学到的主意。这样,咱们就能有一些坚实的根底来树立咱们的刘嘉玲被新了解。

采纳举动的时刻-用unittest测验PID

咱们将拜访PID类(或至少拜访PID类的测验)。咱们将编写测验,以便它们在unittest结构内运转。

咱们将运用unittest结构完成测验。

  1. 创立一个名为新文件 test_pid.py 在同一目录 pid.py 。请注意,这是一个 .py 文件:unittest测验是纯 python源代码,而不是包括源代码的纯文本。这意味着从纪录片的视点来看,测验的用途不大,但能够交流其他优点。
  2. 将以下代码刺进到新创立的 test_pid.py中
from unittest import TestCase, main
from mocker import Mocker
import pid
class test_pid_constructor(TestCase):
def test_without_when(self):
mocker = Mocker()
mock_time = mocker.replace('time.time')
mock_time()
mocker.result(1.0)
mocker.replay()
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=0, initial=12)
mocker.restore()
mocker.verify()
self.assertEqual(controller.gains, (0.5, 0.5, 0.5))
self.assertAlmostEqual(controller.setpoint[0], 0.0)
self.assertEqual(len(controller.setpoint), 1)
self.assertAlmostEqual(controller.previous_time, 1.0)
self.assertAlmostEqual(controller.previous_error, -12.0)
self.assertAlmostEqual(controller.integrated_error, 0)
def test_with_when(self):
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=1, initial=12,
when=43)
self.assertEqual(controller.gains, (0.5, 0.5, 0.5))
self.assertAlmostEqual(controller.setpoint[0], 1.0)
self.assertEqual(len(controller.setpoint), 1)
self.assertAlmostEqual(controller.previous_time, 43.0)
self.assertAlmostEqual(controller.previous_error, -11.0)
self.assertAlmostEqual(controller.integrated_error, 0)
class test_calculate_response(TestCase):
def test_without_when(self):
mocker = Mocker()
mock_time = mocker.replace('time.time')
mock_time()
mocker.result(1.0)
mock_time()
mocker.result(2.0)
mock_time()
mocker.result(3.0)
mock_time()
mocker.result(4.0)
mock_time()
mocker.result(5.0)
mocker.replay()
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=0, initial=12)
self.assertEqual(controller.calculate_response(6), -3)
self.assertEqual(controller.calculate_response(3), -4.5)
self.assertEqual(controller.calculate_response(-1.5), -0.75)
self.assertEqual(controller.calculate_response(‑2.25),
‑1.125)
mocker.restore()
mocker.verify()
def test_with_when(self):
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=0, initial=12,
when=1)
self.assertEqual(controller.calculate_response(6, 2), -3)
self.assertEqual(controller.calculate_response(3, 3), -4.5)
self.assertEqual(controller.calculate_response(‑1.5, 4),
‑0.75)
self.assertEqual(controller.calculate_response(‑2.25, 5),
‑1.125)
if __name__ == '__main__':
main()
  1. 键入以下指令运转测验: $ python test_pid.py

让咱们阅读代码部分,看看每个部分的效果。

from unittest import TestCase, main
from mocker import Mocker
import pid
class test_pid_constructor(TestCase):
def test_without_when(self):
mocker = Mocker()
mock_time = mocker.replace('time.time')
mock_time()
mocker.result(1.0)
mocker.replay()
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=0, initial=12)
mocker.restore()
mocker.verify()
self.assertEqual(controller.gains, (0.5, 0.5, 0.5))
self.assertAlmostEqual(controller.setpoint[0], 0.0)
self.assertEqual(len(controller.setpoint), 1)
self.assertAlmostEqual(controller.previous_time, 1.0)
self.assertAlmostEqual(controller.previous_error, -12.0)
self.assertAlmostEqual(controller.integrated_error, 0)

在一些设置代码之后,咱们进行了测验,当没有给出 when 参数时,PID控制器正常作业。Mocker用于将 time.time 替换为一直回来可猜测值的模仿,然后咱们运用多个断语来承认控制器的特点已初始化为预期值。

def test_with_when(self):
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=1, initial=12,
when=43)
self.assertEqual(controller.gains, (0.5, 0.5, 0.5))
self.assertAlmostEqual(controller.setpoint[0], 1.0)
self.assertEqual(len(controller.setpoint), 1)
self.assertAlmostEqual(controller.previous_time, 43.0)
self.assertAlmostEqual(controller.previous_error, -11.0)
self.assertAlmostEqual(controller.integrated_error, 0)

此测验承认在供给 when 参数时PID结构函数正常作业。与之前的测验不同,不需求运用Mocker,因为测验的成果不应该依赖于除参数值之外的任何东西 - 当时时刻是无关紧要的。

class test_calculate_response(TestCase):
def test_without_when(self):
mocker = Mocker()
mock_time = mocker.replace('time.time')
mock_time()
mocker.result(1.0)
mock_time()
mocker.result(2.0)
mock_time()
mocker.result(3.0)
mock_time()
mocker.result(4.0)
mock_time()
mocker.result(5.0)
mocker.replay()
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=0, initial=12)
self.assertEqual(controller.calculate_response(6), -3)
s章鱼世界官网-Python中的单元测试!elf.assertEqual(controller.calculate_response(3), -4.5)
self.assertEqual(controller.calculate_response(-1.5), -0.75)
sel+f.assertEqual(controller.calculate_response(‑2.25),
‑1.125)
mocker.restore()
mocker.verify()

此类中的测验描绘了 calculate_response 办法的预期行为。第一个测验查看未供给可选的 when 参数时的行为,并模仿 time.time 以使该行为可猜测。

def test_with_when(self):
controller = pid.PID(P=0.5, I=0.5, D=0.5,
setpoint=0, initial=12,
when=1)
self.assertEqual(controller.calculate_response(6, 2), -3)
self.assertEqual(controller.calculate_response(3, 3), -4.5)
self.assertEqual(controller.calculate_response(‑1.5, 4),
‑0.75)
self.assertEqual(controller.calculate_response(‑2.25, 5),
‑1.125)

在此测验中,供给了 when 参数,因而无需模仿 time.time 。咱们只需查看成果是否契合预期。

咱们履行的实践测验与doctest中编写的测验相同。到现在为止,咱们所看到的只是一种表达它们的不同办法。

首要要注意的是,测验文件被划分为承继自 unittest.TestCase的 类,每个类都包括一个或多个测验办法。每个测验办法的称号以单词test最初,单元测验是怎么辨认它们是测验的。

每种测验办法都包括对单个单元的单个测验。这为咱们供给了一种便利的办法来构建咱们的测验,将相关测验组合到同一个类中,以便更简略找到它们。

将每个测验放入自己的办法意味着每个测验都在一个独立的命名空间中履行,这使得相对于doctest风格的测验,使得单元测验式测验更简略彼此搅扰。它还意味着unittest知道测验文件中有多少单元测验,而不是简略地知道有多少表达式(您或许现已注意到doctest将每个 >>> 行作为独自的测验计数)。终究,将每个测验放在自己的办法中意味着每个测验都有一个称号,这或许是一个有价值的功用。

unittest中的测验并不直接重视任何不属于调用 TestCase 的assert办法的任何内容。这意味着当咱们运用Mocker时,咱们不用忧虑从演示表达式回来的模仿目标,除非咱们想要运用它们。这也意味着咱们需求记住写一个断语来描绘咱们想要查看的测验的每个方面。咱们将很快介绍 TestCase 的各种断语办法。

假如您无法履行测验,则测验没有多大用途。现在,咱们将选用的办法是经过Python解说器将测验文件作为程序履行时 调用 unittest.main 。这是运转unittest代码的最简略办法,可是当你在许多文件中散布了很多测验时,这很费事。

假如__name__ =='__ main__':当 Python 加载任何模块时,它将该模块的称号存储在模块中名为__name__的变量中(除非该模块是在指令行上传递给解说器的模块)。该模块一直将字符串'__main__'绑定到其__name__变量。因而,假如__name__ =='__ main__':标明 - 假如此模块直接从指令行履行。

Assertions

Assertions是咱们用来通知unittest测验的重要成果是什么的机制。经过运用恰当的断语,咱们能够精确地通知unittest每次测验的期望。

assertTrue

当咱们调用 self.assertTrue(expression)时 ,咱们通知unittest表达式有必要为true才能使测验成功。

这是一个十分灵敏的断语,因为您能够经过编写恰当的布尔表达式来查看简直任何内容。这也是你应该考虑运用的终究一个断语之一,因为它没有通知unittest你正在进行的比较的类型,这意味着unittest无法清楚地通知你假如测验失利会出现什么问题。

有关此示例,请考虑以下测验代码,其间包括两个确保失利的测验:

from unittest import TestCase, main
class two_failing_tests(TestCase):
def test_assertTrue(self):
self.assertTrue(1 == 1 + 1)
def test_assertEqual(self):
self.assertEqual(1, 1 + 1)
if __name__ == '__main__':
main()

看起来两个测验似乎是能够交换的,因为两个测验都是相同的。当然他们都会失利(或许在不太或许的情况下,他们都会失利),所以为什么挑选一个而不是另一个呢?

看看咱们运转测验时会发作什么(而且还注意到测验没有依照它们编写的次序履行;测验彻底彼此独立,所以不要紧,对吧?):

你看得到不同吗?该 assertTrue 测验能够正确地确认测验失利,但它不知道够陈述关于失利原因的任何有用的信息。该 assertEqual便 测验,而另一方面,他知道首要,它是查看两个表达式是持平的,其次它知道怎么出现的成果,因而,他们将是最有用的:经过评价各个它是表达的比较并在成果之间放置一个 != 符号。它通知咱们什么期望失利,以及相关表达式评价的内容。

assertFalse

assert章鱼世界官网-Python中的单元测试!False 办法会成功时 assertTrue 办法会失利,反之亦然。它在发生 assertTrue所 具有的有用输出方面具有相同的约束,而且在能够测验简直任何条件方面具有相同的灵敏性。

assertEqual

正如 assertTrue 评论中所说到的, assertEqual 断语查看它的两个参数实践上是持平的,而且假如它们不是,则陈述失利,以及参数的实践值。

assertNotEqual

assertNotEqual 每逢断语失利 assertEqual便 断语会成功,反之亦然。陈述失利时,其输出标明两个表达式的值持平,并为您供给这些值。

assertAlmostEqual

正如咱们之前看到的,比较浮点数或许很费事。特别是,查看两个浮点数是否持平是有问题的,因为你或许期望持平的作业 - 在数学上是持平的 - 或许依然终究在最低有用位之间不同。浮点数仅在每个位相一起才持平。

为了处理这个问题,unittest供给了 assertAlmostEqual ,它查看两个浮点值是否简直相同; 它们之间的少数差异是能够忍受的。

让咱们看一下这个问题。假如取平方根7,然后将其平方,则成果应为7.这是一对查看该实际的测验:

from unittest import TestCase, main
class floating_point_problems(TestCase):
def test_assertEqual(self):
self.assertEqual((7.0 ** 0.5) ** 2.0, 7.0)
def test_assertAlmostEqual(self):
self.assertAlmostEqual((7.0 ** 0.5) ** 2.0, 7.0)
if __name__ == '__main__':
main()

test_assertEqual 办法查看

这在实际中是如此。但是,在核算机可用的更专业的数字体系中,取7的平方根然后平方它并不能让咱们回到7,所以这个测验将失利。稍等一下。

测验 章鱼世界官网-Python中的单元测试!test_assertAlmostEqual 办法查看

即便核算时机赞同这是真的,所以这个测验应该经过。

运转这些测验会发生以下成果,尽管您回来的详细数字或许会有所不同,详细取决于运转测验的核算机的详细信息:

不幸的是,浮点数不精确,因为实数行上的大多数数字不能用有限的,非重复的数字序列标明,更不用说只是64位。因而,你从评价数学表达式得到的报答并不是很好。尽管 - 或许简直任何其他类型的作业都满足挨近政府作业 - 所以咱们不期望咱们的测验对这个细小的差异进行狡赖。因而,当咱们比较浮点数是否持平时,咱们应该运用 assertAlmostEqualassertNotAlmostEqual

这个问题一般不章鱼世界官网-Python中的单元测试!会延续到其他比较运算符中。例如,查看一个浮点数小于另一个,因为无意义的过错,不太或许发生过错的成果。只要在相等的情况下,这个问题才会困扰咱们。

  • 章鱼世界官网-北京新发地:猪肉批发价回落 下一年有望根本康复到正常水平
  • A股三大股指全线上涨 沪指重回2900点
  • 请关注微信公众号
    微信二维码
    不容错过
    Powered By Z-BlogPHP