<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Jérémy DECOOL (@jdecool), Ingénieur Etudes et Développement à Lyon</title>
        <description></description>
        <link>https://www.jdecool.fr</link>
        <atom:link href="https://www.jdecool.fr/feed/php.xml" rel="self" type="application/rss+xml" />
        
        
            
        
            
        
            
                320
                <item>
                    <title>Profile your PHPUnit tests using OpenTelemetry</title>
                    <description>&lt;p&gt;When your project grows, the codebase grows and your test suite too. The more the test you write, the longer the execution is. And then, the &lt;code&gt;Allowed memory size exhausted&lt;/code&gt; error occurred in your CI. To solve this issue quickly, you bump PHP allocated memory. But it doesn’t fix the problem, and this cycle goes on for a while. Until you hit critical thresholds.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Fixing memory issues is really difficult, and there are not many tools to help. We need to retrieve information about our test executions. Monitoring a production application is a known good practice. So why this is not applied to our test code?&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://opentelemetry.io &quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenTelemetry&lt;/a&gt; emerged those years. It could be useful to use it in our context to produce traces and metrics about our test suite.&lt;/p&gt;

&lt;p&gt;I’ve recently discovered the &lt;a href=&quot;https://packagist.org/packages/flow-php/phpunit-telemetry-bridge &quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;flow-php/phpunit-telemetry-bridge&lt;/a&gt; library. It brings observability to our PHPUnit tests using OpenTelemetry. The library consists of a PHPUnit extension that collects some data and sends them to any OTLP-compatible backend.&lt;/p&gt;

&lt;p&gt;Start using it by installing the component using Composer:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;composer require --dev flow-php/phpunit-telemetry-bridge&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then add the telemetry configuration into PHPUnit:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;phpunit&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
    &amp;lt;extensions&amp;gt;
        &amp;lt;bootstrap class=&amp;quot;Flow\Bridge\PHPUnit\Telemetry\TelemetryExtension&amp;quot;&amp;gt;
            &amp;lt;parameter name=&amp;quot;service_name&amp;quot; value=&amp;quot;phpunit-opentelemetry&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;transport&amp;quot; value=&amp;quot;curl&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;endpoint&amp;quot; value=&amp;quot;http://localhost:4318&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;emit_traces&amp;quot; value=&amp;quot;true&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;emit_metrics&amp;quot; value=&amp;quot;true&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;emit_test_spans&amp;quot; value=&amp;quot;true&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;emit_test_case_spans&amp;quot; value=&amp;quot;true&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;curl_connect_timeout_ms&amp;quot; value=&amp;quot;1000&amp;quot;/&amp;gt;
            &amp;lt;parameter name=&amp;quot;curl_timeout_ms&amp;quot; value=&amp;quot;2000&amp;quot;/&amp;gt;
        &amp;lt;/bootstrap&amp;gt;
    &amp;lt;/extensions&amp;gt;
&amp;lt;/phpunit&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After that, every time your tests are run, the library will send the telemetry backend. Then you can create some dashboards to visualize the data:&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;/img/blog/20260601-profilez-vos-tests-phpunit-avec-opentelemetry/phpunit-otel-overview.png&quot; alt=&quot;Overview of a PHPUnit test suite&apos;s telemetry in a dashboard&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;Data contains execution details like duration, memory consumption, executed tests, etc.&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;/img/blog/20260601-profilez-vos-tests-phpunit-avec-opentelemetry/phpunit-otel-memory.png&quot; alt=&quot;Memory consumption of PHPUnit tests visualized through OpenTelemetry&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;When using observability in your stack, don’t forget that instrumenting every test can be expensive. Use it when you really need it.&lt;/p&gt;

&lt;p&gt;Want to get more information? Check out &lt;a href=&quot;https://flow-php.com/documentation/components/bridges/phpunit-telemetry-bridge/ &quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the PHPUnit Telemetry bridge documentation&lt;/a&gt;.&lt;/p&gt;
</description>
                    <pubDate>Mon, 01 Jun 2026 00:00:00 +0200</pubDate>
                    <link>https://www.jdecool.fr/en/blog/2026/06/01/profile-your-phpunit-tests-with-opentelemetry.html</link>
                    <guid isPermaLink="true">https://www.jdecool.fr/en/blog/2026/06/01/profile-your-phpunit-tests-with-opentelemetry.html</guid>
                </item>
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
                321
                <item>
                    <title>Execute CTE queries using Doctrine ORM</title>
                    <description>&lt;p&gt;There are a lot of developers who manipulate databases using an ORM and don’t know more SQL than the “classic” &lt;code&gt;SELECT ... FROM ... WHERE ...&lt;/code&gt; queries. But databases have various unknown features that can avoid programing data processing. One of them is CTE (for &lt;em&gt;Common Table Expressions&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;This article describes how to use this feature with PHP Doctrine ORM.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;First, let me explain what a CTE is. A Common Table Expression (CTE) is a named temporary result set that you define at the beginning of a SQL query using the &lt;code&gt;WITH&lt;/code&gt; clause. It exists only for the duration of that query and can be referenced like a table within it.&lt;/p&gt;

&lt;p&gt;To illustrate how it works, imagine a blog where articles can be stored and attached to one category. Categories are organized in a tree structure. Now, we want to retrieve a specific category with all its parents. The naïve PHP implementation can be something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;// src/Repository/CategoryRepository.php
class CategoryRepository extends ServiceEntityRepository
{
    // ...

    /**
     * @return list&amp;lt;Category&amp;gt;
     */
    function getCatagoriesWithParents(int $categoryId): array
    {
        $category = $this-&amp;gt;categoryRepository-&amp;gt;find($categoryId);

        $categories = [
            $category,
        ];

        while ($parent = $category-&amp;gt;getParent()) {
            $categories[] = $parent;
        }

        return $categories;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With the previous version, Doctrine will execute one query per loop: it’s the common N+1 problem. To resolve this issue through an SQL query, we can’t use a basic query. We need a recursive CTE. This SQL query can look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;WITH RECURSIVE cte_category AS (
    -- starting point
    SELECT id, label, parent_id, 0 AS depth
    FROM category
    WHERE id = :id

    UNION ALL

    -- recursivity
    SELECT c.id, c.label, c.parent_id, cp.depth + 1
    FROM category c
    INNER JOIN cte_category cp ON c.id = cp.parent_id
)
SELECT id, label, parent_id FROM cte_category
ORDER BY depth DESC&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First, the previous query retrieves the &lt;code&gt;:id&lt;/code&gt; category. Then, recursively, it retrieves all the parents. The &lt;code&gt;depth&lt;/code&gt; column is used to order the final result.&lt;/p&gt;

&lt;p&gt;The problem with this kind of SQL query is that Doctrine is not able to execute them natively. We can’t use the &lt;code&gt;QueryBuilder&lt;/code&gt; or a &lt;code&gt;DQL&lt;/code&gt; (&lt;em&gt;Doctrine Query Language&lt;/em&gt;) query. We need to execute a native query and map the result on an object.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;// src/Repository/CategoryRepository.php
class CategoryRepository extends ServiceEntityRepository
{
    // ...

    public function findAllWithParents(int $categoryId)
    {
        $rsm = new ResultSetMappingBuilder($this-&amp;gt;getEntityManager());
        $rsm-&amp;gt;addRootEntityFromClassMetadata(Category::class, &amp;#39;c&amp;#39;);

        $sql = &amp;lt;&amp;lt;&amp;lt;SQL
            WITH RECURSIVE with_categories AS (
                SELECT id, label, parent_id, 0 AS depth
                FROM category
                WHERE id = :id

                UNION ALL

                SELECT c.id, c.label, c.parent_id, cp.depth + 1
                FROM category c
                INNER JOIN with_categories cp ON c.id = cp.parent_id
            )
            SELECT id, label, parent_id FROM with_categories
            ORDER BY depth DESC
        SQL;

        return $this-&amp;gt;getEntityManager()
            -&amp;gt;createNativeQuery($sql, $rsm)
            -&amp;gt;setParameter(&amp;#39;id&amp;#39;, $categoryId)
            -&amp;gt;getResult();
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the previous code, the &lt;code&gt;ResultSetMappingBuilder&lt;/code&gt; maps the query results to the &lt;code&gt;Category&lt;/code&gt; entity object properties. The output will be a list of &lt;code&gt;Category&lt;/code&gt; ordered by ancestors.&lt;/p&gt;

&lt;p&gt;This kind of query allows a lot of things. For example, we can retrieve every post of a specific category, including the category parents:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;WITH RECURSIVE category_path AS (
    SELECT id, label, parent_id
    FROM category
    WHERE id = :id

    UNION ALL

    SELECT c.id, c.label, c.parent_id
    FROM category c
    INNER JOIN category_path cp ON c.id = cp.parent_id
)
SELECT a.id, a.title, a.category_id
FROM article a
INNER JOIN category_path cp ON a.category_id = cp.id
ORDER BY a.published_date DESC&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With only one query, every post is retrieved. Without a recursive CTE, multiple successive queries will be necessary. The drawback is it depends on the database engine and could not be available in some databases.&lt;/p&gt;

&lt;p&gt;Moreover, using the &lt;code&gt;ResultSetMappingBuilder&lt;/code&gt; requires all columns needed to hydrate the entity should be included in the &lt;code&gt;SELECT&lt;/code&gt;. Otherwise, the entity will be partially hydrated without any explicit notice or error.&lt;/p&gt;
</description>
                    <pubDate>Sat, 09 May 2026 00:00:00 +0200</pubDate>
                    <link>https://www.jdecool.fr/en/blog/2026/05/09/execute-cte-queries-using-doctrine-orm.html</link>
                    <guid isPermaLink="true">https://www.jdecool.fr/en/blog/2026/05/09/execute-cte-queries-using-doctrine-orm.html</guid>
                </item>
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
                322
                <item>
                    <title>Named constructors as multiple constructors alternative</title>
                    <description>&lt;p&gt;Unlike other programming languages, PHP does not allow for multiple constructors in a class. However, defining multiple constructors can be beneficial in various scenarios, such as creating an object from different data types. If this functionality is not available in PHP, named constructors can be used as an alternative solution.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;What is a named constructor? It is a static method that we can use to create an object instance. These methods have the advantage of being more explicit than the basic constructor, as they can add meaning to the object’s construction.&lt;/p&gt;

&lt;p&gt;Consider the following example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;readonly class Color
{
    public function __construct(
        public int $red,
        public int $blue,
        public int $green,
    ) {}
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The previous code defines an object that stores a color. This color consists of three levels: red, green and blue. The main constructor fills in these corresponding values. However, sometimes it may be useful to create a color from its hexadecimal value. In this case, we could introduce a constructor called &lt;code&gt;fromHexCode&lt;/code&gt; to do this task:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;readonly class Color
{
    public static function fromHexCode(string $code): self
    {
        $code = ltrim($code, &amp;#39;#&amp;#39;);

        $red = hexdec(substr($code, 0, 2));
        $blue = hexdec(substr($code, 2, 2));
        $green = hexdec(substr($code, 4, 2));

        return new self($red, $blue, $green);
    }

    public function __construct(
        public int $red,
        public int $blue,
        public int $green,
    ) {}
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Named constructors can simplify object creation by providing default values based on the context. They also encapsulate the complex creation logic, making the code easier to read and understand.&lt;/p&gt;

&lt;p&gt;This technique is also popular in &lt;em&gt;Domain Driven Design&lt;/em&gt;. It can help clarify the business process that led to the data creation. For example, consider user registration in an application:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;class User
{
    public static function fromRegistration(string $name, string $email, string $password): self
    {
        $user = new self($name, $email, $password);

        // additionnal business logic related to registration

        return $user;
    }

    public static function fromSocialLogin(string $name, string $email): self
    {
        $user = new self($name, $email);

        // additionnal business logic related to social login

        return $user;
    }

    private function __construct(
        public string $name,
        public string $email,
        public ?string $password = null,
    ) {}
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This last example introduces a &lt;code&gt;User&lt;/code&gt; class with a private constructor. To create an object instance, a named constructor must be used. The constructor choice will depend on the business context. This approach allows us to see user creation requirements depends on a specific use case.&lt;/p&gt;

&lt;p&gt;When a user registers via the application, it should provide a name, an email and a password. However if the same user is logged through a social login, we only need the name and the email. The password is not necessary when using an external login system.&lt;/p&gt;

&lt;p&gt;In summary, using named constructors can significantly improve the code base and enhance code readability. I highly recommend that you explore this technique as it under-exploited.&lt;/p&gt;
</description>
                    <pubDate>Tue, 28 Jan 2025 00:00:00 +0100</pubDate>
                    <link>https://www.jdecool.fr/en/blog/2025/01/28/named-constructors-as-multiple-constructors-alternative.html</link>
                    <guid isPermaLink="true">https://www.jdecool.fr/en/blog/2025/01/28/named-constructors-as-multiple-constructors-alternative.html</guid>
                </item>
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
                323
                <item>
                    <title>How to use PHPUnit 10 with Symfony</title>
                    <description>&lt;p&gt;PHPUnit has been release 8 months ago (the 3rd of February 2023). But if we try to use it in a Symfony project using the &lt;code&gt;symfony/phpunit-bridge&lt;/code&gt; component, a &lt;code&gt;PHP Fatal error:  Uncaught Error: Class &quot;PHPUnit\TextUI\Command&lt;/code&gt; occurred.&lt;/p&gt;

&lt;!--more--&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;PHP Fatal error:  Uncaught Error: Class &quot;PHPUnit\TextUI\Command&quot; not found in /home/jdecool/Workspace/sandbox/test/bin/phpunit:11
Stack trace:
#0 {main}
  thrown in /home/jdecool/Workspace/sandbox/test/bin/phpunit on line 11

Fatal error: Uncaught Error: Class &quot;PHPUnit\TextUI\Command&quot; not found in /home/jdecool/Workspace/sandbox/test/bin/phpunit on line 11

Error: Class &quot;PHPUnit\TextUI\Command&quot; not found in /home/jdecool/Workspace/sandbox/test/bin/phpunit on line 11

Call Stack:
    0.0001     396248   1. {main}() /home/jdecool/Workspace/sandbox/test/bin/phpunit:0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Symfony script tries to use a deleted PHPUnit class. While there are several PRs to fix the problem, but none are currently merged.&lt;/p&gt;

&lt;p&gt;If you want to solve this issue, you can simply update the &lt;code&gt;bin/phpunit&lt;/code&gt; file using this patch:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-patch&quot;&gt;-    PHPUnit\TextUI\Command::main();
+    exit((new PHPUnit\TextUI\Application)-&amp;gt;run($_SERVER[&apos;argv&apos;]));
&lt;/code&gt;&lt;/pre&gt;
</description>
                    <pubDate>Tue, 10 Oct 2023 00:00:00 +0200</pubDate>
                    <link>https://www.jdecool.fr/en/blog/2023/10/10/how-to-use-phpunit-10-with-symfony.html</link>
                    <guid isPermaLink="true">https://www.jdecool.fr/en/blog/2023/10/10/how-to-use-phpunit-10-with-symfony.html</guid>
                </item>
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
                324
                <item>
                    <title>How to use Chrome Headless with Behat</title>
                    <description>&lt;p&gt;Headless Chrome is shipping in Chrome 59 (currently in beta), it seems that we
can use the browser without UI. It is very interesting for testing and automated
purpose. In this post, we are going to configure Behat (a PHP framework for
autotesting your business expectations) to use Chrome in headless mode.&lt;/p&gt;

&lt;p&gt;This new Chrome feature interest a large part of the Web community. So much, that
the maintainer of PhantomJS, a headless browser which is also based on Webkit,
&lt;a href=&quot;https://groups.google.com/d/msg/phantomjs/9aI5d-LDuNE/5Z3SMZrqAQAJ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;announced the end of the project&lt;/a&gt;.
So, if you used this in your Behat scenarios, you should change the browser you
used.&lt;/p&gt;

&lt;p&gt;This is an sample of the Behat configuration I use for PhantomJS :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;# behat.yml
default:
    extensions:
        # ...
        Behat\MinkExtension:
            base_url: http://project.dev
            sessions:
                default:
                    selenium2:
                        wd_host: http://localhost:4444/wd/hub&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we have to make some change to be able to use Chrome browser. First, we have
to add the &lt;a href=&quot;https://sites.google.com/a/chromium.org/chromedriver/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ChromeDriver&lt;/a&gt;.
Next, we need to add some configuration directory in our &lt;code&gt;behat.yml&lt;/code&gt; file :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;# behat.yml
default:
    extensions:
        # ...
        Behat\MinkExtension:
            base_url: http://project.dev
            sessions:
                default:
                    selenium2:
                        browser: chrome
                        wd_host: http://localhost:4444/wd/hub
                        capabilities:
                            chrome:
                                switches:
                                    - &amp;quot;--headless&amp;quot;
                                    - &amp;quot;--disable-gpu&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are some little changes if the configuration file. We begin by defining the
&lt;code&gt;browser&lt;/code&gt; we want to use. Then we set up some &lt;code&gt;capabilities&lt;/code&gt; (options that can
add to customize and configure our Chrome session). We add the &lt;code&gt;--headless&lt;/code&gt; argument
to use the headless mode in combination to &lt;code&gt;--disable-gpu&lt;/code&gt; which is temporarily
needed for now.&lt;/p&gt;

&lt;p&gt;Et voilà ! By adding 5 lines of configuration we have replaced the PhantomJS
browser usage by Google Chrome with “headless” mode.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://gist.github.com/jdecool/ec2dbc08e79e66d27b3d56d10ea28bf4&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;The full configuration file is available on Gist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</description>
                    <pubDate>Mon, 08 May 2017 00:00:00 +0200</pubDate>
                    <link>https://www.jdecool.fr/en/blog/2017/05/08/how-to-use-chrome-headless-with-behat.html</link>
                    <guid isPermaLink="true">https://www.jdecool.fr/en/blog/2017/05/08/how-to-use-chrome-headless-with-behat.html</guid>
                </item>
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
    </channel>
</rss>
