当成为团队的新成员时,您如何处理现有集成和单元测试的质量?


21

我在职业生涯中遇到的一个反复出现的主题是成为新的开发人员加入团队,并很快对现有的单元和集成测试套件产生内在的不信任。

在面试过程中,管理层告诉您,他们“大力支持单元测试”,并公开鼓励他们进行测试。他们可以,但是关于测试本身的一切都是错误的。就像他们声称拥有100%集成测试覆盖率但少于10%可重复单元测试覆盖率时声称100%覆盖率这一事实。我发现了一些其他问题:

  1. 在什么是单元测试和什么是集成测试之间没有明确的指示。单元测试和集成测试在同一个类别中混合在一起。

  2. 尚未声明对特定环境的数据库中非常特定的动态数据有明确依赖关系的集成测试。

  3. 非事务集成测试,基本上是可能会或可能不会麻烦自行清理的测试,有时需要手动数据库“清理”以使测试可重复。

  4. 绝不进行任何模拟,而应用程序代码则需要进行大修,以使模拟成为可能。换句话说,设计时不要考虑测试。

  5. 没有明确的命名约定可以快速查看测试名称并大致确定要进行的测试。

这并不是说所有测试都是无用的或不好的,很多测试都相当好并且值得保留,但是有时候感觉就像淘金。我故意避免运行测试,只是因为我担心为黑箱测试用例搞砸数据库。

从本质上讲,这使我对单元和集成测试产生了固有的不信任感,而我个人没有以某种方式编写或审查这些测试。在某种程度上,如果您对测试套件的质量不抱有信心,那么它实际上对团队或项目毫无价值。

当您发现自己处于这种情况时该怎么办?您认为最佳的攻击计划是应对此类问题?

是否应该在跨发行版的巨大努力下重构所有测试?您是否应该放弃这个旧项目可能会有一天可靠的单元测试范围的想法?


6
欢迎来到现实世界,哥们。
tdammers 2011年

20
进行测试感到高兴。
乔尔·埃瑟顿

3
您为什么要为明显低于您的能力水平的公司工作?
TrojanName 2011年

3
@Brian,我很欣赏自我的冲动,但是没有更多的人像我这样思考,那么这些公司将永远无法超越。这是我第一次真正掌握权力,因为我一次只获得了少量的政治重要性。我在这里有一个真正的机会来指导资源以使事情变得更好。我还没有找到一家不需要任何工作的完美公司。就像完美的丈夫或妻子一样,他们不仅会来,一个足够好的人会来,然后您将它们更改为您想要的样子;)
maple_shaft

1
我认为我们可能会为同一支团队工作。现在,您(和我)知道了在下一次面试中如何真正提出问题。(实际上,我的环境几乎没有100%或什至10%的集成测试覆盖率[真正的单元测试?这真是个疯子!],但您已经钉牢了我要处理的所有其他问题。)
Anthony Pegram

Answers:


6

首先,正如其他发布者所写的那样,您应该高兴地理解单元/集成测试(不是以技术的方式,我的意思是理解应该这样做的原因)并由管理层推动。

在开始做所有事情之前,您应该向管理层暴露问题,为什么要做一些事情以及非常外交的态度,以使他们不认为您是世界上最好的程序员(即使您是!:-)。也许他们会告诉您该应用程序将被全新的东西替换,如果是,为什么要麻烦。也许他们会意识到这会很好,并且可以在每个版本之前加快测试阶段。而且是外交与你的队友,可能有百万个理由,为什么它是因为它并没有只是没有理由去寻找一个罪魁祸首。

一个更好的主意是尝试与他们交谈,以便他们可以参与其中,并且您成为智能资产的机会会更少,这比“我”更像“我们”。

现在,将优先事项放在您想做的事情上。确定任务的优先级,始终知道您的首要任务将始终是当前的项目任务...至于您的测试问题,这是我将分三个阶段进行的工作:

  1. 如何区分单元测试和集成测试?以下解决方案可能适用,但不是排他性的:

    • 重构测试用例方法的名称(而不是类,因为正确的行为是使测试用例与被测试的类具有相同的名称)
    • 创建两个注释,一个注释名为“ UnitTest”,另一个注释名为“ IntegrationTest”。这些注释可以在类和方法上使用。如果整个类由单元测试或集成测试组成,则可以使用正确的注释标记该类。如果没有,则可以使用正确的注释标记每个方法。同样,这些注释对于在启动测试之前动态注入灯具很有用(阶段3)
  2. 对于每个集成测试,请列出每个测试开始时数据库中应包含的“数据集”,以及在结束时应删除的数据集(例如:表X,需要带有“ id”的记录)设置为“ 1”,“名称”设置为“ foo”,依此类推)。请注意,您删除的内容可能比开始时要大/小,因为代码本身可能分别从持久层添加/删除对象。您很可能会很快注意到,这些测试用例中的一些需要相同的数据集或同一数据集的一部分。

  3. 与其余阶段相比,前两个阶段可以相对快速地完成。有了数据集之后,就可以为需要它的每个测试用例使用创建数据集夹具。但这会花费一些时间...因此,您可以做一个,看看它花了多少时间,并估计您需要花费更多的时间来完成所有事情。同样,您可以使用该测试向同事展示您做了什么,以及当您不需要具有处于特定状态的数据库来执行测试时为什么生活变得如此轻松。

您可能会注意到,如果您想快速向同事/管理层展示如何完成此阶段,则可以在单个测试课程上完成第1、2和3阶段。正如PéterTörök所写,这也将很有用,以便立即向您的队友展示“好方法”,以便他们停止产生错误的代码。但是,我认为阶段2的其余部分(确定整个测试数据集)最好是迈出一大步。

至于所有这些背后的API /技术,您似乎知道这一主题。

希望能有所帮助。

注意:对于我的建议,我假设您使用Java / C#编写代码,而我知道可以使用批注和AOP。我敢肯定,其他语言也可以做到这一点,但是我不会写我不知道的东西。


1
谢谢...我考虑过使用批注作为标签来标识什么是集成测试和什么是单元测试...您知道是否可以配置类似CruiseControl的CI服务器以基于批注排除某些测试吗?也许那是一个单独的问题。
maple_shaft

抱歉,我不知道使用CruiseControl,所以我对此一无所知。我只是出于好奇而抬头查看了Maven的Surefire插件配置,但这似乎是不可能的,但是根据课程名称完全有可能跳过测试。
2011年

14

您将无法一起修复所有测试。我认为您应该将重点放在改善大修之间。无论是开发人员还是管理人员,都不会同意进行大修,但是如果您表明有办法在不对项目造成负面影响的情况下进行改进,那么他们将更有可能倾听。

首先,除非具有质量测试覆盖范围,否则您不能“​​修复”或重构现有代码,因此,我将首先关注修复您的测试基础结构。

列出需要改进的事项,并尝试对它们进行优先级排序。我认为能够独立且单独运行测试(因此它们不会互相影响)的能力以及单元测试和集成测试的分离是首先要进行的工作。您需要使您和他人轻松地做正确的事。

就应用程序代码而言...您将无法对应用程序体系结构进行完整的检查,因此只能对其进行更好的单元测试。相反,当您放入新代码时,请尝试应用使单元测试更容易的原理(例如依赖注入)。您可能会认为这还不足以带来很大的变化,但令人惊讶的是,开发人员在看到收益后能很快赶上。只需要有人开始做出更好的改变。

与您的团队交谈,让他们接受。您可以做的最重要的事情之一是遵循“ 童子军规则 ”,并进行一些小的改进以使班级或测试的状态更好,然后您发现了它。如果整个团队都遵循这个规则,事情就会好起来很多。

一段时间后,您将有很多代码,它们遵循良好的原则,并且处于不良状态。在这一点上,您已经有了什么好处的基线,团队可以决定对较大的旧遗留物进行较大的重构是否有益,还是可以继续使用。


8
+1,然后添加“以身作则”。没有人喜欢走进来的那个人说“您做错了”,但是如果您表现出改进,他们很有可能会跟进。
StevenV 2011年

2
童子军规则 +1 ,它比任何大修方法都容易使用和出售。
Matthieu M.

10

我必须承认,我将把它作为稀有礼物送达一个项目,在该项目中他们已经进行了大量的单元/集成测试-到目前为止,我从未有过这种运气。即使不是所有人都按预期方式工作,也已经付出了很多努力,即使团队和管理层并不总是遵循最佳实践,他们仍然致力于实现这一目标,所以您无需花时间争论为什么单元测试值得编写。

但是,您所描述的测试确实可以进行一些改进。但是与队友讨论问题时要注意语气。如果您先说“测试本身的一切都是错误的”,那么您可能很快就会疏远团队的其他成员。相反,您应该专注于如何改善当前的事务状态,根据我的经验,我要重申的是,这仍然比平均水平好得多。

IMO 你的首要目标应该是阻止团队进行更多糟糕的测试。因此,首先要向您的队友展示每个特定改进的好处。如果他们看到某种技术的用处(例如削减外部依赖关系,在每次测试后恢复原始状态,或分离单元测试和集成测试),他们将开始应用它们。从长远来看,这本身将缓慢但肯定会提高测试基础的整体质量(如果现在有1000个不良测试用例,并且该团队在明年之前生产1000个良好测试,那么您将降低不良测试的比率从100%到50%)。一旦确定了安全性,您就可以根据情况决定重构现有测试。同样,随着时间的流逝,小的改进将带来巨大的变化。

顺便提一句,从您的帖子语气来看,我觉得您可能曾经是我曾经在的地方:不信任他人所做的工作,无法将任务委派给任何人,因为担心他们的工作不适合您自己的质量标准。以我的经验,这不是一个好地方,因为从长远来看,它很容易导致人身矛盾和倦怠。您不能独自完成所有事情,必须与团队的其他成员一起工作。你们只能一起成功。


6

努力实现测试独立性。如果测试X以测试Y失败的方式修改了测试数据库,则更改测试Y。在这种小情况下,要注意的不是X弄乱了数据库,而是Y具有不适当的依赖关系。删除那些依赖项(通过存根数据库,重组测试或将数据库初始化为Y将通过的状态),现在您有了另一个独立的有效测试。这就是进展(可以说,“修复” X不会弄乱数据库不会)。

尽管他们造成了混乱,但请与他们一起工作的人们保持耐心和尊重,并尽可能地做到最好。他们极有可能尝试做正确的事。记住这一点,并帮助他们做到这一点。


2
我应该提到,原来的混乱创建者都没有了。他们不想处理自己创造并继续前进的技术债务。
maple_shaft

4
@maple_shaft:它们消失了是一件好事...您可以改善事情而不会丢脸。
凯文·克莱恩

2

成为团队新手的好处是您对事物有“新鲜”的态度。坏的部分可能是别人可能很难相信你。

不要列出要完成的事情。但是,选择一件似乎紧急的事情,其他人最有可能做出回应的事情,并提出解决方案。如果可行,那就太好了,然后根据您的第一个成功经验,为另一个问题提出另一种解决方案。

但是,慢慢来,一步一步,希望您的想法在新的团队中慢慢“流行”起来。


2

设置您想看到的示例,但是欣赏另一个开发人员在测试中的观点:一个开发人员可以测试成功,而另一个开发人员可以测试失败,一个开发人员编写了该类,而另一个开发人员可能在编写测试时第一次使用了它。

现有的测试(大多数是erm)仍然有目的,尽管可能不会立即显现出来。我不建议一次全面检查和重构所有内容(这既乏味又容易出错)。不良测试最终需要更新,重写,或者随着软件的发展它们可能已经过时。

如果您的测试方法在某些方面比较优越,那么人们会从该模型中学习或寻求您的帮助。资源将保持平衡,但是您可以根据需要扩展以支持测试。

最终,您希望通过测试来提高程序的质量并提高覆盖率。您可以通过更加注重测试和树立良好榜样来做到这一点-但一定要欣赏别人的观点。

在强调重要性时,您可以使测试的操作环境有所不同-一个明显的例子是并行运行测试。如果它不是可重入的,则说明您已在程序或测试中找到了一个错误(双赢)。更严格的测试环境将迫使不良测试得到修复和/或重写(希望第二次是正确的方法)。慢慢地引入这样的更改(不要一次全部破坏一半的测试-这是一个真正的问题),迫使他们学习什么才是好的测试,最终是好的程序。然后,当您和其他人进入并修改/修复/扩展测试时,请应用您所学到的知识-它是增量式的,您当时对上下文/程序有了更好的了解。


2

随着时间的推移修复它们

我一直处于同样的情况。我每天早上只花一个小时来进行测试并修复它们,直到所有问题都得到解决。这是一个中等大小的代码库,我想我在1.5个月内完成了。我对测试也更有信心。

我个人并不关心测试是单元测试还是集成测试,只要它是一个很好的测试即可。通过良好的测试,我的意思是:

  • 自行清理
  • 可重复
  • 最小化环境相互作用
  • 是一致的

在此过程中,我宣传了更好的测试结构(也就是说,我困扰了很多人)。

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.