11. 文档和测试

在软件开发的过程中,除了代码的编写外,还有两个重要的环节,分别是代码对应的文档和代码的测试。对于编写好的函数或者方法,详细的文档将会帮助使用者更好的使用,代码的测试则是为了更好的交付,保证代码的正常运行。在 Python 中对应的提供了强大的文档生成和查看模块 pydoc 以及单元测试框架 unittest

11.1. 文档的生成和查看

为函数、类以及类中方法等编写文档,只需要在函数、类以及类中方法的定义后再定一个字符串即可,这个字符串就是对应函数、类以及类中方法的文档。新建一个名为 document.py 的 Python 文件,详细代码如下所示:

def my_max(x, y):
	'''
	返回变量 x 和变量 y 中较大的值
	'''
	z = x if x > y else y
	# 返回变量 z 的值
	return z

class Person:
	'''
	定义一个 Person 类
	类中包括 name 、 age 两个变量
	'''
	def __init__(self, name, age):
		'''
		name 初始化该用户的 name
		age 初始化该用户的 age
		'''
		self.name = name
		self.age = age
	def info(self):
		'''
		定义信息输出的方法
		'''
		print("Hello, ", self.name, " , ", self.age)

11.1.1. help() 函数和 __doc__ 属性

Python 中内置的 help() 函数可以用于查看指定函数的说明文档,也可以通过函数的 __doc__ 属性查看函数的说明文档,以 document 模块中的 my_max() 函数为例,首先是 help() 函数,具体的使用方法如下代码所示:

from document import my_max
# 使用 help() 函数查看 my_max() 函数的帮助文档
help(my_max)

运行代码,得到如下的运行结果:

输入图片说明

__doc__ 属性的使用方法如下代码所示:

from document import my_max
# 使用 __doc__ 属性查看 my_max() 函数的帮助文档
print(my_max.__doc__)

运行代码,得到如下的运行结果:

输入图片说明

类与函数的帮助信息的查看方法一样,只是将上述的函数名替换成类名即可。

11.1.2. 使用 pydoc 生成文档

通过 Python 内置的 pydoc 模块,也可以生成、查看帮助文档,使用 pydoc 模块在控制台中查看帮助文档的命令如下:

python3 -m pydoc module_name

其中, -m 是 Python 命令的一个选项,表示运行指定模块,此处表示运行 pydoc 模块。针对上述的 document 模块,执行以下的命令:

python3 -m pydoc document

运行上述命令后,得到如下的结果:

输入图片说明

这种在控制台中查看指定模块的帮助信息依然不太方便,通过 pydoc 模块可以生成 HTML 格式的文档,命令如下:

python3 -m pydoc -w module_name

与之前的命令对比,只是额外指定了-w 选项,该选项代表 write,表明输出 HTML 文挡,针对上述的 document 模块,运行命令后得到一个 document.html 文件,打开文件可以看到完整的帮助文档:

输入图片说明

11.2. 代码测试

通常在编写完代码后,除了要有完善的文档,另一个方面就是在交付代码前进行详细的测试,最简单的测试方法可以使用 print() 方法测试需要测试的运行结果的值。

上述的方法只能是在开发的过程中检查基本的编码逻辑,验证程序的运行结果是否符合预期,是一种非正规的软件测试方法。单元测试是软件测试领域使用较多的一种测试方法,作为一个软件的开发人员需要了解并掌握基本的单元测试方法。在 Python 中提供了 PyUnit 单元测试框架,通过使用 PyUnit ,开发人员可以非常方便地为函数、类提供配套的、可复用的单元测试。

11.2.1. 使用 PyUnit —— unittest

PyUnit 是一个简单、易用的测试框架,其使用断言方法判断期望值和实际值的差异,返回 bool 值。以下述一个简单的 my_add() 函数和 my_sub() 函数为例,新建一个 my_fun.py 文件,具体的代码如下所示:

def my_add(a, b):
	'''
	实现简单的加法运算
	'''
	return a + b

def my_sub(a, b):
	'''
	实现简单的减法运算
	'''
	return a - b

接下来为该模块编写单元测试代码,要想使用 unittest ,在单元测试类中必须继承 unittest.TestCase ,该类中的测试方法需要满足以下几个条件,第一,测试方法没有返回值,第二,测试方法不能有任何参数,第三,测试方法应以 test 开头。因此新建一个test_my_fun.py 文件,具体的代码如下所示:

import unittest
from my_fun import my_add, my_sub

class TestModule(unittest.TestCase):
	# 测试 add() 函数
	def test_my_add(self):
		# 断言 add() 函数的值
		self.assertEqual(my_add(5, 9), 14)
		self.assertTrue(my_add(4, 10) == 14)
		self.assertFalse(my_add(4, 10) == 13)

	# 测试 sub() 函数
	def test_my_sub(self):
		# 断言 sub() 函数的值
		self.assertEqual(my_sub(9, 5), 4)
		self.assertTrue(my_sub(10, 4) == 6)
		self.assertFalse(my_sub(10, 4) == 5)

编写完上述的测试代码后,要想运行测试,需要在 增加如下的代码:

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

运行上述的 Python 文件,如果没有错误,将得到如下结果:

输入图片说明

除了上述的断言,在 unittest.TestCase 中还内置了其他的一些方法来执行断言,常用的方法如下所示:

输入图片说明

11.2.2. 跳过测试用例

在默认情况下, unittest 会自动测试每一个测试用例,但如果希望临时跳过某个测试用例,则可以通过如下两种方式来实现。

  • 使用 skipXxx 装饰器来跳过测试用例。 unittest 一共提供了 3 个装饰器,分别是 @unittest.skip(reason)@unittest.skipIf(condition, reason)@unittest.skipUnless(condition, reason)
  • 使用 TestCaseskipTest() 方法来跳过测试用例

具体使用方法如下代码所示:

# 跳过测试 sub() 函数
@unittest.skip("skip my_sub")
def test_my_sub(self):
	# 断言 sub() 函数的值
	self.assertEqual(my_sub(9, 5), 4)
	self.assertTrue(my_sub(10, 4) == 6)
	self.assertFalse(my_sub(10, 4) == 5)

11.3. 本章小结

本章主要介绍了与 Python 开发相关的两个相关知识,即文档和测试。对于编写好的函数或者方法,详细的文档将会帮助使用者更好的使用,代码的测试则是为了更好的交付,保证代码的正常运行。Python 提供了 pydoc 工具来查看、生成文档,只要开发者为 Python 程序提供了符合格式的文档说明,使用 pydoc 就可直接查看程序中的文档,也可为之生成 HTML 文档。 Python 还提供了单元测试框架 unittest ,方便使用断言的方式对代码进行测试。

本章需要掌握知识点:

  1. 掌握 pydoc 生成文档,查看文档
  2. 掌握单元测试框架 unittest 的使用方法