unit testing是否可以成功添加到现有的生产项目中? 如果是这样,那么值得吗?

我正在强烈考虑将unit testing添加到正在生产的现有项目中。 它是在18个月前开始的,然后才真正看到了TDD (面掌)的好处,所以现在这是一个相当大的解决scheme,有很多项目,我还没有从哪里开始添加unit testing。 是什么让我觉得这是偶尔一个旧的bug似乎重新出现,或者一个错误被固定在没有被固定的情况下检查。 unit testing会减less或防止这些问题发生。

通过阅读类似的问题,我看到了一些build议,比如从bug跟踪器开始,为每个bug编写一个testing用例,以防止回归。 但是,我担心我最终会错过大局,最终会丢失如果我从头开始使用TDD就会包含的基本testing。

是否有任何程序/步骤应该遵循,以确保现有的解决scheme是适当的unit testing,而不是只是入住? 我怎样才能确保testing的质量好,而不是任何testing的情况比没有testing好

所以我想我也问的是,

  • 生产中现有的解决scheme值得付出吗?
  • 最好忽略这个项目的testing,并将其添加到未来可能的重写中?
  • 什么会更有益; 花费几个星期来增加testing或者几个星期增加function?

(显然第三点的答案完全取决于你是否正在与pipe理层或开发人员交谈)


赏金的原因

添加一个赏金,试图吸引更广泛的答案,不仅证实我现有的怀疑,这是一件好事,但也有一些很好的理由反对。

我打算稍后写下这个问题,以利弊告诉pipe理层,花时间把产品的未来发展转移到TDD上是值得的。 我想要接近这个挑战,并发展我的推理,而不是我自己的偏见。

我已经引入了unit testing来编写以前没有的基础代码。 我参与的最后一个大项目是,当我到达团队时,产品已经投入生产,零unit testing。 当我离开时 – 两年后 – 我们有超过4500个左右的代码testing产生了大约33%的代码覆盖率,代码基数为23万+生产LOC(实时金融Win-Forms应用程序)。 这可能听起来很低,但结果是代码质量和缺陷率显着提高 – 加上士气和盈利能力的提高。

当你有相关各方的准确理解和承诺时,就可以做到这一点。

首先,了解unit testing本身就是一项技能是很重要的。 你可以通过“传统”的标准成为一个高效率的程序员,而且仍然很难在大型项目中编写unit testing。

此外,特别是针对您的情况,将unit testing添加到没有testing的现有代码库本身也是一项专业技能。 除非你或者你的团队中的某个人有成功的经验,将unit testing引入现有的代码库,否则我会说阅读Feather的书是一个需求(不是可选或强烈推荐)。

将代码转换为unit testing是对人员和技能的投资,正如代码库的质量一样。 理解这一点在思维和pipe理期望方面非常重要。

现在,您的意见和问题:

但是,我担心我最终会错过大局,最终会丢失如果我从头开始使用TDD就会包含的基本testing。

简短的回答:是的,你会错过testing,是的,他们可能最初看起来像他们将在绿色领域的情况下。

更深层次的答案是这样的:没关系。 你从没有testing开始。 开始添加testing,然后重构。 随着技能水平的提高,开始提高添加到项目中的所有新编写的代码。 继续改进等…

现在,在这两行之间的阅读中,我觉得这是来自“完美是不采取行动的借口”的思想。 更好的思想是关注自我信任。 所以,你可能还不知道如何去做,你会想出如何去填补空白。 所以没有理由担心。

再次,它的一个技能。 你不能从一个“过程”或“一步一步”的烹饪书方式以线性的方式从零testing到TDD完美。 这将是一个过程。 您的期望必须是逐步和渐进的进步和改进。 没有魔法药丸。

好消息是,随着月份(甚至数年)的过去,你的代码将逐渐成为“适当”的,充分考虑和经过良好testing的代码。

作为一个方面说明。 你会发现,在旧的代码库中引入unit testing的主要障碍是缺乏内聚性和过度的依赖性。 因此,您可能会发现最重要的技能将会变成如何打破现有的依赖和解耦代码,而不是自己编写实际的unit testing。

是否有任何程序/步骤应该遵循,以确保现有的解决scheme是适当的unit testing,而不是只是入住?

除非你已经拥有它,否则build立一个构build服务器并build立一个持续的集成构build,在每次login时运行,包括所有带代码覆盖的unit testing。

训练你的员工

从客户的angular度出发,从某处开始并开始添加testing(见下文)。

使用代码覆盖率作为您的生产代码库的多lesstesting的指导性参考。

构build时间应该始终是快速的。 如果你的编译时间很慢,你的unit testing技能就落后了。 find慢testing并改进它们(分离生产代码并单独testing)。 写得很好,你应该能够有几千个unit testing,并在10分钟内完成一个构build(大约1毫秒/testing是一个很好,但非常粗略的指导方针,一些例外可能适用于代码使用reflection等)。

检查和适应。

我怎样才能确保testing的质量好,而不是任何testing的情况比没有testing好。

你自己的判断一定是你现实的主要来源。 没有可以取代技巧的指标。

如果你没有这种经验或判断,请考虑与谁合作。

两个粗略的二级指标是代码覆盖率和构build速度。

生产中现有的解决scheme值得付出吗?

是。 花费在定制系统或解决scheme上的绝大部分资金是在投入生产之后花费的。 投资于质量,人才和技能绝不应该过时。

最好忽略这个项目的testing,并将其添加到未来可能的重写中?

你不仅要考虑对人员和技能的投资,而且还要考虑到总体拥有成本和系统的预期使用寿命。

在大多数情况下,我个人的答案是“当然可以”,因为我知道它好得多,但我承认可能有例外。

什么会更有益; 花费几个星期来增加testing或者几个星期增加function?

都不是。 您的方法应该是将testing添加到您的代码库,而在function方面取得进展。

同样,这是对人员,技能和代码质量的投资,因此需要时间。 团队成员需要学习如何打破依赖关系,编写unit testing,学习新的习惯,提高纪律和质量意识,如何更好地devise软件等。重要的是要明白,当你开始添加testing时,你的团队成员可能不会有这些技能,但他们需要为这个方法取得成功,所以停止进度花费所有的时间来添加大量的testing简直是行不通的。

另外,将unit testing添加到任何规模庞大的项目规模的现有代码库是一项需要承诺和坚持的大型项目。 你不能改变一些根本性的东西,期待大量的学习,并要求你的发起人不要期望任何投资回报,通过停止商业价值的stream动。 这不会飞,坦率地说不应该。

第三,你想在团队中灌输合理的业务重点。 质量永远不会以牺牲客户为代价,如果没有质量,就不能走得快。 而且,客户生活在一个不断变化的世界中,而你的工作就是让他更容易适应。 客户一致既要求质量又要有商业价值。

你正在做的是偿还技术债务。 而你这样做,同时仍然服务于客户不断变化的需求。 随着债务清偿,情况逐渐好转,更好地为客户服务,提供更多的价值。 等等这个积极的势头是你应该瞄准的,因为它强调了可持续的步伐的原则,并将保持和改善道德 – 无论是为您的开发团队,您的客户和利益相关者。

希望有所帮助

  • 生产中现有的解决scheme值得付出吗?

是!

  • 最好忽略这个项目的testing,并将其添加到未来可能的重写中?

没有!

  • 什么会更有益; 花费几个星期来增加testing或者几个星期增加function?

添加testing(特别是自动化testing)使项目在未来继续工作变得更加容易,并且使得向用户发送愚蠢问题的可能性大大降低。

先验testing是检查你是否相信你的代码的公共接口(和其中的每个模块)是否按照你的想法工作。 如果可以的话,还要尝试引导你的代码模块应该有的每个单独的失败模式(注意这可能是不平凡的,你应该小心不要太仔细地检查事情是如何失败的,例如,你不是真的想要做事情就像计算失败时产生的日志消息的数量,因为validation它是否已经被logging了就足够了)。

然后,对bug数据库中的每个当前错误进行testing,以确定错误并确定哪些错误会被修复。 然后修复这些错误! 🙂

增加testing花费的时间在前面,但是在后端你会得到很多回报,因为你的代码质量要高得多。 当您尝试发布新版本或执行维护时,这非常重要。

改造unit testing的问题是你会意识到你没有想到在这里注入一个依赖或者在那里使用一个接口,并且不久之后你将会重写整个组件。 如果你有时间做到这一点,你会build立一个很好的安全网,但你可以一路上引入微妙的错误。

我已经参与了许多真正需要从第一天开始进行unit testing的项目,并且没有简单的方法让它们在那里完成重写,这在代码工作并且已经赚钱的时候通常是不合理的。 最近我写了一些PowerShell脚本,这些脚本以一种重现缺陷的方式来执行代码,只要它们被提出,然后将这些脚本作为一套回归testing来进一步修改。 这样,您至less可以开始为应用程序构build一些testing,而不会对其进行太多的改变,但是,这些更像是端到端的回归testing,而不是正确的unit testing。

我同意大多数人所说的话。 添加testing到现有的代码是有价值的。 我绝不同意这一点,但我想补充一点。

尽pipe将testing添加到现有的代码是有价值的,但确实是有代价的。 这是以构build新function为代价的。 如何平衡这两件事情完全取决于这个项目,还有一些变数。

  • 需要多长时间才能把所有的代码进行testing? 天? 周? 月? 年份?
  • 你在写这个代码的人是谁? 支付客户? 一位教授? 一个开源项目?
  • 你的日程安排是怎样的? 你有严格的期限,你必须满足? 你有没有最后期限?

再次,让我强调,testing是有价值的,你应该努力把你的旧代码进行testing。 这实际上更多的是你如何处理它。 如果你能负担得起,把所有的旧代码都放在testing中,那就去做吧。 如果这是不现实的, 至less应该这样做

  • 你写的任何新代码应该完全在unit testing之下
  • 你碰巧碰到的任何旧代码(错误修复,扩展等)都应该放在unit testing中

而且,这不是一个全部或全部的命题。 如果你有一个四人组的队伍,你可以通过让一两个人承担传统的testing任务来满足你的期限,那就千方百计。

编辑:

我打算稍后写下这个问题,以利弊告诉pipe理层,花时间把产品的未来发展转移到TDD上是值得的。

这就像是问“使用源代码控制有什么优点和缺点? 或者“在招聘人员之前采访人员有什么优点和缺点?” 或者“呼吸有什么优点和缺点?”

有时候,争论只有一面。 您需要针对任何复杂的项目进行某种forms的自动化testing。 不,testing不写自己,是的,需要一些额外的时间才能把事情搞清楚。 但从长远来看,事后编写testing需要花费更多的时间和更多的钱来修复错误。 期。 这里的所有都是它的。

这绝对是值得的。 我们的应用程序具有复杂的交叉validation规则,最近我们不得不对业务规则进行重大更改。 我们结束了冲突,防止用户保存。 我意识到在应用程序中需要花费几分钟的时间才能解决问题。 我想引入自动化的unit testing,并安装了框架,但除了几个虚拟testing之外,我没有做任何事情来确保工作正常。 随着新的业务规则,我开始编写testing。 testing很快确定了造成冲突的条件,我们才弄清楚了规则。

如果您编写的testing涵盖您添加或修改的function,您将立即获益。 如果您等待重写,则可能永远不会进行自动testing。

你不应该花很多时间为已经存在的东西写testing。 大多数时候,你没有现有代码的规范,所以你testing的主要东西是你的逆向工程能力。 另一方面,如果您要修改某些内容,则需要使用testing来覆盖该function,以便您知道是否正确进行了更改。 当然,对于新function,编写失败的testing,然后实现缺失的function。

我会添加我的声音,并说是的,它总是有用的!

有一些区别,你应该记住,虽然:黑盒与白盒,单位与function。 由于定义有所不同,下面是我的意思:

  • 黑盒子 =没有特殊的实现知识的testing,通常是在边缘情况下进行testing,以确保事情的发生像一个天真的用户所期望的那样。
  • 白盒 = 实施知识书写的testing,这些testing通常会尝试着名的失败点。
  • unit testing =单个单元(function,可分离模块等)的testing。 例如:确保您的数组类正常工作,并且您的string比较函数可以为广泛的input返回预期的结果。
  • functiontesting =一次testing整个系统。 这些testing将同时运行一大块系统。 例如:init,打开一个连接,做一些现实世界的东西,closures,终止。 我喜欢在这些和unit testing之间作出区分,因为它们有不同的目的。

当我在游戏后期jointesting的时候,发现我从白盒functiontesting中得到最大的回报。 如果您知道代码的任何部分特别脆弱,请写白盒testing以涵盖问题案例,以确保不会以同样的方式重复两次。 同样,全系统functiontesting是一个有用的完整性检查,可以帮助您确保永远不会破坏最常见的10个用例。

小单元的黑盒和unit testing也很有用,但如果时间有限,最好早点添加。 在你发货的时候,你通常会发现(困难的方式)大多数的边缘情况和这些testing会发现的问题。

像其他人一样,我也会提醒你关于TDD的两件最重要的事情:

  1. 创buildtesting是一项持续的工作。 它永远不会停止。 您应该在每次编写新代码时尝试添加新的testing,或修改现有的代码。
  2. 你的testing套件从来没有错过! 不要让你的testing让你陷入虚假的安全感。 只是因为它通过testing套件并不意味着它正常工作,或者你没有引入微妙的性能回归等。

当我们开始添加testing时,就是在一个十岁左右的大约百万行的代码库中,在用户界面和报告代码中有太多的逻辑。

我们做的第一件事情(build立一个连续的构build服务器之后)是添加回归testing。 这些是端到端的testing。

  • 每个testing套件都将数据库初始化为已知状态。 我们实际上有几十个我们保留在Subversion中的回归数据集(在我们的代码中,因为它的规模很大,所以在我们的代码库中)。 每个testing的FixtureSetUp将其中一个回归数据集复制到一个临时数据库中,然后从那里运行。
  • testing夹具设置然后运行我们感兴趣的结果的一个过程(这一步是可选的 – 一些回归testing只存在testing报告)。
  • 然后,每个testing运行一个报告,将报告输出到.csv文件,并将该.csv的内容与保存的快照进行比较。 这些快照.csvs存储在每个回归数据集旁边的Subversion中。 如果报告输出与保存的快照不匹配,则testing失败。

回归testing的目的是告诉你是否有变化。 这意味着如果你破坏了某些东西,它们就会失败,但是如果你故意改变了某些东西(在这种情况下修复就是更新快照文件),它们也会失败。 您不知道快照文件是否正确 – 系统中可能存在错误(然后在修复这些错误时,回归testing将失败)。

不过,回归testing对我们来说是一个巨大的胜利。 我们的系统中的所有内容都有一个报告,所以通过花费几周的时间在报告中获得testing工具,我们就可以在我们的代码库中获得一定程度的覆盖。 编写相同的unit testing将花费数月或数年时间。 (unit testing会给我们更好的覆盖面,而且本来就不会那么脆弱,但是现在我宁愿有一些东西,而不是等待完美的时间。)

然后,我们回去开始添加unit testing,当我们修复错误,或增加了增强function,或需要了解一些代码。 回归testing绝不会消除unit testing的需要; 他们只是一个第一级的安全网,所以你很快就能获得一定程度的testing。 然后你可以开始重构来打破依赖关系,所以你可以添加unit testing; 回归testing给你一个信心,你的重构不会破坏任何东西。

回归testing有一些问题:它们很慢,而且有太多的原因可以打破。 但至less对我们来说,这是非常值得的。 他们在过去的五年中已经发现了无数的错误,他们在几个小时内就抓住了它们,而不是等待QA周期。 我们仍然有那些原始的回归testing,分布在七个不同的连续构build机器(与运行快速unit testing的机器分开),我们甚至不时添加它们,因为我们仍然有这么多的代码,我们的6000 +unit testing不包括在内。

是否值得向生产中的应用程序添加unit testing取决于维护应用程序的成本。 如果该应用程序有一些错误和改进请求,那么也许这是不值得的努力。 OTOH,如果应用程序是越野车或经常修改,那么unit testing将是非常有益的。

在这一点上,请记住我正在谈论的是有select地添加unit testing,而不是试图产生一套类似于从一开始就实践TDD的testing。 因此,针对第二个问题的后半部分:在下一个项目中使用TDD,无论是新项目还是重写(道歉,但这是另一本书的链接,你应该阅读: 以testing为导向的面向对象软件的发展 )

我对第三个问题的回答与第一个问题相同:取决于项目的背景。

embedded您的post是一个进一步的问题,确保任何改装testing正确完成。 重要的是要确保unit testing真的是单元testing,而这个(通常是不是)意味着加装testing需要重构现有的代码,以允许你的图层/组件解耦(比较dependency injection;控制反转;存根;嘲讽)。 如果你不能执行这个testing,那么你的testing就变成了集成testing,这是有用的,但是比真正的unit testing更有针对性和更脆弱。

你没有提到实现语言,但如果在Java中,那么你可以尝试这种方法:

  1. 在单独的源代码树build立回归或“烟雾”testing,使用一个工具来生成它们,这可能会让你接近80%的覆盖率。 这些testing执行所有的代码逻辑path,并从这一点来validation代码仍然完成它目前的工作(即使存在错误)。 这为您提供了一个安全网,在进行必要的重构时,可以防止无意中更改行为,从而使代码易于手动进行unit testing。

  2. 对于您修复的每个错误或从现在开始添加的function,请使用TDD方法确保新代码被devise为可testing的,并将这些testing放置在正常的testing源树中。

  3. 现有的代码也可能需要改变,或重构,使其可以作为添加新function的一部分进行testing; 您的烟雾testing将为您提供一个安全网,以防止回归或对行为无意的微妙变化。

  4. 通过TDD进行更改(缺陷修复或function)时,完成后可能伴随烟雾testing失败。 由于所做的更改,请validation故障是否如预期的那样,并删除难以读取的烟雾testing,因为您的手写unit testing已全面覆盖该改进的组件。 确保你的testing覆盖率不下降只保持不变或增加。

  5. 修复错误时,请编写一个失败的unit testing,首先显示错误。

我想开始这个答案,说unit testing是非常重要的,因为它可以帮助你在错误投入生产之前捕捉错误。

确定重新引入错误的领域项目/模块。 从那些项目开始写testing。 编写新functiontesting和错误修复是完全有意义的。

生产中现有的解决scheme值得付出吗?

是。 你会看到错误的影响和维护变得更容易

最好忽略这个项目的testing,并将其添加到未来可能的重写中?

我会build议如果从现在开始。

什么会更有益; 花费几个星期来增加testing或者几个星期增加function?

你问的是错误的问题。 当然,function比其他任何东西都重要。 但是,你应该问一下,花几个星期来增加testing会让我的系统更加稳定。 这会帮助我的最终用户吗? 它是否会帮助团队中的新开发人员了解项目,并确保他/她不会因为对变更的整体影响缺乏了解而引入错误。

我非常喜欢重构低垂的果实,作为从哪里开始重构的问题的答案。 这是一种让你的devise变得更好的方法,而不会让你咬牙切齿。

我认为同样的逻辑适用于TDD – 或者只是unit testing:写你需要的testing,因为你需要它们; 为新代码编写testing; 编写testing错误,因为它们出现。 你担心忽略代码库难以触及的领域,这当然是一个风险,但作为一种开始的方式:开始吧! 你可以通过代码覆盖工具来减轻风险,而且风险不是(在我看来)这么大:无论如何,如果你覆盖了这些bug,覆盖了新的代码,覆盖了你正在查看的代码,那么你就覆盖了最需要testing的代码。

  • 是的。 当你开始添加新的function时,它可能会导致一些旧的代码修改,因此它是潜在错误的来源。
  • (见第一个)在开始添加新function之前,所有(或几乎)代码(理想情况下)应该由unit testing覆盖。
  • (见第一和第二):)。 一个新的macros伟的function可以“破坏”旧的工作代码。

是的,它可以:只是试图确保你现在写的所有代码都有一个testing。

如果已经存在的代码需要修改并且可以被testing,那就这样做,但是最好不要过于强烈地试图获得稳定代码的testing。 这种事情往往会产生连锁反应,并可能失去控制。

生产中现有的解决scheme值得付出吗?

是。 但是你不必编写所有的unit testing来开始。 只需将它们逐个添加即可。

最好忽略这个项目的testing,并将其添加到未来可能的重写中?

不,第一次添加破坏function的代码,您会后悔的。

什么会更有益; 花费几个星期来增加testing或者几个星期增加function?

对于新function(代码),这很简单。 你先写unit testing,然后再写function。 对于你在路上决定的旧代码。 你不需要进行所有的unit testing……添加那些最让你不受伤害的unit testing……时间(和错误)会告诉你需要关注哪一个;)

更新

原来的答案6年后,我略有不同。

我认为将unit testing添加到您编写的所有新代码是有意义的 – 然后重构您进行更改以使其可testing的位置。

一次性编写testing代替所有现有的代码将无济于事 – 但是不要为您编写的新代码(或者您修改的区域)编写testing也没有意义。 在重构/添加东西时添加testing可能是添加testing并使代码在现有项目中更容易维护而不进行testing的最佳方式。

较早的答案

我要在这里提出几个眉毛:)

首先,你的项目是什么 – 如果它是一个编译器,一种语言或者一个框架,或者其他任何不会在很长一段时间内发生function变化的东西,那么我觉得joinunit testing是非常棒的。

但是,如果您正在开发一个可能需要更改function的应用程序(因为需求发生变化),那么无需花费额外的工作量。

为什么?

  1. unit testing只涵盖了代码testing – 代码是否按照devise目标进行testing – 它不是替代手动testing(要发现function性错误,可用性问题和所有其他types的问题)

  2. unit testing花费时间! 现在我来自哪里,这是一个宝贵的商品 – 业务通常在一个完整的testing套件中select更好的function。

  3. 如果你的应用程序对用户来说甚至是远程有用的,他们将要求更改 – 所以你将会有更好,更快,可能会做新事物的版本 – 随着代码的增长,可能还会有很多重构。 在dynamic环境中维护一个完整的unit testing套件是一件令人头疼的事情。

  4. unit testing不会影响您的产品的感知质量 – 用户所看到的质量。 当然,你的方法可能和第一天的方法一样,表示层和业务层之间的接口可能是原始的,但猜猜是什么? 用户不关心! 得到一些真正的testing者来testing你的应用程序。 多数情况下,这些方法和接口迟早都要改变。

什么会更有益; 花费几个星期来增加testing或者几个星期增加function? – 有很多东西可以比编写testing做得更好 – 编写新的function,提高性能,改进可用性,编写更好的帮助手册,解决未完成的错误等。

现在,不要误解我的意思 – 如果你绝对肯定未来100年的事情不会改变的话,那就先敲门,然后写下那些testing。 自动化testing对于API来说也是一个好主意,你绝对不想破坏第三方代码。 其他地方,只是让我稍后运送的东西!

你不太可能拥有重要的testing覆盖率,所以你必须对添加testing的位置进行策略:

  • 正如你所提到的那样,当你发现一个bug的时候,现在是编写一个testing(重现它)的好时机,然后修复这个bug。 如果你看到testing重现错误,你可以确定这是一个很好的testing。 鉴于如此大量的错误是回归(50%?),写回归testing几乎总是值得的。
  • 当你进入一个代码区域来修改它时,现在是编写testing的好时机。 根据代码的性质,不同的testing是适当的。 这里有一个很好的build议。

OTOH,不值得仅仅围绕着编写人们喜欢的代码编写testing – 特别是如果没有人会修改代码的话。 它只是没有增加价值(除了可能理解系统的行为)。

祝你好运!

你说你不想买另一本书。 所以,只要阅读Michael Feather关于与遗留代码有效合作的文章即可。 然后买书:)

如果我在你的位置上,我可能会采取一种外在的方法,从functiontesting开始,这个testing可以运行整个系统。 我会尝试使用像RSpec这样的BDD规范语言来重新logging系统的需求,然后通过自动化用户界面编写testing来validation这些需求。

然后,我会为新发现的错误进行缺陷驱动开发,编写unit testing来重现问题,并在错误通过之前处理错误。

对于新的function,我会坚持外在的方法:从RSpec中logging的function开始,并通过自动化用户界面进行validation(当然最初会失败),然后在执行过程中添加更细粒度的unit testing。

我不是这个过程的专家,但是从我所拥有的经验来看,我可以告诉你,BDD通过自动UItesting并不容易,但是我认为这是值得的,而且可能在你的情况下产生最大的收益。

我不是一个经验丰富的TDD专家,但是我当然可以说,尽可能多地进行unit testing是非常重要的。 由于代码已经到位,所以我将开始进行某种unit testing自动化。 我使用TeamCity来执行我的项目中的所有testing,并给出了组件如何完成的一个很好的总结。

随着这一点,我会转向那些真正关键的业务逻辑类似的组件,不能失败。 在我的情况下,有一些基本的三angular问题需要解决各种投入,所以我testing了这些。 我这样做的原因是,当我燃烧午夜油时,很容易浪费时间挖掘真正不需要触摸的代码深度,因为您知道它们已经过所有可能的input(在我的情况下,input数量是有限的)。

好的,所以现在你希望对那些关键的部分感觉更好。 我没有坐下来把所有的testing都敲下来,而是在他们出现的时候就去攻击他们。 如果你遇到了一个真正的PITA修复的bug,那就写下unit testing,然后把它们排除在外。

有些情况下,你会发现testing是困难的,因为你不能从testing中实例化一个特定的类,所以你必须嘲笑它​​。 哦,但也许你不能轻易地嘲笑它,因为你没有写入界面。 我把这些“哎呀”情景作为实现上述界面的机会,因为,这是一件好事。

从那里,我会得到你的构build服务器或任何你已经configuration了代码覆盖工具的自动化。 他们创build带有红色区域的令人讨厌的条形图,其中覆盖率较差。 现在,100%的覆盖率并不是你的目标,100%的覆盖率也不一定意味着你的代码是防弹的,但是当我有空时,红色的栏杆肯定会激励我。 🙂

有这么多好的答案,所以我不会重复他们的内容。 我检查了你的个人资料,看来你是C#.NET开发者。 正因为如此,我添加了对Microsoft PEX和Moles项目的引用,可以帮助您为遗留代码自动生成unit testing。 我知道自动发电不是最好的方式,但至less它是开始的方式。 从MSDN杂志上查看这篇非常有趣的文章,了解如何使用PEX作为遗留代码 。

这取决于…
有unit testing是很好的,但你需要考虑你的用户是谁,他们愿意忍受什么以获得更多的无bug产品。 不可避免地通过重构目前没有unit testing的代码,你会引入错误,许多用户会发现很难理解你是否使产品暂时更有缺陷,从而使其长期受到损害。 最终是用户谁将有最后的发言权…

我build议TopTal工程师阅读一篇精彩的文章 ,解释从哪里开始添加testing:它包含了很多math,但基本思想是:

1)测量你的代码的传入耦合(CA) (其他类使用了多less类,这意味着打破它会造成广泛的损害)

2)测量你的代码的循环复杂度(CC) (更高的复杂度=更高的中断变化)

您需要识别具有高CA和CC的类别,即具有函数f(CA,CC),并且两个度量之间具有最小差异的类别应该被赋予testing覆盖的最高优先级。

为什么? 因为高CA但非常低的CC类非常重要,但不太可能中断。 另一方面,低CA但高CC可能会破坏,但会造成较小的损害。 所以你想要平衡。

是。 不,添加testing。

走向更多的TDD方法实际上会更好地告诉你增加新function的努力,并使回归testing更容易。 一探究竟!