Web开发中的单元测试与集成测试

18

我想请教一下在Web开发中使用单元测试的情况。单元测试的想法很好,但在Web应用程序的环境下,它是否真正有价值?我的问题的第二部分是关于TDD的,如果一个人在实际编码之前创建了一个集成测试,这种方法可以称为“测试驱动开发”吗?

1. 假设

根据定义,单元测试应该只对一个服务层的代码进行测试。如果一个测试跨多个层测试代码,则我们有一个集成测试。

2. 论点

2.1 没有算法

Web应用程序中没有太多算法。这不像构建3D物理引擎,其中每个方法都做一些有挑战性且难以调试的事情。Web应用程序主要是关于集成和生成HTML。

Web应用程序最大的挑战是: - 清晰的代码(所有软件的通用问题,但无法测试) - 数据一致性 - 集成(编程语言、文件系统、配置文件、Web服务器、缓存系统、数据库、搜索引擎、外部API等所有系统必须在请求时协同工作)

如果要为Web应用程序中的每个类构建单元测试,您将测试以下内容(在大多数情况下):填充数组、字符串连接和语言的本机函数。

2.2 成本

仅因为Web应用程序全部关于集成,因此始终存在多个依赖项。您必须模拟许多不同的类,并且编写即使是小型测试也可能实际上是一项重大工作。更糟糕的是,这不仅仅关乎测试。软件需要是可测试的。这意味着一个人几乎必须能够在每个类中注入依赖项。有时无法注入依赖项而不创建两个类或系统之间的额外层。它会使代码复杂化并增加操作成本。

3. 集成测试

如果Web开发全都关于集成,为什么不进行测试呢?这里有一些反对意见。

3.1 集成测试只会说“某事出了问题”,但不会说出具体原因

这实际上取决于:在集成测试失败时找到错误需要多少时间,相对于使代码“可单元测试”和更复杂的时间(我想这是主观的)?根据我的经验,找到问题的源头从来没有花费很长时间。

3.2 您可以在任何环境下运行单元测试,但很难进行集成测试

是的,如果您想在没有数据库的情况下运行集成测试。通常会有一个数据库。只要您在固定数据上操作并在每个测试后清理数据,那么就应该没问题。事务性数据库非常适合此任务。打开事务、插入数据、测试、回滚。

3.3 集成测试难以维护

我无法对此发表评论,因为我所有的测试都能够正常工作,我从未遇到过这样的问题。

4. 创建良好的单元测试!

整个论点可以被攻击为:“如果您正确创建了单元测试,则不会遇到任何问题”。集成测试也可以如此吗?如果创建集成测试更容易,为什么不坚持使用它并做得正确呢?

别误解我的意思,我不反对单元测试。这是一个完美的想法,我向每个人推荐。我正在尝试理解:它是否真正适合 Web 开发?我想听听您们的意见和经验。


5
“2.1 不使用算法” - 这取决于应用程序,不是吗?仅仅因为它存在于网络上并不意味着它不复杂或不包含复杂的算法。 - deceze
@deceze 当然可以!但一般来说,Web应用程序并不会有太多这样的问题。 - Lukasz Kujawa
也许你应该看一下ATDD,它基本上可以解决你的问题。《Growing Object-Oriented Software, Guided by Tests》介绍了在为功能编写失败的验收测试之前,永远不要去实现它的想法。Pluralsight.com有一门关于先测试开发的课程。请查看关于ATDD的 第二部分 课程。 - Songo
@Songo 谢谢你的建议,我一定会去了解一下。只是为了澄清,我并没有实际问题。我想要了解所有的利弊得失。如果单元测试总是最好的选择,那就用它吧。 - Lukasz Kujawa
3个回答

5

这是一个非常好的问题,更多的开发者应该问问自己。

我认为这不仅适用于Web开发,但我认为这是一个很好的例子来讨论。

在决定测试策略时,您提出的观点是非常有效的。在商业世界中,成本(以时间为单位)可能是最重要的因素。我总是遵循一些简单的规则,以保持我的测试策略现实可行。

  • 对于重要的和可单元测试的“库”(Auth、Billing、Service Abstractions等),进行单元测试
  • 如果可能的话,请对模型进行单元测试(确实应该是可能的!)
  • 集成测试应用程序的重要端点(完全取决于应用程序)

一旦你掌握了这三个要点,考虑到你的成本约束限制,你可以继续测试任何有意义的东西,以合理的方式进行测试。

单元测试和集成测试并不是相互排斥的,除非您正在构建一个可以美丽地进行单元测试的库,否则您应该同时进行这两种测试。


3
简短的回答是,是的。单元测试和集成测试都有价值。 个人而言,我并不是很擅长TDD,但我注意到它极大地提高了设计质量,因为我必须先思考再编码。 对我来说,这是非常宝贵的,但它也需要很长时间的适应。 我认为这就是为什么它被广泛误解的主要原因。
让我们看看你的观点:
没有算法(但你的意思是很少):
好吧,如评论所述,这取决于应用程序。这实际上与TDD无关。只有少量算法不是不测试它们的理由。您可能有多种不同的情况和许多不同的状态。知道它们按预期工作不是很好吗?
成本:
当然会有成本,如果项目很小,并且您或您的开发人员对此还不熟悉,则您可能无法从TDD中获得任何价值。但另一方面,一个小项目可能正是开始使用它的最佳方式,这样您就可以为下一个更大的项目做好准备。这是您必须自己计算的。我们是程序员,而不是经济学家。
集成测试:
也要进行测试!

集成测试指出“有东西坏了”,但不说哪里坏了

很抱歉,我不理解这个。

难以维护

如果难以维护,那么你做错了。先编写测试,在更改代码时在实现之前更改测试。在开发过程中失败的测试是TDD的必须要素。实际上,请不要引用我关于TDD的这一点,这只是我对TDD的有限理解。

我认为this是有关单元测试的非常好的引用

单元测试应该是规定性的,而不是描述性的。换句话说,单元测试应该定义您的代码应该做什么,而不是事后说明您的代码做了什么。

归根结底,集成测试和单元测试是两回事。TDD是一种开发方法,集成测试更多地是从用户角度验证应用程序是否按预期工作。

编辑 社区维基关于集成测试的说法:

在集成测试中,所有输入模块都是已经进行过单元测试的模块。这些模块被分组成更大的聚合体,并应用于这些聚合体的集成测试(定义在集成测试计划中)。成功完成集成测试后,集成的系统就可以进行系统测试了。
所以实际上我对于什么是“集成测试”的理解从一开始就是错误的,但我认为我的答案除了最后一段之外并没有太大偏差。

感谢您的时间和回答。您提出了有效的观点。 - Lukasz Kujawa

0

集成测试需要比单元测试更长的时间来执行。

"……关于集成,总是有多个依赖项"——如果你正在编写一个依赖于其他未完成单位的代码,那么你现在无法进行集成测试。如果你想要确保你的代码在这个阶段是有效的,那么你可以进行单元测试。

如果你的团队中的每个成员都在开发自己的依赖单位,他们还不能进行集成测试,因为其他人正在开发所需的单位。但是,如果他们在提交到仓库之前进行单元测试,他们至少可以确保他们的代码是有效的。


感谢您的输入。到目前为止,集成测试的速度还没有成为问题。大多数测试都运行得相当快。 - Lukasz Kujawa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接