自动测试覆盖率可视化

现代的覆盖率报告在某些情况下是没有用的,并且衡量它们的方法主要仅适用于开发人员。您始终可以找出覆盖率的百分比或查看测试期间未使用的代码,但是如果您希望获得可见性,简便性和自动化,该怎么办?



下砍-从Qameta软件从一个报告阿尔乔姆Eroshenko的视频和成绩单Heisenbug会议他介绍了一些开发的简单而优雅的解决方案,这些解决方案可以帮助Yandex.Verticals团队评估由测试自动化工程师编写的测试的覆盖范围。Artem将告诉您如何快速找出所涵盖的内容,所涵盖的内容,已通过的测试以及立即查看可视化报告。




我叫Artyom Eroshenko 埃罗申科姆,我从事自动化测试已有10多年了。我曾经是测试自动化经理,工具开发团队经理,工具开发人员。

目前,我是测试自动化领域的顾问,我与一些与我们建立流程的公司合作。
我还是Allure Report的开发人员和秘密经理。我们最近修复了一个很酷的问题:现在,在JUnit 5中有固定装置。

阿特拉斯框架


我的开发是Atlas Framework。如果有人在2012年开始实现自动化,那时候Java Web驱动程序才刚刚起步,那时候我就做了一个名为HTML Elements的开源库

Html Elements在基于接口构建的Atlas库中有它的延续和重新思考:没有这样的类,没有字段,非常方便,轻巧且易于扩展的库。如果您想了解它,可以阅读本文或查看报告

我的报告致力于测试自动化问题,主要涉及涂料。作为背景,我想参考一下如何在Yandex.Verticals中组织测试过程。

垂直自动化是如何工作的?


Yandex.Verticals测试自动化团队中只有四个人可以自动化四个服务:Yandex.Avto,Work,Real Estate和Parts。就是说,这是一个由小型自动化人员组成的团队,他们做很多事情。我们使API,Web界面,移动应用程序等自动化。总共,我们大约有1.55万次测试,这些测试在不同级别上进行。

团队中测试的稳定性约为97%,尽管我的一些同事说约为99%。如此高的稳定性正是通过对本机技术的简短测试而实现的。通常,我们的测试大约需要15分钟,这非常大,并且我们在大约800个线程中运行它们。也就是说,我们有800个浏览器同时启动-这是我们测试的压力测试。作为铁,我们使用Selenoid(Aerokube)。您可以通过观看2017年的报告了解有关Yandex.Verticals中自动化测试的更多信息,该报告仍然有意义。



我们团队的另一个特点是,我们使包括手工测试人员在内的所有工作都实现了自动化,这为测试自动化的发展做出了巨大贡献。对于他们,我们组织学校,教他们测试,教如何为API,Web界面编写测试,并且通常它们会在测试过程中提供帮助。因此,如有必要,负责发布的人员可以立即更正测试。

在Verticals中,测试开发人员编写测试,他们非常热衷于测试开发,因此可以与我们竞争。您可以从报告“测试React应用程序的整个周期”中了解有关此过程的更多信息。,Alexei Androsov和Natalya Stus讨论了他们如何与我们的Java端到端测试并行地在Puppeteer上编写单元测试。

测试自动化工程师也在我们的团队中编写测试。但是我们经常会开发一些新方法来优化它们。例如,我们实施了屏幕截图测试,通过moki进行测试,减少了测试。一般而言,我们的领域主要是测试中的软件开发人员(SDET),我们更多地是关于如何编写测试的,并且测试基础由我们部分填充,并由手动测试人员提供支持。
开发人员也可以帮助我们,这很酷。

这些过程中出现的问题是,我们并不总是了解已经覆盖的内容和没有覆盖的内容。通过一万五千次测试,并不总是清楚我们要检查的内容。在与经理沟通的情况下尤其如此,经理当然不会测试,而是会监控并提出问题。特别是,如果出现问题是在界面或流程中是否测试过某个特定按钮,则很难回答,因为您需要转到测试代码并查看此信息。

什么经过测试,什么未经测试?


如果您有许多使用不同语言编写的测试,并且都是由受过不同程度培训的人编写的,那么迟早会出现问题,这些测试是否根本不相交?在这个问题的背景下,覆盖范围的问题变得尤为重要。我将概述三个关键主题:

  • 有效衡量覆盖率的方法。
  • API测试的覆盖范围。
  • 网络测试的覆盖范围。

首先,让我们确定覆盖的方式有两种:覆盖需求和覆盖产品代码。

如何衡量需求覆盖率


考虑使用auto.ru作为示例的需求范围。代替auto.ru测试器,我将执行以下操作。首先,我将使用google并立即找到一个特殊要求表。这是需求覆盖范围的基础。



在此表中,需求的名称写在左侧。在这种情况下:帐户,广告,验证和付款,即公告的验证。通常,这是覆盖范围。左部分的细节取决于测试仪的水平。例如,来自Google的工程师拥有49种类型的涂料,这些涂料经过了不同程度的测试。

该表的右侧是需求属性。我们可以使用属性形式的任何东西,例如:优先级,覆盖范围和状态。这可能是上次发布的日期。



因此,某些数据出现在表中。您可以使用专业工具维护需求表,例如TestRail。
右侧有关于树的信息:文件夹指示我们有什么要求,以及如何满足这些要求。有测试用例等。



在垂直行业中,此过程如下所示:手动测试人员描述需求和测试用例,然后将其传递给自动化测试,自动化工具为这些测试编写代码。此外,我们在前面给出了详细的测试用例,其中手动测试人员描述了整个结构。然后有人在github上进行了提交,测试开始变得有益。

这种方法的优缺点是什么?另外,这种方法可以回答我们的问题。如果经理询问我们所涵盖的内容,我将打开平板电脑并显示所涵盖的功能。另一方面,这些要求必须始终保持最新,并且很快就会过时。
当您进行1.5万次测试时,看着TestRail就像看着太空中的一颗星星:它爆炸了很长时间,而光线才刚刚到达您的手中。您看一下当前的测试用例,它已经很长时间已经过时并且无法撤销。

这个问题很难解决。对我们来说,通常是两个不同的世界:存在一个按照自己的规律发展的自动化世界,其中每个失败的测试都将立即得到解决,并且存在一个手动测试和需求卡的世界。除非使用Allure Server,否则它们之间的墙是无法穿透的。现在,我们为他们解决这个问题。

“利弊”的第三点是需要手工工作。在一个新项目中,您需要重新创建一个需求图,编写所有测试用例,等等。它总是需要手工操作,实际上非常可悲。

如何测量代码覆盖率


此方法的替代方法是代码覆盖率。这似乎是我们问题的解决方案。这就是产品代码覆盖范围的样子:



它反映了包装的覆盖范围,或者只是产品中通常所包含内容的一小部分。与以前编写的功能一样,程序包写在左侧。也就是说,我们的涂层最终会附着在一些有形的东西上,在这种情况下,就是包装。属性写在右边:按类覆盖,按方法覆盖,按代码块覆盖和按代码行覆盖。
收集覆盖范围的过程是了解测试通过了哪一行代码,哪些没有通过。这是一个相当简单的任务,但是最近非常相关。

关于代码覆盖率的第一次提及可以追溯到1963年,但是直到现在才在这个方向上取得重大进展。

因此,我们有一个与系统交互的测试。不管他如何与她互动:通过前端,API还是直接爬入后端-我们仅假设我们拥有它。

然后应该进行检测。这是使您了解哪些代码行已被检查以及哪些代码行未被检查的过程。您无需对其进行详细研究,只需要查找框架的名称,在该框架上编写例如Spring,然后InstrumentationCoverage-使用这三个词,您将了解如何完成此工作。

当您的测试检查测试命中和未命中的代码行时,它们会保存文件,其中包含有关覆盖哪些行的信息。根据此信息,您将获得数据。

代码覆盖的优缺点是什么?


代码覆盖率我会立即称之为减号您不会来找经理,也不会显示此盘子,也不会说每个人都已经自动化,因为无法读取此数据,他将要求您返回清晰的数据,以便您快速查看并了解所有内容。

代码覆盖率报告更接近开发。如果我们希望整个团队都能观看,则不能将其用作向团队提供所有数据的常规方法。



这种方法的优点是它总是提供相关数据。您不必做很多工作,一切都将自动完成。只需插入图书馆,您的封面就开始脱落-真的很酷。
这种方法的另一个优点是只需要定制。那里没有什么特别的事情-只需附带特定的说明,调整覆盖范围,它就会自动工作。

需求的覆盖范围使您可以识别未满足的需求,但不允许评估与代码有关的完整性。例如,您开始编写一个新功能“授权”,只需输入“授权功能”,就可以开始对它进行测试。即使您编写了一些新类,您也无法立即在代码中看到此覆盖范围,但是仍然没有任何信息-存在差距。另一方面,这是授权的要求,即使已经实施,但当您计算覆盖范围时,这部分就不重要了,必须手动更新。

因此,我们有一个主意:如果我们能从所有人那里得到最好的呢?为了使报道能回答我们的问题,它始终是相关的并且仅需要自定义。我们只需要从另一个角度看待涂层,即以另一个系统作为涂层的基础。同时,请确保完全自动收集它并带来很多好处。为此,我们将介绍API测试。

测试覆盖率API


承保范围的依据是什么?为此,我们使用Swagger-这是文档API。现在,我无法想象没有Swagger的工作,它是我经常用于测试的工具。如果您不使用Swagger,我强烈建议您访问该网站并熟悉一下自己。在那里,您将立即看到一个非常直观且易于理解的使用示例。
实际上,Swagger是您的服务生成的文档。它包含了:

  • 请求列表。
  • 请求参数:无需拉开开发人员并询问什么参数。
  • 答案码



Swagger的操作原理是生成。使用哪种框架都没有关系。假设是Spring或Go Server,则使用Swagger Codegen组件并生成swagger.json。这是一些规范,然后在此规范的基础上绘制了漂亮的UI。使用swagger.json
对我们很重要:它的支持适用于所有广泛使用的语言。 我们有Open API规范swagger.json。它看起来像这样: 请求看起来像这样:摘要,描述,响应代码和一个“句柄”(路径:/用户)。还有关于查询参数的信息:一切都是结构化的,有一个用户ID参数,它在需要的路径中,例如描述和类型-整数。








有响应代码,也有文档记录:



这个想法浮现在我们的脑海:我们拥有Swagger生成的服务,我们希望在测试中保留相同的Swagger,以便以后进行比较。换句话说,当测试运行时,它们会生成完全相同的Swagger,将其扔到Swagger Diff,我们了解我们检查了哪些参数,句柄,状态代码,等等。这是相同的仪器,相同的覆盖范围,只是最终在我们了解的需求中。

但是,如果您创建一个差异文件怎么办?


我们转向Swagger diff,这是我们需要的。它的工作原理是这样的:您有1.0版,API版本为1.1,它们都生成swagger.json,然后将它们扔到Swagger diff上并查看结果。
结果看起来像这样:



您有信息,例如有一支新笔。您还拥有有关删除内容的信息。这意味着该删除测试了,它们不再相关了。随着有关更改信息的出现,参数也随之更改,因此很明显,此时您的测试将失败。

我们喜欢这个想法,并开始实施。正如我们决定要做的那样:我们有一个从开发人员代码生成的“参考” Swagger,还有一些API测试将生成我们的Swagger,并且将在它们之间进行区分。

因此,我们对服务进行测试:我们拥有Rest Assured,它本身可以访问API上的服务。然后我们对其进行检测。有一种方法:您可以创建过滤器,然后将请求发送至该过滤器,然后它将有关请求的信息直接以swagger.json的形式保存
这是我们需要编写的整个代码,共有69-70行-这是一个非常简单的代码。



有趣的是,我们将本地客户端用于Swagger,就在此处编写。我们甚至不需要创建二进制文件,只需填写Swagger规范即可。



我们有很多需要处理的.json文件-他们编写了Swagger聚合器。这是一个非常简单的程序,可根据以下原理工作:

  • 她补充说,她满足了一个新请求,如果它不在我们的数据库中。
  • 她满足了要求,他有一个新参数-添加。
  • 状态码也一样。

因此,我们可以获得有关所使用的所有笔,参数和状态代码的信息。此外,您可以在此处收集执行这些请求的数据:用户名,登录名等。我们尚未弄清楚如何使用此信息,因为所有信息都是由我们生成的,但是您可以通过某些参数来了解调用某些请求的方式。

因此,我们离胜利几乎只有一箭之遥,但是结果我们拒绝了Swagger Diff,因为它的工作原理略有不同-在差异性概念上。

Swagger Diff说发生了什么变化,而不是覆盖范围,但是我们想显示覆盖范围的结果。有很多额外的数据,它存储有关描述,摘要和其他元信息的信息,但我们没有此信息。当我们制作Diff时,他们写信给我们,“这支笔没有描述”,但它不存在。

自己的报告


我们进行了实现,其工作方式如下:我们有许多来自自动测试的文件,我们具有Swagger服务API,并基于此生成报告。
一个简单的报告如下所示:在上方,您可以看到有关总共有多少支笔(349)的信息,有关哪些笔被完全覆盖的信息(每个参数,状态码等)。您可以选择自己的条件,例如,涵盖多个参数。

这里也有信息,其中40%被部分覆盖-这意味着我们已经对这些笔进行了测试,但是某些内容尚未覆盖,您需要在那里仔细看。空的覆盖范围也被反映出来。



让我们浏览选项卡。这是一个完整的覆盖范围,我们将看到所包含的所有参数,状态码等。



然后我们进行部分覆盖我们看到在登录社交句柄上,一个参数被覆盖,而两个则没有。我们可以对其进行扩展,并查看涵盖了哪些特定参数和状态代码。现在,这对开发人员来说非常方便:应用程序的版本滚动非常快,我们常常会忘记一些参数。



使用此工具,您可以始终保持良好状态,并了解我们已部分涵盖的内容,忘记了哪个参数等等。

最后-耻辱的荣耀,我们仍然必须这样做。当您查看此页并在此处看到“空”时:172-手放下,然后您开始教手测试仪如何编写自动测试,这就是重点。



推出解决方案后,我们获得了什么好处?


首先,我们开始更有意义地编写测试。我们知道我们正在测试,同时我们有两种策略。首先,我们将手动测试人员出现时不存在的东西自动化,并说对于特定服务,一个请求至少执行一次至关重要,然后打开Empty。

第二种选择-我们不会忘记尾巴。就像我说过的那样,API将很快发布,每天可能会有两次或三次发布。一些参数不断地添加到那里:在五千次测试中,无法理解检查的内容和未检查的内容。因此,这是有意识地选择测试策略并至少做某事的唯一方法。
第三个利润是全自动过程。我们借用了这种方法,自动化工作了:我们不需要做任何事情,一切都是自动收集的。

发展思路


首先,我真的不想保留第二份报告,但我想将其集成到Swagger UI中。这是我最喜欢的“ Photoshop Edition报告”:我最近一直在开发一种芯片。在这里立即有关于我们测试过的参数的信息,而没有测试过的。立即使用Swagger提供此信息将很酷。



例如,前端可以亲自查看哪些参数尚未经过测试,确定优先级并确定虽然不需要将其纳入开发过程,但尚不清楚它们的工作情况。或后端书写一支新笔,看到红色并踢测试人员,以便所有内容均为绿色。这很容易做到,我们正朝着这个方向前进。

第二个想法是支持其他工具。实际上,我不想为特定的实现编写过滤器:针对Java,Python等。创建一个代理的想法是,它将通过自身传递所有请求,并为自己保存Swagger信息。因此,我们将拥有一个通用库,无论您使用哪种语言,都可以使用该库。

第三个开发思路是与Allure Report集成。我是这样看的:



通常,当参数被“测试”时,这并不总是告诉我们如何测试它。我想指出该参数并查看测试的具体步骤。

网络测试范围


我想谈的下一点是Web测试的范围。覆盖范围基于您正在测试的站点,并在该站点上编写测试。但是您可以将其设置为覆盖范围的网络界面。例如,它看起来像这样:



如果您查看自己的站点-这是一些元素以及与之交互的方式。这是一个完整的描述:“元素是与之交互的一种方式”。您可以单击链接,可以复制文本,可以将某些内容输入。该站点总体上由其交互的元素和方式组成:



测试的运行方式:它们从某个点开始,例如,填写某种表格(例如授权表格),然后分散到其他页面,然后再分散到另一个页面并结束。

如果管理者询问是否正在测试特定按钮,但是这个问题很难回答:您需要打开代码或转到TestRail,那么我想看到针对该问题的解决方案:



我要指向此元素并查看我们拥有的所有测试在这个项目上。如果有这样的工具,我会很高兴。当我们开始考虑这个想法时,我们首先看了Yandex.Metrica。它们实际上具有与链接映射大致相同的功能。一个好主意。

底线是突出显示它们的方式就像它们已经提供了我们所需的信息一样。他们说:“这里我们已通过此链接14次”,这翻译成测试语言意味着:“在此链接中测试了14个测试”,并以某种方式通过了该链接。但是这个红色链接需要进行多达120项测试,真是有趣的测试!

您可以绘制各种趋势,添加元信息,但是如果我们将其全部考虑并从测试的角度进行绘制,会发生什么?因此,我们有一个任务:指向某个元素并获得带有测试列表的注释。



为了实现这一点,您需要单击图标,然后写一个便笺,这是我们的整个测试。我们在自己的地方使用Atlas,而到目前为止仅与它集成。
Atlas看起来像这样:

SearchPage.open ();
SearchPage.offersList().should(hasSizeGreaterThan(0));

我们希望至少显示一个结果,否则我们将不会对其进行测试。然后,将光标移动到该元素,然后单击它。

searchPage.offer(FIRST).moveCursor();
searchPage.offer(FIRST).actionBar().note().click();

然后,我们将输入User_Text保存并提交。

searchPage.offer(FIRST).addNoteInput().sendKeys(USER_TEXT);
searchPage.offer(FIRST).saveNote().click();

在那之后,我们检查文本是否正确。

 searchPage.offer(FIRST).addNoteInput().should(hasValue(USER_TEXT));

测试在浏览器中运行,Atlas是该测试的代理,我们在这里采用了每个人在收集覆盖率时都使用的相同方法:我们将使用.json进行定位。我们将在其中保存有关所有页面打开,带有元素的所有迭代,谁提交,谁执行sendkey,谁单击,哪些ID等的信息-我们将保留完整的日志。

那么我们该日志重视倾城在每个测试的形式,当我们有很多的locators.json,我们产生meta.json。所有元素的方案都是相同的。

我们有一个用于Google Chrome的插件。我们希望以插件的形式做出决定。我特意制作了一个曲线屏幕截图,以便在locators.json的幻灯片路径上可以看到一个重要的细节



如果您现在生成了报告,那么今天将有一个覆盖图。如果您获取前两周的报告并将其粘贴在此处,则会显示两周前的覆盖率地图。您有时间机器!
但是,当您插入此插件时,它会绘制一个不太友好的界面。



每个元素都有许多测试通过:很显然,有40个测试通过“购买公寓”,标题一次被测试了一次,这很酷,并且还显示了“公寓”选项。您将获得完整的覆盖图。

如果将鼠标悬停在某个元素上,它将获取数据并打印来自tms,Allure Board等的真实测试。结果是有关正在测试的内容和方式的完整信息。
请注意,在每次测试中,您都可能直接在“魅力”报告中失败。



当您打开任何东西时,它将加载新的选择器:如果您有通过这些选择器的任何测试,并且您对该站点进行了某些操作,它将处理并显示整个图片。

什么是利润?


一旦我们实现了这种简单的方法,那么,主要地,我们便开始了解我们在测试中测试的内容。

现在,任何人都可以进入并找到导致脚本的任何“线程”。例如,假设您需要测试付款。显然,付款是通过“付款”按钮进行的​​:单击-显示通过付款按钮的所有测试。很好!您进入其中任何一个并查看脚本。

此外,您了解以前已经测试过的内容。我们生成一个静态文件,您可以指定它的路径并指出两周前进行了哪些测试。如果经理说生产中存在错误,并且在几周前询问我们是否测试了该功能或该功能,那么您以“魅力”报告为例,例如,您没有进行测试。

另一个好处是自动化测试后的审查。在此之前,我们在进行自动化测试之前进行了审核,现在您可以完全按照自己的意愿进行测试。如果您想进行测试-完成,请转到某个分支,启动Allure,将插件的链接删除到手动测试器,并要求查看测试。这正是使您能够加强敏捷策略的过程:团队负责人进行代码审查,而手动测试人员进行测试(脚本)。

这种方法的另一个优点是经常使用的元素。如果我们覆盖该块(其中有87个测试),那么所有这些测试都会掉落。您开始了解测试的脆弱性。



而且,如果“价格从”这一价格块被推翻了,那就可以了,一个测试会下降,一个人会纠正它。如果使用87个测试更改该块,则覆盖率将大幅下降,因为87个测试将不通过且不会检查任何结果。这个障碍需要更多的关注。然后,您需要告诉开发人员该块必须带有ID,因为如果它离开了,一切都会崩溃。

您如何进一步发展?


例如,您可以遵循开发对其他工具(例如Selenide)的支持的方法。我什至不希望支持特定的Selenide,而是支持一种驱动程序实现,无论您使用什么工具,都可以收集定位器。该代理将转储信息,然后显示它。

另一个想法是显示当前的测试结果。例如,将这样的图片立即交给手动测试人员很方便:



您不必去考虑哪些测试已损坏,因为您可以访问站点,单击测试并手动通过,而无需检查其他测试。这很容易,您可以从Allure那里获取此信息并在此处绘制。

您还可以添加“总分”,因为每个人都喜欢图形,因为我想处理重复的测试,这些测试彼此非常相似,其中心部分相同,并且开头和结尾有些变化。



我还想立即看到重复选择器的数量。如果该值很高,则需要在此页面上进行重构并运行测试,否则它们将被捆绑在一起。与我们交互的元素数量也是如此。这是一些常见的症状。但是,一旦您与页面进行交互,由于新的元素和测试用例的总数,该图将跳过,因此您需要添加某种分析,这不会是多余的。

您还可以按层添加测试的分布,因为您不仅希望看到我们拥有这些测试,而且还希望看到此页面上的所有类型的测试,甚至可能是手动测试。

因此,如果存在Java测试以及另一个团队在Puppeteer上编写的测试,我们可以查看特定页面并立即说出我们的测试相交的地方。也就是说,我们将与他们说相同的语言,并且我们将不需要一点一点地收集此信息。如果我们有一个可以在Web界面中显示所有内容的工具,那么比较Java和Puppeteer中的测试的任务似乎不再是可以解决的。

最后,让我们谈谈一般策略。我们已经讨论了什么类型的覆盖率(称为两种),并提出了第三种涂层,因此我们使用了第三种涂层。因此,我们只是从另一个角度审视了这个问题。

一方面,自从1963年以来,就开始进行报道,另一方面,有一些手动测试人员习惯于生活在比代码更真实的世界中。仍然只有结合这两种方法。

有兴趣的人可以随时加入我们的社区。这是我们的两个处理覆盖问题的存储库:


All Articles