透视:
因此,让我们退后一步,问一下TDD正在努力为我们提供哪些帮助。TDD正在尝试帮助我们确定我们的代码是否正确。正确地说,我的意思是“代码是否符合业务要求?” 卖点是我们知道将来会需要更改,并且我们希望确保在进行更改后代码保持正确。
之所以提出这种观点,是因为我认为很容易迷失在细节上,而忽视了我们要实现的目标。
原则-SAP:
虽然我不是TDD方面的专家,但我认为您缺少“单断言原则”(SAP)尝试教授的内容。SAP可以重申为“一次测试一件事”。但是,TOTAT不会像SAP那样轻松地吐槽。
一次测试一件事意味着您专注于一个案例。一条路 一个边界条件;一个错误的情况;一个无论每个测试。其背后的驱动思想是,您需要知道测试用例失败时发生了什么,以便可以更快地解决问题。如果您在一个测试中测试多个条件(即,不止一件事情),但测试失败,那么您的工作量将更大。您首先必须确定多个案例中的哪个失败,然后找出该案例失败的原因。
如果一次测试一件事,则搜索范围会小很多,并且可以更快地发现缺陷。请记住,“一次测试一件事”并不一定会使您一次查看多个过程输出。例如,当测试“已知的良好路径”时,我可能希望看到一个特定的结果值foo
以及中的另一个值,bar
并且我可以foo != bar
在测试中验证这一点。关键是根据要测试的案例对输出检查进行逻辑分组。
原则-PMP:
同样,我想您对于私有方法原理(PMP)教给我们的东西有些遗漏。PMP鼓励我们将系统视为黑匣子。对于给定的输入,您应该获得给定的输出。您不在乎黑匣子如何生成输出。您只关心输出与输入对齐。
对于查看代码的API方面,PMP确实是一个很好的视角。它还可以帮助您确定要测试的范围。确定您的接口点,并验证它们是否符合合同条款。您无需担心接口(也称为私有)方法如何完成其工作。您只需要验证他们做了他们应该做的事情。
已申请TDD(适合您)
因此,您的情况比普通应用程序还有些皱纹。您应用的方法是有状态的,因此它们的输出不仅取决于输入,而且还取决于之前的操作。我敢肯定,我<insert some lecture>
在这里应该说的是状态糟糕透顶等等,但这确实无助于解决您的问题。
我将假设您有某种状态图表,该表显示了各种潜在状态以及触发转换需要执行的操作。否则,您将需要它,因为它将有助于表达该系统的业务需求。
测试:首先,您将获得一组制定状态更改的测试。理想情况下,您将进行测试,以测试可能发生的所有状态变化,但是我可以看到一些场景,您可能不需要进行全部测试。
接下来,您需要构建测试以验证数据处理。当您创建数据处理测试时,其中一些状态测试将被重用。例如,假设您有一个Foo()
基于Init
和State1
状态具有不同输出的方法。您需要将ChangeFooToState1
测试用作设置步骤,以便在“ Foo()
in State1
” 时测试输出。
我想提及这种方法背后的一些含义。 剧透,这是我会激怒纯粹主义者的地方
首先,您必须接受在一种情况下使用某种东西作为测试,而在另一种情况下使用某种东西。一方面,这似乎直接违反了SAP。但是,如果您从逻辑上将其定义ChangeFooToState1
为具有两个目的,那么您仍将符合SAP教导我们的精神。当您需要确保Foo()
更改状态时,可以将其ChangeFooToState1
用作测试。而当需要验证“ Foo()
”的输出时,State1
则ChangeFooToState1
用作设置。
第二项是,从实际的角度来看,您将不需要系统的完全随机单元测试。您应该先运行所有状态更改测试,然后再运行输出验证测试。SAP是该订单背后的一种指导原则。要说明什么是显而易见的-如果某项测试失败,则不能将其用作设置。
把它放在一起:
使用状态图,您将生成测试以涵盖转换。同样,使用图表,您将生成测试以覆盖由状态驱动的所有输入/输出数据处理案例。
如果您采用这种方法,那么bloated, complicated, long, and difficult to write
测试应该会更容易管理。通常,它们的结局应该更小,并且应该更简洁(即,不那么复杂)。您应注意,测试也更加分离或模块化。
现在,我并不是说该过程将完全免于痛苦,因为编写好的测试确实需要一些努力。而且其中有些仍然很困难,因为您要在很多情况下映射第二个参数(状态)。顺便说一句,为什么无状态系统更易于构建测试,这应该更加明显。但是,如果您针对应用程序采用这种方法,则应该发现自己能够证明您的应用程序正常工作。