有没有人在大型公司或大型项目中成功使用过单元测试?
我们当前的数据库有大约300个表,大约有100个根。总共有大约4000列,完成后我们将有大约200万行代码。我想知道 - 那些拥有这样大小(或更大)数据库的公司是否真的经历了Mock / Stub他们的域对象的测试工作?我在一家大公司工作已经两年了,但当时所有大型应用程序都是通过集成测试进行测试的。如果需要进行大量设置,则单元测试通常不受欢迎。
我开始觉得单元测试对于除静态方法之外的任何事情都是浪费时间,因为许多我们的测试方法需要比实际代码更长或更长的时间...特别是设置/安排脚步。更糟糕的是,我们的一位开发人员不断引用肯特贝克的克莱斯勒项目中的单元测试和敏捷方法如此严重失败......而且这种方法不是一种可以很好地扩展的方法。
任何参考或经验都会很棒。管理层喜欢单元测试的想法,但如果他们看到我们正在编写的额外代码(以及我们的挫折感),他们很乐意退出。
答案 0 :(得分:2)
我已经看到TDD在大型项目上工作得很好,特别是为了帮助我们控制遗留代码库。我也看到了大规模的敏捷工作,但我认为仅仅做敏捷实践是不够的。 Richard Durnall写了一篇很棒的文章,讲述了随着敏捷的发展,公司的情况如何发生。我怀疑精益可能更适合组织的更高层次。当然,如果公司文化在敏捷开始被用于多个项目时并不是一个很好的匹配,那么它将无法运行(但其他任何事情都没有;你最终会找到一个无法有效应对变化的公司无论哪种方式)。
无论如何,回到TDD ......测试独立的代码单元有时会很棘手,如果涉及大数据驱动的域对象,我经常不会嘲笑它。相反,我使用构建器模式,以便以正确的方式设置该域对象。
如果域对象具有复杂的行为,我可能会嘲笑它以使其行为可预测。
对我来说,编写单元测试的目的并不是回归测试。它帮助我思考代码的行为,它的职责以及它如何使用其他代码来帮助它完成它的工作。它为其他开发人员提供文档,并帮助我保持设计清洁。我认为它们是如何使用一段代码的例子,为什么它有价值以及你可以从中获得的行为。
通过这种方式考虑它们,我倾向于编写测试,使代码变得容易和安全,而不是将其固定下来,这样就没有人可以破解它。我发现专注于模拟一切,特别是域对象,可能会导致非常脆弱的测试。
TDD的目的是不测试。如果你想测试一些东西,你可以让测试人员手动查看它。测试人员每次都不能这样做的唯一原因是因为我们不断更改代码,因此TDD的目的是使代码易于更改。如果您的TDD不能让您更轻松,请找到不同的方法。
答案 1 :(得分:1)
我在模拟对象和单元测试方面有过一些很好的经验,这些项目有很多前期设计和舒适的工作时间 - 不幸的是,这通常是大多数公司无法承受的奢侈品风险。 GTD和GTDF方法也没有帮助解决问题,因为他们将开发人员放在发布跑步机上。
单元测试的一个大问题是,如果你没有从整个团队中买入,那么一个开发人员用玫瑰色的眼镜(并且没有他们自己的错误)来查看代码只会实现快乐的路径测试是他们能想到的。单元测试并不总是得到应有的保持,因为角落的情况会消失,并不是每个人都喝Kool-Aid。测试与提出算法是一种非常不同的思维模式,许多开发人员真的不知道如何这样思考。
当迭代和开发周期紧张时,我发现自己依靠静态分析工具和复杂性工具对代码质量更有信心。 (FindBugs,PMD,Clang llvm等)即使它们位于您无法直接解决的区域,您也可以将它们标记为地雷,并帮助更好地确定在该区域实施新功能的风险。
答案 2 :(得分:1)
如果您发现模拟/存根是痛苦的并且需要很长时间,那么您可能有一个不是用于单元测试的设计。然后你要么重构,要么和它一起生活。
我会重构。
我有一个大型应用程序,在编写单元测试时没有遇到麻烦,当我知道是时候重构了。
当然,集成测试也没有错。我实际上也有测试DAL或应用程序的其他部分的那些。
所有自动化测试应该形成一个整体,单元测试只是其中的一部分。
答案 3 :(得分:0)
是的。非常广泛。
困难的部分正在制定编写干净代码的规则 - 并且(更难的部分)规则通过重构来消除错误的代码
我曾在世界上最大的银行之一从事过纽约,伦敦,巴黎和东京的项目。它非常好地使用了模拟,并且通过大量的训练我们有非常干净的代码。
我怀疑嘲笑是个问题 - 它们只是一个相当简单的工具。 如果你必须超重地依赖它们,说看起来你需要模拟嘲讽返回嘲讽 - 那么测试或代码出了问题......