云中的黄瓜:使用BDD脚本进行产品压力测试

Pixonic DevGAMM会谈报告的另一笔录。 Anton Kosyakin是一名技术产品经理,正在开发ALICE平台(例如酒店的Jira)。 他讲述了他们如何将现有测试工具集成到项目中,为什么需要负载测试,社区提供了哪些工具以及如何在云中运行这些工具。 以下是演示文稿和报告文本。


我们正在生产一个名为ALICE Platform的产品,现在我将告诉您它们如何解决负载测试问题。



ALICE是吉拉的酒店。 我们正在创建一个平台,以帮助他们处理自己的内幕。 礼宾服务,前台服务员,清洁工-他们还需要门票。 例如:客人打来电话>说您需要打扫房间>员工创建票证>打扫的人知道任务的执行者>执行>更改状态。

我们拥有b2b,因此数量可能并不令人印象深刻-只有1,000家酒店,5,000 DAU。 对于游戏而言,这并不多,但对我们而言却非常酷,因为最多有8个产品服务器,它们几乎无法应付这5000名活跃用户。 由于底层发生的事情略有不同-一堆数据库,事务等。



最重要的是:在过去的一年中,我们增长了2倍,现在我们在50人的区域拥有一支工程团队,我们计划在2019年使用户群翻一番。 这是我们面临的主要挑战。

生活中的一个例子。 在工作了60个小时的一周之后的星期五晚上,在23:00,我结束了最后一个通话,迅速完成了演示文稿,跳上火车,来到了这里。 大约五分钟前,我重新演示了一下。 因此,现在一切对我们都有效,因为我们是一家创业公司,很棒。 在我开车时,技术团队的一部分(我们称之为生产中着火)试图确保系统不会出现故障,同时用户也没有注意到这一点。 他们成功了,我们得救了。

如您所见,到目前为止,我们晚上还不能很好地入睡。 我们确定我们的基础设施将崩溃。 我们面对事实并理解这一点。 一个问题:什么时候? 这就是我们理解负载测试是成功的关键。 这是我们需要关心的。



我们的目标是什么。 首先,我们现在必须准确了解系统的容量和性能,以及它对当前用户的运行情况。 由于某些事情不起作用或进展缓慢,因此这应该在用户与我们违约之前发生(这可能是150家酒店的客户,而且赚了很多钱)。 另外,销售部门有一个计划:在明年增长一倍。 碰巧的是,我们购买了我们的主要竞争对手并将他们的用户迁移到我们自己。

我们必须知道,所有这些都可以承受。 在这些用户来之前,请提前知道,一切都会崩溃。

我们也会发布。 每个星期 在星期一 当然,并非所有版本都扩展了功能,在某些地方进行了维护,在某些地方进行了错误修复,但是我们必须了解用户不会注意到这一点,并且体验不会变差。

但是,作为优秀的开发人员,我们很懒惰,不喜欢工作。 因此,他们询问了社区和Google负载测试有哪些服务/解决方案。 有很多。 有一些简单的东西,例如Apache Bench,它只是通过url中的一百个线程来踢一个站点。 有一个带有机枪的Bees的邪恶版本,所有版本都相同,但是它启动了实例并放下了您的应用程序。 有JMeter,您可以编写一些脚本,在云中运行。



一切似乎都很好,但是经过深思熟虑,我们意识到我们确实必须工作并首先解决一些问题。



首先,您需要编写真实的场景来模拟满负载。 在某些系统上,用随机数据生成随机API调用就足够了。 在我们的情况下,这是长时间的用户场景:我接到一个电话,打开一个屏幕,驱使所有数据(调用了他想要的),保存了下来。 然后,它将出现在将执行请求的另一个人的移动应用程序中。 不是最琐碎的任务。

让我提醒您,每周发布。 功能已更新,脚本必须真正相关。 首先,您需要编写它们,然后再支持它们。

但这不是最大的问题。 以Flood.io为例。 一个很酷的工具,您可以在其中运行Selenium-在Chrome启动时,您可以控制它,并且它可以运行某种脚本。 您可以在其中运行JMeter脚本。 但是,如果我们想在JMeter脚本中运行Selenium,一切都会突然崩溃,因为将它们组合在一起的人做出了许多架构决策。 或者,例如,某些服务可以运行JUnit-它非常简单明了,但是其中一个服务编写了自己的JUnit,它只是忽略了一些东西。



负载生成问题迫在眉睫,因为每种工具都以自己的方式进行生成。 即使您设法确保方案足够,也会出现问题:如何多运行2-4次? 似乎是:运行,一切都很好。 但是没有 这些请求中有各种各样的ID-我们创建一些东西,获取一个新ID,更改旧ID,然后按ID加载实体,将其字段更改为另一个的测试。 加载10次相同实体的10次测试不是很有趣。 因为需要加载10次,然后加载不同的实体并正确缩放此加载。

好的,我们想解决负载测试的问题,以便准确了解应用程序将承受多少用户,并且我们的计划与销售部门的计划一致。 我们分析了市场上的解决方案,然后对意大利面和棍棒进行了盘点。

由于我们每周都会发布,因此自然而然地,我们自动化了一些测试-集成和其他测试。 为此,我们使用黄瓜。 这是用于行为驱动开发的BDD框架。 即 我们要求一些包含步骤的脚本。



我们的基础架构允许我们以两种模式运行集成和功能测试:只需踢后端,抽动API或通过Selenium实际运行Chrome并对其进行管理。

我们喜欢NewRelic。 它可以简单地监视服务器的主要指标。 它集成到JVM中,并拦截对控制器和Endpoint API的所有调用。 他们也为浏览器提供了一个解决方案,并且由于我们在那里拥有大多数功能,因此它也可以在浏览器中执行某些操作并提供某种指标。



因此,您需要将所有内容放在一起。 我们已经自动化了主要方案。 我们的方案(因为它类似于BDD)模仿了实际用户,并且负载类似于实际生产。 同时,我们可以扩展它。 由于这是发布过程的一部分,因此始终保持最新状态。



现在,让我们采用当前市场上的任何工具。 它们使用相同的原语进行操作:http,http,JSON,JUnit上的API调用,仅此而已。 但是,一旦我们尝试对Cucumber进行测试,它们就会执行相同的操作,并且对相同的内容进行操作,但是没有任何效果。 我们开始思考如何应对这一任务。

离题不大,因为BDD在游戏开发中不是一个非常流行的术语,所以它更适用于企业解决方案。



所有方案实际上都描述了某种行为。 场景描述格式非常简单:给定,何时,然后-用称为Gherkin的BDD表示。 对我们来说,黄瓜使用注释和属性将其映射到Java代码。 他做了他在场景中看到的事情:您需要给这个人一个苹果,让我们找到一种实现该目标的方法。



然后我们引入了像功能机器人这样的概念。 这是应用程序的特定客户端,它具有登录用户,注销,创建票证,查看票证列表等的方法。 它可以在三种模式下工作:移动应用程序,Web应用程序以及仅进行API调用。



简而言之,幻灯片上的内容相同。 功能文件分为脚本,有一些步骤,所有这些都是用英语编写的。



然后,Java代码Cucumber开始发挥作用,它将这些脚本映射到实际执行的代码。



此代码使用我们的应用程序。



并根据我们选择的内容:通过Selenium Chrome进入ALICE应用程序。



或通过http API进行相同操作。



然后(感谢Yandex for Allure Reports的人员),所有这些都很好地展示给我们-花费了多少时间,翻转了哪些测试,在哪一步,甚至在出现问题时应用了屏幕截图。



这是我们已经拥有的简短摘要。



如何从中建立负载测试? 我们让詹金斯(Jenkins)运行黄瓜套件。 这些是我们的测试,他们去了爱丽丝。 主要问题是什么? Jenkins在本地运行测试;它无法永远扩展。 是的,我们托管在Amazon的云中,我们可以要求一台超大型计算机。 无论如何,至少在某个时候,我们会打入网络。 有必要以某种方式加载此负载。 感谢亚马逊,他为我们着想。 我们可以将Cucumber Suite包装在Docker容器中,然后使用AWS服务(称为Fargate)说:“请启动它们。” 问题已解决,我们可以在云中运行测试。



然后,由于我们处于云中,因此请运行5-10-20 Cucumber Suite。 但是有一个细微差别:我们所有功能测试的每次运行都会生成一个报告。 一旦我们运行了400个测试并生成了400个报告。

再次感谢Yandex的开放源代码人员,我们阅读了文档和源代码,并意识到有多种方法可以将所有400个报告汇总为一个。 我们稍稍更正了数据,编写了一些扩展名,一切顺利。



现在,从詹金斯(Jenkins),我们说“给我们200个实例”。 “启动400个容器”说,我们的某些编排脚本转到了Amazon。 他们每个人都包含我们的集成测试,它们生成一个报告,该报告通过Aggregator收集在一起,放置在Jenkins中,应用于工作,超级有效。

但是

我敢肯定,你们中的许多人都从测试人员那里得到了奇怪的东西,例如“我玩了一个游戏,跳了10次,猛烈地按下了射击,然后不小心按下了关机按钮-角色开始闪烁,在空中冻结,然后关闭计算机,处理这个。” 您仍然可以与一个人达成共识,并说不可能复制。 但是我们有没有灵魂的机器,它们可以非常快速地执行所有操作,并且在某些地方数据无法加载,无法快速渲染,尝试按下按钮,但是还没有按钮,或者它使用了尚未从服务器下载的某些数据。 一切都崩溃了,测试是有缺陷的。 尽管(我想重点介绍),但是我们有运行Chrome的Java代码,该Chrome通过包装程序连接到另一个Java,并且可以执行某些操作,并且仍可以闪电般的速度运行。

好吧,由此引起的明显问题是:我们有5千个用户,并且仅启动了100个功能测试实例并创建了相同的负载。 这并不是我们想要的,因为我们计划下个月将有6000名用户。 很难理解这样的负载,也很难理解要启动多少个线程。

好,让我们的系统人性化。 用户界面如下所示:



有人打来电话,礼宾部想按下“创建新票”按钮,一个弹出窗口为他弹出,他需要填写所有字段。



但这不是立即发生的。 真正的人,直到他到达鼠标,直到他开始键入,直到他选择了某个东西,再单击“保存”。 因此,让我们放慢测试速度。



我们称之为人工模式。 您只需要测量步骤可以持续多长时间,如果步骤太快则需要一点“睡眠”。 同时,我们可以测量原则上该步骤花费了多少时间-如果5分钟,则可能破坏了用户体验。

由于我们已经进行了许多测试,因此我们没有在此基础上开始重写每个测试。 他们选择了AspectJ,将其添加到我们的代码中,再添加了5行代码,效果很好。

简短的演示。







这是时间轴运行。 绿色测试是好的,某处是坏的。 魅力将向我们展示其翻转位置的详细信息。

这是时间表,表明我们有很多实例。 他们进行了测试,发现有东西掉落了。



该系统确实有效-上周我们对战斗生产进行了首次测试。

现在,关于下一步,我们认为如何可以改进。



最重要的是,我们希望人们有一个很棒的用户体验。 这个想法是,我们可能会在应用程序上产生很大的负载,并且一切似乎都很简单-我们简单地测量了对服务器的每个请求的性能,无论它是在快速响应还是在性能下降开始时继续响应(服务器开始更慢地处理传入请求)。 但是没有 实际上,客户端/应用程序可以一次向服务器抛出多个请求。 然后等待它们全部处理完毕。 而且,如果其中一个请求最长(5秒)如何工作,并持续5秒钟,那么我们绝对不在乎其他人的工作方式-快或慢到4秒。 毕竟,我们仍将等待最长的五秒钟。 或您创建了票证,所有操作都在一毫秒内完成,但是由于内部索引缓存,该票证在系统中出现得太晚了。 常规方法无法解决此问题,因此我们想尝试衡量所有方案,并查看故障单创建脚本实际变差了多少。

因为 我们有所有基于uskey的场景,我们可以通过在接待处奔波一个人和10个清洁工来模仿。 然后是20或30个清洁工。 但是人民的面前仍然是一样的。 即 我们可以通过行为模式生成实际负载,非常接近实际负载。

还可以进行多区域测试。 我们的系统在世界范围内使用(尽管所有内容都托管在美国),因此我们可以从俄罗斯和美国产生负载,以查看其中哪个开始放慢速度。

听众的提问



-您被迫编写大量逻辑,并且当某些内容发生一些变化时,您会在功能测试中破坏很多内容。 事实证明,支持测试所需的时间几乎比开发所需的时间还要多?

“是的,但是没有。” 这是BDD,它们不是功能测试,它们更接近集成测试。 而且,无论我们进行什么更改,情况都将保持不变。 我按下一个按钮,看到一个窗口,在其中输入接收请求的房间的编号,人员的姓名和保留表格的日期。 如果布局发生更改,则字段将反转,如果后端发生了某些情况,则将保存测试,因为我们处于很高的级别,因此单击浏览器中的按钮。 因此,我们可以免受大量更改的影响。 有时候一切都可能崩溃。 因此,在发布过程中,那些编写新功能的人-他们负责查看是否有问题并修复。 但是到目前为止,还没有大量的此类问题。

-而且您没有一种情况,即一次更改后所有测试都变成红色。

-不是。 从理论上讲,如果脚本没有按钮,而是通过其他方式打开用于输入票证信息的窗口,则可能会发生这种情况。 但是,正如我之前所展示的,我们所有的场景都是由步骤组成的。 步骤无所不包,如果我们有100个脚本单击同一按钮,则步骤仍然是一个。 如果由于这一特定步骤导致所有操作失败,我们将对其进行更正,重新编写并所有测试立即变为绿色。

尽管曾经有一次,当我们不小心弄坏了东西时,它发生在我们身上。 仅剩下40%的绿色,尽管之前是99%。 那是一个小小的改变。 我们更正了一个步骤(代码行),所有内容再次变为绿色。

-尽管您没有集成测试,但它们并不完全起作用。 一种或另一种方式,这是一种按下按钮的图形界面,某些与外壳的交互特别发生。 我知道您以这种形式进行测试,您只是同时启动了许多线程。 他们为什么不安排由标准工具(JMeter,Gatling)生成的请求,这些工具不会以任何方式与外壳交互,而只是将请求倒入服务器?

-一切都很简单。 我们的应用程序的架构是什么? 我们有一个后端,我们有一个前端。 前端就是网络。 有一个移动应用程序。 创建票证时,我的前端也会连接到事件服务器。 我在后端创建了一张票,所有坐在同一家酒店的人都在同一家酒店看票,他们将从事件服务器到达:伙计们会更新,那里的数据已更改。 为了将所有内容放在一起,我们有一个要点-这就是客户。 , -, - . , , .

— ? . .

— , , . , Chrome . , , , , , . Chrome — , , . , , Java- . , .

— , , . . , : - ?

— , - . , , , . , , . YouTube , . , . , .

— . - Selenium Grid ? - .

— Cucumber': JAR, JAR Docker image Fargate' , image . flood.io grid Selenium , .

— ? , Chrome, . Internet Explorer 4 ( - ), ? - Android -.

— , enterprise. enterprise , requirements. — , , web view. Android web view , .

— , , Load-? ?

— .



Environment . . , Load, . 4- , , aliceapp.com. Load- , . , 504, , MySQL ElasticSearch.

— ( ), , ? .

— Load- , . 即 .

— , ?

— , . , , , .

— , , .. html API?

— Selenium DOM- : , , key down , — . .

— ? , ?

— . , . QC, , QC. Smoke- -. « -, ». — , , , .

Pixonic DevGAMM Talks


Source: https://habr.com/ru/post/zh-CN428349/


All Articles