如何解释单元测试的价值


30

我想向我的同事介绍单元测试(和一般测试)的概念;现在根本没有测试,通过UI实际执行任务以查看期望的结果来测试事物。就像您想象的那样,代码与确切的实现紧密耦合-甚至导致代码应该放在一个类中并在整个系统中重复使用,并且跨方法进行复制和粘贴。

由于需求的变化,我被要求修改我先前编写的模块,该模块相当松散地耦合在一起(虽然不尽如人意,但在无需引入许多其他概念的情况下,我可以做到最好)。我决定在修订后的代码中包含一套单元测试,以“证明”它可以按预期工作,并演示测试的工作方式。我没有遵循真正的TDD,因为已经编写了一些代码,但是我希望遵循一些TDD概念来创建新代码。

现在,我不可避免地会被问到,为什么要花我一两天以上的时间来编写代码,因为我要与之交互的部分已经存在于系统中(尽管没有任何测试并且非常紧密耦合),当我检查其中的代码时,系统将询问我这个“测试”项目是什么。我可以解释测试的基础知识,但是我无法以其他人会理解的方式解释实际好处(因为他们认为测试需要您自己运行应用程序,因为通常实际的UI在确定功能是否“有效”时很重要“ 或不)。他们不理解松散耦合的思想(显然没有松散耦合的事实;在我编写的代码之外甚至没有任何接口),因此尝试将其用作收益可能会给我带来“恩?” 外观,再也不必放松一些现有模块,并可能引入某种IoC容器,这就像浪费时间,而不是“编程”。

有人对我如何指向此代码有任何建议,并说“我们应该开始创建单元测试”而不会屈服于任何一个居高临下的条件(例如,“编写测试会迫使您编写良好的代码。”这可能意味着代码除非是我的坏人),还是没有浪费时间却没有增加任何实际价值?


1
这听起来像是我问“专家数据库专家”的时间,为什么信用卡信息是A.散列的?B.为什么电话号码字段是nvarchar(MAX)和C。为什么任何表之间都没有关系。他只是不明白。
松饼人

1
(这是一个讽刺的答案,这是个玩笑)->(A)如果数据库服务器出现故障,您将遇到更大的问题。(B)数据存储很便宜,如果要在一个字段中存储元数据该怎么办。(C)NoSQL宝贝;)(再次让我迭代我在开玩笑
2011年

关于伟大的单元测试的艺术,有一整章的内容。
StuperUser 2011年

6
@Wayne,每次我读到您的一个问题时,我深信您需要找到一份新工作。它们是软件开发中过时的遗物,而事实并非如此。如果打开一个窗口供您跳转,请勿回头。
maple_shaft

2
@WayneM,退出。说真的
AK_12年

Answers:


18

我想向我的同事介绍单元测试(和一般测试)的概念

我认为从实践而不是概念的角度出发可能会更好。当然,如果您在非正式讨论中发现您的同事和/或管理层有兴趣听有关单元测试的信息,那就更好了-然后您可以从网络上搜索一些具体的经验/证据,并进行简短的培训等。但是,从您的描述来看,听起来您的队友对这个奇怪的新想法并不十分开放。

在这种情况下,我将开始编写我的小型单元测试,而不必首先向任何人解释太多。每当我更改代码时,都添加几个,而不必尝试完全覆盖所有代码(这会花费过多时间)。理想情况下,如果我设法达到一个很好的平衡,那么当他们注意到我正在编写单元测试时,我可能已经有了一个强大的测试套件,并且需要显示一些具体的结果(例如“在这个测试用例中,我设法捕获了一个错误由上周的更改所引入,否则本应转至质量检查/生产”。对于任何认真的开发人员来说,这将证明测试的价值。

之后,我很容易开始解释单元测试的长期好处,例如

  • 它证明了代码可以随时随地,自动地,随时随地有效地运行,从而
  • 增强了重构的信心,从而改善了设计并提高了可维护性,
  • 如果有问题,单元测试会(几乎)为您提供即时反馈,而不是如果错误是由单独的质量检查部门捕获的,则需要几天或几周的延迟。这通常使您可以在几秒钟内修复该错误,而不用花费数小时/天的时间来调试该代码,因为该代码早已从短期内存中删除。

另请参阅以下相关主题:自动化单元测试,集成测试或验收测试

SO的更早版本:什么是单元测试?


4
+1为实用方面。我们在50多个开发人员中做到了这一点。店,它正在流行。每次我们再获得一个开发者。编写测试后,它们就迷上了。
ale

不好的部分是他正在编写测试,但是他的同事对此一无所知,并将更改生产代码中的某些内容,这将导致测试失败,从而取消他的所有努力:(
Igor Popov

您是先检查测试还是自己保留测试?我可以想像,如果我开始测试文件检查没有从我的老板的approvement审阅不会高兴
弗罗德Akselsen

12

无需恐惧即可重构

从一个稍微不同的角度来看,TDD允许您“重构而无所畏惧”,这是您可以出售团队的主要好处。它阻止开发人员对自己说:

  • “我不想触碰此代码,因为恐怕会破坏它”
  • “我不想在此代码的pof上编写新功能,因为我不知道它是如何工作的”
  • “很遗憾,我担心该代码”

我可以继续弹奏,但是这是很好的基础,例如TDD 上的Bob叔叔TDD上的Martin Fowler

依存关系

哦,我再添加一件事。它将向他们展示TDD如何推动良好的设计,使您能够干净地处理依赖关系。

鲍勃:“哦,c%^ p!老板们只是强迫我们所有人使用MS SQL Server 2008”简:“没关系,因为我们对数据源和DAO类进行了DI操作,所以损害最小化了,我很高兴TDD的鼓励我们沿着那条路走。”


4

在处理没有自动化测试的源代码时,我们必须格外小心,并且需要进行更多审查,以确保我们所做的此类更改不会破坏任何现有功能。

当我们拥有良好的自动化测试用例时,后果将是更快,更自信,更轻松的开发(可能是错误修复,增强或重构)。


4

算一算

  • t mt =手动测试可能会影响的所有内容所需的时间
  • t wt =编写测试所需的时间
  • k =在发布新代码之前您可能必须测试所有内容的次数

    如果是(t wt <t mt)或(t wt <(k * t mt)),那是理所当然的:编写测试将加快开发速度。

否则请查看比率(t wt /(k * t mt))。如果数量很大,请等待另一个机会。否则用回归测试的好处来证明。

注意:在这一点上,我建议仅测试功能,而不要测试单元 -易于证明和理解,并且重构时可以说比单纯的单元测试具有更高价值的工作更少。

注意2:运行测试的时间无关紧要,因为它们是自动化的。在测试运行期间,您可以做其他有成效的事情,除非测试需要很长时间才能使您错过截止日期。这是罕见的。


我给您+1,但是数学看起来很吓人!
韦恩·莫利纳

@Wayne这只是标,他们恐吓。但是编程不是为了娘娘腔!;-)
Steven A. Lowe

1

如果您是Microsoft商店,则有一个建议:在MSDN上找到一些文档,建议将单元测试或宽松的政绩作为最佳实践(我确信有多个实例),如果有冲突,请指向文档。

这听起来像是一种无聊的做事方式,但是我发现使用“最佳实践”一词将使您走很长一段路,尤其是在管理方面。


1

正如我一直建议的那样,如果您知道一个好的实践,最好将它轻轻地引入您的环境中的最佳方法是您自己开始做它,然后在此过程中的某个地方,您的一些同事会看到好处和捡起来。

这里的关键词是进化,而不是革命。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.