在过去的两年里,我在一些项目中使用TDD作为开发风格,但我总是陷入同样的困境:如何测试程序各个部分的集成?
我目前正在做的是为每个类编写一个测试用例(这是我的经验法则:“单元”是一个类,每个类都有一个或多个测试用例)。我尝试通过使用模拟和存根来解决依赖关系,这非常有效,因为每个类都可以独立测试。经过一些编码后,所有重要的类都会进行测试然后我使用IoC容器将它们“连接”在一起。在这里,我陷入困境:如何测试布线是否成功,对象是否按照我想要的方式进行交互?
一个例子:想想一个Web应用程序。有一个控制器类,它接受一组id,使用存储库根据这些ID获取记录,然后迭代记录并将它们作为字符串写入outfile。
为简单起见,会有三个类:Controller
,Repository
,OutfileWriter
。他们每个人都是孤立地进行测试。
我要做的是测试“真正的”应用程序:使用数据库中的一些ID进行http请求(手动或自动),然后查看文件系统是否写入文件。当然,这个过程可以自动化,但仍然是:它不会复制测试逻辑吗?这是所谓的“集成测试”吗?在我最近阅读的关于单元测试的一本书中,在我看来,集成测试更像是一种反模式?
答案 0 :(得分:4)
IMO,我没有文献可以支持我,但我们各种形式的测试之间的关键区别在于范围,
如果您熟悉单元测试,那么毫无疑问没有完美或“魔术子弹”测试。集成和系统集成测试非常类似于单元测试,因为每个测试都是为验证某种行为而设置的一套测试。
对于每个测试,您可以设置范围,然后决定输入和预期输出。然后执行测试,并将实际值评估为预期值。
在实践中,您可能很清楚系统的工作原理,因此编写典型的正面和负面路径测试将会很自然。但是,对于任何足够复杂的应用,期望对每种可能情况进行全面覆盖是不合理的。
不幸的是,这意味着在质量保证[QA],预生产[PP]和生产[产品]周期中会出现意外情况。此时,您尝试在dev中复制这些方案应该作为自动化测试进入集成和系统集成套件。
希望这会有所帮助,:))
ps:pet-peeve#1:管理员或开发人员调用集成和系统集成测试“单元测试”只是因为使用了nUnit或MsTest来自动化它...
答案 1 :(得分:3)
您所描述的确实是集成测试(或多或少)。不,它不是反模式,而是sw开发生命周期的必要部分。
任何相当复杂的程序都不仅仅是其各个部分的总和。所以无论你对它进行单元测试,你仍然没有太多关于整个系统是否按预期工作的线索</ strong>。
为什么会出现以下几个方面:
* 我刚从Luke Hohmann的书“Beyond Software Architecture”中读到的一个例子:在一个应用程序中,通过创建和维护实际机器中HW组件ID的“快照”来应用强大的反盗版防御,开发人员的代码非常适合单元测试。然后QA通过在没有网卡的机器上试用它,在10分钟内设法使应用程序崩溃。事实证明,由于开发人员正在开发Mac,他们理所当然地认为该机器有一个网卡,其MAC地址可以合并到快照中......
答案 2 :(得分:0)
我要做的是为了测试 “真正的”应用程序:制作http 请求(手动或自动) 与数据库中的一些ID和 如果是,请查看文件系统 文件写了。当然这个 流程可以自动化,但仍然: 不重复测试逻辑吗?
也许你是重复的代码,但你不是重复的努力。单元测试和集成测试有两个不同的目的,通常在SDLC中都需要这两个目的。如果可能,将用于单元/集成测试的代码分解为公共库。我还会尝试为您的单元/集成测试提供单独的项目b / c 您的单元测试应该单独运行(快速且无依赖性)。您的集成测试将更加脆弱并经常中断,因此您可能会有不同的策略来运行/维护这些测试。
这就是所谓的“整合 测试“?
确实是的。
答案 3 :(得分:0)
在集成测试中,就像在单元测试中一样,您需要验证测试中发生的情况。在您的示例中,您指定了OutfileWriter
,您需要一些机制来验证文件和数据是否正常。你真的想要自动化这个,所以你可能想要一个:
Class OutFilevalidator {
function isCorrect(fName, dataList) {
// open file read data and
// validation logic
}
答案 4 :(得分:0)
您可以查看“Taming the Beast”,这是Markus Clermont和John Thomas关于AJAX应用程序自动测试的演示文稿。 YouTube Video
相关文章的非常粗略的摘要:您希望使用最小的测试技术进行任何特定验证。以另一种方式拼写相同的想法,您试图最小化运行所有测试所需的时间,而不会牺牲任何信息。
因此,较大的测试主要是确保管道是正确的 - 实际上是插槽A中的标签A,而不是插槽B;这两个组成部分是否同意长度以米为单位,而不是以英尺为单位,等等。
执行代码路径会有重复,并且可能会重用一些设置和验证代码,但我通常不希望您的集成测试包含相同级别的组合爆炸,单位级别。
答案 5 :(得分:0)
使用BDD推动您的TDD将涵盖大部分内容。你可以使用Cucumber / SpecFlow和WatiR / WatiN。对于每个功能,它都有一个或多个场景,并且您一次处理一个场景(行为),当它通过时,您将转到下一个场景,直到该功能完成。
要完成一个场景,您必须使用TDD来驱动必要的代码,以使当前场景中的每个步骤都通过。这些方案对您的后端实现是不可知的,但是它们验证您的实现是否有效;如果在该应用程序的Web应用程序中存在某些不起作用,则该行为需要处于场景中。
正如其他人指出的那样,你当然可以使用集成测试。