在测试版/原型设计期间进行单元测试是一个坏主意吗?

发布于 2024-08-01 16:27:32 字数 629 浏览 5 评论 0原文

我们开始的一个新项目引入了很多我们不太熟悉的新技术,以及我们没有太多实践的架构。换句话说,我们的服务类之间的接口和交互等重建工作相当不稳定,由于内部和客户的反馈,情况更是如此。 尽管我一直对不断变化的规范感到沮丧,但我认为这在某种程度上是构建我们以前从未构建过的东西的必要部分 - 如果我们坚持最初的设计和范围,最终产品可能会是其创新性和实用性远不如现在。

我还介绍了测试驱动开发 (TDD),因为它的好处有详细记录,而且从概念上讲我喜欢这个想法。 还有两个新东西需要学习 - NUnit 和模拟 - 但看到所有这些绿色圆圈让这一切都是值得的。

然而,随着时间的推移,设计中的这些不断变化似乎意味着我花在更改测试上的时间比编写代码本身要多得多。 仅出于这个原因,我就回到了旧的测试方法 - 即非自动化的测试方法。

虽然我毫不怀疑通过数百个优秀的单元测试该应用程序会更加健壮,但我发现启动该产品的时间的权衡基本上是不可接受的。 那么我的问题是 - 你们中是否有人也发现,如果您正在制作某些东西的原型/构建测试版本,TDD 可能会很麻烦? TDD 是否会更自然地与规范更固定的东西或开发人员在语言和技术方面拥有更多经验的东西结合起来? 或者我做错了什么根本性的事情?

请注意,我并不是想在这里批评 TDD - 只是我不确定它总是最适合所有情况。

A new project we began introduced a lot of new technologies we weren't so familiar with, and an architecture that we don't have a lot of practice in. In other words, the interfaces and interactions between service classes etc of what we're building are fairly volatile, even more so due to internal and customer feedback. Though I've always been frustrated by the ever-moving specification, I see this to some degree a necessary part of building something we've never built before - if we just stuck to the original design and scope, the end product would probably be a whole lot less innovative and useful than it's becoming.

I also introduced test-driven development (TDD), as the benefits are well-documented and conceptually I loved the idea. Two more new things to learn - NUnit and mocking - but seeing all those green circles made it all worthwhile.

Over time, however, those constant changes in design seemed to mean I was spending a whole lot more time changing my tests than I was on writing the code itself. For this reason alone, I've gone back to the old ways of testing - that is, not automated.

While I have no doubt that the application would be far more robust with hundreds of excellent unit tests, I've found the trade-off of time to launch the product to be mostly unacceptable. My question is, then - have any of you also found that TDD can be a hassle if you're prototyping something / building a beta version? Does TDD go much more naturally hand-in-hand with something where the specifications are more fixed, or where the developers have more experience in the language and technologies? Or have I done something fundamentally wrong?

Note that I'm not trying to criticise TDD here - just I'm not sure it's always the best fit for all situations.

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

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

发布评论

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

评论(15

世俗缘 2024-08-08 16:27:33

我发现,早期彻底测试会导致大量代码被丢弃,并且让你感到胃里空空的。

测试需要测试的内容而不是多一行代码。 当你弄清楚那是多少钱时,请告诉我。

I've found that thoroughly testing early results in lots of code thrown away and an empty feeling in the pit of your stomach.

Test what needs to be tested and not a line of code more. When you figure out how much that is, let me know.

回忆凄美了谁 2024-08-08 16:27:33

在进行原型设计时,我想说这取决于原型设计的类型。 在演化原型设计中,原型演变成最终应用程序,我会尽早利用单元测试。 如果您使用一次性原型设计,我不会费心进行单元测试 - 最终的应用程序将与原型完全不同。

我不确定你所说的“测试版”是什么意思,因为测试版几乎是成品。 一旦您开始处理将要发布或有可能发布的代码,请确保所有内容都经过良好的测试。

现在,纯粹的测试驱动开发可能有些极端,但重要的是要确保所有可交付的代码在单元、集成和系统级别都经过尽可能的测试。

When prototyping, I would say it depends on the type of prototyping. In evolutionary prototyping, where the prototype evolves into the final application, I would utilize unit testing as early as possible. If you are using throw-away prototyping, I wouldn't bother with unit testing - the final application is going to be nothing like the prototype.

I'm not sure what you mean by "beta", since a beta is almost a finished product. As soon as you start working on code that is going to be shipped, or has a potential to be shipped, make sure everything is well tested.

Now, pure test-driven development might be extreme, but it is important to make sure that all shippable code is as tested as possible, at the unit, integration, and system level.

薄荷港 2024-08-08 16:27:33
  • 给出一个带有移动 X 的路线图是令人沮丧的。
    TDD 或没有 TDD..“必须花费大部分时间更改测试而不是代码”表明规范已发生根本性更改,或者您只是过度嘲笑自己,即“脆弱测试”。 我需要您提供更多意见才能进一步发表评论。
  • Spike/原型制作意味着尝试构建一些东西作为概念证明或验证设计。 有了这个定义,我想说你不需要 TDD 你的原型,因为你的主要目标是学习/减少未知数。 完成此操作后,您应该丢弃原型并通过自动化测试构建生产版本(现在使用 TDD)。 您将这些未经过“测试的原型”发送给客户。
  • 但是,如果手动测试对您来说效果很好,请坚持下去。 我喜欢向自己和其他人证明我的代码只需按一下按钮即可工作 - 避免人类对重复任务的厌倦并进行彻底的测试。

交付原型会比你想象的更早、更严重地咬你一口。 从我这里拿走它。

  • Being given a roadmap with a moving X is frustrating.
    TDD or no TDD.. 'having to spend majority of the time changing the tests instead of the code' indicates either that the specs were changed radically or you just over-mocked yourself a.k.a "fragile tests". I'd need more input from you to comment further.
  • Spike/Prototyping means trying to build something as a proof of concept or validation a design. With this definition, I'd say that you don't need to TDD your proto because your primary goal is learning / reducing the unknowns. Once you've done that you should throw away your proto and build your production version with automated tests (use TDD now). You ship these to the customer not 'tested prototypes'
  • However if manual testing has been working well for you, persist with it. I like to prove to myself and others that my code works at the push of a button - avoid human boredom of repetitive tasks and get thorough testing.

Shipping Prototypes will bite you sooner and harder than you ever imagine. Take it from me.

悍妇囚夫 2024-08-08 16:27:33

你们中是否有人也发现,如果您正在制作某些东西的原型/构建测试版本,TDD 可能会很麻烦?

我有..很多次:)

TDD 是否会更自然地与规范更固定的东西或开发人员在语言和技术方面拥有更多经验的东西结合起来?

并不真地。 TDD 可以很好地适应不断变化的需求,但 TDD 实际上是为了确保稳定且契约驱动的设计:原型实际上并不急需的两件事。

或者我做错了什么根本性的事情吗?

看起来不像:) 您刚刚看到 TDD 除了金树之外还包含其他东西。

have any of you also found that TDD can be a hassle if you're prototyping something / building a beta version?

I have.. Tons of times :)

Does TDD go much more naturally hand-in-hand with something where the specifications are more fixed, or where the developers have more experience in the language and technologies?

Not really. TDD works quite nice with changing requirements, but TDD is really for ensuring a stable and contract-driven design: Two things which prototypes doesn't really need that badly..

Or have I done something fundamentally wrong?

Doesn't look like it :) You've just seen that TDD consists of other things than golden trees..

放血 2024-08-08 16:27:33

“然而,随着时间的推移,这些设计上的不断变化似乎意味着我花在改变测试上的时间比编写代码本身要多得多”

很好。 您应该花费大量时间进行测试。 这很重要,它是你证明你的代码是正确的方式。 “代码少于测试”是一个很好的基准。

这意味着您正在编写有效的测试来证明您对底层技术的期望。

您可能需要考虑这样做。

  1. 某些测试是应用程序的“基本”或“核心”或“持久”功能,与任何技术选择无关。 重点关注这些。 永远不应该改变。

  2. 一些测试确认了技术或实施选择。 这些一直在变化。 也许您应该将这些分开,以便技术变化导致此处的集中变化。

"Over time, however, those constant changes in design seemed to mean I was spending a whole lot more time changing my tests than I was on writing the code itself"

Good. You should spend a lot of time on testing. It's important, and it's how you demonstrate that your code is right. "Less code than test" is a good benchmark.

That means that you were writing effective tests that demonstrated your expectations for the underlying technology.

You may want to consider doing this.

  1. Some tests are "essential" or "core" or "enduring" features of the application independent of any technology choices. Focus on these. The should never change.

  2. Some tests confirm the technology or implementation choices. These change all the time. Perhaps you should segregate these so that the technology changes lead to focused changes here.

迷荒 2024-08-08 16:27:33

在敏捷开发中,有一个“尖峰”的概念——对解决方案或技术进行深入但狭隘的研究。 一旦您对事情的工作方式感到满意,您就可以重新开始具有更高质量水平的新实施。

标记为“测试版”的软件存在一个陷阱 - 突然之间,您最终会得到一些不适合生产的东西作为应用程序的重要组成部分,并且您没有时间重做它。 这很可能会在稍后回来咬你。 原型实际上应该只是原型——不多也不少。

In agile development there's the concept of a "spike" - a deep but narrow investigation of a solution or a technology. Once you're comfortable with how things should work you start over with a new implementation with a higher quailty level.

There's a pitfall with software labeled as "beta" - all of the sudden you end up with something not intended for production as a vital part of your application and you haven't got the time to redo it. This will most likely come back and bite you later on. A protoype should really be just a prototype - no more, no less.

不知在何时 2024-08-08 16:27:33

原型设计旨在用于“这种事情行得通吗”——探索。
所以不需要测试。 但是! 永远扔掉你的原型并从零开始编码!

Prototyping is meant to be the used for "Would this kind of thing work"-exploration.
So there is no need for Testing. BUT! Always throw your Prototype away and code from ground zero!

转瞬即逝 2024-08-08 16:27:33

我没有给你开药方,但我确实有一个诊断:

  • 如果你最终进入调试器,你应该进行更多测试。 即使在最早的原型中,您也希望编写的代码能够工作,对吧? 如果我不进行 TDD,并且遇到错误,则很难改进单​​元测试来查找错误。 去调试器是很诱人的。 因此,我的 TDD 工作目标是生成一组足够好的测试,这样我就不需要调试器了。 做好这件事需要大量的练习。

  • 如果您想重构但由于风险而不想重构,那么您应该进行更多测试。 如果我要处理某些代码超过几个小时,我想进行重构以保持较高的速度。 如果我对重构犹豫不决,就会降低我的工作效率,所以我会尽一切努力使重构安全、简单。 再次强调,良好的测试选择正是我所需要的。

I don't have a prescription for you, but I do have a diagnosis:

  • if you ever end up in a debugger, you shoulda had more tests. Even in the very earliest prototypes, you want the code you write to work, right? If I don't do TDD, and I run in to a bug, it's hard to retrofit unit tests to find the bug. It's tempting to go to the debugger. So, I aim my TDD efforts to produce a good enough set of tests so that I don't need the debugger. Doing this well requires lots of practice.

  • If you want to refactor but don't because of risk, you shoulda had more tests. If I'm going to be working with some code for more than a couple hours, I want to refactor to keep my velocity high. If I hesitate to refactor, it's gonna hurt my productivity, so I do everything I can to make refactoring safe and easy. Again, a good selection of tests is exactly what I need.

小ぇ时光︴ 2024-08-08 16:27:33

正如人们所说,对于纯粹的原型设计来说,没有那么有用。 但原型通常包含随后的应用程序元素。

在构建它时,您希望继续采用哪些可靠的概念? 关键领域模型是什么?围绕这些模型构建测试是有意义的。 然后,它们为探索想法提供了坚实的基础。 通过对部分代码库进行可靠和测试,它可以让您比没有测试的情况下更进一步地使用原型。

选择正确的内容进行测试始终是一个平衡。 从你的描述来看,你似乎同时采用了相当多的新事物——有时这可能太多了,你需要稍微退一步来优化你的进度。

For pure prototyping, as people have said, not so useful. But often a prototype has elements of the application that will follow.

As you build it, what are the solid concepts that you expect to continue? What are the key domain models? It makes sense to build tests around these. Then, they provide a solid base on which to explore ideas. By having part of the code base solid and tested, it allows you to go further with the prototype than you could with no tests.

It's always a balance of picking the right things to test when. It sounds like from your description you are adopting quite a few new things at once-- sometimes this can be too much, and you need to retreat a little bit to optimize your progress.

赏烟花じ飞满天 2024-08-08 16:27:33

然而,随着时间的推移,设计中的这些不断变化似乎意味着我花在更改测试上的时间比编写代码本身要多得多。

我编写(并运行)系统 I/O 的自动化测试。 系统的I/O取决于功能需求,并且不会随着系统实现的变化而变化,因此我可以在不更改自动化测试的情况下重构实现:应该测试内部实施,还是只测试公共行为?

Over time, however, those constant changes in design seemed to mean I was spending a whole lot more time changing my tests than I was on writing the code itself.

I write (and run) automated tests of the system's I/O. The system's I/O depends on the functional requirements, and doesn't change when the system's implementation changes, so I can refactor the implementation without changing the automated tests: Should one test internal implementation, or only test public behaviour?

诺曦 2024-08-08 16:27:33

我通常对此原型代码所做的事情是在没有测试(或不多)的情况下编写它,但在我的 src/test/java 或我放置测试代码的任何地方进行工作。 这样,我就不会无意中将其投入生产。 如果我已经制作了一些我喜欢的原型,那么我将在 src/main/java (我的产品代码)中创建一些内容并对其进行 TDD,在添加测试时一次从原型中提取一段代码。

What I typically do for this prototyping code is to write it without tests (or not many), but do the work under my src/test/java or wherever I'm putting my test code. That way, I won't inadvertently put it into production. If there's something I've prototyped that I like, then I'll create something in src/main/java (my prod code) and TDD it, pulling over code from the prototype one piece at a time as I add tests.

兲鉂ぱ嘚淚 2024-08-08 16:27:33

在原型设计时,我会对放弃 TDD 持谨慎态度。 主要是因为原型往往(但并非总是)演变成最终产品。 如果你能确定原型一旦确定了它们的初衷,就会被扔掉,那么你就可以宽松一点。 然而,如果原型有可能演变成最终产品,或者部分代码将被移植到最终产品中,那么将努力遵循 TDD 原则。

这不仅使您的代码更具可测试性,而且更重要的是(在我看来)它鼓励您遵循良好的软件设计原则。

I would be cautious about dismissing TDD when prototyping. Primarily because prototypes tend to (but not always) evolve into the final product. If you can be sure that the prototypes are thrown out once they have established what ever it was they were started for, then you can be a bit more lax. If however it there is a chance that either the prototype will evolve into the final product, or parts of the code will be ported into the final product, then would endeavor to follow TDD principles.

Not only does this make your code more testable, but more importantly (in my mind) it encourages you to follow good software design principles.

滴情不沾 2024-08-08 16:27:33

如果它实际上是一个原型,并且您打算在完成后将其扔掉,那么请采取任何能让您度过该阶段的路线。 但是,问问你自己,你的原型实际上被扔掉的频率有多少,而它们渗透到你的最终产品中的频率又是多少?

有一个很好的演示< /a> 在 TDD 上的 JavaOne。 真正好的结果之一是,当您必须编写测试来满足实际需求时,您往往会更好地理解它们。 这是除了该方法带来的所有重构和代码质量优势之外的。

If it's actually a prototype and you are going to throw it away when you're done, then take whatever route gets you through that phase. But, ask yourself, how often do your prototypes actually get thrown away vs. how often do they creep into you're final product?

There was a good presentation at JavaOne on TDD. One of the really nice outcomes was that you tended to understand your actual requirements much, much better when you had to author tests to meet them. This is in addition to all of the refactoring and code quality benefits that came along with the approach.

薄荷梦 2024-08-08 16:27:33

当我接触一项新技术时,我通常会编写一些测试作为原型的基础。 这里的主要优点是,它让我能够习惯小而易理解的部分的技术,并且我可以用唯一有效的文档形式记录我的进展:代码。

这样,我可以测试假设(当我在数据库中保留空字符串时会发生什么?DB2 将返回空字符串,Oracle 将返回 NULL)并确保它们在我处理原型时不会更改。

可以将这项工作视为许多微小的原型,全部纳入几个单元测试中。

现在我的产品的设计会随着时间的推移而改变,但这些尖峰测试仍然有效:底层框架不会仅仅因为我现在追求不同的解决方案而改变。 事实上,这些测试将使我能够迁移到该技术的下一个版本,因为当我一直使用的假设之一发生变化时,它们会发出警报。 否则,我必须继续使用当前版本,或者对任何升级都非常小心,因为我无法确定它会破坏什么。

When I get in contact with a new technology, I usually write a couple of tests which I use as the basis of the prototype. The main advantage here is that it allows me to get used to the technology in small, digestible parts and that I document my progress in the only valid form of documentation: code.

That way, I can test assumptions (what happens when I persist an empty string in a database? DB2 will return an empty string, Oracle will return NULL) and make sure they don't change while I work on the prototype.

Think of this work as many, tiny prototypes all rolled into a couple of unit tests.

Now the design of my product will change over time but these spike tests are still valid: The underlying framework doesn't change just because I now pursue a different solution. In fact, these tests will allow me to migrate to the next version of the technology since they will ring an alarm when one of the assumptions I've been using has changed. Otherwise, I'd have to stay with the current version or be very careful with any upgrade since I couldn't be sure what it would break.

寄居者 2024-08-08 16:27:32

简而言之,TDD 对于测试版非常有价值,但对于原型设计来说可能就不那么有价值了。

我认为区分测试版和原型版非常重要。

beta 版本本质上是仍在开发中的生产版本,因此在这种情况下您绝对应该使用 TDD。

原型/概念验证是您构建的某种东西,其明确意图是一旦您从中得到了想要的答案就将其丢弃。

确实,项目经理会倾向于推动将原型用作生产代码的基础,但抵制这种做法非常重要。 如果您知道这是不可能的,请像对待生产代码一样对待原型代码,因为您知道它将在将来成为您的生产代码 - 这意味着您应该将 TDD 与它一起使用出色地。

当您学习新技术时,大多数代码示例等都没有考虑到单元测试,因此很难将新技术转化为单元测试思维。 绝对感觉有很多开销。

然而,根据我的经验,单元测试通常确实会迫使您突破正在学习的新技术的界限。 很多时候,您需要研究和学习新技术提供的所有不同的钩子,因为您需要能够通过 DI 等隔离技术。

单元测试不是只遵循老路,而是经常迫使您更深入地学习技术,因此可能感觉像是开销的东西实际上只是一个更深入的原型 - 一个通常更有价值的原型,因为它涵盖了更多的领域。

就我个人而言,我认为对新技术进行单元测试是一个很好的学习工具。

我认为,您似乎在测试可维护性方面遇到的症状有点正交。 您的测试可能过度指定,这在使用已知技术时也可能发生(但我认为当您使用已知技术时,可能更容易陷入这个陷阱同时也学习新技术)。

xUnit 测试模式一书描述了过度指定测试反模式,并提供了大量指导和帮助可以帮助您编写更易于维护的测试的模式。

The short answer is that TDD is very valuable for beta versions, but may be less so for prototyping.

I think it is very important to distinguish between beta versions and prototyping.

A beta version is essentially a production version that is just still in development, so you should definitely use TDD in that scenario.

A prototype/proof of concept is something you build with the express intent of throwing it away once you've gotten the answers out of it that you wanted.

It's true that project managers will tend to push for the prototype to be used as a basis for production code, but it is very important to resist that. If you know that's not possible, treat the prototype code as you would your production code, because you know it is going to become your production code in the future - and that means you should use TDD with it as well.

When you are learning a new technology, most code samples etc. are not written with unit tests in mind, so it can be difficult to translate the new technology to the unit testing mindset. It most definitely feels like a lot of overhead.

In my experience, however, unit testing often really forces you to push the boundaries of the new technology that you are learning. Very often, you need to research and learn all the different hooks the new technology provides, because you need to be able to isolate the technology via DI or the like.

Instead of only following the beaten path, unit testing frequently forces you to learn the technology in much more depth, so what may feel like overhead is actually just a more in-depth prototype - one that is often more valuable, because it covers more ground.

Personally, I think unit testing a new technology is a great learning tool.

The symptoms you seem to experience regarding test maintainability is a bit orthogonal, I think. Your tests may be Overspecified, which is something that can happen just as well when working with known technologies (but I think it is probably easier to fall into this trap when you are also learning a new technology at the same time).

The book xUnit Test Patterns describes the Overspecified Test antipattern and provides a lot of guidance and patterns that can help you write more maintainable tests.

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