串行测试 并行测试

by Karel Rochelt

卡雷尔·罗切尔特(Karel Rochelt)

如何通过CircleCI测试并行性增加构建时间 (How to boost build time with CircleCI test parallelism)

Providing an error-free API for a heavily developed project is not an easy task. Likely, the first things that come to mind are tests. For a mid-sized API, you may write hundreds or even thousands of end-to-end tests. These tests significantly prolong build times.

为高度开发的项目提供无错误的API并非易事。 可能想到的第一件事就是测试。 对于中型API,您可以编写数百甚至数千个端到端测试。 这些测试大大延长了构建时间。

In this post, we will explain how we solved long build times with CircleCI test parallelism and Gradle/Grails for Amio main service.

在这篇文章中,我们将说明如何使用CircleCI测试并行性和用于Amio主服务的Gradle / Grails解决较长的构建时间。

CircleCI设置 (CircleCI setup)

CircleCI’s documentation does a decent job of explaining how their command line interface (CLI) tool should be used to enable test parallelism. When I started looking into it for the first time, it wasn’t entirely obvious what the returned result would look like. I was asking myself, “So, I’ll run this command and it will magically start splitting my tests?” Well, of course not! The result is a list of test files that should be executed on a particular container.

CircleCI的文档在解释如何使用其命令行界面 (CLI)工具来启用测试并行性方面做得不错。 当我第一次开始研究它时,返回的结果看起来并不完全是显而易见的。 我问自己:“那么,我将运行此命令,它将神奇地开始拆分测试?” 好吧,当然不会! 结果是应在特定容器上执行的测试文件的列表。

Does that sound complicated? Let me explain in an example.

这听起来复杂吗? 让我举例说明。

The first thing we have to do is to set the parallelism key in the .circleci/config.yml file. From the CircleCI docs:

我们要做的第一件事是在.circleci/config.yml文件中设置并行键。 从CircleCI文档:

The parallelism key specifies how many independent executors will be set up to run the steps of a job.

parallelism键指定将设置多少个独立执行器来运行作业的各个步骤。

Any value greater than one will enable parallel execution, but for the sake of this example, let’s go with two. This way, every time a CircleCI job is started, it will spawn two containers which will both do the same tasks.

任何大于1的值都将允许并行执行,但就本示例而言,让我们处理2。 这样,每次启动CircleCI作业时,它将产生两个容器,它们将执行相同的任务。

If we were to use the parallelism key with no additional configuration, it would just run all of our tests twice. That is not what we want. We want to split our tests between the containers.

如果我们使用并行键而不进行其他配置,则它将只运行两次所有测试。 那不是我们想要的。 我们想在容器之间拆分测试。

That’s where the CircleCI CLI comes in. It offers two commands which, when used together, split our tests into equal portions across our two containers.

这就是CircleCI CLI的用处。它提供了两个命令,这些命令一起使用时,会将我们的测试分成两个容器,分成相等的部分。

Let’s say these are the test files in our project:

假设这些是我们项目中的测试文件:

src/integration-test/groovy/com/package1/Test1.groovysrc/integration-test/groovy/com/package1/Test2.groovysrc/integration-test/groovy/com/package2/Test3.groovysrc/integration-test/groovy/com/package2/Test4.groovysrc/integration-test/groovy/com/package2/Test5.groovy

Naturally, we will have other source files in our project; not just our tests. They may be located in the same src/integration-test/… directory. To achieve our goal of test splitting, we need to select only the test files for the project. That is done by using the glob command:

当然,我们的项目中将包含其他源文件。 不只是我们的测试。 它们可能位于相同的src/integration-test/…目录中。 为了实现我们的测试拆分目标,我们只需要为项目选择测试文件。 这可以通过使用glob命令来完成:

circleci tests glob "src/integration-test/**/*.groovy"

This command will output the list of our tests (all 5 of them). ? Now we use the split command to, well, split them between containers:

此命令将输出我们的测试列表(全部5个)。 ? 现在,我们使用split命令在容器之间分割它们:

circleci tests glob "src/integration-test/**/*.groovy" | circleci tests split --split-by=timings

The split command offers several strategies to split the tests but timings is my favorite. It uses the timings data that is collected by CircleCI (this has to be enabled via the store_test_results key) to split the tests into portions that take a similar time to execute. Container indexing is automatic. We can run the same command on every container. In our example, running the command on Container 0 might output:

split命令提供了几种拆分测试的策略,但是timings是我的最爱。 它使用CircleCI收集的计时数据(必须通过store_test_results键启用此计时数据)将测试分成需要花费相似时间执行的部分。 容器索引是自动的。 我们可以在每个容器上运行相同的命令。 在我们的示例中,在容器0上运行命令可能会输出:

src/integration-test/groovy/com/package1/Test1.groovysrc/integration-test/groovy/com/package2/Test3.groovy

And on Container 1:

在容器1上:

src/integration-test/groovy/com/package1/Test2.groovysrc/integration-test/groovy/com/package2/Test4.groovysrc/integration-test/groovy/com/package2/Test5.groovy

I say “might” because the real result would depend on the timings data. As you can see, every container got its half of the tests.

我说“可能”是因为实际结果将取决于计时数据。 如您所见,每个容器都进行了一半的测试。

Gradle设置 (Gradle setup)

Splitting the tests in CircleCI was the easy part. The hard part is getting Gradle to execute just the tests that are in the result of the split command. If we were using JavaScript and Mocha, it would be much easier. Mocha accepts a list of files which should be executed. With Gradle 3, I had been using this command to run tests: ./gradlew check -i

在CircleCI中拆分测试很容易。 困难的部分是让Gradle仅执行split命令结果中的测试。 如果我们使用JavaScript和Mocha,那会容易得多。 Mocha接受应执行的文件列表。 在Gradle 3中,我一直使用此命令来运行测试: ./gradlew check -i

Gradle’s documentation isn’t really helpful. Just figuring out what the check task does is a pain. Thankfully, it is possible to pass our test list as a parameter to the Gradle task.

Gradle的文档并没有真正帮助。 仅弄清楚检查任务的作用是很痛苦的。 幸运的是,可以将我们的测试列表作为参数传递给Gradle任务。

./gradlew check -i -PtestFilter="`circleci tests glob "src/integration-test/**/*.groovy" | circleci tests split --split-by=timings`"

Now, when the check task is started, it has access to the testFilter parameter. To make everything work, we also need to add some code that can handle the parameter in our build.gradle:

现在,当check任务启动时,它可以访问testFilter参数。 为了使一切正常,我们还需要在build.gradle中添加一些可以处理参数的代码

integrationTest {  if (project.hasProperty("testFilter")) {    List<String> props = project.getProperties().get("testFilter").split("\\s+")    props.each {      include(it.replace("src/integration-test/groovy/com/", "**/").replace(".groovy", ".class"))    }  }}

Note that the parameter was passed to the task as a single string. In the code block above, Line 3 contains logic to split it back into rows. Calling include will tell Gradle to execute only the tests that we include. Now we can include all the rows, and we’re good, right?

请注意,该参数已作为单个字符串传递给任务。 在上面的代码块中,第3行包含将其拆分回行的逻辑。 调用include将告诉Gradle仅执行我们包含的测试。 现在我们可以包括所有行了,我们很好,对吧?

Nope. Gradle doesn’t know how to work with source files. It only understands classes. We need to pass the compiled class files to it.

不。 Gradle不知道如何使用源文件。 它只了解类。 我们需要将编译后的类文件传递给它。

There are two problems with that. First, the compiled classes are not in the same directory. Second, the suffix is not .groovy but .class.

这有两个问题。 首先,已编译的类不在同一目录中。 其次,后缀不是.groovy而是.class。

To overcome the first problem, we replaced the common prefix with **/. This says, “Look in the root directory and all its subdirectories.” Of course, you could replace it with something like build/classes/integrationTest/com. That is cleaner, but not necessary. This should be safe as long as the test classes names are unique. Line 5 in the code block above includes logic that solves both of these problems.

为了解决第一个问题,我们将通用前缀替换为** /。 它说:“查看根目录及其所有子目录。” 当然,您可以将其替换为build/classes/integrationTest/com 。 那比较干净,但不是必需的。 只要测试类名称是唯一的,这应该是安全的。 上面代码块中的第5行包含解决了这两个问题的逻辑。

In the end, your .circleci/config.yml should look something like this (just the relevant part):

最后,您的.circleci/config.yml应该看起来像这样(只是相关部分):

- run:    # This is just for debugging purposes, you can omit this step    name: test splitting output    command: circleci tests glob “src/integration-test/**/*.groovy” | circleci tests split --split-by=timings | xargs -n 1 echo
- run:    name: test    command: ./gradlew check -i -PtestFilter="`circleci tests glob “src/integration-test/**/*.groovy” | circleci tests split --split-by=timings`"

结论 (Conclusion)

And that’s it! Easy, right? Well, it was a bit more work than it should have been. Having our test times cut nearly in half was definitely worth it! Applying test parallelism, we’ve decreased the build time from around 15 minutes to 9 minutes.

就是这样! 容易吧? 好吧,这比应做的工作多了一点。 我们的测试时间缩短了将近一半绝对值得! 应用测试并行性,我们将构建时间从大约15分钟减少到了9分钟。

翻译自: https://www.freecodecamp.org/news/how-to-boost-build-time-with-circleci-test-parallelism-f89e5eab1397/

串行测试 并行测试

串行测试 并行测试_如何通过CircleCI测试并行性增加构建时间相关推荐

  1. AsyncTask——AsyncTask串行and并行

    一.前言 AsyncTask,相信你不会陌生,也许你很幸运,早已了解了AsyncTask这个家伙挖的坑,也许你已经被坑过了,也许你没坑了,然而还没有发觉. 本次笔者将带大家一起来看下AsyncTask ...

  2. 同步、异步 与 串行、并行的区别

    同步.异步: 指的是能否开启新的线程.同步不能开启新的线程,异步可以. 串行.并行: 指的是任务的执行方式.串行是指多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个.并行指的是多个任务可以同 ...

  3. java sync和async区别_GCD中串行、并行与async、sync的区别

    * author:conowen@大钟 * E-mail:conowen@hotmail.com 队列由一个或多个任务组成,当这些任务要开始执行时,系统会分别把他们分配到某个线程上去执行. 串行队列. ...

  4. 串行、并行、并发,别再傻傻分不清了!

    开足码力,码动人生,微信搜索[ 程序员大帝 ],关注这个一言不合就开车的的代码界老司机 本文 GitHub上已经收录 https://github.com/BeKingCoding/JavaKing ...

  5. 并发、并行、同步、异步、进程,线程、串行、并行?一文弄懂八大概念

    并发.并行.同步.异步.进程,线程.串行.并行?一文弄懂八大概念 参考博文:并发.并行.串行.同步.异步的区别? java多线程详解(并发,并行,同步) 文章目录 并发.并行.同步.异步.进程,线程. ...

  6. 深度解析串行并发并行,开发人员需彻底搞懂丨mysql|redis|skynet|协程|索引|读写分离|分布式锁|主从同步

    深度解析串行并发并行,开发人员需彻底搞懂 视频讲解如下,点击观看: 深度解析串行并发并行,开发人员需彻底搞懂丨mysql|redis|skynet|协程|索引|读写分离|分布式锁|主从同步丨C/C++ ...

  7. 技能梳理37@stm32+按键+光耦+锁存+串行转并行+继电器

    技能梳理37@stm32+按键+光耦+锁存+串行转并行+继电器 1.项目简介 2.实现逻辑 3.应用场景 #主从机有线控制 #开关操作 4.核心代码梳理 //根据按下的按键执行相应的操作 void h ...

  8. 吃个快餐都能学到串行、并行、并发

    Java 多线程系列文章第 3 篇 这篇文章继续来唠唠概念,讲这三兄弟:串行(Serial).并行(Parallel).并发(Concurrent). 吃快餐 出门在外吃饭是一件头疼的事,用我大学舍友 ...

  9. 51单片机之IO口扩展——74HC595芯片串行转并行实验

    我们都知道通信从大的方面有两种:串行和并行.串行的最大优点是占用总线少,但是传输速率低:并行恰恰相反,占用总线多,传输速率高.市面上有很多这样的芯片,有串入并出的(通俗讲就是 一个一个进,最后一块出来 ...

最新文章

  1. 构造函数,实例,原型,以及原型链
  2. .NET Core的文件系统[3]:由PhysicalFileProvider构建的物理文件系统
  3. 服务器负载信息失败,网络故障分析案例:负载均衡系统造成网络业务访问失败...
  4. 一行代码太长的解决方法
  5. html怎么让js延迟3秒跳转,JS使用setInterval或setTimeout隔几秒后跳转页面
  6. 大剑无锋之二分搜索、二分搜索时间复杂度、三分查找呢?
  7. Linux中ls -l(ll)返回结果中的文件访问权限-rw-r--rw-
  8. 中查询一个文件夹下文件数量_如何在 Bash 中使用循环 | Linux 中国
  9. shell echo 彩色字体
  10. POI--HSSFCell类
  11. python中not是什么意思_python中的not具体使用及意思
  12. 鞍钢不愿意上涨的原因分析
  13. xp 无法关闭计算机,xp系统不能关机解决方法
  14. 分库分表会带来读扩散问题?怎么解决?
  15. matlab实现拉依达准则,拉依达准则matalb程序
  16. STM32 定时器的简单应用 1ms中断代码
  17. Office2016零售版(Retail)转批量授权(VOL)
  18. 计算机excel还原,『怎么还原电脑自带的excle』excel表格保存过了怎么恢复原来的数据...
  19. 【Spring】@Lazy注解
  20. 微博数据分析工具限时福利!购买西瓜微数加送会员时长 ,最多加赠1个月!

热门文章

  1. JVM—类加载过程学习
  2. 接口 java 1614953826
  3. 冒泡排序 实现数据的由大到小排序
  4. java演练0920 我们9203班 02 随机点名功能实现
  5. 导航第四版-分类专栏
  6. mysql-查询二-分组与聚合
  7. 使用 Swagger 2 构建 RESTful APIs
  8. Struts2 ( 二 )
  9. Netty 5.X 官方指南翻译版6:Writing a Time Client
  10. 实时检索系统Zoie实现分析