Max*_* A. 19 java tdd automated-tests unit-testing scala
我是一名高级工程师,在另外四人的团队中工作,他们使用自行开发的内容管理应用程序来驱动美国大型专业体育网站.大约两年前我们已经开始实施这个项目并选择Java作为我们的平台,尽管我的问题不是特定于Java的.自从我们开始以来,我们的队伍中出现了一些流失.尽管重要的决定是通过共识做出的,但我们每个人在决定实施细节方面都有很大的自由度.
我们是一个相对年轻的项目,但是当没有一个开发人员知道应用程序的所有内容时,我们已经到了这一点.其主要原因是我们快速的发展速度,其中大部分都发生在我们这项运动赛季揭幕战的紧张之中; 以及我们的测试覆盖率基本上为0的事实.
我们都理解TDD的理论上的好处,并且原则上同意如果我们多年来开始并坚持使用它,这种方法将改善我们的生活和代码质量.这从未成功,现在我们负责一个未经测试的代码库,这个代码库仍然需要大量扩展,并且在生产中被积极使用并且依赖于公司结构.
面对这种情况,我只看到两种可能的解决方案:(1)追溯性地为现有代码编写测试,或者(2)尽可能多地重写应用程序,同时狂热地遵守TDD原则.我认为(1)基本上不实用,因为我们在项目中有一个地狱般的依赖图.几乎没有一个组件可以单独测试; 我们不知道所有用例; 由于业务需求或对不可预见问题的反应,用例在测试过程中可能会发生变化.由于这些原因,我们无法确定我们的测试一旦完成就会变成高质量.有可能导致团队陷入虚假的安全感,微软的错误会在没有人注意的情况下蔓延.鉴于投资回报率的前景黯淡,我或我们的团队很难证明这种管理努力的合理性.
方法(2)更具吸引力,因为我们将遵循测试优先原则,从而产生几乎100%覆盖的代码.即使最初的努力最初导致覆盖码的岛屿,这将为我们提供在项目范围覆盖范围内的重要滩头阵地,并帮助解耦和隔离各种组件.
两种情况下的缺点是,我们团队的业务生产率可能会在任何测试推动期间显着减速或完全消失.我们无法承受在业务驱动的紧缩期间这样做,尽管它之后是相对平静的,我们可以为我们的目的利用.
除了选择正确的方法((1),(2)或其他未知解决方案之外),我需要帮助回答以下问题:我的团队如何确保我们的努力不会长期浪费通过无法维护的测试和/或在业务需求滚动时未能编写新的测试?我对此提出了广泛的建议,无论是胡萝卜还是胡萝卜.
无论如何,感谢阅读有关这种自我造成的困境.
S.L*_*ott 12
"这两种情况的不利之处在于,我们团队的业务生产率可能会在任何测试推动期间显着放缓或完全消失."
这是对事实的常见误解.现在你有了你不喜欢的代码并且难以维护."地狱依赖图"等
因此,您所做的"紧缩"发展导致了昂贵的返工.返工如此昂贵,你不敢尝试.这说明你的紧缩发展不是很有效.它在当时似乎很便宜,但回想起来,你注意到你真的在抛弃开发资金,因为你创造了有问题的,昂贵的软件,而不是创建好的软件.
TDD可以改变这一点,这样你就不会生产维护费用昂贵的紧缩软件.它无法解决所有问题,但它可以清楚地表明,将注意力从"紧缩"转移到可以产生更好的软件,从长远来看,这种软件成本更低.
根据您的描述,您当前的代码库中的一些(或全部)是负债,而不是资产.现在想想TDD(或任何学科)将做些什么来降低这种责任的成本.当您产生责任时,"生产力"问题不适用.
TDD的黄金法则:如果您停止创建负责的代码,该组织将获得积极的投资回报率.
小心问如何保持目前的生产节奏.一些"生产力"正在产生没有价值的成本.
"我们的组件几乎都不能单独测试;我们不知道所有的用例"
正确.对现有代码库进行改装单元测试非常困难.
"有可能导致团队陷入虚假的安全感,微软的错误会在没有人注意到的情况下蔓延开来"
假.没有"虚假的安全感".每个人都知道测试充其量只是充满希望.
此外,现在你有可怕的错误.你有这么糟糕的问题你甚至都不知道它们是什么,因为你没有测试覆盖率.
与无法测试的代码相比,交易一些微妙的错误仍然是一个巨大的进步.我会在任何一天对未知错误采取微妙的错误.
"方法(2)更具吸引力"
是.但.
您之前的测试工作被一种奖励紧缩程序的文化所颠覆.
有什么变化吗?我对此表示怀疑.您的文化仍然会奖励紧缩的节目.您的测试计划可能仍会被破坏.
你应该看看中间地带.你不能指望一夜之间"狂热地坚持TDD原则".这需要时间和重大的文化变革.
您需要做的是将应用程序分解成碎片.
例如,考虑模型 - 服务 - 视图层.
您拥有核心应用程序模型(持久性事物,核心类等),需要进行广泛,严格的可信赖测试.
您的应用程序服务需要进行一些测试,但受"由于业务需求或对不可预见的问题的反应而导致测试推送期间的用例可能会发生变化"的影响.尽可能多地进行测试,但不要违背下一季准时发货的必要性.
您有需要进行一些测试的视图/演示文稿,但不是核心处理.这只是演示.随着人们想要不同的选择,观点,报告,分析,RIA,GUI,浮华和嘶嘶声,它将不断变化.
我需要帮助回答以下问题:我的团队如何确保我们的工作从长远来看不会因未经维护的测试和/或在业务需求不断发布时未能编写新的测试而浪费?
确保构建过程在每个构建上执行测试,并在出现故障时使构建失败.
你使用持续集成吗?哈德森是一个很好的工具.它可以为项目生命周期内的每个构建保留一组测试,失败次数,测试覆盖率等.这有助于您在覆盖率下降时轻松关注.
正如您所提到的,将单元测试改造为现有项目可能相当困难,更不用说TDD了.祝你好运!
更新:我还想指出,100%的测试覆盖率并不是一个很好的目标,当你尝试从80%或90%左右时,它的回报会逐渐减少.要获得最后几个百分点,您需要开始模拟代码中的每个可能的分支.你的团队将开始花时间模拟在现实生活中不可能发生的场景("当我关闭它时,这个流实际上不会抛出IOException,但我需要覆盖这个分支!")或者你的实际价值没有实际价值测试.我在我的团队中找到了一个人来验证,if (foo == null) throw new NullPointerException(...);因为方法的第一行实际上在值为时抛出异常null.
花更多的时间来测试真正重要的代码,而不是变得过于强迫性地让每一条最后一行在Emma或Cobertura中显示为绿色.
我认为(1)基本上不实用,因为我们在项目中有一个地狱般的依赖图.几乎没有一个组件可以单独测试; 我们不知道所有用例;
这是你真正的问题.
您可以从编写基本上自动化测试过程的集成测试开始.你可以从门外获得价值.您需要的是一个重构的安全网,只要您破坏了代码,它就会给您一个提示.利用最广泛的交易来运用应用程序,自动完成抽取过程并将预期与实际进行比较.
一旦你有了这个,开始尝试打破一些依赖图,这样你就可以隔离片段进行测试.
每当你有一个bug修复时,为它复制错误的单元测试.然后修复代码并重新运行测试.您应该看到测试通过成功.将此作为标准错误跟踪和修复程序.该测试列表将像银行账户中的利息一样增长.
我同意CI建议.将代码覆盖率指标添加到Hudson或Cruise Control.
不言而喻,您正在使用Subversion,Git或其他源代码管理系统,对吧?
这是一个漫长的过程,但最终还是值得的.