Unit testing 我们应该单元测试方法实际做什么,还是应该做什么?

Unit testing 我们应该单元测试方法实际做什么,还是应该做什么?,unit-testing,Unit Testing,这个问题可能有点奇怪,但我会解释的 考虑以下几点: 我们有一个服务FirstNameValidator,是我为其他开发人员创建的,因此他们有一个一致的方法来验证一个人的名字。我想测试它,但因为全套可能的输入是无限的(或非常大),我只测试少数情况: Assert.IsTrue(FirstNameValidator.Validate("John")) Assert.IsFalse(FirstNameValidator.Validate("$$123")) 我还有LastNameValidator,

这个问题可能有点奇怪,但我会解释的

考虑以下几点: 我们有一个服务
FirstNameValidator
,是我为其他开发人员创建的,因此他们有一个一致的方法来验证一个人的名字。我想测试它,但因为全套可能的输入是无限的(或非常大),我只测试少数情况:

Assert.IsTrue(FirstNameValidator.Validate("John"))
Assert.IsFalse(FirstNameValidator.Validate("$$123"))
我还有
LastNameValidator
,它99%相同,我也为它编写了一个测试:

Assert.IsTrue(LastNameValidator.Validate("Doe"))
Assert.IsFalse(LastNameValidator.Validate("__%%"))
但后来出现了一种新的结构——人名,它由名字和姓氏组成。我们也想验证它,所以我创建了一个PersonNameValidator。显然,为了可重用性,我只调用FirstNameValidator和LastNameValidator。一切都很好,直到我想写一个测试

我应该测试什么

FirstNameValidator.Validate实际上是用正确的参数调用的吗

或者我需要创建几个案例并测试它们

这实际上是一个问题——我们是否应该测试服务应该做什么?它将验证PersonName,它是如何实现的,我们实际上并不关心。因此,我们传递一些有效和无效的输入,并期望相应的返回值


或者,也许,它实际上是做什么的?就像它实际上只是调用其他验证器一样,所以测试(.net mocking framework允许它)。

单元测试应该是一个正常运行的代码单元的验收标准。。。 他们应该测试代码应该做什么和不应该做什么,在编写测试时,您经常会发现一些特殊情况

如果你重构代码,你通常需要重构测试。。。这应该被视为最初努力的一部分,并且应该给你的灵魂带来欢乐,因为你已经使产品和过程有了如此巨大的改进

当然,如果这是一个具有外部(或内部,取决于公司文化)消费者的图书馆,在完成之前,你有文档要考虑。


编辑:这些测试也很弱,你应该对每个测试中的合法性有一个定义,并且实际测试至少所有类别的glyphps的包含和排除。。。他们仍然可以使用相关代码进行测试。。。ie
isValidUsername(name,allowspace)
可以用于名字和全名,具体取决于是否允许使用空格。

您的问题表述得有点奇怪:您描述的两个选项都将测试函数是否按其应有的方式运行-但在每种情况下,粒度都不同。在一种情况下,您将基于函数用户可用的API测试行为。功能是否以及如何在其他功能/组件的帮助下实现其功能并不相关。在第二种情况下,单独测试行为,包括函数与其依赖组件交互的方式

总的来说,不可能说哪一个更好——取决于具体情况,每个选项可能是最好的。一般来说,隔离一个软件通常需要更多的努力来实现测试,并使测试在实现更改时更加脆弱。这意味着,只有在有充分理由的情况下,才应该进行隔离。在讨论您的具体案例之前,我将描述一些建议隔离的情况

  • 使用原始依赖组件(DOC),您可能无法测试所需的所有内容。假设您的代码对文档返回错误代码的情况进行错误处理。但是,如果无法轻松地使文档返回错误代码,则很难测试错误处理。在这种情况下,如果您将文档加倍,您可以使加倍返回一个错误代码,从而也测试您的错误处理
  • DOC可能具有不确定性或特定于系统的行为。一些例子是随机数生成器或日期和时间函数。如果这使得测试函数变得困难,那么用double替换DOC将是一个论点,这样您就可以控制为函数提供的内容
  • 文档可能需要非常复杂的设置。想象一下,需要提供一个复杂的数据库或一些复杂的xml文档。一方面,这会使您的设置变得非常复杂,另一方面,如果文档发生更改,您的测试将变得脆弱,并且可能会中断(假设XML模式发生更改…)
  • 文档的设置或对文档的调用非常耗时(想象一下从网络连接读取数据、计算下一步棋步、解决TSP等等)。或者,文档的使用大大延长了编译或链接的时间。使用double可以显著缩短执行或构建时间,执行/构建测试的频率越高,这就越有趣
  • 您可能没有文档的工作版本-文档可能仍在开发中,尚未可用。然后,使用双打,您可以开始测试
  • 文档可能是不成熟的,因此您的测试版本不稳定。在这种情况下,您可能会对测试结果失去信任,并开始忽略失败的测试
  • 文档本身可能有其他依赖项,这些依赖项存在上述一些问题

这些标准有助于就隔离是否必要做出明智的决定。考虑到你的具体例子:你描述情况的方式给我的印象是,上述标准都没有得到满足。对我来说,这将导致一个结论,即我不会将函数
PersonNameValidator
与其文档
FirstNameValidator
LastNameValidator

隔离在SE.SE:,(可能还有其他)上的相关跨站点副本