为什么自动化测试在我的公司中总是失败?


178

我们试图在我的公司中多次引入开发人员自动化测试。我们的质量检查团队使用Selenium来自动化UI测试,但是我一直想介绍单元测试和集成测试。过去,每次我们尝试时,每个月的第一个月或第二个月每个人都会感到兴奋。然后,几个月后,人们只是停止这样做。

一些观察和问题:

  1. 自动化测试是否有效?我曾经在其他公司工作的大多数同事都尝试过并未能实施自动测试策略。我仍然没有看到一个实际使用它并且不仅仅谈论它的现实软件公司。因此,许多开发人员将自动化测试视为理论上很棒的东西,但实际上却行不通。我们的业务团队希望开发人员即使花费30%的额外时间来做到这一点(至少他们这样说)。但是开发商对此表示怀疑。

  2. 没有人真正知道如何正确地进行自动化测试。是的,我们都已经在互联网上阅读了单元测试示例,但是将它们用于大型项目则完全是另外一回事。罪魁祸首是嘲笑/存根数据库或其他不平凡的事情。与编写实际测试相比,您最终花了更多的时间进行模拟。然后,当编写测试花费的时间比编写代码花费的时间长时,就是您放弃了。

  3. 在复杂的以数据为中心的Web应用程序中,有没有很好的使用单元测试/系统集成测试的例子?有开源项目吗?我们的应用程序以数据为中心,但也具有大量的域逻辑。我在某个时候尝试了存储库方法,发现它对于单元测试相当不错,但是它是以能够轻松优化数据访问为代价的,它增加了另一层复杂性。

我们有一个由20个经验丰富的开发人员进行的大型项目。这似乎是引入单元测试/集成测试的理想环境。

为什么对我们不起作用?您是如何在公司工作的?


14
您的技术栈是什么?
Florian Margaine 2013年

7
WebForms几乎不可能正确地进行单元测试。您可以使用MVP(模型/视图/演示器)模式将表示逻辑移动到可测试的组件。
皮特

12
@MasonWheeler:在这两种情况下,您都构造了一个了不起的论据,它反驳了最初不被接受的前提:也就是说,存在单元测试以证明正确性。
史蒂文·埃弗斯

10
@ MasonWheeler-使用该参数,您永远不要尝试任何质量检查,因为您永远不会证明没有错误。那甚至不是目标。良好的自动化UI和单元测试策略只是使质量检查摆脱死记硬背的测试,并使他们专注于探索性测试。
亚历克斯

15
令我震惊的是,有几个人说,他们几个月以来从未见过自动化测试。我曾在德国的大约五家大公司担任顾问,如果您不编写测试,他们会解雇您。自动化测试不是一个理论主题,它在全球范围内都得到了成功的实践,并且可以显着提高代码质量(如果操作正确的话)。

Answers:


89

进行单元测试最困难的部分是让学科首先/尽早编写测试。大多数开发人员习惯于只钻研代码。当您试图弄清楚如何编写代码测试时,它也会减慢开发过程的速度。但是,随着测试能力的提高,速度会加快。并且由于进行了编写测试,因此代码的初始质量更高。

开始时,尝试仅编写测试。在一开始时不必担心太多的事情。保持测试简单。测试是代码,可以/应该重构。尽管按照这些原则进行测试很难,但也可能是设计。TDD确实致力于使用大多数设计模式(以我的经验,尤其是工厂模式)。

确保测试达到一定程度的可见性。将它们集成到发布过程中,在代码审查期间询问它们。发现的任何错误均应进行测试。这些都是TDD发光的地方。

这里有一些我认为有用的资源:

http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf

http://www.agitar.com/downloads/TheWayOfTestivus.pdf

编辑:

编写测试时要记住的一件事。您没有尝试指定有关代码实现的任何内容,仅是行为。编写代码时,您一直对其进行测试。尝试使用调试语句等执行它。编写测试将使它正式化,并提供您所进行测试的记录。这样,您可以放心地检查功能,而不会意外跳过在开发过程中记住的测试用例。


将其作为诊断功能引入的另一种方法...又称开机自检(POST),几乎可以交付客户代码...而不仅仅是一堆简单的测试,这就是测试和功能。
JustinC

另外,请避免使用TDD反模式
加里·罗

4
Misko Hevery在youtube上也有一些很棒的视频,内容涉及编写可测试的代码,我认为这是无价的。youtube.com/watch?v=acjvKJiOvXw
Despertar

“确保测试获得一定程度的可见性”-这对于成功至关重要。如果没有人能看到您的测试执行情况,他们将看不到该值。应将测试作为连续集成的一部分自动进行检入,然后进行报告。我在Tesults(tesults.com)工作,其存在的原因是因为测试可见性提供了巨大的影响。
技能M2

77

我在很多方面都同意您的团队。

  1. 大多数单元测试的价值值得怀疑。由于绝大多数测试似乎太简单了。

  2. 编写好的可测试代码比仅工作代码要难得多。开发人员社区中有很大一部分人相信只是让它起作用,而不是本身具有代码/设计质量。还有更大比例的人甚至不知道什么是质量代码。

  3. 编写单元测试代码可能比实际代码本身花费更长的时间。

  4. 弄清楚如何充分测试更复杂的代码(即,您真正感兴趣的彻底测试代码)超出了许多开发人员的能力。

  5. 维护单元测试需要太多时间。较小的更改可能会产生较大的连锁反应。自动化单元测试的主要目标是找出更改是否违反了代码。但是,99%的失败最终是测试而不是代码。

面对上述所有问题,没有比通过自动化测试更好的方法来进行代码更改,并且对某些事情不会意外中断表示信心。

通过不使用单元测试的教科书,可以在某种程度上缓解以上某些问题。

通过在模块/封装级别进行自动化测试,可以更好地测试许多类型的设计/应用程序。以我的经验,大多数编码错误不是因为一个类中的代码编码不正确,而是因为编码人员不了解他们的类应该如何与其他类一起工作。在这种类型的测试中,我看到了很多优点。但是再一次,这些测试比单元(类级别)测试更难编写。

真正归结为开发人员是否相信该过程。如果这样做的话,他们将编写良好的单元测试,及早发现错误并成为支持者。如果他们不这样做,那么他们的单元测试将大体上是无用的,并且不会发现任何错误,并且他们的单元测试理论是无用的(在他们看来)。

最重要的是,我本人已经几个月没有见过完整的自动化单元测试方法了,但是尽管我们对真正需要测试的问题有所选择,但是自动化单元测试的想法仍然存在。这种方法的批评家往往要少得多,并且被所有开发人员(而不是少数几个)所接受。


24
我倾向于同意这一点。我们已经习惯了仅在出现故障后才进行测试(即使该中断是在开发过程中进行的)。永远不要预先花太多的时间来获得很少的回报。
2013年

5
@Izkata我见过成功完成的另一种方法是在Frobinate()通过其他方式验证系统可服务后,编写相对少量的称为顶级方法的高级测试(而不是在其下方调用的数十种较小的方法)作为烟雾测试,任何较低级别的更改都不会破坏任何内容。通常,这些测试使用的数据与所提供的键盘用户测试的一部分相同,因此客户可以看到系统正在执行他们想要的操作。之后,代码覆盖率工具可以标识尚未覆盖的边缘情况。
Dan Neely

3
我没有说“全面自动化测试”,而是说“全面自动化UNIT测试”。巨大差距。我至少在模块级别使用自动化测试已有十年了。单元测试是在类级别。我相信,在测试应该相互合作而不是个人合作的课程时,我会付出更多的努力。但是,即使在那儿,我们仍然使用实用的方法,并有选择地选择编写自动测试的位置/位置。
Dunk

2
没有良好的单元测试覆盖率,您将如何重构?还是不进行重构,如何防止代码逐渐退化为不可维护性?
凯文·克莱恩

1
@Leonardo他们没有-他们太害怕改变任何东西。或者,他们将所有的技术债务积saved起来,并在数周/数月后搁置起来,一次全部解决。
GraemeF

33

罪魁祸首是嘲笑/存根数据库或任何不简单的事情。

还有你的问题。

每个人都很好地说明了如何将单元测试集成到您的环境中。如何迫使人们做得足够多,以使他们看到实际的价值并“坚持”下去。但是,如果这样做非常痛苦,并且/或者没有提供任何好处,它就不会坚持下去。

存根数据库应该很简单。而不是将接口放入某些数据库支持以提供其结果,而是放入一个简单的硬编码对象。如果您不能这样做,则说明您的设计/体系结构有问题。您的代码假定它要去数据库,或者您没有接口抽象来更改它。

这不仅仅是测试/质量问题。一旦您要更改数据库提供程序,或者改为访问云,或者支持未连接的移动应用程序,您的设计就会失败。如果您不能支持最简单的灵活性案例,那么您当然不能支持您的业务不可避免地需要的更复杂的事情。


4
硬编码来自模拟对象的小存根的数据库返回值是一种将测试与数据库中可能更改和破坏代码的任何内容(例如,列重命名)隔离开的好方法。在某些情况下这是适当的,但是易于使用的临时测试数据库对于保持稳定很重要,除非您希望在某天更改它时将其破坏。如果换出数据库时代码中断,那是测试应该捕获的代码错误(如果要避免这种情况,您将要在多个数据库下运行测试套件。)

8
@fennec-单元测试不是用来测试数据库的,它们是用来测试依赖于数据库值才能起作用的代码的。
Telastyn

3
一切顺利,直到您对操作数据库的代码进行单元测试。:P对于很多人来说,是很多代码。

4
@fennec-将接口存根以确保您的写入正在编写正确的对象,这比简单得多要复杂得多。只有当您的类试图直接通过接口发送SQL时,这种情况才会变得很难(阅读:您的设计很糟糕)。
Telastyn

5
@Telastyn可能是我误会了,但是最终某些类需要精疲力尽并编写SQL或编写文件或发送数据或与GPU进行接口。大多数抽象在某种程度上都有不可避免的泄漏。他们只是务实而未必可怕。
学徒队列

21

您需要从小的,易于自动化的,高价值的东西开始。摘下一些低垂的甜水果,您将可以出售该过程。显示它如何在某个深夜或周末致电中为某人节省了费用。然后,您可以从那里扩展。

为了很好地进行自动化测试,您需要一个既有资源又有传播者的人,并且需要高层管理人员的支持。

与其他敏捷项目一样对待自动化测试开发。定期进行完整的测试。

从注释中补充:这更多是管理问题。在记录该代码之前,该代码是否被视为“完成”?在签入之前?在包含并通过单元测试之前?

您如何处理此问题实际上取决于您的角色。你是同行吗?如果是这样,请向他人展示如何使您的代码更易于重用和维护。你是领导吗?选择您的代码问题最多的程序员,并帮助他们添加测试以避免这些问题。你是老板吗 将其设置为“在单元测试通过之前,代码不会完成的标准。”


17
“拿出一些甜美,低垂的水果,您就可以出售该过程。”:我认为他们已经到了这个阶段(他们看到了使用单元测试的潜在优势),这就是为什么他们被说服了尝试一下。问题在于,如何系统地将低水平的成果扩展到进行单元测试。我从事的唯一一个系统地使用单元测试的项目比实际的产品代码具有更多的单元测试代码。如果团队不准备花更多的时间在单元测试上而不是实际的应用代码上,那么IMO可能就行不通了。
乔治,

4
那更多是管理问题。在记录该代码之前,该代码是否被视为“完成”?在签入之前?在包含并通过单元测试之前?您如何处理此问题实际上取决于您的角色。你是同行吗?如果是这样,请向他人展示如何使您的代码更易于重用和维护。你是领导吗?选择您的代码问题最多的程序员,并帮助他们添加测试以避免这些问题。你是老板吗 其设置为标准“的代码不这样做,直到单元测试是在和传球。
跳过霍夫曼

1
@SkipHuffman您的评论应作为对当前答案的编辑添加。
radu florescu

15

遵守这些基本规则。测试:

  1. 必须定期运行!您可以在每个签入之前/之后或每天早晨在每个构建上运行测试。自动触发优于手动触发。因为从理论上讲,您可以让团队中的每个人负责确保他们运行测试,如果它不是自动化的,则可能发生的频率不够高!而且,如果您没有足够频繁地运行测试,那么他们俩都发现错误太晚了,因此会鼓励大量失败的测试,从而导致第2点:

  2. 如果那些现在定期运行的测试没有妨碍您,那么您仍然只会成功。我们所说的测试是:

    一种。一定不要花太长时间(主观地)就可以为它们提供的价值!快速进行测试。不要让人们检入测试,这将浪费您的时间来让他们运行!

    b。一定不可靠。尽可能避免多线程测试。像其他代码一样,将工程实践应用于您的测试:特别是-代码检查您的测试!

    C。一定不要比测试的实际代码更难修复和维护。如果对代码库的一行很小的更改需要您修复10个不同的测试,则您的编码速度确实会很烂。

最后,规则3。测试不仅必须像规则2一样不能提供负值,还必须提供正值。测试...

  1. 当它们失败时,一定要告诉您一些您关心的事情!(请不要执行带有模糊错误消息的测试,或者仅仅是给您带来可笑的抱怨,例如“您忘记在Windows 2008计算机上运行测试”!)。

违反规则3的一种流行方法是测试错误的事物。有时是因为测试太大或没有重点。但是通常这是由于没有测试客户会关心的事情以及测试无关的实现细节而产生的。(但是有时候测试实现细节也可以进行有效的测试-IMO只是通过实践来决定哪个。)

结论:这些基本规则将您引向可持续测试学科的总体方向,而这正是您迫切需要的。在测试时,请问问自己该测试是否真正可持续和可维护。记得:

  • 如果测试不可持续,它们就会被废弃,从而浪费精力
  • 如果测试不可持续,则您停止进行测试,并且您的团队也将在测试方面变得越来越好!最后一点:

测试实际上很难。您应该期望,当您开始编写测试时,您团队的测试基本上会变得很糟糕。不要气disc。每当您发现旧的测试很糟糕并且不可持续时,就不要扔掉它们。


12

1. 真的有效吗?

是的,确实可以-如果操作正确。关键是测试人员需要在工程师实施新功能后调整和扩展其自动化脚本。

2. 没有人真正有经验或不知道如何正确进行自动化测试。

找一位顾问(知道如何正确完成工作的人)。或者,投入更多时间。另一种选择是拥有更大的测试团队,他们会手动执行相同的测试(容易出错)。

3.我们有一个大型项目,其中有20位经验丰富的开发人员正在为此工作。因此,引入单元测试/集成测试应该是一个很好的环境。为什么对我们不起作用?您是如何在公司工作的?

如果他们拒绝进行单元测试,我不会称他们为“经验丰富的开发人员”。有很多很棒的文章介绍了测试(单元测试和集成测试)的积极好处,最后归结为您的公司花了多少bug。例如,我在一家质量很重要的公司工作,因此不可避免地要进行单元和集成测试。您可以轻松地找到很多文章,这些文章告诉您单元测试只会使bug数量减少30%!(实际上,它在20-90%的范围内,平均为30%,但仍然很多。)

要使其在您的公司中正常工作,请聘请顾问或将此任务分配给高级工程师(这将需要他一段时间才能完成)。然后,强迫所有人遵守规则。


20
我必须指出,实际上,“如果操作正确”,一切都可以工作。但是,这对所有人口都没有很大帮助,但对所有人口中的极少数人来说都是如此。为了使一个过程真正能够声称它有效,它在完成“某种程度”后也必须起作用。
Dunk

11
我将指出,将每个人的情况过度概括为您自己的情况(即,我不会称他们为“经验丰富的开发人员”。.质量很重要)不仅表明您缺乏经验的广度,而且效率也不高。每个行业都有自己的“作品”定义;以及需要在单元,集成和系统级别进行什么程度的测试。许多“异常优秀”的开发人员已经意识到,与自动化集成测试相比,单元测试几乎没有什么优势。他们还意识到这可能仅适用于其特定行业。
Dunk

11
“如果他们拒绝进行单元测试,我不会称他们为'经验丰富的开发人员'。” 这仅仅是没有真正的苏格兰人的谬论。软件行业在没有进行单元测试的情况下发展了几十年,而如今在没有软件的情况下,该行业中的大多数仍在发展。这可能是一个好主意,但这不是强制性的。
Noah Yetter

1
“不浪费时间在单元测试上”:我将其表述为“不浪费时间在无用的单元测试上”。盲目地对所有内容进行单元测试可能会浪费大量时间。
Giorgio

1
@Dunk我真的很讨厌整个测试优先的TDD现象,但是我不同意您的第一个陈述。您要么做正确的事,要么不做正确的事。您可以很好地进行一个单元测试,也许可以看到它的优点,但是您永远不会看到任何一件做得很不错的事情。
Erik Reppen

10

有很多原因导致引入自动化测试可能会失败。我认为这可以归结为这样一个事实,即程序员倾向于不改变他们的编码习惯,并且没有完全能力进行单元测试。

许多想从自动化测试入手的人试图将它们引入现有的代码库中。他们将尝试编写集成测试,以一次测试现有应用程序的许多功能。众所周知,这种集成测试太难了,维护起来也太昂贵。建议:为新的代码库引入自动化测试。

单元测试是可以自动化的良好测试。上面的所有内容(集成测试,组件测试,系统测试)也可以自动进行测试,但是一旦同时进行更多的功能测试,成本效益比就会迅速下降。如果您在未经单元测试的功能上进行此类测试,则会放大这种负面影响。建议:在单元测试级别上引入自动测试,并在单元测试的坚实基础上构建自动集成测试

从以上几点来看,自动化测试的成功很大程度上取决于单元测试的有效性。如果您对单元测试感到满意,则可以使用有效的单元测试。当人们开始进行单元测试时,他们倾向于将其现有的代码和编码习惯改造成单元测试。具有讽刺意味的是,这是学习单元测试的最困难的方法。此外,单元测试还要求您更改编码方式(例如,应用SOLID原则)。大多数程序员很快就停止编写单元测试,因为他们认为学习曲线太陡了,并且发现将单元测试包裹在一个不太容易测试的设计代码周围是很尴尬的。建议:使用新代码从头开始学习单元测试,并处理您需要更改编码习惯的事实。

还有很多其他因素,但是我发现对于大多数程序员而言,更改其代码编写方式很麻烦。未经测试编写的代码看起来就不同了。如果您不能将代码压缩到可测试的设计中,则很可能无法编写有效的单元测试。这破坏了有效的自动化测试的基础。

我自己经历了这一点,现在很高兴在一家成功引入自动化测试的公司工作。关于其他因素,我可以写很多东西,但我认为编码习惯和单元测试是最重要的。幸运的是,有些人比我更有经验,并用自己的专业知识来写书。其中一本书是.NET中的Brownfield应用程序开发,由于您使用的是Microsoft技术堆栈,因此我真的可以推荐。


Introduce automated tests on the unit test level and build automated integration tests on a solid foundation of unit tests.+1
c69 2013年

10

我在上面的答案中没有清楚看到的一件事是,单元测试本质上是一种公共物品,也是一种私人费用。我写了一个博客张贴关于它在这里

可以得出的结论是,尽管一组测试对团队或单个开发人员都有利,但编写测试在大多数情况下是对进行测试的人的一种代价。

简而言之,除非以某种方式强制执行测试,并且上面的答案列出了执行此操作的多种不同方式,否则没有个人开发人员可以这样做。

在我工作过的一家公司中,编写单元测试是提供功能的必要部分。除非单元测试是提交或新功能的一部分,否则不接受新代码-对开发人员给出的每个“任务”都有简短的代码审查。在您的工作场所实施类似的政策可能是值得的。


8

有趣的是,该业务比开发人员更具亲测性!在我看来,您面临的最大挑战将是克服开发人员对变革的抵制。他们需要重新定义对工作的理解,以包括单元测试。

没有什么比早期的单元测试成功对您有所帮助,可以帮助您的开发人员克服编写测试的阻力。如果您推动他们去做一些新的事情,请确保您首先推动几乎可以肯定的奖励。

@SkipHuffman谈到了这一点,但是我要直言不讳。有些事物比其他事物更适合于自动化测试。对于第一遍,我不会测试数据库或UI。来自数据库的输入可能很难设置和拆除。UI输出测试往往会因外观和感觉的变化而迅速中断,而这些变化与您的测试完全无关。

我所谓的“中间件”非常适合单元测试。明确定义了输入和输出条件的代码。如果您遵循DRY原则(不要重复自己),那么您将编写一些小类或函数来解决应用程序特有的重复出现的问题。

单元测试是限制更改现有内部组件的风险的好工具。在更改已经使用了很长时间的内部组件之前,编写单元测试。这些测试证明保留了当前可以使用的功能。进行更改并且所有单元测试都通过后,您知道您还没有打破任何“下游”问题。如果确实发现下游问题,请为其添加单元测试!

罗恩·海菲茨(Ron Heifitz)会说: “解决人们所持有的价值观中的冲突,或者缩小人们所代表的价值观与他们所面对的现实之间的差距。适应性工作需要改变价值观,信念或行为。” 克服了人类对变更的抵触后,您可以根据需要扩展到更困难的测试区域。


6
“克服开发人员对变更的抵制”:并非每一种抵制都是没有道理的,并且不应使用“抵制变更”的论点来避免诚实的讨论。
乔治

7

关于自动化测试的一件事是,它要求您编写可测试的代码。这本身并不是一件坏事(事实上,这是件好事,因为它劝阻通常应避免的许多实践),但是,如果您尝试对现有代码进行单元测试,则可能不是以可测试的方式编写。

单例,静态方法,注册表,服务定位器等之类的东西都引入了很难模拟的依赖项。违反Demeter定律意味着您的代码库太多部分对代码库其他部分的功能了解得太多,从而引入了其他难以破解的依赖。所有这些事情使得很难将模块与其余代码库隔离开来,并且如果您不能单独测试模块,那么单元测试将失去很多价值。如果测试失败,是因为被测单元发生故障,还是由于其依赖项之一发生故障,或者是因为通过从属数据源提取的数据不是测试编写者所期望的?如果你可以的话'

我见过的大多数未考虑到单元测试的代码库本质上都是不可测试的,因为编码人员倾向于专注于使代码按他们期望的那样工作,而不是进行保持松散耦合和依赖关系明确的必要工作。考虑到单元测试而编写的代码看起来会非常不同。

很多人在第一次开始进行单元测试时就采取了幼稚的方法,他们认为他们可以为现有的代码库编写大量的测试,但是一切都会很好,但是由于上述问题。他们开始发现必须在单元测试中进行大量设置才能完全运行它们,并且结果常常令人质疑,因为代码中缺乏隔离性意味着您无法追踪导致测试失败的原因。他们还倾向于尝试编写“聪明的”测试,这些测试演示了系统如何工作的高度抽象的方面。这往往会失败,因为“聪明”的单元测试本身就是潜在的错误源。测试是否由于测试模块中的错误而失败,还是由于测试中的错误?测试应该非常简单,以至于不可能有任何漏洞隐藏在其中。实际上,最佳测试很少会超过2行,第一行指示被测单元执行某项操作,第二行则断言所执行的操作是预期的。

如果您的团队认真考虑采用单元测试,那么从现有项目开始是不明智的。如果不进行重大重构,您团队的现有项目可能无法测试。最好使用一个新项目作为学习单元测试的基础,因为您可以使用一个干净的平台。您可以设计新的代码库,以使依赖注入优于单例,注册表和其他此类隐藏的依赖关系,您可以将其编写为依赖接口而不是实现等。您还可以(并且应该)与要测试的代码一起编写测试,因为事后编写测试会导致单元测试,以确保被测试的模块执行了您认为可能要执行的操作,而不是那些测试了它可以执行的操作规格说明应该做什么。

一旦您对单元测试有了信心,您的团队就可能开始意识到其现有代码中的缺陷,这些缺陷将成为单元测试的障碍。这是您可以开始重构现有代码以使其更具可测试性的时候。不要雄心勃勃,立即尝试做所有这些事情,或者尝试替换一个可以使用全新系统的系统,只需从找到易于测试的代码库中开始(那些没有任何依赖项或存在明显依赖项的地方),并为它们编写测试。我知道我说过与代码一起编写测试比之后编写测试更可取,但是即使后来编写的测试也具有作为起点的价值。编写测试就好像您对类的工作方式一无所知,除了其规范要求的内容外。当您运行测试并获得失败时,则说明或实现均不正确。仔细检查两者,以确定哪个是错误的,然后相应地更新测试或代码。

摘下低挂的水果后,您的实际工作就开始了。您需要开始在代码库中查找隐藏的依赖项,并一次对其进行更正。在这一点上不要过于雄心勃勃,只需要一次执行一个模块,或者甚至在一个模块中只执行一个问题,直到解决测试障碍并继续下一步。

TL:DR:大多数人认为测试很容易,您可以轻松地将测试改编为现有代码。这两个假设都是错误的。如果您考虑到这两个事实而着手进行项目的单元测试,那么您更有可能成功。


提示:将TL; DR:放在顶部-我必须阅读您的所有帖子才能开始阅读!(这有点失误了)
gbjbaanb 2014年

4
  • 您公司中是否有人在自动化测试方面拥有丰富的经验?

如果没有,自动化测试计划可能会失败。就像许多其他编程技能一样,自动化测试是一项技能,如果您没有经验的人,很难说出自动化测试是好的自动测试,还是有实际价值的不良测试,随机失败/需要频繁更新/实际上没有执行任何有趣的代码。

  • 那个人有领导力吗?他们有能力要求改变吗?

如果没有人听,他们说测试不好就没关系。(请注意,不必正式化领导权。拥有一支关心团队的团队也很好。)

  • 您是否正在开发工具和流程,以使自动化测试更易于实施并集成到开发周期中?

开发人员很懒。您需要使自己希望他们完成的事情变得容易,而让他们不希望自己完成的事情变得更加困难。您应该确保测试库可以轻松完成与测试设置和拆卸相关的任务,尤其是与环境相关的设置,例如测试数据库等。(在一些评论中讨论了模拟数据库,但应谨慎使用。真实的数据库应该易于启动,并允许您测试组件和流程生命周期的交互,通常比单元测试更重要和更有效。单个数据访问器。)

您还应该确保您的IDE具有启动测试套件的好方法。您应该经常运行测试套件,以便人们注意到它何时失败,而不是让它在痛苦中徘徊。开发人员对反馈的反应也很好,例如,如果测试失败,则自动集成系统会还原其更改。或者,更好的是,积极的反馈:一个自动集成系统,该系统可以捕获错误并保护您免受破坏。


我认为说开发人员是懒惰是不公平的。在您的经验中可能就是这种情况,但是肯定不是普遍真理。
2013年

4

首先,如果您的开发人员没有看到测试的价值,那可能是因为您的测试没有价值,不是因为您的开发人员对他们的价值或总体而言对测试的价值视而不见。在其福音传教士中,有一种趋势认为测试驱动的开发不会失败,它只会被懒惰的懒惰开发者失败。我认为这是错误的并且适得其反。

当我被介绍到测试驱动开发时,它意味着有效地编写测试,以验证永不失败的方法永不失败。首先,这很好,因为您会获得漂亮的绿色检查和成就感。稍后,在重构代码之后,您会得到数十个令人发指的红色Xes,这些代码中没有什么比代码已更改,测试不再有效以及您浪费大量时间编写代码要多的了。

您要避免这种情况。

从那时起,我采用了另一种方法进行测试。代替的接口实现对,我有一个接口,实现,测试三倍。接口指定行为,实现执行行为,测试检查行为。

我想这似乎很明显,但是对我来说,它区分了必须证明可以按指定方式工作的代码和可以按您认为适当的程度测试的代码。您必须证明的代码是您提供给外部的接口;剩下的就是你自己关心的问题。

在这种情况下,我会问开发人员,他们是否在代码中看到了适合进行此类测试的自然划分。有团队A实施和团队B使用的接口吗?在这种情况下,确保接口B符合预期的行为符合团队B的利益。要求B团队为其编写测试,然后告知A团队以确保其实现符合该测试;或者,如果没有,有意没有,则与其他团队讨论意外更改,以便他们可以为此做准备。

我认为这将说明测试的价值。它本身不是目的,尽管有可爱的绿色格子。它的存在是要明确一个开发人员对另一个开发人员做出的承诺,并确保将承诺满足双方的要求。


1
我喜欢比别人认为需要像这样的细节进行测试的代码更好阅读的代码。
Erik Reppen

1
我觉得漂亮的绿色勾是问题所在-它使测试成为某种游戏。
gbjbaanb 2014年

2

在一个大型的现有项目中添加大量的单元测试是一项艰巨的工作。如果您已经找到了一个适合您的好的模拟框架,那么您应该已经解决了最困难的问题。

我建议您在添加功能/修复错误时尝试添加测试。修复错误是最简单的错误。编写由于您的错误而失败的测试,然后修复该错误。同时,您可能会发现自己编写了一些更简单的测试并通过了。当然,您确实希望为此使用一小段易于测试的代码。

一旦人们开始习惯于为更简单的事情编写测试,您应该希望他们发现自己编写的代码更具可测试性。

我还建议您衡量测试的代码覆盖率(我过去曾将cobertura用于Java)。您将需要一个连续的集成服务器来运行测试并定期(每天,每次签入)生成指标。如果您的开发人员很热衷,那么他们将希望看到覆盖范围随着时间的推移而增加,并且他们可以看到一些


2

我认为您可能需要长时间玩。要获得认可,您可以做的一件事是尝试对您编写的下一个功能进行彻底的单元测试,然后跟踪一段时间内的错误数量。您应该希望发现主要错误会在早期发现(特别是如果将其与Test-Driven Design结合使用),并且回归的数量应该很少。经过一段时间(例如1年),将统计数据与具有类似复杂性的未经单元测试的功能进行比较。如果您可以证明新的错误和回归的数量明显减少,那么您已经为其提供了经济上的依据,并且产品团队很难忽略。

我遇到的情况是我可以使用TDD和单元测试作为主要功能。在开发阶段结束之后的五年中,没有一个bug被报告。当要求进行新的且有风险的增强功能时,我能够实现它并捕获单元测试中的所有回归。


1

我强烈认为,由于一些因素,许多团队已经大大低估了单元测试的价值,其中许多因素已经在答案中得到了强调。

开发人员通常承受着“完成任务”的压力,因此证明代码块可以为客户提供充分的证明。这几乎总是适用于咨询公司和人为驱动的质量检查:如果客户不需要单元测试并且考虑到足够的实时演示,那么客户将完全失败,因为他将签署可能隐藏错误的代码。

通常,开发人员会感到沮丧。成为程序员是一项艰巨的工作:完成一项任务并转到下一个任务是令人满意的,因此每个人都想着急并完成。直到他们被一辆带有重大错误的公共汽车撞到,而该错误在最初的质量检查之后几个月就出现了。在这种情况下,自动化和连续的质量检查不是管理人员的问题,而是开发人员的问题(他们仍然会因工作而获得报酬,也许是加班费)。

但是有一个例外

我坚信自动测试模型的接受是所进行测试“人性化”的功能。如果您正在使用前端测试Web模块,则尽管使用了Selenium之类的工具,您更有可能自己填写表格,查看结果并相信确定性。您会忘记稍后重新运行测试,或者您太懒了以至于无法再次执行旧的测试,这就是为什么有时在以后发现错误的原因。为了利用这一点,在银行环境中(根据我的个人工作经验),已经证明可以接受强大的代码模块化和严格的“修改旧代码”规则。

相反,如果开发人员负责开发高度自动化和大量数据的模块,那么他将更有可能编写详尽的单元测试并将其提交给测试批次。这是因为用从外部数据源(无论是否经过模拟)转换后的数据填充大型XML有效负载并不是一件容易的事。一些测试开发人员最终将为这种特定类型的测试构建一个小巧而有趣的前端。当我读硕士论文时,我正在使用每秒处理6000条以上syslog消息的日志总线,并且我必须测量数据包丢失和损坏:我自然地为几乎所有组件(尤其是Syslog解析器)编写了单元测试和压力测试。

为了使开发人员更易于单元测试

我相信他们必须被迫这样做。如果您是聪明的客户,则需要您的顾问在每个QA中运行完整的测试套件。如果您是优秀的团队领导者,您可能会考虑将以下任务分配给聪明的开发人员:构建内部测试平台。使用内部效果平台反模式没什么可看的,而是一组帮助器类,数据库模拟,配置,解析器,转换器,瑞士军刀来帮助开发人员立即构建测试。

当前的测试平台(例如NUnit)是通用的,可让您验证通用的断言。正确使用依赖项注入和特定于项目的工厂,可以帮助开发人员减少测试代码的数量并提高工作效率。我还没有机会在一个完整的项目上进行实验,我无法提供现实的反馈。


1

自动化测试就像软件开发一样。不幸的是,您雇用的测试人员原本打算编写测试用例,计划,策略,遵循检查过程,手动测试和记录错误。

一旦赋予他们自动测试职责,它就包括一定数量的软件开发。这里的问题是,无论您使用什么工具(出于天生的缘故,不要争论这一点),自动化测试都需要每天进行维护和更新。随着开发人员更改代码,

  • 您需要确保测试保持运行状态。
  • 您需要确保没有删除测试,因为它们没有运行
  • 您的测试指标需要显示您在上一个版本和该版本上运行的内容。确保您的测试用例数量没有减少。
  • 就像开发一样,需要对测试用例进行审查,以确保人们不会陷入混乱,将1个测试分为2个只是为了增加数量(有时将测试外包,因此此跟踪很重要)
  • 开发人员与测试人员之间进行更多的“健康”沟通非常重要
  • non-functional测试分开,不要期望它们每天都运行,这需要时间来保持这些更新,这是很好的。但是不要放弃,确保他们得到维护。

由于这些原因,您失败了

  • 您的测试工程师是没有分析技能的手动测试工程师。他们不知道a ifwhile循环之间的区别。坦率地说,因为没有课程教授自动测试,所以他们只教授手动测试。
  • 您的测试工程师太忙于手动测试您的构建并记录错误,因此他们无法进行自动测试
  • 您的测试经理不在乎自动化测试的指标,只是因为它们显示无效数据(在项目开始时),并且他们在日常的会议和会议中不花力气或优先级来强调自动化和运行自动化的重要性
  • 您选择为具有较短保质期的移动应用程序自动化测试。在撰写本文时,请稳定自动化测试套件,以使您的应用程序需求发生变化,而您应该专注于测试运行应用程序的Web服务
  • 您不了解自动化测试团队遵循的里程碑是开发团队,功能完善,代码完善,代码锁定和代码冻结。
  • 您不会在手动测试人员和自动测试人员之间进行区分。
  • 他们俩的薪水都相同,并向同一位经理报告,理想情况下,他们应该向开发经理报告,并且他们的薪水应与开发人员的薪水相匹配。
  • 您实际上认为并相信junit不足以开发自动化测试:)。

根据我的经验,这些经验适用于非常重视自动化测试并了解开发人员作为自动化测试工程师非常重要的公司。根据我为那些不了解的人工作的经验,无论您向他们解释了多少,都可以理解其中的区别。


在单元测试和集成测试的情况下,应该编写测试的人是开发人员,而不是单独的“测试工程师”。(如问题所述,QA(即测试工程师)实际上已经在使用自动化UI测试。)
PaŭloEbermann

实际上,任何编写自动化测试的人都应该具有开发技能。
Siddharth
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.