关闭

Python单元测试之道:从入门到精通的全面指南(下)

发表于:2023-7-21 09:43

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:techlead_krischang    来源:稀土掘金

  五、实战演练:Python单元测试的完整项目示例
  在这一部分,我们将通过一个简单的项目来展示如何在实践中应用Python单元测试。我们将创建一个简单的“分数计算器”应用,它可以执行分数的加、减、乘、除运算。
  5.1 创建项目
  首先,我们创建一个新的Python项目,并在项目中创建一个fraction_calculator.py文件。在这个文件中,我们定义一个Fraction类,用来表示分数。这个类有两个属性:分子(numerator)和分母(denominator)。
  # fraction_calculator.py
  class Fraction:
      def __init__(self, numerator, denominator):
          if denominator == 0:
              raise ValueError("Denominator cannot be zero!")
          self.numerator = numerator
          self.denominator = denominator
  5.2 编写单元测试
  然后,我们创建一个test_fraction_calculator.py文件,在这个文件中,我们编写单元测试来测试Fraction类。
  # test_fraction_calculator.py
  import unittest
  from fraction_calculator import Fraction
  class TestFraction(unittest.TestCase):
      def test_create_fraction(self):
          f = Fraction(1, 2)
          self.assertEqual(f.numerator, 1)
          self.assertEqual(f.denominator, 2)
      def test_create_fraction_with_zero_denominator(self):
          with self.assertRaises(ValueError):
              Fraction(1, 0)
  if __name__ == '__main__':
      unittest.main()
  在这个测试类中,我们创建了两个测试方法:test_create_fraction测试正常创建分数,test_create_fraction_with_zero_denominator测试当分母为零时应抛出异常。
  5.3 执行单元测试
  最后,我们在命令行中运行test_fraction_calculator.py文件,执行单元测试。
  python -m unittest test_fraction_calculator.py
  如果所有的测试都通过,那么我们就可以有信心地说,我们的Fraction类是正确的。
  5.4 扩展项目
  当然,我们的项目还远远没有完成。Fraction类还需要添加许多功能,如加、减、乘、除运算,约简分数,转换为浮点数等。对于每一个新的功能,我们都需要编写相应的单元测试来确保其正确性。并且,我们也需要不断地运行这些单元测试,以确保我们的修改没有破坏已有的功能。
  单元测试是一个持续的过程,而不是一次性的任务。只有不断地编写和运行单元测试,我们才能保证我们的代码的质量和可靠性。
  六、Python单元测试的最佳实践
  在实际编写和执行Python单元测试的过程中,有一些最佳实践可以帮助我们提高工作效率,并保证测试的质量和可靠性。
  6.1 始终先编写测试
  按照测试驱动开发(TDD)的原则,我们应该先编写测试,然后再编写能通过测试的代码。这样可以帮助我们更清晰地理解我们要实现的功能,同时也能保证我们的代码是可测试的。
  6.2 保持测试的独立性
  每个测试都应该是独立的,不依赖于其他测试。如果测试之间有依赖关系,那么一个测试失败可能会导致其他测试也失败,这会使得测试结果难以理解,也会使得测试更难维护。
  6.3 测试所有可能的情况
  我们应该尽可能地测试所有可能的情况,包括正常情况、边界情况和异常情况。例如,如果我们有一个函数,它接受一个在0到100之间的整数作为参数,那么我们应该测试这个函数在参数为0、50、100和其他值时的行为。
  6.4 使用模拟对象
  在测试涉及到外部系统(如数据库、网络服务等)的代码时,我们可以使用模拟对象(Mocking)来代替真实的外部系统。这样可以使得测试更快、更稳定,并且更易于控制。
  6.5 定期运行测试
  我们应该定期运行我们的测试,以确保我们的代码没有被破坏。一种常见的做法是在每次提交代码之前运行测试。此外,我们还可以使用持续集成(Continuous Integration)工具,如Jenkins、Travis CI等,来自动运行我们的测试。
  6.6 使用代码覆盖率工具
  代码覆盖率是一个度量标准,用来表示我们的测试覆盖了多少代码。我们可以使用代码覆盖率工具,如coverage.py,来度量我们的代码覆盖率,并努力提高这个指标。但是,请记住,代码覆盖率并不能保证我们的测试的质量和完整性。它只是一个工具,我们不能过分依赖它。
  # 运行代码覆盖率工具的示例
  # 在命令行中输入以下命令:
  $ coverage run --source=. -m unittest discover
  $ coverage report
  以上的命令将首先运行你的所有单元测试,并收集代码覆盖率信息。然后,它将显示一个代码覆盖率报告,这个报告将告诉你哪些代码被测试覆盖了,哪些代码没有被覆盖。
  七、工具和资源
  在进行Python单元测试时,有一些工具和资源可以帮助我们提高效率和质量。
  7.1 Python内置的unittest模块
  Python内置的unittest模块是一个强大的单元测试框架,提供了丰富的断言方法、测试套件、测试运行器等功能。如果你想要进行单元测试,unittest模块是一个很好的开始。
  # unittest模块的基本使用
  import unittest
  class TestMyFunction(unittest.TestCase):
      def test_add(self):
          self.assertEqual(add(1, 2), 3)
  if __name__ == '__main__':
      unittest.main()
  7.2 pytest
  pytest是一个流行的Python测试框架,比unittest更简洁,更强大。它不仅可以用于单元测试,还可以用于功能测试、集成测试等。
  # pytest的基本使用
  def test_add():
      assert add(1, 2) == 3
  7.3 mock
  mock模块可以帮助你创建模拟对象,以便在测试中替代真实的对象。这对于测试依赖于外部系统或难以构造的对象的代码非常有用。
  # mock模块的基本使用
  from unittest.mock import Mock
  # 创建一个模拟对象
  mock = Mock()
  # 设置模拟对象的返回值
  mock.return_value = 42
  # 使用模拟对象
  assert mock() == 42
  7.4 coverage.py
  coverage.py是一个代码覆盖率工具,可以帮助你找出哪些代码没有被测试覆盖。
  # coverage.py的基本使用
  coverage run --source=. -m unittest discover
  coverage report
  7.5 Python Testing
  Python Testing是一个关于Python测试的网站,提供了许多有关Python测试的教程、工具、书籍和其他资源。网址是:pythontesting.net
  八、总结
  希望通过本文,你对Python单元测试有了更深入的理解和应用。单元测试是软件开发过程中非常重要的一环,正确地进行单元测试可以帮助我们提高代码质量,发现和修复问题,以及提高开发效率。Python提供了一系列强大的工具来进行单元测试,这些工具能够帮助我们编写更好的单元测试。
  在编写单元测试的过程中,我们不仅可以发现和修复问题,还可以深入理解我们的代码和业务逻辑,提高我们的编程技能。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号