<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Tomas Norre Mikkelsen</title>
    <description>The latest articles on Forem by Tomas Norre Mikkelsen (@tomasnorre).</description>
    <link>https://forem.com/tomasnorre</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F356682%2F867fba26-3d17-46e6-96ea-0b296504a4dd.jpg</url>
      <title>Forem: Tomas Norre Mikkelsen</title>
      <link>https://forem.com/tomasnorre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tomasnorre"/>
    <language>en</language>
    <item>
      <title>Running TYPO3 11 with ddev</title>
      <dc:creator>Tomas Norre Mikkelsen</dc:creator>
      <pubDate>Sat, 02 Jan 2021 12:43:26 +0000</pubDate>
      <link>https://forem.com/tomasnorre/running-typo3-11-with-ddev-5h5l</link>
      <guid>https://forem.com/tomasnorre/running-typo3-11-with-ddev-5h5l</guid>
      <description>&lt;p&gt;I recently started a new Project with TYPO3 11 and ddev, there a two things your should be aware of. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make sure to use ddev 1.16.5 or never.&lt;/li&gt;
&lt;li&gt;Add the default &lt;code&gt;.htaccess&lt;/code&gt; to you &lt;code&gt;public&lt;/code&gt;-folder, otherwise the backend Route will not work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My setup is as you see, with &lt;code&gt;apacehe-fpm&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;When Running with &lt;code&gt;nginx-fpm&lt;/code&gt; no additional configuration is needed besides &lt;code&gt;ddev 1.16.5&lt;/code&gt; or never.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;RewriteEngine&lt;/span&gt; &lt;span class="n"&gt;On&lt;/span&gt;

&lt;span class="n"&gt;RewriteRule&lt;/span&gt; ^(?:&lt;span class="n"&gt;fileadmin&lt;/span&gt;/|&lt;span class="n"&gt;typo3conf&lt;/span&gt;/|&lt;span class="n"&gt;typo3temp&lt;/span&gt;/|&lt;span class="n"&gt;uploads&lt;/span&gt;/) - [&lt;span class="n"&gt;L&lt;/span&gt;]

&lt;span class="n"&gt;RewriteCond&lt;/span&gt; %{&lt;span class="n"&gt;REQUEST_FILENAME&lt;/span&gt;} !-&lt;span class="n"&gt;f&lt;/span&gt;
&lt;span class="n"&gt;RewriteCond&lt;/span&gt; %{&lt;span class="n"&gt;REQUEST_FILENAME&lt;/span&gt;} !-&lt;span class="n"&gt;d&lt;/span&gt;
&lt;span class="n"&gt;RewriteCond&lt;/span&gt; %{&lt;span class="n"&gt;REQUEST_FILENAME&lt;/span&gt;} !-&lt;span class="n"&gt;l&lt;/span&gt;
&lt;span class="n"&gt;RewriteCond&lt;/span&gt; %{&lt;span class="n"&gt;REQUEST_URI&lt;/span&gt;} ^/&lt;span class="n"&gt;typo3&lt;/span&gt;/.*$
&lt;span class="n"&gt;RewriteRule&lt;/span&gt; ^&lt;span class="n"&gt;typo3&lt;/span&gt;/(.*)$ %{&lt;span class="n"&gt;ENV&lt;/span&gt;:&lt;span class="n"&gt;CWD&lt;/span&gt;}&lt;span class="n"&gt;typo3&lt;/span&gt;/&lt;span class="n"&gt;index&lt;/span&gt;.&lt;span class="n"&gt;php&lt;/span&gt; [&lt;span class="n"&gt;QSA&lt;/span&gt;,&lt;span class="n"&gt;L&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>typo3</category>
      <category>ddev</category>
      <category>nginx</category>
      <category>apache</category>
    </item>
    <item>
      <title>Hacktoberfest - Random Issue Picker</title>
      <dc:creator>Tomas Norre Mikkelsen</dc:creator>
      <pubDate>Tue, 29 Sep 2020 20:26:24 +0000</pubDate>
      <link>https://forem.com/tomasnorre/hacktoberfest-random-issue-picker-49lm</link>
      <guid>https://forem.com/tomasnorre/hacktoberfest-random-issue-picker-49lm</guid>
      <description>&lt;p&gt;The &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest2020&lt;/a&gt; is just around the corner, but where to contribute?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/icanhazstring"&gt;Andreas Frömer&lt;/a&gt; has created a small tool that can help you. The "Random Issue Picker" selects a random issue from GitHub based on certain criteria. &lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements for the tool:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;PHP 7.3+&lt;/li&gt;
&lt;li&gt;composer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to use it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/icanhazstring/random-issue-picker.git
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;random-issue-picker
&lt;span class="nv"&gt;$ &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;bin/rip random:issue &lt;span class="nt"&gt;-l&lt;/span&gt; js &lt;span class="nt"&gt;--label&lt;/span&gt; hacktoberfest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will then post information on the issue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Hamburger icon &lt;span class="k"&gt;in &lt;/span&gt;dark mode
&lt;span class="nt"&gt;---------------------------&lt;/span&gt;

https://github.com/Ninja-Developers/Tech_Phantoms_website/issues/66


Hamburger icon &lt;span class="k"&gt;in &lt;/span&gt;dark mode blends with the background. Icon color can be changed to white. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can copy/paste or click the link to the issue and start working and earn your hackathon T-shirt.&lt;/p&gt;

&lt;p&gt;Have fun, and have a great Hacktoberfest. &lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>random</category>
      <category>development</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Codeception tests in Travis CI with DDEV and Selenium</title>
      <dc:creator>Tomas Norre Mikkelsen</dc:creator>
      <pubDate>Sat, 02 May 2020 15:29:24 +0000</pubDate>
      <link>https://forem.com/tomasnorre/codeception-tests-in-travis-ci-with-ddev-and-selenium-1607</link>
      <guid>https://forem.com/tomasnorre/codeception-tests-in-travis-ci-with-ddev-and-selenium-1607</guid>
      <description>&lt;p&gt;Recently I posted about how to run codeception with DDEV. &lt;br&gt;
&lt;a href="https://dev.to/tomasnorre/codeception-ddev-selenium-docker-36kk"&gt;https://dev.to/tomasnorre/codeception-ddev-selenium-docker-36kk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is of course really nice, but having it as part of the CI pipeline is even better.&lt;/p&gt;

&lt;p&gt;So I decided to try to make it run within &lt;a href="https://travis-ci.org/"&gt;Travis CI&lt;/a&gt; which is my preferred public CI at the moment. &lt;/p&gt;
&lt;h2&gt;
  
  
  What to do?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Signup with travis-ci and registre your repository&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;.travis.yml&lt;/code&gt; to your github repository&lt;/li&gt;
&lt;li&gt;Make changes and push, and wait for the results of the tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can see the step in the &lt;a href="https://docs.travis-ci.com/user/tutorial/"&gt;Travis CI Tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The advantages here is that you will have your behaviour driven tests executed on every commit and pull request, to make sure you or others don't break functionality. &lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring Travis CI
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;.travis.yml&lt;/code&gt; is the configuration file for Travis CI. I contains different step and instructions to enable travis to do what you want.&lt;/p&gt;

&lt;p&gt;This can be used to run PHPUnit, Checking Coding Standard, Codeception tests and so on, only your imagination is the limit. &lt;/p&gt;

&lt;p&gt;This is how the &lt;code&gt;.travis.yml&lt;/code&gt; looks like for my &lt;a href="https://github.com/tomasnorre/ddev-codeception-poc"&gt;https://github.com/tomasnorre/ddev-codeception-poc&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;language: php
dist: bionic

notifications:
  email:
    on_success: never
    on_failure: never

before_install:
  # turn off XDebug for speed up
  - phpenv config-rm xdebug.ini || return 0

php:
  - '7.4'

services:
  - docker

cache:
  directories:
    - $HOME/.composer/cache

before_script:
  - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
  - sudo apt update
  - sudo apt install docker-ce
  - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  - sudo chmod +x /usr/local/bin/docker-compose
  - docker-compose --version
  - wget https://github.com/drud/ddev/releases/download/v1.13.1/ddev_linux.v1.13.1.tar.gz
  - tar vxzf ddev_linux.v1.13.1.tar.gz
  - sudo chmod +x ddev
  - sudo chmod +x mkcert
  - ./mkcert -install

jobs:
  fast_finish: true
  include:
    -
      stage: Tests
      name: "Code ception"
      script:
        - composer install
        - ./ddev --version
        - ./ddev start
        - php vendor/bin/codecept run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I had to install a never version of docker, manually to meet the requirements from &lt;a href="https://ddev.com"&gt;ddev&lt;/a&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  The result
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiwjx45kw14jwawb8fnn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiwjx45kw14jwawb8fnn9.png" alt="Codeception in Travis CI output console" width="638" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have fun.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>codeception</category>
      <category>travis</category>
      <category>php</category>
    </item>
    <item>
      <title>TYPO3 Crawler with TYPO3 9 &amp; 10 Support</title>
      <dc:creator>Tomas Norre Mikkelsen</dc:creator>
      <pubDate>Tue, 14 Apr 2020 14:47:05 +0000</pubDate>
      <link>https://forem.com/tomasnorre/typo3-crawler-with-typo3-9-10-support-4h1n</link>
      <guid>https://forem.com/tomasnorre/typo3-crawler-with-typo3-9-10-support-4h1n</guid>
      <description>&lt;p&gt;11th of November 2018, I added the &lt;code&gt;typo3/cms-core:^9.5&lt;/code&gt; to the composer dependency for the TYPO3 Crawler extension, the goal was set to make the Crawler compatible with TYPO3 9 LTS. &lt;/p&gt;

&lt;p&gt;Unfortunately, it's been a very look journey, also way too long, as we are facing the TYPO3 10 LTS release in just a couple of days. &lt;/p&gt;

&lt;p&gt;Finally, can I not only present a Crawler 9.0.0 which is compatible with TYPO3 9 LTS but at least as important also compatible with TYPO3 10LTS. &lt;/p&gt;

&lt;h3&gt;
  
  
  What has been added, changed or removed?
&lt;/h3&gt;

&lt;p&gt;It's too much to list here so I'll recommend to browser through the &lt;a href="https://github.com/AOEpeople/crawler/blob/master/CHANGELOG.md"&gt;changelog on Github&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Breaking Changes
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Support for TYPO3 8&lt;/li&gt;
&lt;li&gt;Support for TYPO3 7&lt;/li&gt;
&lt;li&gt;PHP support for &lt;code&gt;&amp;lt;7.2&lt;/code&gt; &lt;a href="https://github.com/TomasVotruba"&gt;@TomasVotruba&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Remove root_template_pid option &lt;a href="https://github.com/bmack"&gt;@bmack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Dependency for &lt;code&gt;helhum/typo3-console&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;RealURL support&lt;/li&gt;
&lt;li&gt;"legacy" Scheduler Tasks&lt;/li&gt;
&lt;li&gt;nc_staticfile_cache hook not needed for TYPO3 9 LTS+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As integration the thing you need to pay most attention to is the Crawler Tasks, they need to be reconfigured as the Tasks classes are removed.&lt;/p&gt;

&lt;p&gt;You will need to reconfigure them using the &lt;code&gt;Execute console commands&lt;/code&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thanks to ...
&lt;/h3&gt;

&lt;p&gt;All these changes wouldn't be possible without help from others, or perhaps, but then we would have a release before TYPO3 11 LTS ;) &lt;/p&gt;

&lt;p&gt;There have been 13 different contributors to the &lt;code&gt;typo3v9&lt;/code&gt; development branch, since the beginning. Thanks a lot to everyone pushing changes, fixes etc. &lt;/p&gt;

&lt;p&gt;But of course also thanks to everyone contributing in the form of issues/bug reports and testing, this is also really important contributions, please keep doing that. &lt;/p&gt;

&lt;p&gt;There are four persons, especially that I want to thank for helping out during this period of time. Three of them and I really got kick-started at the TYPO3 Developer Days 2019 (hereafter T3DD19), and I got the motivation back to really get it off the table. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You might know them already:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benni Mack&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/bmack"&gt;Github&lt;/a&gt; &lt;a href="https://twitter.com/bennimack"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Benni has helped the Crawler a lot getting closer to the TYPO3 Core and using more standard PHP Libraries, to have less Crawler specific code. He is also always a good sparing when having questions on best practises. &lt;/p&gt;

&lt;p&gt;He has for instance introduced/changed following into the crawler&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execution Strategy classes&lt;/li&gt;
&lt;li&gt;Migrated FE hooks to PSR-15 middleware&lt;/li&gt;
&lt;li&gt;Backend Module switched to Fluid templates&lt;/li&gt;
&lt;li&gt;Implemented Site Handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tizian Schmidlin&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/cdro"&gt;Github&lt;/a&gt; &lt;a href="https://twitter.com/TizianTweets"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tizian started working on the Crawler even before I got to know him in person, at the T3DD19. Tizian has been taking care of most of the Doctrine migration and implemented the new Workers that is also included in the TYPO3 Core to decouple the Crawler dependency in &lt;code&gt;indexed_search&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tobias Stahn&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/tstahn"&gt;Github&lt;/a&gt; &lt;a href="https://twitter.com/tstahn_io"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also got to know Tobias at the T3DD19, he had some question regarding the Crawler and we connected very well. &lt;/p&gt;

&lt;p&gt;Since then Tobias has been very helpful with e.g implementing Extension API to handle extension settings. Besides that Tobias also has been helping with improving the documentation and done a lot of testing and review. &lt;/p&gt;

&lt;p&gt;The last but not least person I want to say thank to is: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tomáš Votruba&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/TomasVotruba"&gt;Github&lt;/a&gt; &lt;a href="https://twitter.com/VotrubaT"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tomas isn't from the TYPO3 Community, but from &lt;a href="https://getrector.org/"&gt;Rector&lt;/a&gt;, he helped set up a better CI Pipeline with PHPStan, Rector, Coding Standards etc. This is something that will really benefit the TYPO3 Crawling in the future as it will be used in every commit forward in time.&lt;/p&gt;

&lt;p&gt;Besides helping with the CI pipeline, he also helped clean up the code and removed support for &lt;code&gt;PHP &amp;lt;7.2&lt;/code&gt; which makes the crawler or more modern codebase. There are still work to be done, but with the help from Tomas and Rector, the next steps to deprecated PHP 7.2 will be easier.&lt;/p&gt;

&lt;h4&gt;
  
  
  Thanks again
&lt;/h4&gt;

&lt;p&gt;I cannot pay them for their help in any way besides saying thanks as often as possible, if you want to tip them a little something, I think you should be able to find a Paypal, Github sponsoring, amazon wishlists or similar somewhere on their social profiles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sponsors
&lt;/h3&gt;

&lt;p&gt;Of course, &lt;a href="https://aoe.com"&gt;AOE&lt;/a&gt; is one of my biggest sponsors, as they have allowed me to do some of the work during my normal working hours. &lt;/p&gt;

&lt;p&gt;But they are not the only one to say thanks to. During the last one and a half year, some people has sponsored me over &lt;a href="https://www.amazon.de/hz/wishlist/ls/17UAQSDUH49DK"&gt;Amazon Wishlist&lt;/a&gt;, &lt;a href="https://github.com/tomasnorre"&gt;Github Sponsor&lt;/a&gt;, &lt;a href="https://www.paypal.me/tomasnorre/10"&gt;Paypal&lt;/a&gt; and so on. &lt;/p&gt;

&lt;p&gt;It ranges from money and golf tees to Klarstein food processor, Ubiquiti cloud key and Ubiquiti switch. I'm thankful for every single piece of it, big or small, your appreciation is an important part, not the size of the gift/donation.&lt;/p&gt;

&lt;p&gt;People/companies who have donated/sponsored me in that period are, no specific order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dkd.de"&gt;DKD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://b13.com"&gt;B13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/bennimack"&gt;Benni Mack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/T3RevNeverEnd"&gt;Olivier Dobberkau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/thomas_hempel"&gt;Thomas Hempel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/benjaminkott"&gt;Benjamin Kott&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kaystrobach"&gt;Kay Strobach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/Haassie82"&gt;Richard Haeser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/Markus306"&gt;Markus Günther&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/briezler"&gt;Benjamin Riezler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to all of you!&lt;/p&gt;

&lt;p&gt;It's important to mention that they have all been sponsoring me personally and not AOE, as most of the work in done in my spare time unrelated to my work at AOE. &lt;/p&gt;

&lt;h3&gt;
  
  
  Some fun facts
&lt;/h3&gt;

&lt;p&gt;As already mentioned I started this work on the 11th of November 2018, roughly one and a half year ago. &lt;/p&gt;

&lt;p&gt;Since then we had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~ 170 Commits&lt;/li&gt;
&lt;li&gt;13 Contributors&lt;/li&gt;
&lt;li&gt;319 files changed, 8236 insertions(+), 22502 deletions(-)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bug and issues
&lt;/h3&gt;

&lt;p&gt;If you find any bugs or issues in general with the crawler please create and &lt;a href="https://github.com/aoepeople/crawler/issues"&gt;issue on Github&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Future ?
&lt;/h3&gt;

&lt;p&gt;The next period of time, I will of course take care of the bugs and issues being reported. &lt;/p&gt;

&lt;p&gt;My main work will be focussed on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixing the Functional tests for &lt;code&gt;TYPO3 ^10.3&lt;/code&gt; - haven't proven any problems with the functionality, so decided to launch with 5 failing tests.&lt;/li&gt;
&lt;li&gt;Adding behaviour driven tests, there are already a few added to the pipeline but want more, to ease the development further. &lt;/li&gt;
&lt;li&gt;Add better test coverage in general&lt;/li&gt;
&lt;li&gt;Refactor some of the "too big"-functions that make the maintenance to hard. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Currently, there are no big features in the pipeline, but hoping to continue improving the code base, so the next update will get smaller and closer to the LTS releases of the TYPO3 CMS.&lt;/p&gt;

&lt;p&gt;I am looking forward to what the next time will bring, &lt;/p&gt;

&lt;p&gt;#HappyCrawling!&lt;/p&gt;

</description>
      <category>typo3</category>
      <category>php</category>
      <category>crawler</category>
      <category>extension</category>
    </item>
    <item>
      <title>How rector made my life easier</title>
      <dc:creator>Tomas Norre Mikkelsen</dc:creator>
      <pubDate>Wed, 01 Apr 2020 05:15:45 +0000</pubDate>
      <link>https://forem.com/tomasnorre/how-rector-made-my-life-easier-4b01</link>
      <guid>https://forem.com/tomasnorre/how-rector-made-my-life-easier-4b01</guid>
      <description>&lt;p&gt;In November 2019 I stared (*) the &lt;a href="https://github.com/rectorphp/rector"&gt;https://github.com/rectorphp/rector&lt;/a&gt;, as I just learned about how cool &lt;a href="https://getrector.org/"&gt;Rector&lt;/a&gt; was and how it could help me improve and migrate my legacy code.&lt;/p&gt;

&lt;p&gt;My star on github, was as first used as a bookmark, but some days later, the team from Rector contacted me, and this change a lot regarding my view on refactoring, complexity and automation tools for development.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1196711403333332992-386" src="https://platform.twitter.com/embed/Tweet.html?id=1196711403333332992"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1196711403333332992-386');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1196711403333332992&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  What did I win?
&lt;/h2&gt;

&lt;p&gt;I contacted the rector team as instructed in the tweet, and &lt;a href="https://twitter.com/VotrubaT"&gt;Tomas Votruba&lt;/a&gt; got back to me, and we discussed how he could help me. &lt;/p&gt;

&lt;p&gt;As I'm most active with the &lt;a href="https://typo3.org"&gt;TYPO3&lt;/a&gt; &lt;a href="https://extensions.typo3.org/extension/crawler"&gt;Crawler extension&lt;/a&gt; I ask for help to migrate/optimise the current typo3v9-branch, as this is my work in progress branch for the next major release.&lt;/p&gt;

&lt;p&gt;Tomas implemented following in our CI pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AOEpeople/crawler/commit/3d79302d238740aea378857956ddf193a457848c"&gt;[CI] Add Rector CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AOEpeople/crawler/commit/7e94d3bb6205785fde70ad1180a8996b32e2b411"&gt;[Travis] Cleanup and split jobs clearly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AOEpeople/crawler/commit/717c86ff588a8f7f2e96f98fdac9df0e9744a44a"&gt;[TASK] Apply static + PSR-12 set&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AOEpeople/crawler/commit/8dfe2490a336a7cc93474d1fa861ad40a45ccf77"&gt;Apply PHP 7.1 and PHP 7.2 features&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All this done within a week, and the code base was already improve a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's all?
&lt;/h2&gt;

&lt;p&gt;The win wasn't "only" the 4 commits from Tomas, that helped me one time. He help me setup some basics that will help me a lot in the future. &lt;/p&gt;

&lt;h3&gt;
  
  
  CI
&lt;/h3&gt;

&lt;p&gt;Now we have Rector CI, Code Standard and PHPStan checks as part of our &lt;a href="https://travis-ci.org/github/AOEpeople/crawler"&gt;Travis CI Pipeline&lt;/a&gt; and this is done for every single commit and pull request, so the quality of the code commit since then will also be improved, cleaner and easier to maintain in the future. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7pgmhk1w8sd6o0bzoy1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7pgmhk1w8sd6o0bzoy1d.png" alt="Travis CI - Static" width="800" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Development
&lt;/h3&gt;

&lt;p&gt;Next time I want to deprecate a PHP Version e.g. PHP 7.2 and PHP 7.3, I can add PHP Sets to the &lt;a href="https://github.com/AOEpeople/crawler/blob/typo3v9/ecs.yaml"&gt;&lt;code&gt;ecs.yaml&lt;/code&gt;&lt;/a&gt; and the run the command &lt;code&gt;.Build/bin/ecs check Classes Configuration Tests --fix&lt;/code&gt; and then most, if not all of the changes are done automatically within a few seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The future for me
&lt;/h2&gt;

&lt;p&gt;I don't see how my work as PHP Developer will continue without using a tool like rector, it makes a lot of things way easier.&lt;/p&gt;

&lt;p&gt;The rector is in general a tool that can help a lot with PHP and framework updates like &lt;a href="https://symfony.com/"&gt;symfony&lt;/a&gt;, but as I'm more a TYPO3 kind of person, I've joined an initiative to make migration sets for TYPO3 Core Updates as well.&lt;/p&gt;

&lt;p&gt;This will ease the upgrade from e.g. TYPO3 9 LTS to TYPO3 10 (Soon to be LTS), but this is something I'll share more about later.&lt;/p&gt;

</description>
      <category>php</category>
      <category>rector</category>
      <category>deprecation</category>
      <category>automation</category>
    </item>
    <item>
      <title>Curl Proxy vs X-Forward-For</title>
      <dc:creator>Tomas Norre Mikkelsen</dc:creator>
      <pubDate>Sat, 28 Mar 2020 14:13:12 +0000</pubDate>
      <link>https://forem.com/tomasnorre/curl-proxy-vs-x-forward-for-1nnc</link>
      <guid>https://forem.com/tomasnorre/curl-proxy-vs-x-forward-for-1nnc</guid>
      <description>&lt;p&gt;When working with cUrl and proxies in PHP and a lot of request, first of all it can of course help to run multiple process at the same time, but besides that how you use the proxy itself can be a huge performance boost if done like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;        &lt;span class="nv"&gt;$curlResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sourceUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getProxy&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;           &lt;span class="nv"&gt;$headerData&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'X-Forwarded-For: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getProxy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;       &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;       &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_SSL_VERIFYHOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;       &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_SSL_VERIFYPEER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sourceUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_FOLLOWLOCATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HTTPHEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headerData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;       &lt;span class="c1"&gt;// Set proxy if applicable&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nv"&gt;$proxyIp&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="kc"&gt;FALSE&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nv"&gt;$proxyIp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;           &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_PROXY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$proxyIp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;           &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HTTPPROXYTUNNEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;       &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sb"&gt;```

`&lt;/span&gt;

&lt;span class="nc"&gt;This&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;small&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;The&lt;/span&gt; &lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;important&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;instead&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sb"&gt;`CURLOPT_PROXY`&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="sb"&gt;`CURLOPT_HTTPPROXYTUNNEL`&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sb"&gt;`X-Forward-For`&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;trick&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;

&lt;span class="nc"&gt;The&lt;/span&gt; &lt;span class="n"&gt;win&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;due&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;they&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt; &lt;span class="n"&gt;latency&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;ever&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;simulated&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;actually&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;

&lt;span class="nc"&gt;I&lt;/span&gt;&lt;span class="s1"&gt;'m using this test for GEO IP redirects etc. and when testing e.g. 300 redirects, then it does matter that you gain a four times faster job than you had before. With this said this of course depends on the proxy speed, but i'&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;guarantee&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>curl</category>
      <category>forward</category>
      <category>php</category>
      <category>proxy</category>
    </item>
    <item>
      <title>Codeception Tests with DDEV and Selenium</title>
      <dc:creator>Tomas Norre Mikkelsen</dc:creator>
      <pubDate>Sat, 28 Mar 2020 12:49:59 +0000</pubDate>
      <link>https://forem.com/tomasnorre/codeception-ddev-selenium-docker-36kk</link>
      <guid>https://forem.com/tomasnorre/codeception-ddev-selenium-docker-36kk</guid>
      <description>&lt;p&gt;Running behaviour driven tests like &lt;a href="https://codeception.com/"&gt;Codeception&lt;/a&gt; can bring some advantages to your project, and will help you detect if you break functionality on updates, changes etc. &lt;/p&gt;

&lt;p&gt;This blog post will help you setup the basics needed for developing your own tests and running them locally with &lt;a href="https://www.ddev.com/"&gt;ddev&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;DDEV installed on you local machine &lt;/li&gt;
&lt;li&gt;Project setup locally with &lt;a href="https://www.ddev.com/"&gt;ddev&lt;/a&gt;, in this case I will use a plain &lt;code&gt;phpinfo()&lt;/code&gt; site to lower complexity. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't have a setup locally already, you can do this by follwoing the &lt;a href="https://www.ddev.com/get-started/"&gt;ddev get started guide&lt;/a&gt;, you can also close my repository on github, then you will not need to do the changes your self to check the prove of concept.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/tomasnorre/ddev-codeception-poc.git
$ cd ddev-codeception-poc
$ composer install
$ ddev start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you choose the later one, you can skip the instructions in step 1-3, and go directly to executing the tests, but I would recommend you to do the steps manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Setup Selenium in DDEV
&lt;/h2&gt;

&lt;p&gt;As you might already know ddev is based on docker, so to setup selenium, we need to add a custom &lt;code&gt;docker-composer.selenium.yml&lt;/code&gt; to your ddev setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd /path/to/your/local/project/.ddev
$ touch docker-compose.selenium.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use you default editor to edit the &lt;code&gt;docker-compose.selenium.yaml&lt;/code&gt; file. This configuration is take from the &lt;a href="https://github.com/SeleniumHQ/docker-selenium#version-3"&gt;Selenium Github Page&lt;/a&gt;, with a few adjustments, like the &lt;code&gt;version: '3.6'&lt;/code&gt;, &lt;code&gt;container_name&lt;/code&gt; and removing the &lt;code&gt;firefox&lt;/code&gt; and &lt;code&gt;opera&lt;/code&gt; part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.6'
services:
  selenium-hub:
    image: selenium/hub:3.141.59-20200326
    container_name: ddev-${DDEV_SITENAME}-selenium-hub
    ports:
      - "4444:4444"

  chrome:
    image: selenium/node-chrome:3.141.59-20200326
    container_name: ddev-${DDEV_SITENAME}-chrome
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can restart you ddev project with &lt;code&gt;ddev restart&lt;/code&gt; and you will have a selenium container running together with your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Install Codeception
&lt;/h2&gt;

&lt;p&gt;Steps copied from &lt;a href="https://codeception.com/quickstart"&gt;Codeception QuickStart Guide&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ composer require "codeception/codeception" --dev
$ php vendor/bin/codecept init acceptance

Let's prepare Codeception for acceptance testing
Create your tests and run them in real browser

? Where tests will be stored? (tests)
? Select a browser for testing (chrome)
  [0] chrome
  [1] firefox
 &amp;gt; 0
 Ensure that you have Selenium Server and ChromeDriver installed before running tests
? Start url for tests (http://localhost)
 Created test directories inside at tests
 Adding codeception/module-webdriver for WebDriver to composer.json
1 new packages added to require-dev
? composer.json updated. Do you want to run "composer update"? (y/n) y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this we know have a &lt;code&gt;codeception.yml&lt;/code&gt; in our root folder, next to &lt;code&gt;composer.json&lt;/code&gt; and we have a &lt;code&gt;tests&lt;/code&gt; folder, also in our root folder, that is created and populated with Codeception setup. &lt;/p&gt;

&lt;p&gt;As I didn't adjust the start url as part of the initiation I need to adjust it manually. &lt;br&gt;
Open the &lt;code&gt;codeception.yml&lt;/code&gt; and adjust&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enabled:
    - WebDriver:
        url: http://localhost/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enabled:
    - WebDriver:
        url: http://web/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this will make the Codeception make requests against the docker-container named web, which is your application container, in a default ddev setup. &lt;/p&gt;

&lt;h2&gt;
  
  
  3. Small Test example
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;tests&lt;/code&gt; folder we also have a file &lt;code&gt;LoginCest.php&lt;/code&gt; which we are going to adjust, to add new tests. &lt;/p&gt;

&lt;p&gt;The naming of the file, isn't important at this stage, but I would suggest to have files and structures match your application and what you're testing, this keeps it easier to find, correct, and add new tests.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;tests/LoginCest.php&lt;/code&gt; with your editor. Currently it looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php
class LoginCest 
{    
    public function _before(AcceptanceTester $I)
    {
        $I-&amp;gt;amOnPage('/');
    }

    public function loginSuccessfully(AcceptanceTester $I)
    {
        // write a positive login test 
    }

    public function loginWithInvalidPassword(AcceptanceTester $I)
    {
        // write a negative login test
    }       
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;_before()&lt;/code&gt; is actions that will be executed before every test. The two other tests are empty right now so if you run &lt;code&gt;php vendor/bin/codecept run&lt;/code&gt; you will have a green test result.&lt;/p&gt;

&lt;p&gt;Let us add some more meaning full tests. First remove the two empty tests and add&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function canSeePHPVersion(AcceptanceTester $I)
{
    $I-&amp;gt;canSee('PHP Version 7.4.3');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will check if it finds the string "PHP Version 7.4.3" on the page &lt;code&gt;/&lt;/code&gt; as that's the page defined in the &lt;code&gt;_before()&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;Lets run the tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ php vendor/bin/codecept run

Codeception PHP Testing Framework v4.1.4
Powered by PHPUnit 8.5.2 by Sebastian Bergmann and contributors.
Running with seed:


Acceptance Tests (1) -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
✔ LoginCest: Can see php version (1.78s)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Time: 2.91 seconds, Memory: 12.00 MB

OK (1 test, 1 assertion)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This page used can also be changed by doing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function canSeePHPVersion(AcceptanceTester $I)
{
    $I-&amp;gt;amOnPage('/index.php');
    $I-&amp;gt;canSee('PHP Version 7.4.3');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have failing tests, there will be a link echoed in your terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;There was 1 failure:

---------
1) LoginCest: Can see php version
 Test  tests/LoginCest.php:canSeePHPVersion
 Step  Can see "PHP Version 7.4.2"
 Fail  Failed asserting that  on page /index.php
--&amp;gt; PHP Version 7.4.3
System Linux ddev-codeception-poc-web 4.19.76-linuxkit #1 SMP Thu Oct 17 19:31:58 UTC 2019 x86_64
Build Date Feb 24 2020 18:39:14
Server API FPM/FastCGI
Virtual Directory Support disabled
Configuration File (php.ini) Path /etc/php/7.4/fpm
Loaded Configuration File /etc/php/7.4/fp
[Content too long to display. See complete response in '/path/to/Projects/ddev-codeception-poc/tests/_output/' directory]
--&amp;gt; contains "PHP Version 7.4.2".

Scenario Steps:

 3. $I-&amp;gt;canSee("PHP Version 7.4.2") at tests/LoginCest.php:12
 2. $I-&amp;gt;amOnPage("/index.php") at tests/LoginCest.php:11
 1. $I-&amp;gt;amOnPage("/") at tests/LoginCest.php:6

Artifacts:

Png: /path/to/Projects/ddev-codeception-poc/tests/_output/LoginCest.canSeePHPVersion.fail.png
Html: /path/to/Projects/ddev-codeception-poc/tests/_output/LoginCest.canSeePHPVersion.fail.html

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;png&lt;/code&gt; version is a screenshot, so if the text/element you are looking for are below the fold, you will not see it. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;html&lt;/code&gt; version is a scrollable version of the page, be aware that this might look quite rubbish, if the Javascript, css etc, isn't loaded correct, which often is the case, so might be difficult to spot the problem. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is as you see a very small and compact example on how you can run Codeception in DDEV setup. &lt;/p&gt;

&lt;p&gt;I'm far from expert on the field, neither ddev nor Codeception, but if you have any questions feel free to reach out to me on &lt;a href="https://twitter.com/tomasnorre"&gt;https://twitter.com/tomasnorre&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have also pushed the example setup to my github account, so if you want to discuss something, that could benefit others, you can create an issue at &lt;a href="https://github.com/tomasnorre/ddev-codeception-poc/issues"&gt;https://github.com/tomasnorre/ddev-codeception-poc/issues&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codeception</category>
      <category>ddev</category>
      <category>selenium</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
