需要违反的限制或我们如何加速功能测试三遍

图片

功能测试是一件有用的事情。 最初,他们并不需要花费很多时间,但是该项目正在不断发展,并且需要越来越多的测试。 我们无意容忍交付速度的下降,并且,我们在积strength力量的同时,加快了三倍的功能测试速度。 在本文中,您将找到通用的提示,但是,您会注意到对大型项目有特殊的效果。

简要介绍一下应用程序


我的团队正在开发一个公共API,该API为2GIS用户提供数据。 当您转到2gis.ru并查找“超级市场”时,您会得到一个组织列表-这是来自我们API的数据。 在我们的2000+ RPS上,如果某种功能崩溃,几乎每个问题都变得至关重要。

该应用程序是用Scala编写的,测试是用PHP编写的,数据库是PostgreSQL-9.4。 我们有大约25,000个功能测试,它们需要30分钟才能在专用的虚拟机上完成以进行一般回归。 测试的持续时间并没有给我们带来多少麻烦-我们已经习惯了这样的事实,即在旧框架上进行测试可能需要60分钟。

我们如何加快所谓的“快速”测试


这一切都是偶然发生的。 通常会发生。 我们支持一项功能,同时通过测试。 他们的人数在增加,完成它的必要时间也增加了。 一旦测试开始超出指定的时间限制,因此执行过程将被强制终止。 不完整的测试充满了代码中遗漏的问题。

我们分析了测试的速度,并迅速完成了加速测试的任务。 因此开始了一项名为“测试缓慢-修复它”的研究。

以下是我们在测试中发现的三个主要问题。

问题1:滥用jsQuery



我们拥有的所有数据都存储在PostgreSQL数据库中。 通常以json的形式,因此我们积极使用jsQuery。

这是我们在数据库中进行查询以获取必要数据的示例:

SELECT * FROM firm WHERE json_data @@ 'rubrics.@# > 0' AND json_data @@ 'address_name = *' AND json_data @@ 'contact_groups.#.contacts.#.type = “website”' ORDER BY RANDOM() LIMIT 1 

可以很容易地注意到该示例连续多次使用json_data,尽管这样写是正确的:

 SELECT * FROM firm WHERE json_data @@ 'rubrics.@# > 0 AND address_name = * AND contact_groups.#.contacts.#.type = “website”' ORDER BY RANDOM() LIMIT 1 

这样的缺点不太明显,因为在测试中,我们不是用手编写所有查询,而是使用QueryBuilders,它们自己在指定必要的功能后编写。 我们认为这不会影响查询的执行速度。 因此,在代码中看起来像这样:

 $qb = $this>createQueryBulder() ->selectAllBranchFields() ->fromBranchPartition() ->hasRubric() ->hasAddressName() ->hasWebsite() ->orderByRandom() ->setMaxResults(1); 

不要重复我们的错误 :如果在一个JSONB字段中有多个条件,请在单个运算符'@@'的框架中描述所有条件。 重做之后,我们将每个请求的执行时间缩短了两倍。 以前,所描述的请求花费了7500毫秒,但现在花费了3500毫秒。

问题2:额外的测试数据



密钥提供对我们API的访问,每个用户都有自己的API。 以前,在测试中,通常需要修改键设置。 因此,测试失败了。

我们决定为每次回归运行创建几个具有必要设置的关键点,以避免交叉问题。 而且由于创建新密钥不会影响整个应用程序的功能,所以这种测试方法不会影响任何事情。 他们在这样的条件下生活了大约一年,直到他们开始处理生产力。

钥匙不多-1000件。 为了加快应用程序的速度,我们将它们存储在内存中,每隔几分钟或根据需要进行更新。 因此,保存下一个密钥后,测试开始了同步过程,我们没有等待其结束-我们收到了响应“ 504”,该响应已写入日志中。 同时,该应用程序丝毫没有发出任何问题的信号,我们认为一切对我们都很好。 回归测试过程本身仍在继续。 最后,事实证明我们总是很幸运,而且我们的钥匙也被保存了下来。

我们一直无知,直到我们检查了日志。 原来,我们创建了密钥,但是在运行测试后没有删除它们。 因此,我们已经积累了其中的500,000。

不要重复我们的错误:如果您在测试中以某种方式修改了数据库,请确保确保数据库恢复到原始状态。 清理数据库后,密钥更新过程加速了500次。

问题3:随机抽样



我们喜欢在不同的数据上测试应用程序。 我们有很多数据,并且会定期发现问题。 例如,在某些情况下,我们没有上传有关广告的数据,但测试却及时地发现了这个问题。 因此,在我们测试的每个请求中,您都可以看到ORDER BY RANDOM()

当我们使用EXPLAIN查看有无随机性的查询结果时,我们发现性能提高了20倍。 如果我们谈论上面的例子,那么在没有随机的情况下,它的工作时间为160ms。 我们认真考虑了该怎么做,因为我们真的不想完全放弃这栋随意的房子。

例如,在新西伯利亚,大约有15万家公司,而当我们试图找到一家拥有地址,网站和标题的公司时,我们几乎从整个数据库中收到了一条随机记录。 我们决定将选择的人数减少到符合我们条件的前100家公司。 思想的结果是不断选择不同的数据和速度之间的折衷:

 SELECT * FROM (SELECT * FROM firm_1 WHERE json_data @@ 'rubrics.@# > 0 AND address_name = * AND contact_groups.#.contacts.#.type = "website"' LIMIT 100) random_hack ORDER BY RANDOM() LIMIT 1; 

用这种简单的方法,我们在20倍加速时几乎没有损失。 这样的请求的执行时间为180ms。

不要重复我们的错误:当然,这一刻几乎不能称为错误。 如果您确实有很多测试,请始终考虑一下数据中需要多少随机性。 在查询执行到数据库的速度与选择的唯一性之间进行权衡,使我们将SQL查询的速度提高了20倍。

再次简短列出操作:


  1. 如果我们在JSONB字段中指定了几种选择数据的条件,则必须在单个运算符'@@'中列出它们。
  2. 如果我们创建测试数据,请确保将其删除。 即使它们的存在似乎并不影响应用程序的功能。
  3. 如果每次运行都需要随机数据,我们会在样本的唯一性和执行速度之间找到折衷方案。

由于进行了简单(并且可能甚至很明显)的修改,我们使回归加快了三倍。 现在我们的25K测试可以在10分钟内通过。 这不是限制-我们接下来将优化代码。 尚不知道有多少意外发现在那等着我们。

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


All Articles