You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: cookbooks/custom_formatter.rst
+52-51Lines changed: 52 additions & 51 deletions
Original file line number
Diff line number
Diff line change
@@ -1,41 +1,41 @@
1
1
Writing a custom Behat formatter
2
2
================================
3
3
4
-
How to write a custom formatter for Behat?
4
+
How to write a custom formatter for Behat?
5
5
6
6
Introdution
7
7
-----------
8
8
9
-
Why a custom formatter?
9
+
Why a custom formatter?
10
10
~~~~~~~~~~~~~~~~~~~~~~~~
11
11
12
12
Behat has three native formatters:
13
13
14
-
- **pretty**: the default formatter, that does print every line in green (in case of a successful test) or red (if it does fail),
14
+
- **pretty**: the default formatter, which prints every line in green (if a test passes) or red (if it fails),
15
15
- **progress**: print a "dot" for each test, and a recap of all failing tests at the end,
16
16
- **junit**: outputs a `junit <https://junit.org/>`__ compatible XML file.
17
17
18
18
Those are nice, and worked for most of the cases. You can use the "progress" one for the CI, and the "pretty" for development for example.
19
19
20
-
But you might want to handle differently the output that Behat renders.
21
-
In that cookbook, we will see how to implement a custom formatter for `reviewdog <https://github.com/reviewdog/reviewdog>`__,
20
+
But you might want to handle differently the output that Behat renders.
21
+
In this cookbook, we will see how to implement a custom formatter for `reviewdog <https://github.com/reviewdog/reviewdog>`__,
22
22
a global review tool that takes input of linters or testers, and that can send "checks" on github, bitbucket or gitlab PR.
23
23
24
24
Reviewdog can handle `two types of input <https://github.com/reviewdog/reviewdog#input-format>`__:
25
25
26
26
- any stdin, coupled with an "errorformat" (a Vim inspired format that can convert text string to machine-readable errors),
27
27
- a `"Reviewdog Diagnostic Format" <https://github.com/reviewdog/reviewdog/tree/48b25a0aafb8494e751387e16f729faee9522c46/proto/rdf>`__: a JSON with error data that reviewdog can parse.
28
28
29
-
In my case, I tried parsing behat's output with errorformat, but I do not know this language, and the multi-line behat output with "dots" didn't make it simple.
29
+
In my case, I tried parsing Behat's output with errorformat, but I do not know this language, and the multi-line Behat output with "dots" didn't make it easy.
30
30
So I decided to create a custom formatter for Behat.
31
31
32
-
This way, I will still have behat's human-readable stdout, and a JSON file written that reviewdog can understand.
32
+
This way, I will still have Behat's human-readable stdout, and a JSON file written that reviewdog can understand.
33
33
34
34
Let's dive
35
35
----------
36
36
37
-
Behat allows us to load "extensions", that can add features to the language. In fact, it is a core functionnality to implement PHP functions behind gherkin texts.
38
-
Those extensions are simple classes, that are loaded in Behat.
37
+
Behat allows us to load "extensions", that can add features to the language. In fact, it is a core functionality to implement PHP functions behind gherkin texts.
38
+
Those extensions are just classes that are loaded by Behat to register configuration and features.
39
39
40
40
Behat is powered by Symfony: if you know it, you will already know the concepts under the hood, if you don't, that's not a problem and not required to create your extension.
41
41
@@ -44,18 +44,18 @@ Anatomy of a formatter extension
44
44
45
45
A formatter extension requires three things to work:
46
46
47
-
- a class that "defines" the extension, to make you extension work with behat,
48
-
- a "formatter", that can listen to behat events, and converts behat's tests result to anything you want,
49
-
- an "output printer", that does write the converted data anywhere you want (mainly the stdout, a file or a directory).
47
+
- a class that "defines" the extension, to make your extension work with Behat,
48
+
- a "formatter", that can listen to Behat events, and converts Behat's tests result to anything you want,
49
+
- an "output printer", that writes the converted data anywhere you want (mainly the stdout, a file or a directory).
50
50
51
51
Create the extension
52
52
~~~~~~~~~~~~~~~~~~~~
53
53
54
-
Any behat extensions must implements ``Behat\Testwork\ServiceContainer\Extension``. Under the hood, it does implements Symfony ``CompilerPass``.
54
+
Any Behat extensions must implement ``Behat\Testwork\ServiceContainer\Extension``. Under the hood, it implements Symfony ``CompilerPass``.
55
55
It is a way to inject anything you want into Behat's kernel.
56
56
57
-
It our case, we need to load the "formatter" in behat's kernel, and tagged it as an output formatter.
58
-
This way behat will allows our extension to be configured as a formatter. You can register multiple formatters with the same extension if you like.
57
+
In our case, we need to load the "formatter" in Behat's kernel, and tag it as an output formatter.
58
+
This way Behat will allow our extension to be configured as a formatter. You can register multiple formatters with the same extension if you like.
59
59
60
60
.. code:: php
61
61
@@ -86,18 +86,18 @@ This way behat will allows our extension to be configured as a formatter. You ca
@@ -111,7 +111,7 @@ This way behat will allows our extension to be configured as a formatter. You ca
111
111
Create the formatter
112
112
~~~~~~~~~~~~~~~~~~~~
113
113
114
-
The formatter will listen to behat's events, and create output data depending on the type of event, the current state, etc.
114
+
The formatter will listen to Behat's events, and create output data depending on the type of event, the current state, etc.
115
115
116
116
.. code:: php
117
117
@@ -135,7 +135,7 @@ The formatter will listen to behat's events, and create output data depending on
135
135
}
136
136
137
137
/**
138
-
* setParameter will be called for each key given to the formatter in your behat.yml file.
138
+
* setParameter will be called for each key given to the formatter in your behat.yml file.
139
139
* We will see that later in the "integration".
140
140
* In our case, the only allowed parameter is a "file_name" that must be a string : the JSON file that we will write.
141
141
*/
@@ -160,13 +160,13 @@ The formatter will listen to behat's events, and create output data depending on
160
160
public function getParameter($name) { }
161
161
162
162
/**
163
-
* Our formatter is a Symfony EventSubscriber.
164
-
* This method tells behat where we want to "hook" in the process.
163
+
* Our formatter is a Symfony EventSubscriber.
164
+
* This method tells Behat where we want to "hook" in the process.
165
165
* Here we want to be called:
166
166
* - at start, when the test is launched with the `BeforeExerciseCompleted::BEFORE` event,
167
167
* - when a step has ended with the `StepTested::AFTER` event.
168
-
*
169
-
* There is a lot of other that can be found here: https://github.com/Behat/Behat/tree/2a3832d9cb853a794af3a576f9e524ae460f3340/src/Behat/Testwork/EventDispatcher/Event
168
+
*
169
+
* There are a lot of other events that can be found here in the Behat\Testwork\EventDispatcher\Event class
170
170
*/
171
171
public static function getSubscribedEvents()
172
172
{
@@ -218,7 +218,7 @@ The formatter will listen to behat's events, and create output data depending on
@@ -439,26 +440,26 @@ For example if you want the pretty formatter by default, but both progress and r
439
440
file_name: 'reviewdog-behat.json'
440
441
441
442
442
-
Enjoy!
443
+
Enjoy!
443
444
-------
444
445
445
-
That's how you can write a simple custom behat formatter!
446
+
That's how you can write a basic custom Behat formatter!
446
447
447
-
If you have much more complex logic, and you need to formatter to be more dynamic, behat do provide a FormatterFactory interface.
448
-
You can see usage examples directly in `behat's codebase <https://github.com/Behat/Behat/tree/2a3832d9cb853a794af3a576f9e524ae460f3340/src/Behat/Behat/Output/ServiceContainer/Formatter>`__,
449
-
but in a lot of cases, the simple formatter should work.
448
+
If you have much more complex logic, and you need the formatter to be more dynamic, Behat do provide a FormatterFactory interface.
449
+
You can see usage examples directly in `Behat's codebase <https://github.com/Behat/Behat/tree/2a3832d9cb853a794af3a576f9e524ae460f3340/src/Behat/Behat/Output/ServiceContainer/Formatter>`__,
450
+
but in a lot of cases, something like this example should work.
450
451
451
-
Want to use reviewdog and the custom formatter yourself?
452
+
Want to use reviewdog and the custom formatter yourself?
If you want to use the reviewdog custom formatter, you can find it on github: https://github.com/jdeniau/behat-reviewdog-formatter
455
456
456
-
There are other behat custom formatters in the wild, especially `BehatHtmlFormatterPlugin <https://github.com/dutchiexl/BehatHtmlFormatterPlugin>`__,
457
-
that I did not test, but helped me understand how does behat formatter system works, and can output an HTML file that can help you understand why your CI is failing.
457
+
There are other Behat custom formatters in the wild, especially `BehatHtmlFormatterPlugin <https://github.com/dutchiexl/BehatHtmlFormatterPlugin>`__.
458
+
I did not test that, but it helped me understand how the Behat formatter system works, and it can output an HTML file that can help you understand why your CI is failing.
458
459
459
460
460
461
About the author
461
462
~~~~~~~~~~~~~~~~
462
463
463
464
Written by `Julien Deniau <https://julien.deniau.me>`__,
464
-
originally posted as a blog post `on my blog <https://julien.deniau.me/posts/2024-01-24-custom-behat-formatter>`__.
465
+
originally posted as a blog post `on my blog <https://julien.deniau.me/posts/2024-01-24-custom-behat-formatter>`__.
0 commit comments