我们已经尝试将单元测试引入当前的项目中,但是似乎没有用。额外的代码似乎已经成为维护工作的头疼问题,因为当内部框架发生更改时,我们必须四处解决并修复所有与之相关的单元测试。
我们有一个用于对控制器进行单元测试的抽象基类,它充当调用子类的抽象方法实现的模板,即,框架调用Initialize,因此我们的控制器类都有自己的Initialize方法。
我曾经是单元测试的拥护者,但是它似乎不适用于我们当前的项目。
谁能帮助您确定问题以及我们如何使单元测试对我们有用而不是不利于我们?
Answers:
如果测试是针对严重依赖全局状态或深陷于丑陋方法中的程序式代码编写的,则可能会让人难以忍受。如果您使用OO语言编写代码,请有效使用OO构造来减少这种情况。
代码中的阻塞点比其他部分更频繁地更改。在您的代码库中执行此操作,您的测试将变得更加健康。
竭尽所能缩小测试范围以及执行测试的周围环境。
您可能无法删除所有重复项,但仍尝试在引起痛苦的地方将其删除。确保您没有删除太多重复项,以至于某人无法进入并一目了然地告诉测试内容。(有关同一概念的另一种解释,请参阅Paul Wheaton的“邪恶的单元测试”文章。)
考虑一下Selenium记录和回放测试所涉及的复杂性,以及与测试单个方法相比,您可能会发生的变化。
真正的单元测试需要真正的隔离。单元测试不会命中数据库或打开套接字。不要嘲笑这些互动。验证您是否与协作者正确交谈,而不是此方法调用的正确结果是“ 42”。
一个特定的团队是否将测试所有代码进行测试,还是为每行代码编写“测试优先”,尚有待商debate。但是他们应该至少首先编写一些测试吗?绝对。在某些情况下,首先测试无疑是解决问题的最佳方法。
您是否正在测试足够小的代码单元?除非您从根本上更改核心代码中的所有内容,否则您应该不会看到太多更改。
一旦一切稳定,您将更欣赏单元测试,但是即使现在您的测试也突出了对框架更改的传播程度。
这是值得的,尽您所能坚持下去。
没有更多信息,很难知道您为什么遭受这些问题。有时不可避免的是,更改接口等会破坏很多事情,而其他时候则是设计问题。
尝试对遇到的故障进行分类是一个好主意。你有什么问题?例如,它是由于API更改而进行测试维护(如使其在重构后进行编译!),还是归因于API更改的行为?如果可以看到模式,则可以尝试更改生产代码的设计,或者更好地隔离测试以免更改。
如果在许多地方进行一些更改会给测试套件带来难以估量的破坏,那么您可以做一些事情(大多数只是常见的单元测试技巧):
开发小代码单元并测试小代码单元。提取有意义的接口或基类,以便代码单元中包含“接缝”。您需要引入的依赖关系越多(或更糟的是,使用“ new”在类内部实例化),更改代码的可能性就越大。如果每个代码单元都具有少数依赖项(有时是一对或根本没有),那么最好避免更改。
只能断言测试需要什么。不要断言中间,偶然或无关的状态。按合同设计和按合同测试(例如,如果要测试堆栈弹出方法,则不要在推送后测试count属性-应该在单独的测试中)。
我看到了这个问题,尤其是在每个测试都是一个变体的情况下。如果任何偶然状态发生变化,它将破坏声明在其上的所有内容(无论是否需要声明)。
与普通代码一样,在单元测试中使用工厂和构建器。我了解到,在API更改后,大约有40个测试需要更新构造函数调用时...
同样重要的是,请先使用前门。如果可用,您的测试应始终使用正常状态。仅在需要时(即没有要验证的状态)使用基于交互的测试。
无论如何,要点是我将尝试找出测试为何/在何处中断并从那里进行。尽最大努力使自己与变化隔离。
我不确定使您的代码难以维护测试的具体问题,但是当我遇到类似的问题而导致测试中断时,我可以分享一些自己的经验。我最终了解到,缺乏可测试性主要是由于被测类的一些设计问题:
因此,我发现通常我的测试正在中断-不是由于被测类的更改-而是由于被测类正在调用的其他类的更改。通常,重构类以请求其数据依赖性并使用模拟对象进行测试(EasyMock等针对Java)使测试更加集中和可维护。我真的很喜欢一些有关此主题的网站:
当然,一切都附带价格。在开发的早期阶段,通常必须更改许多单元测试。
您可能想查看一下代码中的一些内容,以进行更多的封装,创建更少的依赖关系等。
当您临近生产日期时,您会很高兴拥有这些测试,请相信我:)
我建议您投资测试自动化工具。如果您使用的是持续集成,则可以使其协同工作。有一些工具可以扫描您的代码库并为您生成测试。然后将运行它们。这种方法的缺点是它太通用了。因为在许多情况下,单元测试的目的是破坏系统。我编写了许多测试,是的,如果代码库发生更改,我必须更改它们。
自动化工具有一条很好的界线,您肯定会更好地覆盖代码。
但是,使用基于wrttien develper的良好测试,您还将测试系统完整性。
希望这可以帮助。
额外的代码似乎已经成为维护工作的头疼问题,因为当内部框架发生更改时,我们必须四处解决并修复所有与之相关的单元测试。
另一种选择是,当您的Framework更改时,您无需测试更改。或者您根本不测试框架。那是你要的吗?
您可以尝试重构您的框架,使其由可以独立测试的较小部分组成。然后,当您的Framework发生更改时,您希望(a)更改的部分更少或(b)更改的主要部分是组成这些部分的方式。两种方式都可以使您更好地重用代码和测试。但是涉及真正的智力努力。不要指望那么容易。
有时,设计TDD测试会引发对应用程序本身设计的质疑。检查您的类是否设计得很好,您的方法一次只执行一件事。如果设计得好,编写代码来测试简单的方法和类应该很简单。