因此,我试图使我的单元测试尽可能地按书进行,但是当我测试一些简单的添加/删除方法时,这会很麻烦。
对于add方法,我基本上必须创建一个虚拟对象并将其添加,然后在测试成功之后,我必须删除该虚拟对象。
对于删除测试,我显然必须创建一个虚拟对象,以便可以将其删除。
如您所见,如果一项测试失败,那么另一项测试也会失败,因为它们都是必需的。
与需要编写“取消订单”测试的系统相同……那么首先需要取消一些虚拟订单,这是否违反单元测试的准则?
这样的案件应该如何处理?
因此,我试图使我的单元测试尽可能地按书进行,但是当我测试一些简单的添加/删除方法时,这会很麻烦。
对于add方法,我基本上必须创建一个虚拟对象并将其添加,然后在测试成功之后,我必须删除该虚拟对象。
对于删除测试,我显然必须创建一个虚拟对象,以便可以将其删除。
如您所见,如果一项测试失败,那么另一项测试也会失败,因为它们都是必需的。
与需要编写“取消订单”测试的系统相同……那么首先需要取消一些虚拟订单,这是否违反单元测试的准则?
这样的案件应该如何处理?
Answers:
好吧,您所做的没有错。多个测试可以覆盖相同的代码;这仅意味着一个问题将导致多个测试失败。您要避免的测试取决于其他测试的结果。即,删除测试取决于已运行的添加测试,因此,如果在添加测试之前运行删除测试,它将失败。为避免该问题,请确保在每个测试开始时都有一个“空白”,这样在给定测试中发生的情况不会影响后续测试。
做到这一点的一种好方法是针对内存数据库运行测试。
在添加测试中,创建一个空数据库,添加对象,并断言它确实已添加。
在删除测试中,使用要删除的对象创建数据库。删除对象,并断言它已被删除。
用您的拆卸代码删除数据库。
使用交易。
如果使用的数据库支持事务,则在事务中运行每个测试。在测试结束时回滚事务。然后,每个测试将使数据库保持不变。
是的,要取消订单,您首先必须创建一个订单。没关系。测试将首先创建一个订单,然后将其取消,然后确认该订单已被取消。
你做的很好。单元测试的唯一且唯一的基本原则是覆盖您拥有的每个代码路径,因此您可以确信您的代码正在执行应做的事情,并在更改和重构后继续执行。使单元测试保持小巧,简单和单一用途是一个值得的目标,但这不是根本。进行调用两个API相关方法的测试本身并不值得怀疑,实际上,正如您所指出的那样,这通常是必要的。拥有冗余测试的缺点在于,它们需要花费更多的时间来编写代码,但是由于几乎所有开发中的内容,这都是您必须始终付出的一种折衷,而最佳的解决方案几乎从来都不是极端问题之一。
软件测试技术千差万别,您对它们的了解越多,您将开始看到很多不同的(有时是相互矛盾的)指南。没有一本“书”。
我认为您处于一种已经看到一些有关单元测试的指导的情况,例如
等等。所有这些都是正确的,具体取决于您如何定义“单元测试”。
我将“单元测试”定义为类似以下内容:“一种测试,它针对一个代码单元行使一项功能,与其他相关组件隔离开来”。
根据该定义,您所做的(如果需要在运行测试之前将记录添加到数据库中)根本不是“单元测试”,而是更多的通常称为“集成测试”的测试。(根据我的定义,真正的单元测试不会访问数据库,因此您无需在删除记录之前添加记录。)
一个集成测试将行使使用多个组件(例如,用户界面功能和数据库),这将适用于单元测试的指导并不一定适用于集成测试。
正如其他人在回答中提到的那样,即使您做的事情与某些单元测试指南相违背,您所做的也不一定是错误的。相反,请尝试推断每种测试方法中实际要测试的内容,如果发现需要多个组件来满足您的测试,并且某些组件需要预先配置,请继续进行操作。
但最重要的是,要了解软件测试种类繁多(单元测试,系统测试,集成测试,探索性测试等),并且不要尝试将一种类型的指导应用于所有其他类型。