向遗留代码添加单元测试

发布于 2024-08-07 00:08:25 字数 1432 浏览 6 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

往事随风而去 2024-08-14 00:08:26

另请查看遗留代码单元测试领域的新方法 - Asis 项目,它的灵感来自 < a href="http://approvaltests.sourceforge.net/" rel="noreferrer">ApprovalTests 项目并分享其关键概念。

正如本文中提到的 ApprovalTests 方法:

通常,您有一个巨大的遗留代码项目,但没有测试
全部,但您必须更改代码才能实现新功能,或者
重构。遗留代码的有趣之处在于——它有效!它
不管它是如何写的,它都可以工作多年。这是一个非常伟大的
该代码的优点。获得批准后,只需进行一次测试即可获得
所有可能的输出(HTML、XML、JSON、SQL 或任何可能的输出)
是)并批准,因为你知道 - 它有效!当你完成后
这样的测试并批准了结果,你真的更安全了
重构,从现在起您“锁定”了所有现有行为。

Asis 工具正是通过自动创建和运行特征测试来维护遗留代码。

有关更多信息,请参阅

Look also at the new approach in the area of legacy code unit testing - Asis project, it is inspired by ApprovalTests project and shares its key concepts.

As mentioned about ApprovalTests approach in this article:

Often you have a huge legacy code project where you have no tests at
all, but you have to change code to implement a new feature, or
refactor. The interesting thing about legacy code is - It works! It
works for years, no matter how it is written. And this is a very great
advantage of that code. With approvals, with only one test you can get
all possible outputs (HTML, XML, JSON, SQL or whatever output it could
be) and approve, because you know - it works! After you have complete
such a test and approved the result, you are really much safer with a
refactoring, since now you "locked down" all existing behavior.

Asis tool is exactly about mantaining the legacy code through creating and running characterization tests automatically.

For further information look at

烟凡古楼 2024-08-14 00:08:26

如果您计划重构遗留代码,那么必须创建这些单元测试。不要担心模拟或存根 - 担心测试系统的输入和输出,以便您的更改或重构工作不会破坏当前功能。

我不会对你撒谎,对遗留代码进行单元测试改造很困难——但这是值得的。

If you are planning on refactoring the legacy code then creating those unit tests is a must. Don't worry about mocking or stubbing - worry about testing the inputs and outputs of the system so that your changes or refactoring efforts don't break current functionality.

I won't lie to you, retrofitting unit tests to legacy code is difficult - but it is worth it.

黎歌 2024-08-14 00:08:26

单元测试的一种替代方法是特征测试,这一点也在有效处理遗留代码中介绍。我通过这样的测试得到了有趣的结果。它们比单元测试更容易设置,因为您从可以测试的点进行测试(称为接缝)。缺点是,当测试失败时,您对问题位置的提示较少,因为测试区域可能比单元测试大得多。日志记录在这里很有帮助。


xUnit 系列的单元测试框架可用于编写特征测试。

在此类测试中,根据事实编写断言,验证代码的当前行为。与单元测试不同,它们并不证明代码是正确的,它们只是确定(表征)代码的当前行为。

该过程与 TDD 类似:

  • 为代码的一部分编写测试
  • 执行它 - 失败
  • 根据观察到的代码行为修复测试
  • 执行它 - 通过
  • 重复

如果修改代码的外部行为,测试将会失败。代码的外部行为?听起来很熟悉?是的,就是这样,我们来了。现在您可以重构代码。

显然,风险取决于特征测试的覆盖范围。

One alternative to unit tests, also introduced in Working effectively with legacy code is characterization tests. I had interesting results with such tests. They're easier to set-up than unit tests as you test from point than can be tested (called seam). The drawback is that when a test fails, you have less hint about the location of the problem as the area under test can be much larger than with unit tests. Logging helps here.


A unit test framework such those of the xUnit family can be used to write characterization tests.

In such tests, written after the facts, assertions verify the current behavior of the code. Unlike unit tests, they do not prove that the code is correct, they are just pinning down (characterizing) the current behavior of the code.

The process is similar as the TDD one,:

  • write a test for a portion of code
  • execute it - fail
  • fix the test from the observed behavior of the code
  • execute it - pass
  • repeat

The tests will fail if you modify the external behavior of the code. External behavior of the code ? sounds familiar ? Yes it is, here we are. Now you can refactor the code.

Obviously the risk depends on the coverage of the characterization tests.

若沐 2024-08-14 00:08:26

查看免费的开源单元测试实用程序库 ApprovalTests。如果您是 .NET 开发人员,创建者 Llewellyn Falco 制作了一系列视频展示了他如何使用 ApprovalTests 改进新代码和旧代码的单元测试。

Take a look at the free, open source unit-testing utility library, ApprovalTests. If you are a .NET developer, the creator, Llewellyn Falco, has made a series of videos showing how he uses ApprovalTests to improve unit testing for both new and legacy code.

泪痕残 2024-08-14 00:08:26

我前段时间在 XPDays http://xpdays.com.ua/archive/xp-days-ukraine-2012/materials/legacy-code/

该演示文稿应该回答为什么有时如此重要的问题在处理遗留代码时,从集成/功能甚至高级验收测试开始。然后慢慢地、一步一步地引入单元测试。没有代码示例 - 抱歉,但是您可以在 Michaels Feathers 的书“有效处理旧代码”中找到大量代码示例。

您还可以检查旧版代码撤退 http://www.jbrains.ca/legacy-code-retreat< /a> 并查找您所在地区的会议。

I've been speaking some time ago about idea of Reversed Tests Pyramid in Legacy Code at XPDays http://xpdays.com.ua/archive/xp-days-ukraine-2012/materials/legacy-code/

This presentation should answer the question why it is so important sometimes to start with integration/functional or even high level acceptance tests when working with legacy code. And then slowly, step by step introducing unit tests. There are no code examples - sorry, but you can find bunch of them in Michaels Feathers book "Working effectively with Legacy Code".

Also you can check Legacy Code Retreat http://www.jbrains.ca/legacy-code-retreat and look for that meeting in your area.

枯叶蝶 2024-08-14 00:08:25

我发现最好的方法是逐步添加单元测试,而不是直接跳出来说我们现在将对应用程序进行单元测试。

因此,如果您要接触代码以进行错误修复或重构,请首先编写单元测试。对于错误,单元测试将有助于证明问题出在哪里,因为您可以复制它。

如果重构,你会想要编写单元测试,但你可能会发现测试是不可能编写的,所以你可能需要找到一个高层,调用将要重构的函数,并对那部分进行单元测试。然后,当您重构攻击性功能时,编写测试,以便确保它按预期运行。

没有简单的方法可以做到这一点。

这个问题可能有助于提供更多建议。
如何将单元测试引入到大型遗留 (C/C++) 代码库?

The best way, I have found, is to incrementally add the unit tests, not to just jump in and say we will now unit test the application.

So, if you are going to touch the code, for bug fixes or refactoring, then first write the unit tests. For bugs unit tests will help prove where the problem is, as you can duplicate it.

If refactoring, you will want to write unit tests, but you may find that the test is impossible to write, so you may need to find a high level, that calls the function that will be refactored, and unit test that part. Then, as you refactor the offensive function, write your tests so you can ensure that it is operating as it should.

There is no easy way to do this.

This question may help with more suggestions.
How do you introduce unit testing into a large, legacy (C/C++) codebase?

揪着可爱 2024-08-14 00:08:25

Michael Feathers 所著的《有效处理遗留代码》是一本涵盖该主题的整本书。 Michael 指出,为遗留代码引入测试通常太困难,因为它的结构不可测试。我从这本书中得到最多的是一些名为“Sprout 函数”和“Sprout 类”的模式。 sprout 函数封装了您需要在代码中进行的更改。然后,您仅对这些函数进行单元测试。 sprout 类的想法相同,只是新功能包含在类中。

Michael Feathers book "Working Effectively with Legacy Code" is an entire book covering this topic. Michael states that it is often too difficult to introduce tests for legacy code because it is not structured to be testable. What I got out of the book the most was a couple of patterns named "Sprout functions" and "Sprout classes". A sprout function is one that encapsulates the change that you need to make in the code. You then unit test these functions only. The sprout class is the same idea except the new functionality is contained in a class.

复古式 2024-08-14 00:08:25

是的,而且通常会很痛苦。我经常不得不编写集成测试。

单元测试的艺术一书对此有一些很好的建议。它还推荐了《有效使用旧代码》一书;我还没有读过后者,但它在我的书堆里。

编辑:但是,是的,即使是最小的代码覆盖率也是值得的。它给了我重构代码的信心和安全网。

编辑:我确实读过《有效地使用遗留代码》,它非常好。

Yes, and it's generally painful. I've often ended up having to write integration tests instead.

The book The Art of Unit Testing has some good advice on this. It also recommends the book Working Effectively with Legacy Code; I haven't read the latter yet, but it's on my stack.

EDIT: But yes, even minimal code coverage was worthwhile. It gave me confidence and a safety net for refactoring the code.

EDIT: I did read Working Effectively with Legacy Code, and it's excellent.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文