第17章:Python TDD回顾与总结钱币类开辟

打印 上一主题 下一主题

主题 872|帖子 872|积分 2616

写在前面


这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我忽然思考,对于测试开辟工程师来说,什么才更有价值呢?怎样让 AI 工具更好地辅助本身写代码,大概优质的单元测试是一个切入点。 就我个人而言,这本书确实很有帮助。第一次读的时间,很多细节我都不太懂,但将书中内容应用到工作中后,我受益匪浅。好比面临一些让人抓狂的代码筹划时,书里的方法能让我渐渐深入理解代码的逻辑与筹划。 作为一名测试开辟工程师,我想把学习这本书的履历分享给大家,希望能给大家带来帮助。因为现在工作中大多使用 Python 代码,以是我把书中JAVA案例都用 Python 代码进行了改写 。
问题背景阐明

在完成钱币类的一系列开辟与优化后,对整个开辟过程进行回顾和总结具有紧张意义。通过回顾,可以总结履历教训,发现开辟过程中的长处和不足之处,为将来的项目开辟提供参考,同时也有助于加深对测试驱动开辟流程和方法的理解和掌握,进步开辟者的技术程度和开辟效率。
完成钱币类的一系列开辟与优化后,对整个过程进行回顾总结,有助于加深对Python TDD的理解,为后续开辟积聚履历。
17.1 思绪阐明

回顾从简单的乘法功能测试到复杂的多币种钱币运算实现的过程,分析测试驱动开辟的流程、遇到的问题及解决方法,总结代码优化和筹划的思绪。
17.2 测试代码(综合回顾测试)

  1. import unittest
  2. class Bank:
  3.     def __init__(self):
  4.         self.rates = {}
  5.     def addRate(self, from_currency, to_currency, rate):
  6.         self.rates[(from_currency, to_currency)] = rate
  7.     def rate(self, from_currency, to_currency):
  8.         if from_currency == to_currency:
  9.             return 1
  10.         return self.rates.get((from_currency, to_currency), 1)
  11.     def reduce(self, source, to):
  12.         if isinstance(source, Sum):
  13.             amount = source.augend.reduce(self, to).amount + source.addend.reduce(self, to).amount
  14.             return Money(amount, to)
  15.         elif isinstance(source, Money):
  16.             rate = self.rate(source.currency, to)
  17.             return Money(source.amount / rate, to)
  18. class Expression:
  19.     def reduce(self, bank, to):
  20.         pass
  21. class Money(Expression):
  22.     def __init__(self, amount, currency):
  23.         self.amount = amount
  24.         self.currency = currency
  25.     def plus(self, addend):
  26.         return Sum(self, addend)
  27.     def times(self, multiplier):
  28.         return Money(self.amount * multiplier, self.currency)
  29.     def reduce(self, bank, to):
  30.         rate = self.rate(bank, to)
  31.         return Money(self.amount / rate, to)
  32. class Sum(Expression):
  33.     def __init__(self, augend, addend):
  34.         self.augend = augend
  35.         self.addend = addend
  36.     def reduce(self, bank, to):
  37.         amount = self.augend.reduce(bank, to).amount + self.addend.reduce(bank, to).amount
  38.         return Money(amount, to)
  39. class Dollar(Money):
  40.     def __init__(self, amount):
  41.         super().__init__(amount, "USD")
  42. class Franc(Money):
  43.     def __init__(self, amount):
  44.         super().__init__(amount, "CHF")
  45. class TestAllCurrencyOperations(unittest.TestCase):
  46.     def test_mixed_addition(self):
  47.         bank = Bank()
  48.         bank.addRate("CHF", "USD", 2)
  49.         five_dollars = Dollar(5)
  50.         ten_francs = Franc(10)
  51.         result = five_dollars.plus(ten_francs).reduce(bank, "USD")
  52.         self.assertEqual(result.amount, 10)
  53.         self.assertEqual(result.currency, "USD")
  54.     def test_dollar_multiplication(self):
  55.         five_dollars = Dollar(5)
  56.         result = five_dollars.times(3)
  57.         self.assertEqual(result.amount, 15)
  58.         self.assertEqual(result.currency, "USD")
  59. if __name__ == '__main__':
  60.     unittest.main()
复制代码
17.3 源码阐明

这段综合测试代码涵盖了多币种加法运算和钱币乘法运算的测试用例。通过回顾整个开辟过程,我们从最初的简单功能渐渐实现了复杂的钱币运算系统。在这个过程中,不断地编写测试用例、实现功能代码、优化代码结构,遵照TDD的流程解决了各种问题,进步了代码的质量和可维护性。总结这些履历,能帮助我们在将来的Python开辟中更好地应用TDD方法。
TDD过程中的关键要点回顾

在讲授和实践TDD的过程中,有几个关键要点反复出现,这些要点对于理解和应用TDD至关紧张。

  • 让测试工作的方式
1.1 伪实现:在TDD流程中,当编写完测试用例后,为了快速验证测试框架是否正常工作,以及测试用例是否可以大概按照预期运行,我们会接纳伪实现的方式。这是一种临时性的代码实现,它并不寻求功能的完备性和正确性,只是简单地让测试可以大概通过。例如,在开辟钱币类的乘法功能时,最初的times方法大概只是返回一个固定值,像这样:
  1. class Dollar:
  2.     def __init__(self, amount):
  3.         self.amount = amount
  4.     def times(self, multiplier):
  5.         return 0  # 伪实现,仅为使测试通过
复制代码
通过这种方式,我们可以快速查抄测试环境和测试用例的根本逻辑是否正确。如果此时测试可以大概顺遂通过,阐明测试框架和测试用例的根本设置没有问题;如果测试失败,我们可以先排查测试相关的问题,而不是纠结于功能代码的实现细节。一旦确认测试环节无误,我们再渐渐美满功能代码,将伪实现替换为真正的功能实现。
1.2 三角丈量:三角丈量是一种通过多个雷同的测试用例来渐渐明确需求和实现通用解决方案的方法。当我们只有一个测试用例时,大概会编写一个仅实用于该特定情况的代码实现,这大概导致代码缺乏通用性。而三角丈量通过增加更多相似但又有渺小差异的测试用例,帮助我们发当代码中的共性和变化点,从而筹划出更通用的解决方案。例如,在测试Dollar对象的乘法方法times时,我们最初大概只有一个测试用例:
  1. def test_dollar_multiplication():
  2.     five = Dollar(5)
  3.     result = five.times(2)
  4.     assert result == 10
复制代码
此时,times方法的实现大概只是针对5 * 2这个特定情况编写的。为了确保times方法在各种输入下都能正确工作,我们可以增加更多测试用例:
  1. def test_dollar_multiplication():
  2.     five = Dollar(5)
  3.     result = five.times(2)
  4.     assert result == 10
  5.     result = five.times(3)    assert result == 15    ten = Dollar(10)    result = ten.times(4)    assert result == 40
复制代码
通过这些差异输入的测试用例,我们可以发现乘法运算的通用规律,进而实现一个可以大概实用于各种输入的times方法,制止返回常量值,使代码更具通用性和健壮性。
1.3 显式实现:显式实现是TDD过程的终极阶段,在这个阶段,我们根据之前编写的测试用例和通过三角丈量明确的需求,实现完备、正确且符合业务逻辑的功能代码。此时的代码不仅要满意所有测试用例的要求,还要考虑代码的性能、可读性、可维护性等方面。例如,在钱币类开辟中,经过伪实现和三角丈量阶段后,我们终极实现的times方法大概是这样的:
  1. class Dollar:
  2.     def __init__(self, amount):
  3.         self.amount = amount
  4.     def times(self, multiplier):
  5.         return self.amount * multiplier
复制代码
这个实现是基于前面的测试和分析,明确了乘法运算的具体需求后完成的,它可以大概正确处理各种输入情况,并且符合钱币金额乘法运算的实际逻辑。

  • 消除重复:去掉测试代码和步伐代码间的重复部分,是推进筹划和开辟的紧张手段。在TDD开辟过程中,随着功能的增加和代码量的增长,很轻易出现重复代码。这些重复代码大概存在于测试用例中,也大概在功能代码中,大概在两者之间。重复代码不仅增加了代码量,还会使维护变得困难,因为一处修改大概需要在多个地方同步进行。通过重构,我们可以提取重复的代码片断,将其封装成独立的函数、方法或类,使代码更加简便、易维护。例如,在测试差异钱币类的乘法和加法运算时,如果多个测试用例中都有创建钱币对象和进行根本断言的重复代码,我们可以将这些重复部分提取出来,封装成一个辅助函数或测试基类中的方法,减少代码冗余。
  • 测试的控制力:当开辟过程中遇到不确定因素时,要增强测试的控制力,如同在路面湿滑时增大摩擦力;而当情况明朗时,则可以加速前进,进步开辟效率。在TDD中,测试的控制力表现在对测试用例的编写和执行上。当开辟过程中遇到新的功能需求、复杂的业务逻辑或不确定的技术方案时,我们需要编写更多详细的测试用例,覆盖各种大概的情况,确保代码在各种条件下都能正确运行。这就好比在路面湿滑时,我们需要鉴戒翼翼地控制车辆,增加摩擦力以确保安全行驶。例如,在实现多币种钱币运算时,由于涉及汇率转换、差异钱币对象的组合等复杂情况,我们需要编写大量测试用例来验证各种情况下的运算结果是否正确。而当我们对某个功能已经非常熟悉,代码实现也相对稳定时,我们可以恰当减少测试用例的数量,大概接纳更高效的测试计谋,进步开辟效率,就像在路况良好时可以恰当加速行驶一样。但需要注意的是,即使在情况明朗时,也不能完全忽视测试,仍然要包管代码的质量和正确性。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表