打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
That’s Not TDD

“That’s Not TDD”

by DAVIDBERNSTEIN on JANUARY 17, 2009

A few months ago I was visiting a client who was having a lot of problems using TDD.

“It takes over half an hour to run our unit tests,” he said.

“You are not doing TDD,” I said. “In order for tests to be valuable, all of them must run fast—within a few seconds, or developers will stop running tests frequently.”

“But how do I make them run fast?” he asked. “Just connecting to the database takes 30 seconds.”

So I showed him a technique called Dependency Injections that allowed him to insert a mock object instead of the database. “You don’t need to test the database,” I said. “Remember, a test should test everything NOT under its control, so you should mock out all dependencies to get them under your control.”

Another problem they were having, which I hear a lot lately, is that their tests seem to be more of a burden than a help. “It will take a day to refactor the code and three days to refactor the tests,” is a statement that I often hear from clients.

This problem stems from thinking about TDD as a form of QA. TDD is not QA. QA is about insuring something works correctly; TDD is about expressing the intention of the system using assertions. In QA, we try to assure quality by testing as many things as possible that could go wrong; in TDD we try to express the intention of the system in as few tests as possible.

Most developers that I’ve met believe that code quality is a good thing, so they strive to write high-quality code, and their code is always clean. But tests are also code, and I often see poor code quality propagate in tests.

For example, I have seen the same developers who carefully removed redundancy in their production code write a huge number of redundant tests. Redundant tests are bad for the same reason that any redundancy is bad—it makes extra work refactoring if something changes.

Tests are most valuable when they break—at least that is when I am most glad I have them. But for any conceivable single change to a system, only one test should break. In other words, no two tests should break for the same reason. This is easier said than done but if you follow this rule, you will find it much easier to refactor tests when you refactor your code.

In summary, tests are code too, and their quality should be kept high. Each intention in the system should be expressed once in a test, and no other test should fail for the same reason.

几个月前,我去一个客户那里,他们在使用测试驱动开发上遇到了很多问题。

  “我们的单元测试用例要半个小时才能跑完,”他说。

  “你们这不是在做驱动测试开发,”我说。“为了让测试发挥效能,所有的测试必须在几秒钟内能跑完,否则的话,程序员不得不频繁的停下来等待测试。”

  “可是怎样才能让它们快起来?”他问,“光连接数据库就需要30秒”

  于是,我想他展示了一种叫做依赖注入的技术,它能让你使用一个伪造对象来模拟数据库。“你并不需要测试你数据库,”我说。“记住,测试应该是测试那些不受控制的东西,对于测试所依赖的东西,你应该使用模拟工具使它们处于控制之中。”

  他们遇到的另外一个问题 —— 我最近也是听到了很多次 —— 是他们的测试程序不但没起到好的作用,反而成了一个负担。“我们三天两头的要重构程序,关联的就需要重构测试程序”,这样的话从客户那里可以经常听到。

  这种问题是他们把TDD想成了QA。TDD不是QA。QA是来保证程序能正确的运行的。TDD是使用断言(assertion)来表现系统的关键特征。在QA里,我们用尽可能多的方法来测试系统中可能会出错的地方。在TDD里,我们用应尽可能少的测试来表现系统的关键特征。

  我遇到的大多数开发人员都很重视代码质量,努力写出高质量的代码,程序看起来很整洁。但测试用程序也是程序,经常的我能看到测试程序就写的不是那么好。

  例如,一些程序员会很认真的把产品程序里的冗余部分清理干净,但在测试程序中却留下大量的无用的代码。任何冗余都不是好事,冗余的测试也是如此,如果程序有变化,冗余的测试会花掉你额外的时间去重构。

  当系统出问题时,测试程序就体现出来了它最大的价值,至少对我来说是最欣慰的时候。然而,对于系统,任何一个改动只应会让一个测试失败。换句话说,没有任何两个测试的失败原因是相同的。这说起来容易做起来难,但如果你尊重这个原则,你将会发现,当你重构代码时,重构测试程序是会容易多了。

  目前就说这些问题。总之,测试也是程序,它们也要保持高质量。系统中的每个关键特征都用一个测试来表现,没有第二个测试会因为这同一个问题而失败。

What do you think? I’d love to hear your thoughts, ideas and suggestions. Please feel free to share your comments below.

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
测试驱动开发——读《浮现式设计》有感
胡百敬(书评--提升软件质量的必经之路)
打造高效的技术团队,我会关注的7个点
我在ThoughtWorks中的敏捷实践
破解敏捷测试的十大"神话"
程序员眼中的测试
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服