单元测试检查特定代码单元或模块是否按照开发人员的预期执行。 大多数时候,我们测试的代码单元是一个函数。
同样,我们可以测试所有功能。 作为最佳实践,至少在开发过程中,我们应该进行单元测试。
因此,在开发过程的早期阶段,它会检测到错误,我们可以在不花费太多时间的情况下修复它们。 如果我们跳过这些测试,那么在继续项目时将很难修复错误。
Python 单元测试设置
Python 提供了一个不同的单元测试框架,称为unittest。 unittest 框架提供了一些特性。
我们使用此方法执行的测试是相互独立的。 换句话说,测试的成功或失败不取决于其他测试结果。
它还提供 setup()
和 teardown()
函数以及测试自动化。 setup()
函数允许我们设置在每个测试方法之前执行的指令。
teardown()
函数将描述在每个测试方法之后运行的指令。
unittest 为我们提供了一些用于单元测试的基本概念,例如测试夹具、测试用例、测试套件和测试运行器。 本文讨论使用 unittest 框架构建用于单元测试的 setup() 函数。
创建要测试的函数
首先,我们需要构建一些函数来测试。 让我们创建四个函数来对两个数字进行加、减、乘、除和求余数。
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
return a / b
def remainder(a, b):
return a % b
我们可以使用 print()
函数来测试上述函数,但对于成百上千的代码来说,它不太实用。 那么,让我们创建一个模块来测试功能。
创建测试模块
我们应该根据命名约定来命名我们的测试模块。 我们使用 test_ 作为名称的第一部分,然后是模块的名称。
让我们为本教程创建测试模块 test_calc.py。
命名约定:
test_<name>
然后我们必须将 unittest 框架和 numCal 模块导入到我们的测试模块中。 unittest 包含在标准库中,所以我们可以直接导入它。 numCal 是我们需要测试的模块。
import unittest
import numCal
下一步,我们可以创建一个继承自 unittest.TestCase 的类,这样我们就可以访问该类中的更多测试功能。
class TestNumCal(unittest.TestCase):
在类内部,我们为每个函数创建方法。 我们在命名方法的时候需要按照命名约定来命名。
当我们运行测试模块时,它会知道哪个方法代表测试,因为名称的第一部分是测试。 否则,它不会识别测试方法并跳过它们。
首先,我们为 add()
函数创建一个测试方法。
def test_add(self):
self.assertEqual(numCal.add(10, 5), 15)
与每个方法一样,self 是 test_add() 方法的第一个参数。 我们在第二行中使用了 assertEqual()
方法。
由于我们的 TestNumCal 类继承自 unittest.TestCase,因此我们可以访问所有可用的断言方法。 诸如 assertEqual()
、assertNotEqual()
、assertTrue()
、assertFalse()
和 assertIn()
等方法可用于单元测试,还有更多。
assertEqual()
方法检查函数返回的值与我们期望的值之间的相等性。
然后我们需要将测试模块设置为直接从编辑器运行。 否则,当我们尝试执行测试模块时,它将不会运行。
因此,为此,我们可以使用下面的代码。
if __name__ == '__main__':
unittest.main()
现在我们的代码应该如下所示。
import unittest
import numCal
class TestNumCal(unittest.TestCase):
def test_add(self):
self.assertEqual(numCal.add(10, 5), 15)
if __name__ == '__main__':
unittest.main()
现在我们可以通过运行 test_calc.py 模块来测试 add() 函数。
输出:
在这里,点表示测试通过。 如果测试失败,就会出现F,如果有错误,就会出现错误信息。
下面,圆点显示测试了多少个单元。
现在让我们再创建四个测试方法来测试其余的功能。
import unittest
import numCal
class TestNumCal(unittest.TestCase):
def test_add(self):
self.assertEqual(numCal.add(10, 5), 15)
def test_subtract(self):
self.assertEqual(numCal.subtract(10, 5), 5)
def test_multiply(self):
self.assertEqual(numCal.multiply(10, 5), 50)
def test_divide(self):
self.assertEqual(numCal.divide(10, 5), 2)
def test_remainder(self):
self.assertEqual(numCal.remainder(10, 5), 0)
if __name__ == '__main__':
unittest.main()
根据每个功能,我们应该更改测试方法名称。
输出:
这里困难的部分是需要在每个测试方法中设置每个函数的值。 当我们有数百种测试方法时,这将是一个问题。
如果需要更改值,我们必须审查每个测试方法并更改它们。
我们可以构建 setup()
函数来克服这个问题。 通过这种方法,我们只需要声明一次值。 然后在每个方法之前执行。
创建 setUp() 函数
def setUp(self):
print("\nsetUp")
self.num1 = 10
self.num2 = 5
设置 setup()
函数后,还需要更改函数的参数。 首先,让我们更改 test_add 方法。
def test_add(self):
print("Add")
self.assertEqual(numCal.add(self.num1, self.num2), 15)
如上所述,我们可以对剩余的方法进行更改,我们的完整代码应该如下所示。
完整代码:
import unittest
import numCal
class TestNumCal(unittest.TestCase):
def setUp(self):
print("\nsetUp")
self.num1 = 10
self.num2 = 5
def test_add(self):
print("Add")
self.assertEqual(numCal.add(self.num1, self.num2), 15)
def test_subtract(self):
print("Subtract")
self.assertEqual(numCal.subtract(self.num1, self.num2), 5)
def test_multiply(self):
print("Multiply")
self.assertEqual(numCal.multiply(self.num1, self.num2), 50)
def test_divide(self):
print("Divide")
self.assertEqual(numCal.divide(self.num1, self.num2), 2)
def test_remainder(self):
print("remainder")
self.assertEqual(numCal.remainder(self.num1, self.num2), 0)
if __name__ == '__main__':
unittest.main()
输出:
在输出中,五个点表示测试已通过以及运行的测试数。 在它下面,值是在每次测试之前设置的; 为了识别这一点,我们放置了 print()
函数。
因此,在测试方法开始之前,setup()
函数会执行定义的指令,并使用它们进行测试。
总结
在本文中,我们了解了什么是单元测试和单元测试框架以及如何构建测试模块。 最重要的是,我们学习了如何使用 setup()
函数来设置一些定义的指令在每个测试方法之前执行。
当需要运行许多测试并且需要更改参数的值时,setup()
函数会派上用场。