Skip to content

Commit 55eab17

Browse files
committed
improved parallel excution chapter
1 parent 77ad83f commit 55eab17

File tree

1 file changed

+43
-103
lines changed

1 file changed

+43
-103
lines changed

guides/12-ParallelExecution.md

Lines changed: 43 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,10 @@
11
# Parallel Execution
22

3-
When execution time of your tests is longer than a coffee break, it is a good reason to think about making your tests faster. If you have already tried to run them on SSD drive, and the execution time still upsets you, it might be a good idea to run your tests in parallel. However, PHP runs in a single-process and you can't parallelize tests natively similarly to how this works in Java or in NodeJS. In this guide we will overview the options you have to run your tests in parallel.
3+
When execution time of your tests is longer than a coffee break, it is a good reason to think about making your tests faster. If you have already tried to run them on SSD drive, and the execution time still upsets you, it might be a good idea to run your tests in parallel. However, PHP runs in a single-process and you can't parallelize tests natively similarly to how this works in Java or in NodeJS.
44

5-
Parallel Test Execution consists of 3 steps:
6-
7-
* splitting tests
8-
* running tests in parallel
9-
* merging results
10-
11-
Depending on the project size and requirements you can choose the proper way to implement parallel testing.
5+
Depending on the project size and requirements you can choose how the best to implement parallel testing for your case.
126
In this guide we will overview possible options.
137

14-
## Continuous Integration
15-
16-
If you use modern Continuous Integration setup you can split your tests by jobs and run them in parallel.
17-
In this case the burden of parallelization lies on CI server.
18-
This makes a lot of sense as a single machine has limited resources. So even if PHP could spawn multiple processes with tests at one point you would still need to split tests in CI jobs.
19-
If you split tests into CI jobs, you are limited only to the number of agents (build servers) that the CI can provide. For cloud-based services like GitHub Actions, GitLab CI, CircleCI, etc, this number is unlimited.
20-
21-
![](images/codeception-pipeline.png)
22-
23-
On the first stage, tests should be split into groups. The group file should be committed into the repository or passed to next stage as an artifact.
24-
25-
On the second stage tests are executed. XML, HTML, and CodeCoverage reports must be stored as artifacts.
26-
27-
On the third stage the results from previous jobs must be collected or aggregated.
28-
298
## Sharding
309

3110
Minimal setup can be implemented by executing several independent CI jobs and running.
@@ -63,7 +42,17 @@ By running tests with Testomat.io reporter attached results will be sent to a ce
6342
TESTOMATIO={apiKey} TESTOMATIO_TITLE="Build $BUILDID" ./vendor/bin/codecept run --shard 3/4
6443
```
6544

66-
## Building Pipeline
45+
46+
## Building Pipeline
47+
48+
While sharding provides a simplified setup for testing the complete pipeline schema may look like this.
49+
50+
![](images/codeception-pipeline.png)
51+
52+
* On the first stage, tests should be split into groups. The group file should be committed into the repository or passed to next stage as an artifact.
53+
* On the second stage tests are executed. XML, HTML, and CodeCoverage reports must be stored as artifacts.
54+
* On the third stage the results from previous jobs must be collected or aggregated.
55+
6756

6857
To get more control on how the jobs are split excuted and results aggregated you can use a task runner.
6958

@@ -83,21 +72,12 @@ $ composer require codeception/robo-paracept --dev
8372

8473
{% endhighlight %}
8574

86-
You need to install Codeception after, if codeception is already installed it will not work.
87-
{% highlight bash %}
88-
89-
$ composer require codeception/codeception
90-
91-
{% endhighlight %}
92-
9375
### Setting up Robo
9476

9577
Initializes basic RoboFile in the root of your project
9678

9779
{% highlight bash %}
98-
99-
$ robo init
100-
80+
robo init
10181
{% endhighlight %}
10282

10383
Open `RoboFile.php` to edit it
@@ -113,7 +93,7 @@ class RoboFile extends \Robo\Tasks
11393
11494
{% endhighlight %}
11595
116-
Each public method in robofile can be executed as a command from console. Let's define commands for 3 steps and include autoload.
96+
Each public method in robofile can be executed as a command from console. Let's define commands for 3 stages and include autoload.
11797
11898
{% highlight php %}
11999
@@ -122,8 +102,8 @@ require_once 'vendor/autoload.php';
122102
123103
class Robofile extends \Robo\Tasks
124104
{
125-
use \Codeception\Task\MergeReports;
126-
use \Codeception\Task\SplitTestsByGroups;
105+
use Codeception\Task\Merger\ReportMerger;
106+
use Codeception\Task\Splitter\TestsSplitterTrait;
127107
128108
public function parallelSplitTests()
129109
{
@@ -143,34 +123,13 @@ class Robofile extends \Robo\Tasks
143123
144124
{% endhighlight %}
145125
146-
If you run `robo`, you can see the respective commands:
126+
When running `robo` you should see all 3 that these methods availble as CLI commands:
147127
148-
{% highlight bash %}
149-
150-
$ robo
151-
Robo version 0.6.0
152-
153-
Usage:
154-
command [options] [arguments]
155-
156-
Options:
157-
-h, --help Display this help message
158-
-q, --quiet Do not output any message
159-
-V, --version Display this application version
160-
--ansi Force ANSI output
161-
--no-ansi Disable ANSI output
162-
-n, --no-interaction Do not ask any interactive question
163-
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
164-
165-
Available commands:
166-
help Displays help for a command
167-
list Lists commands
168-
parallel
169-
parallel:merge-results
170-
parallel:run
171-
parallel:split-tests
172-
173-
{% endhighlight %}
128+
```
129+
parallel:split-tests
130+
parallel:run
131+
parallel:merge-results
132+
```
174133
175134
#### Step 1: Split Tests
176135
@@ -211,10 +170,13 @@ Tasks from `\Codeception\Task\SplitTestsByGroups` will generate non-intersecting
211170

212171
{% endhighlight %}
213172

173+
But what if one group of your tests runs for 5 mins and other for 20mins. In this case, you can balance execution time by using [SplitTestsByTime](https://github.com/Codeception/robo-paracept#splittestsbytime) task. It will generate balanced groups taking the execution speed into account.
174+
175+
> More splitting strategies are implemented within [Robo-paracept](https://github.com/Codeception/robo-paracept#tasks) package.
176+
214177
Let's prepare group files:
215178

216179
{% highlight bash %}
217-
218180
$ robo parallel:split-tests
219181

220182
[Codeception\Task\SplitTestFilesByGroupsTask] Processing 33 files
@@ -239,38 +201,20 @@ Let's try to execute tests from the second group:
239201

240202
{% highlight bash %}
241203

242-
$ codecept run acceptance -g paracept_2
204+
$ php vendor/bin/codecept run acceptance -g paracept_2
243205

244206
{% endhighlight %}
245207

246208
#### Step 2: Running Tests
247209

248-
Robo has `ParallelExec` task to spawn background processes.
249-
250-
##### Inside Container
210+
At this point you should decide if tests are executed on the same job or use multiple jobs for them. We recommend using multiple jobs, as in this case the burden of parallelization goes to CI server. This makes a lot of sense as a single machine has limited resources. If you split tests into CI jobs, you are limited only to the number of agents (build servers) that the CI can provide. For cloud-based services like GitHub Actions, GitLab CI, CircleCI, etc, this number is unlimited.
251211

252-
If you are using [Docker](#docker) containers you can launch multiple Codeception containers for different groups:
253-
254-
{% highlight php %}
212+
> Please refer to documentation of your CI platform to learn how to set up multiple jobs runnninng in parallel. Then proceed to merging of results.
255213

256-
public function parallelRun()
257-
{
258-
$parallel = $this->taskParallelExec();
259-
for ($i = 1; $i <= 5; $i++) {
260-
$parallel->process(
261-
$this->taskExec('docker-compose run --rm codecept run')
262-
->option('group', "paracept_$i") // run for groups paracept_*
263-
->option('xml', "tests/_log/result_$i.xml") // provide xml report
264-
);
265-
}
266-
return $parallel->run();
267-
}
268-
269-
{% endhighlight %}
214+
In some situations you may want to keep tests running on the same machine and scale it up with more resourses. This makes sense if you have heavy application setup for each test run and setting it up for each machine can waste a lot of resources.
270215

271-
##### Locally
272216

273-
If you want to run tests locally just use preinstalled `taskCodecept` task of Robo to define Codeception commands and put them inside `parallelExec`.
217+
To execute tests in multiple processes Robo has `ParallelExec` task to spawn background processes.
274218

275219
{% highlight php %}
276220

@@ -304,41 +248,37 @@ $ robo parallel:run
304248
In case of `parallelExec` task we recommend to save results as JUnit XML, which can be merged and plugged into Continuous Integration server.
305249

306250
{% highlight php %}
307-
308251
<?php
309-
function parallelMergeResults()
252+
public function parallelMergeResults()
310253
{
311254
$merge = $this->taskMergeXmlReports();
312255
for ($i=1; $i<=5; $i++) {
313256
$merge->from("tests/_output/result_paracept_$i.xml");
314257
}
315258
$merge->into("tests/_output/result_paracept.xml")->run();
316259
}
317-
318-
319260
{% endhighlight %}
320261
Now, we can execute :
321262
{% highlight bash %}
322263

323264
$ robo parallel:merge-results
324265

325266
{% endhighlight %}
326-
`result_paracept.xml` file will be generated. It can be processed and analyzed.
327267

328-
#### All Together
268+
`result_paracept.xml` file will be generated. It can be processed and analyzed.
329269

330-
To create one command to rule them all we can define new public method `parallelAll` and execute all commands. We will save the result of `parallelRun` and use it for our final exit code:
270+
If you prefer HTML reports, they can be generated in the same way:
331271

332272
{% highlight php %}
333-
334-
<?php
335-
function parallelAll()
273+
public function parallelMergeResults()
336274
{
337-
$this->parallelSplitTests();
338-
$result = $this->parallelRun();
339-
$this->parallelMergeResults();
340-
return $result;
275+
$merge = $this->taskMergeHtmlReports();
276+
for ($i=1; $i<=5; $i++) {
277+
$merge->from("tests/_output/result_$i.html");
278+
}
279+
$merge->into("tests/_output/result.html")->run();
341280
}
342281

343-
344282
{% endhighlight %}
283+
284+

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy