<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PHPStorm Archives - Víctor Dorado</title>
	<atom:link href="https://www.victordorado.es/category/phpstorm/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.victordorado.es/category/phpstorm/</link>
	<description></description>
	<lastBuildDate>Mon, 03 Mar 2025 16:30:22 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Tests Unitarios en Drupal. Parte 2: Sujetos de test con dependencias</title>
		<link>https://www.victordorado.es/2025/03/02/tests-unitarios-en-drupal-parte-2-sujetos-de-test-con-dependencias/</link>
					<comments>https://www.victordorado.es/2025/03/02/tests-unitarios-en-drupal-parte-2-sujetos-de-test-con-dependencias/#respond</comments>
		
		<dc:creator><![CDATA[vidorado]]></dc:creator>
		<pubDate>Sun, 02 Mar 2025 19:44:44 +0000</pubDate>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHPStorm]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://www.victordorado.es/?p=2353</guid>

					<description><![CDATA[<p>En esta segunda parte veremos tests un poco más avanzados, donde es necesario simular (mockear) las dependencias de nuestra clase sujeto. Además, podremos ver un caso típico de testing por intervalos, donde debemos comprobar que cada intervalo produce la salida correcta.</p>
<p>The post <a href="https://www.victordorado.es/2025/03/02/tests-unitarios-en-drupal-parte-2-sujetos-de-test-con-dependencias/">Tests Unitarios en Drupal. Parte 2: Sujetos de test con dependencias</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">En esta segunda parte veremos<strong> tests un poco más avanzados, donde es necesario simular (mockear) las dependencias</strong> de nuestra clase sujeto.</p>



<p class="wp-block-paragraph">Además, <strong>podremos ver un caso típico de testing por intervalos</strong>, donde debemos comprobar que cada intervalo produce la salida correcta.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Videocurso Testing en Drupal - Parte 2: Tests Unitarios con Dependencias" width="1290" height="726" src="https://www.youtube.com/embed/Vbcpnh0lU4I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://www.victordorado.es/2025/03/02/tests-unitarios-en-drupal-parte-2-sujetos-de-test-con-dependencias/">Tests Unitarios en Drupal. Parte 2: Sujetos de test con dependencias</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.victordorado.es/2025/03/02/tests-unitarios-en-drupal-parte-2-sujetos-de-test-con-dependencias/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Tests unitarios en Drupal con PHPUnit y PHPStorm</title>
		<link>https://www.victordorado.es/2025/02/28/tests-unitarios-en-drupal-con-phpunit-y-phpstorm/</link>
					<comments>https://www.victordorado.es/2025/02/28/tests-unitarios-en-drupal-con-phpunit-y-phpstorm/#respond</comments>
		
		<dc:creator><![CDATA[vidorado]]></dc:creator>
		<pubDate>Fri, 28 Feb 2025 02:26:39 +0000</pubDate>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHPStorm]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://www.victordorado.es/?p=2349</guid>

					<description><![CDATA[<p>En este vídeo veremos, de forma muy resumida, cómo se puede crear un test unitario en Drupal. Crearemos un servicio muy simple y un test que compruebe que el servicio se comporta como esperamos.</p>
<p>The post <a href="https://www.victordorado.es/2025/02/28/tests-unitarios-en-drupal-con-phpunit-y-phpstorm/">Tests unitarios en Drupal con PHPUnit y PHPStorm</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>En esta ocasión, esta publicación estará en español,</strong> ya que aún no tengo la soltura para grabar un vídeo en inglés 😁. No obstante, esto es un comienzo para, algún día, dar ese paso.</p>



<p class="wp-block-paragraph">En este vídeo <strong>veremos, de forma muy resumida, cómo se puede crear un test unitario en Drupal.</strong> Crearemos un servicio muy simple y un test que compruebe que el servicio se comporta como esperamos. Además, podremos apreciar, en primera persona, las <strong>ventajas de programar con TDD </strong>(Test Driven Development).</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Videocurso Testing en Drupal - Parte 1: Tests Unitarios" width="1290" height="726" src="https://www.youtube.com/embed/JDM8cLCbdW4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://www.victordorado.es/2025/02/28/tests-unitarios-en-drupal-con-phpunit-y-phpstorm/">Tests unitarios en Drupal con PHPUnit y PHPStorm</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.victordorado.es/2025/02/28/tests-unitarios-en-drupal-con-phpunit-y-phpstorm/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Improve your code quality from PHPStorm with PHP_CodeSniffer</title>
		<link>https://www.victordorado.es/2024/06/28/improve-your-code-quality-with-php-codesniffer-phpstan-eslint-stylelint-phpstorm-integration/</link>
		
		<dc:creator><![CDATA[vidorado]]></dc:creator>
		<pubDate>Fri, 28 Jun 2024 20:01:01 +0000</pubDate>
				<category><![CDATA[DDEV]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHPStorm]]></category>
		<guid isPermaLink="false">https://www.victordorado.es/?p=2284</guid>

					<description><![CDATA[<p>Learn how to set up some quality tools with PHPStorm and DDEV: PHP_CodeSniffer, PHPStan, and others</p>
<p>The post <a href="https://www.victordorado.es/2024/06/28/improve-your-code-quality-with-php-codesniffer-phpstan-eslint-stylelint-phpstorm-integration/">Improve your code quality from PHPStorm with PHP_CodeSniffer</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Following a consistent code style in a project is crucial for making it easier for developers to read each other&#8217;s code</strong>. When the code feels familiar, cognitive effort can be redirected to more important tasks.</p>



<p class="wp-block-paragraph">However, <strong>adhering to agreed-upon rules isn&#8217;t always easy.</strong> <strong>With many conventions to remember, we need tools to assist us</strong>. This is where our quality tools come in. They provide a powerful toolkit to ensure that our coding standards and style agreements are met. Furthermore, we can configure PHPStorm to use these tools, creating an integrated in-editor coding experience.</p>



<p class="wp-block-paragraph"><strong>In this article we will be working on a Drupal project, but the process is applicable to any project type</strong>, as long as we will be using standard npm/yarn and Composer package management to get the tools.</p>



<h2 class="wp-block-heading">Installing PHP_CodeSniffer</h2>



<p class="wp-block-paragraph">We will install it with Composer, as usual for many other PHP packages. We will also use a handy tool to ease the installation process.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="#ddev composer require --dev squizlabs/php_codesniffer dealerdirect/phpcodesniffer-composer-installer drupal/coder" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">ddev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">composer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">require</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">--</span><span style="color: #D8DEE9">dev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">squizlabs</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">php_codesniffer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">dealerdirect</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">phpcodesniffer</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">composer</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">installer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">drupal</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">coder</span></span></code></pre></div>



<p class="wp-block-paragraph">After that, as the documentation states (<a href="https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer">https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer</a>) we must ensure the following config is present in our composer.json:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
    &quot;config&quot;: {
        &quot;allow-plugins&quot;: {
            &quot;dealerdirect/phpcodesniffer-composer-installer&quot;: true
        }
    }
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">config</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">: </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">allow-plugins</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">dealerdirect/phpcodesniffer-composer-installer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">If we are using Composer &lt; 2.2 it won&#8217;t and we will have to add it with the following command:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">composer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">allow</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">plugins</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">dealerdirect</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">phpcodesniffer</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">composer</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">installer</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span></code></pre></div>



<p class="wp-block-paragraph">After that, we will let the magic happen:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# composer install" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">composer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Now, we can execute the phpcs command inside our DDEV web container</strong>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev exec phpcs --version
Registering sniffs in the PEAR standard... DONE (28 sniffs registered)
PHP_CodeSniffer version 3.10.1 (stable) by Squiz and PHPCSStandards" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">ddev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">exec</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">phpcs</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">--</span><span style="color: #D8DEE9">version</span></span>
<span class="line"><span style="color: #D8DEE9">Registering</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sniffs</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PEAR</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">standard</span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">DONE</span><span style="color: #D8DEE9FF"> (</span><span style="color: #B48EAD">28</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sniffs</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">registered</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9">PHP_CodeSniffer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">version</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.10</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">stable</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">by</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Squiz</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PHPCSStandards</span></span></code></pre></div>



<p class="wp-block-paragraph">Note that PHP_CodeSniffer says something about a &#8220;standard&#8221;. <strong>PHP_CodeSniffer checks our code against one of various possible &#8220;standards&#8221;</strong>, and there are some of them bundled by default with it. The default standard that will be used is the &#8220;PEAR&#8221; one.</p>



<p class="wp-block-paragraph">But, for a Drupal project (a website, a theme, a contrib module&#8230; etc.), <strong>we must use a special crafted standard called &#8220;Drupal&#8221;</strong>, that has all the Drupal community-agreed coding standards. Thanks to our previously installed <code>dealerdirect/phpcodesniffer-composer-installer</code>, we can see that the standards &#8220;Drupal&#8221; and &#8220;DrupalPractice&#8221; are installed:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev exec phpcs -i
The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, Drupal, DrupalPractice, VariableAnalysis and SlevomatCodingStandard" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">ddev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">exec</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">phpcs</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">i</span></span>
<span class="line"><span style="color: #D8DEE9">The</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">installed</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">coding</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">standards</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">are</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MySource</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PEAR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PSR1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PSR2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PSR12</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Squiz</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Zend</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Drupal</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DrupalPractice</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">VariableAnalysis</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SlevomatCodingStandard</span></span></code></pre></div>



<p class="wp-block-paragraph">(DrupalPractice is a more exhaustive standard that checks not only the coding style used, but also some best practices for Drupal development).</p>



<p class="wp-block-paragraph"><strong>In this article, we will focus in the use of PHPCS through the UI, that is what will make a more &#8220;realtime&#8221; development experience</strong>. Using phpcs from the command line is harder, and is often only used by cli scripts, like in CI environment QA tests, or s Git <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">precommit hook</a> in a local development environment.</p>



<h2 class="wp-block-heading">Integrating PHP_CodeSniffer with PHPStorm</h2>



<p class="wp-block-paragraph">PHPStorm has friendly configuration dialogs for some popular quality tools, and one of them is PHPCS.</p>



<p class="wp-block-paragraph"><strong>Is highly recommended executing PHPCS inside our DDEV container</strong>, <strong>in order to keep consistency with our project&#8217;s PHP version and configuration</strong> instead of relying on our own machine config. To do so, first we must have a PHPStorm &#8220;DDEV&#8221; PHP interpreter (check my previous article <a href="https://www.victordorado.es/2024/03/18/phpunit-up-and-running-with-drupal-ddev-and-phpstorm/">PHPUnit up and running with Drupal, DDEV and PHPStorm</a> to know how to accomplish it).</p>



<p class="wp-block-paragraph">Then, go to Settings, under the &#8220;PHP &#8211; Quality Tools&#8221; section, and open the first accordion, setting its configuration and options as follows:</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="993" height="312" src="https://www.victordorado.es/wp-content/uploads/2024/06/image-4.png" alt="" class="wp-image-2286" srcset="https://www.victordorado.es/wp-content/uploads/2024/06/image-4.png 993w, https://www.victordorado.es/wp-content/uploads/2024/06/image-4-300x94.png 300w, https://www.victordorado.es/wp-content/uploads/2024/06/image-4-768x241.png 768w" sizes="(max-width: 993px) 100vw, 993px" /></figure>



<p class="wp-block-paragraph"><strong>Notice that Drupal Core uses a different more relaxed standard</strong>. If you are going to develop for core you should set the coding standard to &#8220;Custom&#8221; and point to your project&#8217;s <code>&lt;drupal-root>/core/phpcs.xml.dist</code></p>



<p class="wp-block-paragraph">You can also configure some additional inspection settings in the &#8220;Editor &#8211; Inspections&#8221; menu:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="422" src="https://www.victordorado.es/wp-content/uploads/2024/06/image-5-1024x422.png" alt="" class="wp-image-2287" srcset="https://www.victordorado.es/wp-content/uploads/2024/06/image-5-1024x422.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/06/image-5-300x124.png 300w, https://www.victordorado.es/wp-content/uploads/2024/06/image-5-768x316.png 768w, https://www.victordorado.es/wp-content/uploads/2024/06/image-5.png 1158w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Once configured, edit any file and <strong>PHPStorm will automatically execute PHPCS, showing the warnings and errors</strong> in that file.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="946" height="408" src="https://www.victordorado.es/wp-content/uploads/2024/06/image-6.png" alt="" class="wp-image-2288" srcset="https://www.victordorado.es/wp-content/uploads/2024/06/image-6.png 946w, https://www.victordorado.es/wp-content/uploads/2024/06/image-6-300x129.png 300w, https://www.victordorado.es/wp-content/uploads/2024/06/image-6-768x331.png 768w" sizes="(max-width: 946px) 100vw, 946px" /></figure>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">Maintaining a consistent code style in our projects is made easier with these supportive tools. Including them in every developer&#8217;s toolkit is highly beneficial.</p>
<p>The post <a href="https://www.victordorado.es/2024/06/28/improve-your-code-quality-with-php-codesniffer-phpstan-eslint-stylelint-phpstorm-integration/">Improve your code quality from PHPStorm with PHP_CodeSniffer</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PHPUnit up and running with Drupal, DDEV and PHPStorm</title>
		<link>https://www.victordorado.es/2024/03/18/phpunit-up-and-running-with-drupal-ddev-and-phpstorm/</link>
		
		<dc:creator><![CDATA[vidorado]]></dc:creator>
		<pubDate>Mon, 18 Mar 2024 00:01:03 +0000</pubDate>
				<category><![CDATA[DDEV]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHPStorm]]></category>
		<guid isPermaLink="false">https://www.victordorado.es/?p=2229</guid>

					<description><![CDATA[<p>Getting PHPStorm, DDEV, Drupal and PHPUnit to work together is not a trivial task. Read this guide to get up and running!</p>
<p>The post <a href="https://www.victordorado.es/2024/03/18/phpunit-up-and-running-with-drupal-ddev-and-phpstorm/">PHPUnit up and running with Drupal, DDEV and PHPStorm</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">There are some articles out there about this topic: like the official <a href="https://ddev.readthedocs.io/en/latest/users/install/phpstorm/#enabling-phpunit" data-type="link" data-id="https://ddev.readthedocs.io/en/latest/users/install/phpstorm/#enabling-phpunit" target="_blank" rel="noreferrer noopener">DDEV docs PHPStorm &#8211; Enabling PHPUnit</a> or Matt Glaman&#8217;s <a href="https://mglaman.dev/blog/running-drupals-phpunit-test-suites-ddev" data-type="link" data-id="https://mglaman.dev/blog/running-drupals-phpunit-test-suites-ddev" target="_blank" rel="noreferrer noopener">Running Drupal&#8217;s PHPUnit test suites on DDEV</a>, <strong>but</strong> <strong>I haven&#8217;t found it so easy to figure it out. So, I&#8217;m writing this guide</strong>, although knowing that one day it will become obsolete, like it always have been with guides and new versions of things 🙂</p>



<h2 class="wp-block-heading">First step: enabling DDEV integration plugin for PHPStorm</h2>



<p class="wp-block-paragraph">DDEV has a PHPStorm plugin that eases a lot working with DDEV. <strong>One of the great things DDEV&#8217;s plugin does is creating a CLI interpreter</strong> that executes PHP code inside the web container. This will be the cornerstone of our setup.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="675" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-7-1024x675.png" alt="" class="wp-image-2231" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-7-1024x675.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-7-300x198.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-7-768x507.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-7.png 1128w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Setting DDEV as the project&#8217;s CLI interpreter and the Test framework interpreter</h2>



<p class="wp-block-paragraph">Under Settings -&gt; PHP section, we can now select the DDEV CLI interpreter:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="183" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-9-1024x183.png" alt="" class="wp-image-2232" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-9-1024x183.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-9-300x54.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-9-768x137.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-9.png 1129w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">If you don&#8217;t see the interpreter, check that you have a Docker connection added in Build, Execution, Deployment -&gt; Docker:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="685" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-10-1024x685.png" alt="" class="wp-image-2233" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-10-1024x685.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-10-300x201.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-10-768x514.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-10.png 1113w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">And check that &#8220;Use Compose V2&#8221; is enabled under the Tools subsection:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="685" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-11-1024x685.png" alt="" class="wp-image-2234" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-11-1024x685.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-11-300x201.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-11-768x514.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-11.png 1113w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Now, we must go to PHP -&gt; Test Frameworks and add a new one that uses the DDEV CLI interpreter:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="546" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-12-1024x546.png" alt="" class="wp-image-2235" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-12-1024x546.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-12-300x160.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-12-768x409.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-12.png 1394w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">We must also set a custom Default configuration file named phpunit.xml and located in our project&#8217;s root directory. DDEV&#8217;s CLI interpreter runs inside the web docker container, so we must set the path as it&#8217;s seen inside the container: <code>/var/www/html/phpunit.xml</code>. (this file doesn&#8217;t exist yet, we will create it later).</p>



<p class="wp-block-paragraph"><strong>Now, we have to tell PHPStorm to run this project&#8217;s tests with this new test framework</strong>. Go to Run -&gt; Edit configurations menu and clear any configuration you may find here.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="727" height="352" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-14.png" alt="" class="wp-image-2237" style="object-fit:cover" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-14.png 727w, https://www.victordorado.es/wp-content/uploads/2024/03/image-14-300x145.png 300w" sizes="(max-width: 727px) 100vw, 727px" /></figure>



<p class="wp-block-paragraph">Then, click on Edit configuration templates&#8230; -&gt; PHPUnit and set DDEV as the Command Line Interpreter:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1007" height="681" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-13.png" alt="" class="wp-image-2236" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-13.png 1007w, https://www.victordorado.es/wp-content/uploads/2024/03/image-13-300x203.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-13-768x519.png 768w" sizes="(max-width: 1007px) 100vw, 1007px" /></figure>



<h2 class="wp-block-heading">Creating project&#8217;s PHPUnit configuration file</h2>



<p class="wp-block-paragraph">Copy core&#8217;s PHPUnit configuration file <code>/web/core/phpunit.xml.dist</code> to <code>/phpunit.xml</code>, and edit it as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;phpunit xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
         bootstrap=&quot;web/core/tests/bootstrap.php&quot;
         colors=&quot;true&quot;
         beStrictAboutTestsThatDoNotTestAnything=&quot;true&quot;
         beStrictAboutOutputDuringTests=&quot;true&quot;
         beStrictAboutChangesToGlobalState=&quot;true&quot;
         failOnWarning=&quot;true&quot;
         printerClass=&quot;\Drupal\Tests\Listeners\HtmlOutputPrinter&quot;
         cacheResult=&quot;false&quot;
         xsi:noNamespaceSchemaLocation=&quot;https://schema.phpunit.de/9.3/phpunit.xsd&quot;&gt;
  &lt;php&gt;
    &lt;ini name=&quot;error_reporting&quot; value=&quot;32767&quot;/&gt; &lt;!-- 32767 = E_ALL. --&gt;
    &lt;ini name=&quot;memory_limit&quot; value=&quot;-1&quot;/&gt;
    &lt;env name=&quot;SIMPLETEST_BASE_URL&quot; value=&quot;http://my-project.ddev.site&quot;/&gt;
    &lt;env name=&quot;SIMPLETEST_DB&quot; value=&quot;mysql://db:db@db:3306/test&quot;/&gt;
    &lt;env name=&quot;BROWSERTEST_OUTPUT_DIRECTORY&quot; value=&quot;&quot;/&gt;
&lt;!--    &lt;env name=&quot;SYMFONY_DEPRECATIONS_HELPER&quot; value=&quot;weak&quot;/&gt;--&gt;
  &lt;/php&gt;

  &lt;testsuites&gt;
    &lt;testsuite name=&quot;unit&quot;&gt;
      &lt;directory&gt;web/modules/custom/*/tests/src/Unit/&lt;/directory&gt;
    &lt;/testsuite&gt;
    &lt;testsuite name=&quot;kernel&quot;&gt;
      &lt;directory&gt;web/modules/custom/*/tests/src/Kernel/&lt;/directory&gt;
    &lt;/testsuite&gt;
    &lt;testsuite name=&quot;functional&quot;&gt;
      &lt;directory&gt;web/modules/custom/*/tests/src/Functional/&lt;/directory&gt;
    &lt;/testsuite&gt;
    &lt;testsuite name=&quot;functional-javascript&quot;&gt;
      &lt;directory&gt;web/modules/custom/*/tests/src/FunctionalJavascript/&lt;/directory&gt;
    &lt;/testsuite&gt;
  &lt;/testsuites&gt;

  &lt;listeners&gt;
    &lt;listener class=&quot;\Drupal\Tests\Listeners\DrupalListener&quot;&gt;
    &lt;/listener&gt;
    &lt;!-- The Symfony deprecation listener has to come after the Drupal listener --&gt;
    &lt;listener class=&quot;Symfony\Bridge\PhpUnit\SymfonyTestsListener&quot;&gt;
    &lt;/listener&gt;
  &lt;/listeners&gt;

  &lt;coverage&gt;
    &lt;include&gt;
      &lt;directory suffix=&quot;.php&quot;&gt;web/modules/custom/*/src&lt;/directory&gt;
    &lt;/include&gt;
  &lt;/coverage&gt;

&lt;/phpunit&gt;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">&lt;?</span><span style="color: #5E81AC">xml</span><span style="color: #8FBCBB"> version</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">1.0</span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB"> encoding</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">UTF-8</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">?&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">&lt;phpunit</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">xmlns</span><span style="color: #ECEFF4">:</span><span style="color: #8FBCBB">xsi</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">http://www.w3.org/2001/XMLSchema-instance</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">bootstrap</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">web/core/tests/bootstrap.php</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">colors</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">true</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">beStrictAboutTestsThatDoNotTestAnything</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">true</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">beStrictAboutOutputDuringTests</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">true</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">beStrictAboutChangesToGlobalState</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">true</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">failOnWarning</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">true</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">printerClass</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">\Drupal\Tests\Listeners\HtmlOutputPrinter</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">cacheResult</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">false</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #8FBCBB">xsi</span><span style="color: #ECEFF4">:</span><span style="color: #8FBCBB">noNamespaceSchemaLocation</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://schema.phpunit.de/9.3/phpunit.xsd</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;php&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;ini</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">error_reporting</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">32767</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">/&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">&lt;!-- 32767 = E_ALL. --&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;ini</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">memory_limit</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;env</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">SIMPLETEST_BASE_URL</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">http://my-project.ddev.site</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;env</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">SIMPLETEST_DB</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mysql://db:db@db:3306/test</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;env</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">BROWSERTEST_OUTPUT_DIRECTORY</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #616E88">&lt;!--    &lt;env name=&quot;SYMFONY_DEPRECATIONS_HELPER&quot; value=&quot;weak&quot;/&gt;--&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;/php&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;testsuites&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;testsuite</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">unit</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;directory&gt;</span><span style="color: #D8DEE9FF">web/modules/custom/*/tests/src/Unit/</span><span style="color: #81A1C1">&lt;/directory&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/testsuite&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;testsuite</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">kernel</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;directory&gt;</span><span style="color: #D8DEE9FF">web/modules/custom/*/tests/src/Kernel/</span><span style="color: #81A1C1">&lt;/directory&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/testsuite&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;testsuite</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">functional</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;directory&gt;</span><span style="color: #D8DEE9FF">web/modules/custom/*/tests/src/Functional/</span><span style="color: #81A1C1">&lt;/directory&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/testsuite&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;testsuite</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">functional-javascript</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;directory&gt;</span><span style="color: #D8DEE9FF">web/modules/custom/*/tests/src/FunctionalJavascript/</span><span style="color: #81A1C1">&lt;/directory&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/testsuite&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;/testsuites&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;listeners&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;listener</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">\Drupal\Tests\Listeners\DrupalListener</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/listener&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">&lt;!-- The Symfony deprecation listener has to come after the Drupal listener --&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;listener</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Symfony\Bridge\PhpUnit\SymfonyTestsListener</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/listener&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;/listeners&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;coverage&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;include&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;directory</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">suffix</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">.php</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">web/modules/custom/*/src</span><span style="color: #81A1C1">&lt;/directory&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/include&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;/coverage&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">&lt;/phpunit&gt;</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>These are all the customizations that have been made:</strong></p>



<p class="wp-block-paragraph">1. Adjust the boostrap path to core&#8217;s bootstrap</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="bootstrap=&quot;web/core/tests/bootstrap.php&quot;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">bootstrap=&quot;web/core/tests/bootstrap.php&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">2. Set site URL and database connection details (for Kernel, Functional&#8230; etc. tests). Note that PHPUnit will be executed inside the web container, so we must set &#8220;db&#8221; and port 3306 as our database host, as it is seen from the web container. We also set the testing database name to &#8220;test&#8221;, that is the convention.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&lt;env name=&quot;SIMPLETEST_BASE_URL&quot; value=&quot;https://my-project.ddev.site&quot;/&gt;
&lt;env name=&quot;SIMPLETEST_DB&quot; value=&quot;mysql://db:db@db:3306/test&quot;/&gt;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">&lt;env</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">SIMPLETEST_BASE_URL</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://my-project.ddev.site</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #81A1C1">&lt;env</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">SIMPLETEST_DB</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mysql://db:db@db:3306/test</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">/&gt;</span></span></code></pre></div>



<p class="wp-block-paragraph">3. Finally, we adjust all test suites to only execute tests from our custom modules by default, if we execute phpunit without file parameters nor filters.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&lt;testsuite name=&quot;unit&quot;&gt;
  &lt;directory&gt;web/modules/custom/*/tests/src/Unit/&lt;/directory&gt;
&lt;/testsuite&gt;
&lt;testsuite name=&quot;kernel&quot;&gt;
  &lt;directory&gt;web/modules/custom/*/tests/src/Kernel/&lt;/directory&gt;
&lt;/testsuite&gt;
..." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">&lt;testsuite</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">unit</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;directory&gt;</span><span style="color: #D8DEE9FF">web/modules/custom/*/tests/src/Unit/</span><span style="color: #81A1C1">&lt;/directory&gt;</span></span>
<span class="line"><span style="color: #81A1C1">&lt;/testsuite&gt;</span></span>
<span class="line"><span style="color: #81A1C1">&lt;testsuite</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">kernel</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;directory&gt;</span><span style="color: #D8DEE9FF">web/modules/custom/*/tests/src/Kernel/</span><span style="color: #81A1C1">&lt;/directory&gt;</span></span>
<span class="line"><span style="color: #81A1C1">&lt;/testsuite&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">...</span></span></code></pre></div>



<h2 class="wp-block-heading">Installing PHPUnit</h2>



<p class="wp-block-paragraph">As simple as installing these packages with Composer</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev composer require --dev \
  phpunit/phpunit \
  phpspec/prophecy-phpunit \
  symfony/phpunit-bridge \
  dmore/chrome-mink-driver \
  behat/mink-browserkit-driver \
  behat/mink-selenium2-driver \
  mikey179/vfsstream" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># ddev composer require --dev \</span></span>
<span class="line"><span style="color: #D8DEE9FF">  phpunit/phpunit \</span></span>
<span class="line"><span style="color: #D8DEE9FF">  phpspec/prophecy-phpunit \</span></span>
<span class="line"><span style="color: #D8DEE9FF">  symfony/phpunit-bridge \</span></span>
<span class="line"><span style="color: #D8DEE9FF">  dmore/chrome-mink-driver \</span></span>
<span class="line"><span style="color: #D8DEE9FF">  behat/mink-browserkit-driver \</span></span>
<span class="line"><span style="color: #D8DEE9FF">  behat/mink-selenium2-driver \</span></span>
<span class="line"><span style="color: #D8DEE9FF">  mikey179/vfsstream</span></span></code></pre></div>



<ul class="wp-block-list">
<li><strong>phpunit/phpunit</strong> &#8211; The PHPUnit core package.</li>



<li><strong>phpspec/prophecy-phpunit</strong> &#8211; The Prophecy mocking system. In a lot of tests it is used instead of PHPUnit Mock Object Framework, the PHPUnit standard.</li>



<li><strong>symfony/phpunit-bridge</strong> &#8211; Bridges the gap between Symfony and PHPUnit.</li>



<li><strong>dmore/chrome-mink-driver</strong> &#8211; Required for some Kernel nad Functional tests.</li>



<li><strong>behat/mink-browserkit-driver</strong> &#8211; Required for some Functional tests.</li>



<li><strong>mikey179/vfsstream</strong> &#8211; Some tests make use of this virtual filesystem mocker.</li>
</ul>



<h2 class="wp-block-heading">Configuring DDEV Selenium Standalone Chrome</h2>



<p class="wp-block-paragraph">This config is necessary to execute Javascript and FunctionalJavascript Drupal tests. PHPUnit needs a headless Chromium browser to control and to send commands to. That&#8217;s what this DDEV addon provides.</p>



<p class="wp-block-paragraph">Follow the instructions in <a href="https://github.com/ddev/ddev-selenium-standalone-chrome">https://github.com/ddev/ddev-selenium-standalone-chrome</a>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev get ddev/ddev-selenium-standalone-chrome" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">ddev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">get</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ddev</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">ddev</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">selenium</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">standalone</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">chrome</span></span></code></pre></div>



<p class="wp-block-paragraph">Then, update your <code>.ddev/config.selenium-standalone-chrome.yaml</code> and set the local domain for your DDEV project, making sure you set it as <code>http://</code> and not <code>https://</code> (I got an &#8220;invalid cookie domain&#8221; error when I did).</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="#ddev-generated  &lt;- REMOVE THIS LINE

...

- SIMPLETEST_BASE_URL=http://my-project.ddev.site

...

- DRUPAL_TEST_BASE_URL=http://my-project.ddev.site

...

- DTT_BASE_URL=http://my-project.ddev.site" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">ddev</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">generated</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">&lt;-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REMOVE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">THIS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LINE</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SIMPLETEST_BASE_URL</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">http</span><span style="color: #ECEFF4">:</span><span style="color: #616E88">//my-project.ddev.site</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DRUPAL_TEST_BASE_URL</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">http</span><span style="color: #ECEFF4">:</span><span style="color: #616E88">//my-project.ddev.site</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DTT_BASE_URL</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">http</span><span style="color: #ECEFF4">:</span><span style="color: #616E88">//my-project.ddev.site</span></span></code></pre></div>



<p class="wp-block-paragraph">Then, restart DDEV:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev restart" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">ddev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">restart</span></span></code></pre></div>



<h2 class="wp-block-heading">Executing tests from the command line</h2>



<p class="wp-block-paragraph">If we want being able to execute our tests easily from outside the web container, we must create the file <code>/.ddev/commands/web/phpunit</code> with this content:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="#!/bin/bash

phpunit &quot;$@&quot;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">phpunit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$@</span><span style="color: #ECEFF4">&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">And now, outside the web container, we can do:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev phpunit
# ddev phpunit --testsuite &lt;name&gt;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># ddev phpunit</span></span>
<span class="line"><span style="color: #D8DEE9FF"># ddev phpunit --testsuite </span><span style="color: #81A1C1">&lt;name&gt;</span></span></code></pre></div>



<h2 class="wp-block-heading">Executing tests from PHPStorm</h2>



<p class="wp-block-paragraph">From PHPStorm&#8217;s interface, <strong>we can go to any test case class and use the GUI to run its tests</strong>, either all at once or one by one, simply clicking on the run icons next to the class and test method definitions:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="806" height="269" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-16.png" alt="" class="wp-image-2241" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-16.png 806w, https://www.victordorado.es/wp-content/uploads/2024/03/image-16-300x100.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-16-768x256.png 768w" sizes="(max-width: 806px) 100vw, 806px" /></figure>



<p class="wp-block-paragraph"><strong>We can even right click on any directory in the project&#8217;s explorer and click on &#8220;Run (tests PHPUnit)&#8221; and all tests in that directory will be executed.</strong> This is very convenient when we want to debug only a test method or execute only one type of tests inside a module, for example.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="162" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-15-1024x162.png" alt="" class="wp-image-2239" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-15-1024x162.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-15-300x47.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-15-768x121.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-15-1536x243.png 1536w, https://www.victordorado.es/wp-content/uploads/2024/03/image-15.png 1729w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph"><strong>Getting PHPStorm, DDEV, Drupal and PHPUnit to work together is not a trivial task</strong>. Although DDEV&#8217;s PHPStorm plugin eases a bit the task, we have yet to wire all the things correctly.</p>
<p>The post <a href="https://www.victordorado.es/2024/03/18/phpunit-up-and-running-with-drupal-ddev-and-phpstorm/">PHPUnit up and running with Drupal, DDEV and PHPStorm</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Debug your Drupal code with PHPStorm, DDEV and Xdebug</title>
		<link>https://www.victordorado.es/2024/03/17/debug-your-drupal-code-with-phpstorm-ddev-and-xdebug/</link>
		
		<dc:creator><![CDATA[vidorado]]></dc:creator>
		<pubDate>Sun, 17 Mar 2024 17:37:16 +0000</pubDate>
				<category><![CDATA[DDEV]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHPStorm]]></category>
		<guid isPermaLink="false">https://www.victordorado.es/?p=2186</guid>

					<description><![CDATA[<p>Debugging goes next level when it's done with a tool like Xdebug and through a debugging GUI like PHPStorm has.</p>
<p>The post <a href="https://www.victordorado.es/2024/03/17/debug-your-drupal-code-with-phpstorm-ddev-and-xdebug/">Debug your Drupal code with PHPStorm, DDEV and Xdebug</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>How would have been our lives without debuggers?</strong> We would have been spreading <code>print_r</code>, <code>echo</code> and the like everywhere. Our world got better with tools like Krumo or (in the case of Drupal) with <code>dpm()</code>, but nothing like a real [IDE + debugger] couple like [PHPStorm + Xdebug].</p>



<p class="wp-block-paragraph">If you also add DDEV and its docker containers to the mix, it&#8217;s not easy to get all pieces working, without a proper recipe. This article aims to be that recipe.</p>



<h2 class="wp-block-heading">Preparing DDEV&#8217;s web container</h2>



<p class="wp-block-paragraph">DDEV automatically adds two environment variables to its <code>.ddev-docker-compose-base.yaml</code> file:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="PHP_IDE_CONFIG=serverName=${DDEV_SITENAME}.${DDEV_TLD}
DRUSH_ALLOW_XDEBUG=1" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">PHP_IDE_CONFIG</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">serverName</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">DDEV_SITENAME</span><span style="color: #ECEFF4">}.</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">DDEV_TLD</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9">DRUSH_ALLOW_XDEBUG</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">1</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Mind the serverName because we will need it later</strong>, when configuring a server in PHPStorm.</p>



<p class="wp-block-paragraph">Now, we must config the Xdebug PHP extension. Create a new directory <code>.ddev/php/</code> and create a file called <code>xdebug.ini</code> inside it, with this content.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="xdebug.client_port = 9000
xdebug.idekey = PHPSTORM
xdebug.mode = develop,debug
xdebug.start_with_request = yes" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">xdebug</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_port</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">9000</span></span>
<span class="line"><span style="color: #D8DEE9">xdebug</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">idekey</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PHPSTORM</span></span>
<span class="line"><span style="color: #D8DEE9">xdebug</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">mode</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">develop</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9">debug</span></span>
<span class="line"><span style="color: #D8DEE9">xdebug</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">start_with_request</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">yes</span></span></code></pre></div>



<p class="wp-block-paragraph">I like to set <code>xdebug.start_with_request=yes</code> and turn on and off the web contaniner&#8217;s xdebug PHP extension with <code>ddev xdebug on</code> and <code>ddev xdebug off</code>. You could set <code>xdebug.start_with_request=no</code> and play with a browser switch like <a href="https://chromewebstore.google.com/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc" data-type="link" data-id="https://chromewebstore.google.com/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc" target="_blank" rel="noreferrer noopener">Xdebug Helper</a>, but this won&#8217;t have effect on drush commands.</p>



<p class="wp-block-paragraph">After that, we have to restart DDEV&#8217;s web container:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev restart" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">ddev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">restart</span></span></code></pre></div>



<h2 class="wp-block-heading">Configuring PHPStorm</h2>



<p class="wp-block-paragraph">Now, we must create a new PHP server under Settings -&gt; PHP -&gt; Servers. Recall the server name we saw in DDEV&#8217;s config: it was <code>${DDEV_SITENAME}.${DDEV_TLD}</code>, that translates to <code>my-project.ddev.site</code> if your DDEV project is named <code>my-project</code>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="740" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-1024x740.png" alt="" class="wp-image-2187" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-1024x740.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-300x217.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-768x555.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image.png 1037w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">We need to set path mappings for the webserver docroot directory. A path mapping &#8220;maps&#8221; a real directory path in your filesystem with a directory inside the DDEV docker web container. In our case, <strong>a DDEV drupal project has its web server&#8217;s document root in <code>/var/www/html/web</code>, so we have to set this mapping</strong>:</p>



<ul class="wp-block-list">
<li><code>/path/to/your/project<strong>/web</strong> -&gt; /var/www/html<strong>/web</strong></code></li>
</ul>



<p class="wp-block-paragraph"><strong>However, I recommend also adding this mapping </strong>to be able to debug vendor code.</p>



<ul class="wp-block-list">
<li><code>/path/to/your/project<strong>/vendor</strong> -&gt; /var/www/html<strong>/vendor</strong></code></li>
</ul>



<p class="wp-block-paragraph">With these mappings, PHPStorm now knows how to map between the same file as it&#8217;s seen inside/outside DDEV&#8217;s web container.</p>



<p class="wp-block-paragraph">After that, to be sure everything is ok,<strong> I recommend checking and configuring the Xdebug installation</strong> under PHP -&gt; Debug:</p>



<p class="wp-block-paragraph">First, click on the &#8220;Validate&#8221; link:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="916" height="279" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-1.png" alt="" class="wp-image-2188" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-1.png 916w, https://www.victordorado.es/wp-content/uploads/2024/03/image-1-300x91.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-1-768x234.png 768w" sizes="(max-width: 916px) 100vw, 916px" /></figure>



<p class="wp-block-paragraph">In the next screen configure the docroot directory as it&#8217;s seen by PHPStorm (your real machine path to the web directory inside your project directory) and the URL where the project&#8217;s docroot will be accesible. Then, click on &#8220;Validate&#8221;.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="861" height="690" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-2.png" alt="" class="wp-image-2189" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-2.png 861w, https://www.victordorado.es/wp-content/uploads/2024/03/image-2-300x240.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-2-768x615.png 768w" sizes="(max-width: 861px) 100vw, 861px" /></figure>



<p class="wp-block-paragraph"><strong>I strongly recommend unchecking these two &#8220;Force break&#8221; checkboxes</strong>, because we don&#8217;t want the execution to be paused if we don&#8217;t set or don&#8217;t reach a breakpoint. I remember myself waiting a drush command to finish unaware that the execution was paused, because of this.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="908" height="744" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-6.png" alt="" class="wp-image-2193" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-6.png 908w, https://www.victordorado.es/wp-content/uploads/2024/03/image-6-300x246.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-6-768x629.png 768w" sizes="(max-width: 908px) 100vw, 908px" /></figure>



<p class="wp-block-paragraph">So far, we have configured DDEV and PHPStorm to &#8220;connect&#8221; between them and our next step will be to set a breakpoint. For example, we can break on the <code>handle()</code> call that <code>Drupal\Core\DrupalKernel</code> class does on every page load.</p>



<p class="wp-block-paragraph">Click next to the line number and a red dot will appear. This is our breakpoint. The PHP execution will stop here until we let it continue.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="437" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-4-1024x437.png" alt="" class="wp-image-2191" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-4-1024x437.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-4-300x128.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-4-768x328.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-4.png 1404w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph"><strong>Remember to enable xdebug PHP extension on DDEV&#8217;s </strong>web container with</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# ddev xdebug on" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">ddev</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xdebug</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">on</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>And to tell PHPStorm to listen</strong> to incoming debug connections with the <img decoding="async" style="width:21px;height:auto;" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-8.png" alt="Listen icon"> icon.</p>



<p class="wp-block-paragraph"><strong>Now, reload any page</strong> in your browser and you will view a system notification letting you know that PHPStorm requires your attention. Go for it and you will see the breakpoint&#8217;s line highlighted and <strong>a panel where you can explore all the variables in it&#8217;s scope.</strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="470" src="https://www.victordorado.es/wp-content/uploads/2024/03/image-5-1024x470.png" alt="" class="wp-image-2192" srcset="https://www.victordorado.es/wp-content/uploads/2024/03/image-5-1024x470.png 1024w, https://www.victordorado.es/wp-content/uploads/2024/03/image-5-300x138.png 300w, https://www.victordorado.es/wp-content/uploads/2024/03/image-5-768x352.png 768w, https://www.victordorado.es/wp-content/uploads/2024/03/image-5.png 1426w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph"><strong>You can browse the variables panel and deep dive into the tree structures. This is VERY useful</strong>, specially when debugging a framework like Drupal that has many nesting levels on its variables.</p>



<p class="wp-block-paragraph"><strong>You can also select any piece of code, right click on it and click on &#8220;Evaluate expression&#8221;</strong> and you could test it inside that paused execution state. You can even write directly your own expressions.</p>



<p class="wp-block-paragraph">You can continue the execution step-by-step (step over, F8), even traveling inside method calls (step into, F7), or continue the execution until the next breakpoint (or the same breakpoint if it&#8217;s reached again)</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">Debugging goes next level when it&#8217;s done with a tool like Xdebug and through a debugging GUI like PHPStorm has.</p>
<p>The post <a href="https://www.victordorado.es/2024/03/17/debug-your-drupal-code-with-phpstorm-ddev-and-xdebug/">Debug your Drupal code with PHPStorm, DDEV and Xdebug</a> appeared first on <a href="https://www.victordorado.es">Víctor Dorado</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
