测试驱动开发背后的哲学

发布于 2024-09-10 20:02:48 字数 1431 浏览 10 评论 0原文

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

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

发布评论

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

评论(7

笛声青案梦长安 2024-09-17 20:02:48

看起来您最终编写的测试与实际代码一样多。

是的,有时测试比实际代码更多。您似乎缺少的好处是,当您更改一些看似不相关的代码并且旧的测试失败时,对小事情的测试将在以后对您有所帮助。

假设稍后您决定将页面标题生成抽象为一个帮助程序方法,该方法为您构建所有页面标题。如果您已经进行了测试,那么您就会知道您的助手正在工作(或没有)。

It seems that you end up writing as many tests as actual code.

Yes, and sometimes more tests than actual code. The benefit you seem to be missing is that testing for the little things will help you later when you change some seemingly non-related piece of code, and your old tests break.

Let's say that later on you decide to abstract your page title generation into a helper method that builds all of your page titles for you. If you already have the tests in place, then you'll know that your helper is working (or not).

满意归宿 2024-09-17 20:02:48

它被称为“测试驱动设计”是有原因的。TDD

是一种设计实践,旨在生成最简单、可行的东西,或者比生成回归套件更有价值。 、低耦合的对象以及具有其他理想质量特征的代码

AgileData.org 是这么说的这样:

一种观点是 TDD 的目标是规范而不是验证。换句话说,这是在编写功能代码之前仔细思考设计的一种方法。

您可能会发现整篇文章很有趣,尤其是神话和误解

是的,您最终可能会得到与产品代码类似数量的测试代码行。从业者认为,当更改成本高昂时,您可以预先完成编写测试的工作,或者在最后完成工作(可能还有更多),修复错误。

It's called "Test Driven Design" for a reason

As valuable or perhaps more valuable than generating a regression suite, TDD is a design practice intended to generate the simplest thing that will work, objects with low coupling, and code with other desirable quality characteristics

AgileData.org says it this way:

One view is the goal of TDD is specification and not validation. In other words, it’s one way to think through your design before your write your functional code.

You may find the entire article interesting, especially the Myths and Misconceptions.

And, yes, you will probably end up with similar numbers of lines of test code as you do product code. Practitioners believe that you do the work up front writing test or you do the work (and possibly a lot more) at the end, fixing bugs, when change is expensive.

许久 2024-09-17 20:02:48

测试的基本原则是,对于任何具有 N 个分支的给定代码段,随后您可以通过该代码采取多达 2N 条可能的路径。这意味着对于某些实际上可能非常小的方法,其使用方法的数量可能比方法本身要多得多。

这是一个常见的场景:

if (@user.posts.count > @limit.posts)
  # Branch 1
  flash.now[:error] = "You have posted too many times today."
elsif (@user.suspended?)
  # Branch 2
  flash.now[:error] = "Your account is suspended. You cannot post."
else
  if (@post.special? and [email protected]_special?)
    # Branch 3
    flash[:warning] = "You cannot create special posts."
    @post.special = false
  # else
    # Branch 4
    # Not branching also has to be tested
  end

  if (@user.recently_created?)
    # Branch 5
    @post.newbie = true
  # else
    # Branch 6
  end

  # Branch 7
end

unless (flash[:error])
  @post.save!
end

虽然这非常简单,但创建导致逻辑流经正确分支的环境却不是。您可能必须为每个特定的测试用例编写一个测试用例。这并不总是微不足道的,但如果您有许多准备好的固定装置或工厂方法来构建几乎准备就绪的东西,您可以使它变得更容易。

如果不使用自动测试来测试每个单独的案例,则由于无意的更改而发生故障的可能性会很大。为了确保它正常工作,您必须手动运行这些路径,并且您经常会忘记其中一条,然后这会引起麻烦,可能是令人尴尬的情况。

例如,减少测试的方法是通过消除不会增加业务价值的业务逻辑来降低代码复杂性。只保留最重要的东西,丢弃任何多余的东西。

如果您正在为一些应该很简单的东西编写一千个不同的测试,那么它在设计方面可能不够简单。

The basic principle at work in testing is that for any given piece of code with N branches, there are subsequently as many as 2N possible paths you can take through that code. That means for some method that might actually be pretty small, the number of ways it can be used can take a lot more to describe than the method itself.

Here's a common scenario:

if (@user.posts.count > @limit.posts)
  # Branch 1
  flash.now[:error] = "You have posted too many times today."
elsif (@user.suspended?)
  # Branch 2
  flash.now[:error] = "Your account is suspended. You cannot post."
else
  if (@post.special? and [email protected]_special?)
    # Branch 3
    flash[:warning] = "You cannot create special posts."
    @post.special = false
  # else
    # Branch 4
    # Not branching also has to be tested
  end

  if (@user.recently_created?)
    # Branch 5
    @post.newbie = true
  # else
    # Branch 6
  end

  # Branch 7
end

unless (flash[:error])
  @post.save!
end

Although this is pretty straightforward, creating the circumstances that will cause the logic to flow through the correct branches is not. You will probably have to write a test case for each specific one. This is not always trivial, but you can make it easier if you have a number of prepared fixtures or factory methods that construct things nearly ready to go.

Without testing each of these individual cases using automatic tests the chance of a malfunction due to an inadvertent change is significant. To ensure that it's working you will have to manually run through these paths, and it's often that you'll forget one and later this will cause trouble, probably the embarrassing variety.

The way to do less testing is to have lower code complexity by eliminating business logic that doesn't add business value, for instance. Keep only the most imperative things, discard anything superfluous.

If you're writing a thousand different tests for something that should be simple, maybe it's not simple enough in terms of design.

倒数 2024-09-17 20:02:48

看起来您最终编写的测试与实际代码一样多

这就是想法。

It seems that you end up writing as many tests as actual code

That is the idea.

伪装你 2024-09-17 20:02:48

TDD 背后的想法是拥有一组始终需要运行的测试,即使是设置标题也是如此。这样你就不会在推动某些东西生存并说“哦,标题不再存在了”。您有一组回归测试,这样当您越来越多地处理一个项目时,当您在几个月未受影响的项目返回时,您不会最终破坏项目。

此外,当我编写测试时,它迫使我真正思考问题,而不是仅仅扔掉代码。我发现当我使用 TDD 或 BDD 时需要更少的重构。因为匆忙而坐下来写的代码最终变得草率。也许只有我一个人,我需要TDD来让我走在笔直的窄路上。

have a set of tests that always need to run even for setting the title is the idea behind TDD. That way you never push something to live and say "doh, the title isn't there anymore". You have a set of regression tests so that as you work on a project more and more, you don't end up breaking things down the road when you come back to a project after it has been untouched for a few months.

Additionally, when I write tests, it forces me to really think about the problem instead of just throwing code out there. I find that I need to refactor less when I am using TDD or BDD. The code that I just sit down and write because I am in a hurry ends up being sloppy. Perhaps it is just me, I need TDD to keep me on the straight and narrow road.

小清晰的声音 2024-09-17 20:02:48

在我的团队中,我们为除 UI 之外的所有内容编写单元测试。
有一些工具可以帮助测试 UI,但我们认为 UI(如标题)过于动态而无法测试。

这就是为什么在为 Web 编码时,很多人更喜欢 MVC 设计模式,它在 ui 和后台代码之间创建了很大的分离,因此它允许您通过单元测试覆盖几乎所有代码。

是的,我们编写了大量的单元测试!这是了解您的代码是否真正有效的唯一真正方法!

In my team, we wrote unit tests for everything but UI.
There are some tools that can help testing UI, but we believe that the UI (like title) is too dynamic to test.

That's why when coding for the web, alot of people prefer the MVC design pattern, it creates a big seperation between ui and code behind, so it allows you to cover almost all of your code with unit tests.

And YES, We write a whole lot of unit tests!! It's the only REAL way to know your code really works!

执手闯天涯 2024-09-17 20:02:48

在项目的设计周期期间,TDD 迫使您在编写任何代码之前考虑应用程序的代码接口。反过来,这迫使您思考要解决的实际问题,而不是仅仅编写一些代码,如 杰夫·拉诺特提到

此外,由于单元测试集中于单个单元,因此您还可能编写集中且可重用的类,而不是紧密耦合的类。

开发周期中,您只需编写使单元测试通过所需的代码。您不必再担心设计细节,可以专注于实际实现。

在产品的生命周期期间,维护工作更容易,因为您的测试套件会快速告诉您代码的更改是否破坏了任何内容。

During the design cycle of a project, TDD forces you to think about your application's code interface before writing any code at all. This, in turn, forces you to think about the actual problem you're trying to solve, instead of just writing some code, as Geoff Lanotte mentioned.

Also, because unit tests are focused on a single unit, you're also likely to write classes that are focused and reusable, instead of classes that are coupled tightly.

During the development cycle, you only have to write the code that's necessary to make the unit tests pass. You don't have to worry much about design details anymore, allowing you to focus on the actual implementation.

During the life cycle of the product, it's easier to do maintenance work, because your test suite will quickly tell you if changes in the code have broken anything.

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