![]() |
1
82
只测试一件事可以隔离这件事,并证明它是否有效。这就是单元测试的想法。测试多个东西的测试没有错,但这通常被称为集成测试。根据上下文,两者都有优点。 举个例子,如果你的床头灯没有打开,而你更换了灯泡并切换了延长线,你不知道是哪种改变解决了这个问题。本应进行单元测试,并分离您的关注点以隔离问题。 更新:我读了这篇文章和链接的文章,我不得不说,我很震惊: https://techbeacon.com/app-dev-testing/no-1-unit-testing-best-practice-stop-doing-it 这里有实质,它让精神之汁流动。但我认为这与最初的观点相吻合,即我们应该进行背景要求的测试。我想我只是想补充一下,我们需要更确切地了解在系统上进行不同测试的好处,而不是交叉手指的方法。测量/量化和所有这些好东西。 |
![]() |
2
74
我在这里要冒一个险,说“唯一测试一件事”的建议并不像有时所说的那么有帮助。 有时测试需要一定的设置。有时他们甚至会服用一定量的 时间 (在现实世界中)建立。通常,你可以一次性测试两个动作。 优点:所有设置只发生一次。你在第一次行动后的测试将证明,在第二次行动之前,世界就是你所期望的样子。更少的代码,更快的测试运行。 缺点:如果 任何一个 如果操作失败,您将得到相同的结果:相同的测试将失败。与在两个测试中只进行一个操作相比,您对问题所在的信息更少。 事实上,我发现这里的“骗局”并不是什么问题。堆栈跟踪通常会很快缩小范围,我无论如何都会确保修复代码。 这里有一个稍微不同的“骗局”,它打破了“编写新测试,使其通过,重构”的循环。我认为这是 理想的 循环,但并不总是反映现实。有时,在当前测试中添加一个额外的操作和检查(或者可能只是对现有操作进行另一个检查)比创建一个新的操作更实用。 |
![]() |
3
13
通常不建议使用检查多个事物的测试,因为它们耦合更紧密,更脆弱。如果你更改了代码中的某些内容,那么更改测试将需要更长的时间,因为有更多的事情需要考虑。 [编辑:] 好的,假设这是一个样本测试方法:
如果你对条件A的测试失败了,那么B、C和D似乎也会失败,不会给你任何帮助。如果你的代码更改也会导致C失败怎么办?如果你把它们分成4个单独的测试,你就会知道这一点。 |
![]() |
4
11
哈哈。..单元测试。 将任何“指令”推得太远,它很快就会变得不可用。 单一单元测试测试单一事物和单一方法执行单一任务一样好。但依我之见,这并不意味着一个测试只能包含一个断言语句。 是
比…好
在我看来,这是品味问题,而不是良好的做法。我个人更喜欢后者。 但是
实际上,这是“指令”希望你不惜一切代价避免的,也是最快耗尽我理智的东西。 最后的结论是,将语义相关且易于测试的东西组合在一起,这样失败的测试消息本身就足够有意义,可以直接进入代码。 这里关于失败测试报告的经验法则是:如果你必须先阅读测试的代码,那么你的测试结构不够好,需要更多地拆分成更小的测试。 我的2美分。 |
![]() |
5
8
想想造一辆车。如果你要应用你的理论,只测试大事,那么为什么不做一个测试,让汽车穿过沙漠呢。它坏了。好的,那么告诉我是什么导致了这个问题。你不能。这是一个情景测试。 功能测试可能是打开发动机。它失败了。但这可能是由于多种原因。你仍然不能确切地告诉我是什么导致了这个问题。不过,我们越来越近了。 单元测试更具体,它将首先确定代码的损坏位置,但它也将(如果进行适当的TDD)帮助将代码构建成清晰的模块化块。 有人提到使用堆栈跟踪。算了,那是第二种选择。浏览堆栈跟踪或使用调试是一件痛苦的事情,而且可能很耗时。尤其是在较大的系统和复杂的bug上。 单元测试的良好特性:
|
![]() |
6
6
使用测试驱动开发,您将首先编写测试,然后编写代码以通过测试。如果你的测试是集中的,那么编写通过测试的代码会更容易。 例如,我可能有一个接受参数的方法。我可能首先想到的一件事是,如果参数为null,会发生什么?它应该抛出ArgumentNull异常(我认为)。因此,我编写了一个测试,检查在传递null参数时是否抛出了异常。运行测试。好吧,它抛出NotImplementedException。我通过更改代码以抛出ArgumentNull异常来解决这个问题。运行我的测试,它通过了。然后我想,如果它太小或太大,会发生什么?啊,这是两个测试。我先写一个太小的案例。 关键是我不会一下子想到方法的行为。我通过思考它应该做什么来逐步(和逻辑地)构建它,然后在构建过程中实现代码和重构,使其看起来很漂亮(优雅)。这就是为什么测试应该小而集中,因为当你思考行为时,你应该以小而可理解的增量来发展。 |
![]() |
7
4
只验证一件事的测试使故障排除更容易。这并不是说你不应该也有测试多个东西的测试,或者共享相同设置/拆卸的多个测试。 这里应该有一个说明性的例子。假设你有一个带有查询的堆栈类:
以及改变堆栈的方法
现在,考虑以下测试用例(我在这个例子中使用了类似Python的伪代码。)
从这个测试用例中,您可以确定是否有问题,但无法确定它是否与
如果我们为每种方法及其行为添加单独的测试用例,事情就会变得更容易诊断。此外,通过为每个测试用例进行新的设置,我们可以保证问题完全在失败的测试方法调用的方法中。
就测试驱动开发而言。我个人编写更大的“功能测试”,首先测试多个方法,然后在开始实现单个部分时创建单元测试。 另一种看待它的方式是单元测试验证每个单独方法的契约,而更大的测试验证对象和整个系统必须遵循的契约。
我仍然在使用三个方法调用
通过向单个测试添加更多断言,您可以获得类似的功能,但随后断言失败将被隐藏。 |
![]() |
8
4
如果你正在测试多个东西,那么它就被称为集成测试。..不是单元测试。您仍然可以在与单元测试相同的测试框架中运行这些集成测试。 集成测试通常较慢,单元测试较快,因为所有依赖关系都是模拟/伪造的,所以没有数据库/web服务/慢速服务调用。 我们在提交到源代码控制时运行单元测试,我们的集成测试只在夜间构建中运行。 |
![]() |
9
3
如果你测试了不止一件事,而你测试的第一件事失败了,你将不知道你测试的后续事情是通过还是失败。当你知道所有会失败的事情时,修复起来会更容易。 |
![]() |
10
3
较小的单元测试可以更清楚地说明失败时的问题所在。 |
![]() |
11
3
GLib,但希望仍然有用,答案是单位=1。如果你测试了不止一件事,那么你就不是单元测试。 |
![]() |
12
2
关于你的例子:如果你在同一个单元测试中测试添加和删除,你如何验证该项目是否被添加到你的列表中?这就是为什么您需要添加并验证它是在一个测试中添加的。 或者以灯为例:如果你想测试你的灯,你所做的就是打开开关然后关闭,你怎么知道灯曾经打开过?你必须采取中间的步骤,看看灯并确认它是否亮着。然后你可以关闭它并确认它已关闭。 |
![]() |
13
2
我支持单元测试应该只测试一件事的想法。我也有点偏离了它。今天我进行了一次测试,昂贵的设置似乎迫使我在每次测试中做出多个断言。
与此同时,我真的很想看到我所有失败的断言,而不仅仅是第一个。我原以为他们都会失败,我需要知道我真正得到了多少回报。但是,将每个测试分开的标准[SetUp]将导致对慢速服务的3次调用。突然间,我想起了一篇文章,其中提到使用“非传统”测试结构是隐藏单元测试一半好处的地方。(我想这是Jeremy Miller的帖子,但现在找不到了。)突然间,[TestFixtureSetUp]浮现在我的脑海里,我意识到我可以进行一次服务调用,但仍然有单独的、富有表现力的测试方法。
这个测试中有更多的代码,但它通过一次向我显示所有不符合预期的值,提供了更多的价值。 一位同事还指出,这有点像Scott Bellware的specunit.net: http://code.google.com/p/specunit-net/ |
![]() |
14
1
非常精细的单元测试的另一个实际缺点是它破坏了 DRY principle 我参与过一些项目,其中的规则是类的每个公共方法都必须有一个单元测试([TestMethod])。显然,每次创建公共方法时,这都会增加一些开销,但真正的问题是,它给重构增加了一些“摩擦”。 它类似于方法级文档,拥有它很好,但这是另一件必须维护的事情,它使更改方法签名或名称变得更加繁琐,并减缓了“floss重构”(如中所述 "Refactoring Tools: Fitness for Purpose" 爱默生·墨菲-希尔和安德鲁·P·布莱克。PDF,1.3mb)。 与设计中的大多数事情一样,“测试应该只测试一件事”这句话并没有捕捉到一种权衡。 |
![]() |
15
1
当测试失败时,有三种选择:
细粒度试验 描述性名称 帮助读者了解 为什么? 编写了测试,这反过来又使得更容易知道选择上述选项中的哪一个。测试名称应描述测试指定的行为,并且仅限于 每次测试一个行为 -这样,读者只需阅读测试的名称,就能知道系统的功能。看见 this article 了解更多信息。 另一方面,如果一个测试做了很多不同的事情,并且它有一个非描述性的名称(例如以实现中的方法命名的测试),那么很难找出测试背后的动机,也很难知道何时以及如何更改测试。 以下是它的样子(与 GoSpec ),当每个测试只测试一件事时:
|
![]() |
16
1
好吧,这样当一些测试失败时,你就知道哪种方法失败了。 当你必须修理一辆无法正常工作的汽车时,知道发动机的哪个部分出了故障会更容易。
让我们假设加法方法已损坏,无法添加,而删除方法已损坏且无法删除。您的测试将检查添加和删除后的列表是否与最初的大小相同。你的测试会成功的。虽然你的两种方法都会被打破。 |
![]() |
17
0
免责声明:这是一个深受《xUnit Test Patterns》一书影响的答案。 每次测试只测试一件事是提供以下好处的最基本原则之一:
我只能看到一个原因,为什么你可能会从验证多个东西的测试中受益,但这实际上应该被视为一种代码气味:
|
|
wavesinaroom · 断言结构向量长度 9 月前 |
![]() |
Tim Kirkwood · 比较空数据帧 10 月前 |
![]() |
Kamran Khan · 使用单元测试ASP。NET核心 1 年前 |
![]() |
paymer · 为什么我的代码没有删除我的单元测试生成的zip文件? 1 年前 |
![]() |
Ricky Mo · 角度测试如何模拟导入的const 1 年前 |
![]() |
Natty · Visual Studio中缺少“代码覆盖率结果” 1 年前 |