如何说服开发人员和管理层使用自动化测试而不是手动测试






4.97/5 (25投票s)
大家都知道自动化测试很好,单元测试很好,我们都应该这样做。但是,当你试图说服管理层,告诉他们今后交付任何东西都需要花费两倍的时间时,你会被请出会议室。了解我是如何说服一位开发主管进行自动化测试的。
引言
大家都同意自动化测试是件好事,我们都应该写单元测试。我们阅读文章和博客,以了解单元测试领域的最新动态,以便在午餐时与同行交谈时听起来很酷。但是,当我们真正坐下来尝试自己编写自动化测试或单元测试时——“算了,这是浪费时间,让我的 QA 来测试吧;这比这更可靠,也更有保证。当有那么多其他函数需要先进行单元测试时,测试这些函数有什么意义呢?”你是否也曾经有过这样的时刻,或者你身边有人有过?请继续阅读。
开始
我与我们的开发主管 Rob(取了一个非常通用的名字,因为我上一篇文章引起了一些麻烦)进行了一次谈话,他负责我们工程团队的“全局”。一如既往,在将自动化测试 (AT) 和单元测试 (UT) 引入常规开发计划时,存在一些阻力。Rob 也有关于缺乏强大的 AJAX 网站 AT 工具的合理观点。他还对如何以及在何处对我们的代码进行 AT 感到困惑,以便我们不仅仅是在测试数据库故障,而是测试执行业务逻辑和渲染逻辑的真实用户操作。因此,这次讨论包含了很多有用的信息,当你想要向你的 ASP.NET 和/或 AJAX 开发团队推销 AT,最终推销给高层管理人员,以便为你神圣的努力赢得足够的时间时,这些信息将帮助你做出正确的决定。
2007 年 1 月星期五 – 走廊
Omar:嘿 Rob,我们需要开始进行 AT,至少在我们的 Web 服务上。我们在手动 QA 上浪费了太多时间。QA 人员刚刚告诉我,他们昨晚加班进行回归测试,发现了一些明显的 Bug 来自开发,本应该在开发人员的电脑上就能发现。开发人员抱怨 QA 报告 Bug 太晚,导致他们加班。PM 说他们早上 9 点上班,晚上 11 点下班,已经 3 个月了。我们必须停止这种状况。过去 5 个冲刺(sprint)一直都是这样。这些家伙快要 burnout 了,纷纷寻找其他工作,要求加薪等等。我们必须更快地完成测试,并阻止明显的 Bug 进入 QA。我们需要自动化测试,以便开发人员可以在将代码提交给 QA 之前,从他们的电脑上运行自动化的回归测试套件,从而使 QA 免于每月重复的手动测试工作。QA 需要以自动化的方式运行更多的测试,而不是进行手动测试,这样他们就可以快速报告 Bug,以便开发人员在正常工作时间内修复。
Rob:当然,听起来很有趣。我会做一些可行性检查,看看如何将它纳入我们的下一个冲刺。
一个月后……在洗手间(面对领队)
Omar:嘿 Rob,让我们开始进行 AT 吧。上个月我没看到任何测试。我们这个冲刺可以开始吗?
Rob:当然,我们肯定可以从这个冲刺开始。我去找找看哪个工具适合我们。
又过了一个月……在会议室
Omar:嘿 Rob,到目前为止我还没有在解决方案中看到任何 AT。我们来认真开始做 AT 吧。你有没有制定计划,打算如何开始对 Web 服务进行 AT?
Rob:是的,我做了一些研究,找到了一些工具。但大多数工具都是针对非 AJAX 网站的,你可以通过编程方式访问 URL 或通过编程方式对 URL 进行 HTTP POST。你还可以录制浏览器上的按钮点击和表单提交。有 Visual Studio 的 Web Test,它在录制常规 ASP.NET 网站方面做得相当好,但在 AJAX 网站方面就比较差了。而且,你需要购买 Team Suite 版本才能获得 Web Test 功能。此外,录制和回放测试并不能真正帮助我们,因为所有这些测试都包含硬编码的数据。我们无法使用现成的工具来重复特定的步骤很多次,并使用随机数据。我们需要使用随机数据集来仔细、系统地进行测试,有时还要使用数据库中的真实数据。例如,一个常见的场景是从数据库加载 100 个随机用户帐户,然后以编程方式将这些用户登录到他们的门户,并测试门户是否显示了这些用户的个性化数据。所有这些都需要通过 AJAX 完成,而不使用任何浏览器重定向或表单提交,因为有一个页面允许用户使用 Ajax 调用登录,然后在成功登录后动态地在同一页面上渲染门户。UI 是通过 Javascript 渲染的,所以只有真实浏览器才能渲染它,而我们必须查看浏览器来测试输出。
Omar:我明白了,所以你不能使用 Visual Studio Web Test 在浏览器上运行 AT,因为它不允许你访问浏览器渲染的 HTML。你只能测试 Web 服务器返回的 HTML。因为我们是 AJAX 网站,我们的大部分工作都是通过 JavaScript 完成的——它们调用 Web 服务并渲染 UI。嗯,我在想如何使用 VS 来实现这一点。至少我们可以访问 Web 服务,看看它们是否返回了正确的 JSON。这样我们几乎可以测试整个 Web 服务、业务层和数据访问层。但它并不能真正取代手动 QA 的需求,因为 JavaScript 中有很多渲染逻辑。
Rob:现在有一个名为 Watin 的新项目,看起来很有前景。你可以编写 C# 代码来指示浏览器执行诸如单击按钮、运行 JavaScript 等操作,然后你可以检查浏览器在其 DOM 中渲染的内容并运行你的测试。但是,它仍然处于起步阶段。所以,真的没有一个好的工具来对 AJAX 网站进行 AT。我们还是坚持手动 QA 吧,这比开发人员想出的任何方法都更准确。我们可以将一组数据交给 QA,让他们输入并检查结果。
Omar:我们绝对需要想办法减少对手动 QA 的依赖。这根本无法扩展。每个冲刺,我们都必须冻结代码,然后交给 QA。他们运行他们庞大的测试脚本一整天。然后第二天,我们会收到 Bug 报告需要修复。如果出现严重的回归 Bug,我们必须取消冲刺,或者通宵工作来修复它,并进行夜间 QA 以满足部署日期。在过去的一年里,每个冲刺我们都会遇到一些 Bug,导致开发和 QA 工作到深夜。我们必须赋予开发人员自动化 AT 工具,以便他们可以自动运行完整的回归测试脚本。
Rob:你说的是一个非常漫长的项目。编写如此多的 AT 来进行完整的回归测试将是一个持续一个多月的项目。我们必须找到合适的工具集,计划要 AT 的区域以及如何进行,然后让开发和 QA 团队合作,准备好正确的测试。然后,在每个冲刺之后,我们必须保持测试套件的更新,以捕捉新的 Bug 和功能。
Omar:是的,这无疑是一个复杂的项目。我们必须达到一个阶段,让开发人员能够运行自动化 AT,而不是让 QA 测试每个任务的回归 Bug。事实上,我们应该有一个自动化的构建,在每次签入后运行所有 AT 并自动进行回归测试。
Rob:我们有自动化的构建和部署。所以,这已经完成了。我们需要将自动化的 AT 添加进去。说真的,考虑到我们产品的规模,要编写如此多的 AT 来自动完成所有回归测试是绝对不可能的。这不值得花费时间和金钱。我们的 QA 团队做得很好。他们可以在部署后休息一天,因为他们会通宵工作。
Omar:实际上,QA 团队正处于辞职的边缘。他们似乎有无尽的工作量。部署后,他们必须在生产环境上进行手动回归测试,以确保生产环境没有出现问题。在进行这些工作的同时,他们必须参加冲刺启动会议并编写测试计划。当他们快要完成时,开发人员会签入一些东西,并要求对不同的模块进行回归测试。在他们完成这些任务之前,我们就到了代码冻结期,他们必须完成所有这些任务级别的测试以及整个回归测试。所以,他们每个冲刺都会有几天需要昼夜不停地工作。他们真的受不了了。
Rob:这和我们的生活有什么区别?在部署日期熬夜之后,第二天我们必须参加长达 8 小时的冲刺计划会议。然后,我们必须从第二天立即开始处理任务,并在不到一周的时间内达到代码冻结。然后 QA 在最后一刻会提出很多 Bug。我们必须在冲刺的最后三天昼夜不停地工作来修复这些 Bug。然后,在令人筋疲力尽的部署日之后,我们必须熬夜等待 QA 报告任何关键 Bug,并在生产环境中立即修复它。我们也濒临崩溃。
Omar:我明白了。整个团队肯定都达到了极限。所以,这就是为什么我们需要自动化测试,因为它能解决开发和 QA 团队的问题。开发人员将以更快的速度完成测试,这样他们就不会在最后收到 Bug 报告,然后通宵修复它们。同样,通过让系统承担大部分测试工作,我们可以减轻 QA 团队持续的过度工作。
Rob:这肯定会毁掉团队。我们每个冲刺都有太多的产品功能和 Bug 修复要做。现在,如果我们要求每个人都为他们所做的每个任务编写 AT,那将是一个很大的负担。我们不能同时做这两件事。
Omar:同意。我们必须削减产品功能或 Bug 修复。我们必须在每个冲刺中腾出时间来编写 AT。
Rob:祝你好运。让我们看看你如何说服产品团队。
Omar:我先说服你。你是否相信我们应该这样做。
Rob:还没有。我真的看不到近期的收益,即使两个月后。我们有很多功能要做,还有很多客户要服务,我们无法进行足够的 AT 来真正减轻 QA 的负担。它只会成为每次冲刺,甚至每次任务的干扰和延误。
Omar:让我给你看一张图,我相信它会产生影响。
你看,我们写的自动化测试越多,花在手动 QA 上的时间就越少。这些时间可以用于进行新测试或任务级测试,提高每个已发布新功能的质量,并显著减少发布到生产环境的新 Bug。因此,我们在每个成功的冲刺后会发现越来越少的 Bug。
Rob:是的,我明白了,你不必说服我。但从整体收益的角度来看,我没有看到好处。我们在未来两个月内是否能更快地交付更好的产品?我们没有。我们交付的功能和 Bug 修复更少,却花费了大量时间编写对最终用户没有影响的 AT。
Omar:让我看看你的假设是否正确。
你看,自动化测试越多,QA 就能花更多时间在新功能或新 Bug 上。我同意,在最初的一两个冲刺中,测试新功能/Bug 的速度会下降,但随后它们会逐渐被赶上来,甚至变得更好。一开始,启动自动化测试的开销很大。但是随着冲刺的进行,需要编写的 AT 的数量会逐渐稳定下来,很快就会与新功能/Bug 成正比。不再需要花时间为旧的东西编写测试。因此,四个冲刺后编写的 AT 数量正好是我们该冲刺新任务所需的。
Rob:看看如果我们根本不做自动化测试,而是保持手动,会怎样?图看起来如何?
Omar:未来看起来相当黯淡。随着我们不断向产品添加内容,我们将花费大量时间进行回归测试,以至于 QA 最终将全职从事回归测试。他们将没有时间用于新功能,由于 QA 缺乏关注,我们将有更多的新 Bug 从 QA 泄漏到生产环境中。
Rob:好吧,我们怎么开始?
Omar:第一步是完成回归测试,这样我们就可以摆脱每个冲刺结束时那种长达 24 小时的马拉松式 QA。此外,我看到太多的开发人员在提交了一些任务后要求 QA 进行这里那里的回归测试。所以,QA 总是从每个冲刺的开始到结束都在进行回归测试。他们应该只测试尚未编写自动化测试的新内容,并让自动化测试处理现有的测试。
Rob:这很难说服管理层。我们将不得不说:“在接下来的一个月里,我们将只有一半的生产力,因为我们想花时间自动化我们的 QA 流程,这样从第二个月开始,我们就可以自动进行测试,QA 就可以有更多空闲时间。”
Omar:不,我们这样说:“在接下来的一个月里,我们将花 50% 的时间来自动化 QA,这样 QA 就可以多花 50% 的时间来测试新功能。这将使每个冲刺中产生的新 Bug 减少 50%。一个月后,这将为开发人员腾出 50% 的时间来构建新功能。”我们向他们展示这张图。
Rob:这似乎会很有说服力。但最初的几个冲刺,我们的速度会非常慢,以至于有些人可能会被解雇。想想看,从管理层的角度来看,开发团队的生产力突然减半。他们只构建了少量新功能,Bug 也不是以高速率修复的。客户在抱怨,投资者要求退款。情况会变得非常糟糕。你想承担这个风险吗?
Omar:我可以看到这是一个非常艰难的决定。我知道 CEO 会说什么,“我们需要从明天开始提高一倍的生产力,否则我们最好收拾东西回家。告诉我一些能让我们从明天开始提高一倍生产力的事情,而不是减半。”但你可以看到几个月后会发生什么。情况会糟到那时再做这件事是不可能的。我们甚至无法提出这个建议。现在,至少我们可以争辩,他们仍然有听取长期想法的意愿。但将来,当我们的 QA 团队全职进行回归测试,新功能 Bug 频频发布到生产环境,每次发布后新 Bug 的比例增加,更多的客户在抱怨,半成品功能在生产环境上运行——我们可能不得不关闭公司以求生存。
Rob:我们应该从第一天就开始进行自动化测试。
Omar:是的,不幸的是我们没有,而且我们拖延得越久,就会越困难。我确信我们会在下一个项目中从第一天就开始编写自动化测试,但我们必须挽救这个项目。
Rob:好的,我被说服了。我们怎么开始?我们肯定需要对业务逻辑层和数据访问层进行 AT。我们是开始为 DAL 和业务层中的每个函数编写 AT 吗?
Omar:在我看来,为 DAL 编写 AT 是没有意义的。请记住,我们的时间非常有限。我们最多有两个冲刺的时间来自动化 AT。在那之后,我们就不能再奢侈地花一半的时间来编写 AT 了。我们将不得不回到功能和 Bug 修复模式。所以,让我们明智地利用时间。我们只测试业务层函数怎么样?
Rob:那么,我们测试业务层中的函数,比如CreateCustomer
、EditCustomer
、DeleteCustomer
、AddNewOrder
?
Omar:这是业务层的最后一个层次吗?还有其他更高级别的层次来聚合这些类似 CRUD 的函数吗?
Rob:在许多领域,它就像 CRUD,只是对 DAL 的一个简单的包装,只有一些小的验证和异常处理。但有些地方有复杂的函数,会进行很多不同的 DAL 调用。例如,UpdateCustomerBalance
——它会调用很多 DAL 类来计算客户的当前余额。
Omar:Web 服务是否会调用多个业务类?它们是否像另一个聚合业务层的级别?
Rob:是的,Web 服务主要由用户操作调用,它们通常会调用多个业务层类来完成工作。
Omar:缓存是在哪里完成的?
Rob:Web 服务层。
Omar:这听起来是一个不错的开始 AT 的地方。我们将编写少量的 AT,仍然测试大部分业务层和数据访问类,并确保验证、缓存、异常处理代码运行良好。
Rob:但是还有其他工具和服务会调用业务层。例如,我们有一个运行的 Windows 服务,它直接调用业务层。
Omar:我们可以重构它,让它调用 Web 服务吗?
Rob:不行,那将是创建 10 个新的 Web 服务。开发工作量太大了。
Omar:好的,那么我们单独为那些业务层类编写 AT。我猜会有些重叠。一些 Web 服务调用也会测试那些业务类。但没关系。我们*应该*对业务层进行 AT。但我们没有时间,所以我们从一个更高级别的开始。Web 服务实际上并不是“单元”,但你必须做你必须做的事情。至少测试 Web 服务将确保我们通过 AT 覆盖了所有的用户操作。
Rob:是的,测试 Web 服务至少能确保用户操作得到测试。后台的 Windows 服务不是我们主要的担忧。现在我们如何测试表示层逻辑?我们有 ASP.NET 页面,还有那些 JavaScript 渲染代码。
Omar:我们用 Watin 来做。
Rob:如何将其作为 AT 套件的一部分?
Omar:Watin 可以很好地与 NUnit、mbUnit、xUnit 集成。我喜欢 xUnit。它是最实用的。特别是 SubSpec 插件,用于 xUnit 的 BDD 非常棒!
Rob:好的,那么我们如何对 UI 进行 AT?一个测试函数会点击登录链接,填写电子邮件和密码框,然后点击“确定”。然后等待一秒钟,看看 JavaScript 是否正确渲染了 UI?
Omar:差不多是这样。我们稍后可以详细讨论如何测试它。但是你怎么测试 UI 是否正确渲染?
Rob:我们从浏览器的 DOM 中检查用户的数据,比如姓名、电子邮件、余额等是否在浏览器的 HTML 中可用。
Omar:这真的能测试表示层逻辑吗?如果数据放错了位置怎么办?如果由于 CSS 错误,它没有正确渲染怎么办?
Rob:嗯,真的没有办法弄清楚它是否正确渲染。我们可以让 QA 人员在 Watin 在浏览器上运行测试时密切关注 UI。你可以在浏览器上看到 Watin 在做什么。
Omar:好的,这是一种方法,当然比 QA 完成整个步骤要快。但是否可以像匹配浏览器屏幕与某个截图一样自动完成?
Rob:是的,我们需要 AI 来做到这一点。
Omar:说真的,我们能不能编写一个简单的 UI 捕获和比较工具?假设我们拍摄一张正确输出的截图,然后清除一些可以变化的区域。然后 Watin 运行测试,它拍摄当前浏览器视图的截图,然后与某个截图进行匹配?这是想法。
假设这是一个我们想要在浏览器中匹配的模板截图。我们正在测试 Google 的搜索结果页面,以确保当我们提供某些预定义查询时,页面始终返回特定结果。所以,当 Watin 运行测试并将浏览器带到 Google 搜索结果页面时,它会拍摄一张截图,并忽略灰色区域中的任何内容。然后,它会对模板的其余部分进行逐像素匹配。所以,无论搜索查询是什么,无论 Google 在结果顶部提供什么广告,只要第一个结果是我们正在寻找的,测试就会通过。
Rob:正如我所说,这是 AI 的范畴。某个高度复杂的存在会比较两张截图,说,是的,它们差不多匹配,测试通过。
Omar:我认为在许多情况下,一个相当简单的位图匹配就足够了。只是一个想法,想想看。这样我们就可以测试 CSS 是否给我们像素完美的输出。QA 拍摄一张预期输出的截图,然后让自动化测试与浏览器当前的实际输出进行匹配。
Rob:好的,都是些好主意。让我们看看我们能做到多少。我们将从 Web 服务 AT 开始。然后我们将逐渐转向基于 Watin 的测试。现在是时候将这个提案推销给产品团队,然后再推销给管理团队了。
Omar:是的,至少让 Web 服务得到测试,这样 QA 在花费时间测试之前就能发现很多 Bug。目标是让开发人员尽可能快地完成尽可能多的测试,自动地,而不是让 QA 花时间在这些测试上。我们还可以将这些 Web 服务 AT 放入负载测试套件中,并对整个 Web 服务层进行负载测试。这将确保我们的代码是生产质量的,并且能够承受高流量。
Rob:明白了,再见。
. . .
一年后 – 代码冻结日
Omar:嘿 Rob,我们这个冲刺怎么样?
Rob:相当不错。3672 个 AT 中有 3842 个通过了。我们知道其中一些失败的原因。我们可以很快修复它们,并在午餐时运行一次完整的回归测试,离开时再运行一次。QA 昨天已经很好地完成了新功能的测试,他们今天还可以再检查一遍。我们的一些新功能也 covered by ATs 了。剩下的我们可以在下一个冲刺完成,不用担心。
Omar:太棒了。周末愉快。周一见。