<?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>DEV Community: Max</title>
    <description>The latest articles on DEV Community by Max (@maxlmator).</description>
    <link>https://dev.to/maxlmator</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%2F10170%2FAHBysCT-.jpeg</url>
      <title>DEV Community: Max</title>
      <link>https://dev.to/maxlmator</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxlmator"/>
    <language>en</language>
    <item>
      <title>Prettier Code</title>
      <dc:creator>Max</dc:creator>
      <pubDate>Mon, 18 Feb 2019 16:56:39 +0000</pubDate>
      <link>https://dev.to/maxlmator/prettier-code-1ogd</link>
      <guid>https://dev.to/maxlmator/prettier-code-1ogd</guid>
      <description>&lt;p&gt;If you care about code formatting, you might want to take a look at &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt;. It changed the way I think about coding styles quite a bit.&lt;/p&gt;

&lt;p&gt;So I used to spend a lot of time fiddling with code styles. From debating spaces vs. tabs to comparing &lt;a href="https://symfony.com/doc/current/contributing/code/standards.html"&gt;Symfony's Coding Standards&lt;/a&gt; and &lt;a href="https://github.com/google/styleguide"&gt;Google's Styleguides&lt;/a&gt;. With JavaScript starting to be the language of choice for most new projects, I settled on the &lt;a href="https://github.com/airbnb/javascript"&gt;Airbnb JS Style Guide&lt;/a&gt; and with the matching linter rules the topic was settled for quite some time.&lt;/p&gt;

&lt;p&gt;But half a year ago, we decided at work to use &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; for a new project. And this has changed how I think about code styleguides in a pretty fundamental way: I just don't care anymore.&lt;/p&gt;

&lt;p&gt;What prettier does: Instead of looking at the code style as it was written and applying rules on it, Prettier parses the code and prints it in its own format. So the leeway classic styleguides give every developer isn't a topic to ponder on anymore.&lt;/p&gt;

&lt;p&gt;Like many linters, it automatically reformats the files on saving. At first it felt like a heavy intrusion in my work. After all I  – at least pretended – to put some effort and pride into the styling of the code I wrote. But a few days later I almost completely stopped thinking about code formatting. Months later I'm on the other end: I write code and am always heavily confused, if it doesn't automatically get reformated in the now familiar Prettier-style.&lt;/p&gt;

&lt;p&gt;So if you happen to start a fresh project, just give Prettier a try for a couple of days.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Makefiles to Rule Them All</title>
      <dc:creator>Max</dc:creator>
      <pubDate>Tue, 17 Apr 2018 05:45:00 +0000</pubDate>
      <link>https://dev.to/maxlmator/makefiles-to-rule-them-all-46e4</link>
      <guid>https://dev.to/maxlmator/makefiles-to-rule-them-all-46e4</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/maxlmator/adding-a-microblog-to-jekyll-39cp"&gt;last blogpost&lt;/a&gt; you might have already stumbled over me using a &lt;a href="https://www.gnu.org/software/make/manual/make.html"&gt;Makefile&lt;/a&gt; to simplify a project task. My enthusiasm for Makefiles goes a bit further and I add one to most of my projects by now. Here is why I do this and how they make my everyday developer life a bit easier.&lt;/p&gt;

&lt;p&gt;None of my projects is written in C or C++ which rely on a Makefile for compiling them. Instead my projects are written in JavaScript (Node), Ruby and PHP. I use the make command as a wrapper for the individual tools coming with each ecosystem to create a common interface. This way I can just run &lt;code&gt;make test&lt;/code&gt; no matter whether the tests are in JavaScript and use &lt;a href="https://mochajs.org/"&gt;Mocha&lt;/a&gt; or use &lt;a href="https://phpunit.de/"&gt;PHPUnit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Besides the different set of tools belonging to a platform (e.g. Node’s &lt;a href="https://www.npmjs.com/"&gt;npm&lt;/a&gt;, PHP’s &lt;a href="https://getcomposer.org/"&gt;Composer&lt;/a&gt; and Ruby’s &lt;a href="http://bundler.io/"&gt;Bundler&lt;/a&gt;) there are a few more difference between projects that I created a shortcut for: To run a project locally it might be anything between &lt;code&gt;npm run&lt;/code&gt;, a Docker container or a Vagrantbox. And on the plain level of a project’s structure there is also a wide variance: Everything might be in the root directory, or split in a &lt;code&gt;src/&lt;/code&gt; and &lt;code&gt;docker/&lt;/code&gt; directory. Every project is its own special snowflake in this regard.&lt;/p&gt;

&lt;p&gt;After a short trial with shell scripts to do repetitive tasks always from the project root I quickly switched to use &lt;code&gt;make&lt;/code&gt; instead. It’s widely available and make it easy to handle different commands. So I started to develop my strategy for Makefiles. It’s schema applies to most of my web-based projects perfectly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;make setup&lt;/code&gt; – Does everything which might be necessary on the first setup like installing the dependencies, like run &lt;code&gt;npm install&lt;/code&gt; for a node-project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;make run&lt;/code&gt; – This will mostly default to &lt;code&gt;docker-compose up&lt;/code&gt;. Or to &lt;code&gt;bundle exec jekyll serve --drafts&lt;/code&gt; for this blog.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;make test&lt;/code&gt; – You might have guessed it: This one executes the unit tests of the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course it doesn’t stop there. There are often a bunch more commands which might for example trigger an existing build system like &lt;a href="https://ant.apache.org/"&gt;ant&lt;/a&gt;. Or just as an alias for the &lt;code&gt;npm scripts&lt;/code&gt;. Nonetheless it’s a great shortcut saving me quite some time when switching between projects.&lt;/p&gt;

&lt;p&gt;A small example for a PHP project, which uses Composer and comes with a Docker-Compose setup. The tests are executed within the Docker container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
&lt;span class="nl"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;src/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    composer &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;
&lt;span class="nl"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    docker-compose run web /bin/bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'composer test'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if you also happen to often switch between diverse projects, maybe you also want to give Makefiles a try.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>devtips</category>
    </item>
    <item>
      <title>Adding a Microblog to Jekyll</title>
      <dc:creator>Max</dc:creator>
      <pubDate>Sun, 15 Apr 2018 14:30:00 +0000</pubDate>
      <link>https://dev.to/maxlmator/adding-a-microblog-to-jekyll-39cp</link>
      <guid>https://dev.to/maxlmator/adding-a-microblog-to-jekyll-39cp</guid>
      <description>&lt;p&gt;Since I learned about &lt;a href="https://micro.blog"&gt;micro.blog&lt;/a&gt; &lt;a href="https://dev.to/2018/the-comeback-of-feeds"&gt;back in January&lt;/a&gt; I wanted to give it a try on my blog. For the last few days I had a few attempts on it. And as you can see at &lt;a href="https://dev.to/microblog"&gt;xam.io/microblog&lt;/a&gt; and on &lt;a href="https://micro.blog/xam"&gt;micro.blog&lt;/a&gt; I was successful. Now I want to share how I implemented it.&lt;/p&gt;

&lt;p&gt;A hat tip to the &lt;a href="https://brightlycolored.org/2017/02/creating-a-microblog-with-jekyll/"&gt;Creating a Microblog with Jekyll&lt;/a&gt; post which covers a lot of the groundwork. I picked up a lot of his ideas and will focus a bit more on the integration with my existing blog in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Collection for the Microblog
&lt;/h2&gt;

&lt;p&gt;Since I wanted to keep the regular posts separate from the microblog posts, I decided to use a &lt;a href="https://jekyllrb.com/docs/collections/"&gt;collection&lt;/a&gt; to do so. If you don’t care about this separation as much, using a dedicated category within the regular posts is probably the easier option.&lt;/p&gt;

&lt;p&gt;So here the configuration for the collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;collections:
  microblog:
    output: true
    permalink: microblog/:year/:month/:title/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I decided to keep the &lt;code&gt;:year/:month/:title&lt;/code&gt; path for the microblog posts, but on level deeper at &lt;code&gt;microblog&lt;/code&gt; — of course the permalink schema is totally up to you.&lt;/p&gt;

&lt;p&gt;This configuration will pick up any files in the &lt;code&gt;_microblog&lt;/code&gt; directory, interpret them as part of the &lt;code&gt;microblog&lt;/code&gt; collection and create a rendered HTML page in the output directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Microblog Posts to the Index Page
&lt;/h2&gt;

&lt;p&gt;Items from collections aren’t part of the &lt;code&gt;site.posts&lt;/code&gt; array that’s normally looped over on the index page, listing one item after the other. Instead they can be accessed by using &lt;code&gt;site.microblog&lt;/code&gt;. To merge them together (and have them paginated), I replaced the (no longer maintained) &lt;a href="https://github.com/jekyll/jekyll-paginate"&gt;jekyll-paginate&lt;/a&gt; with the &lt;a href="https://github.com/sverrirs/jekyll-paginate-v2"&gt;jekyll-paginate-v2 gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the front-matter of my &lt;code&gt;index.html&lt;/code&gt; I now have this configuration to paginate over both, the posts and the microblog:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--------
layout: default
pagination:
  enabled: true
  collection: posts, microblog
  per_page: 10 # Number of entries per page
  permalink: "page/:num/" # Permalink structure
  sort_reverse: true # Newest first
--------

{% for post in paginator.posts %}
    {% if post.collection == 'microblog' %}
        {% include microblog.html %}
    {% else %}
        {% include post.html %}
    {% endif %}
{% endfor %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;microblog.html&lt;/code&gt; is a reduced version of my &lt;code&gt;post.html&lt;/code&gt; template that usually renders a blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Separate Pages for Posts and Microblog only
&lt;/h2&gt;

&lt;p&gt;As you can see this blog also has &lt;strong&gt;Posts&lt;/strong&gt; page (containing only regular posts) and a &lt;strong&gt;Microblog&lt;/strong&gt; page containing only the microblog posts.&lt;/p&gt;

&lt;p&gt;To do so I have copied the &lt;code&gt;index.html&lt;/code&gt; as &lt;code&gt;microblog.html&lt;/code&gt; (for the microblog) and as &lt;code&gt;posts.html&lt;/code&gt; (for the regular posts). But changed the &lt;code&gt;collection:&lt;/code&gt; frontmatter to only include &lt;code&gt;microblog&lt;/code&gt; or &lt;code&gt;posts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The permalink structure of the pagination is relative to the source directory, together with the permalink configuration for posts and microblog, this is the current URL schema on this site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ -- Page with microblog and posts
/page/:num/ -- Pagination for both microblog and posts

/posts/ -- Page only with posts
/posts/page/:num/ -- Pagination for regular posts
/:year/:month/:title/ -- URL for single posts

/microblog/ -- Page only with microblog
/microblog/page/:num/ -- Pagination for microblog posts
/microblog/:year/:month/:title/ -- URL for a single microblog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding a Feed for the Microblog
&lt;/h2&gt;

&lt;p&gt;For now I keep my regular feed (available at &lt;a href="///atom.xml"&gt;/atom.xml&lt;/a&gt;) limited to regular posts only. But I created a separate feed for the microblog (&lt;a href="///microblog.xml"&gt;/microblog.xml&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Since also the regular feed doesn’t use any Jekyll plugin, I also opted for the vanilla approach for the microblog feed — my &lt;code&gt;microblog.xml&lt;/code&gt; template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--------
layout: null
--------
&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"&amp;gt;
  &amp;lt;channel&amp;gt;
    &amp;lt;title&amp;gt;xam.io | Microblog&amp;lt;/title&amp;gt;
    &amp;lt;description&amp;gt;Microblog of Max Kleucker&amp;lt;/description&amp;gt;
    &amp;lt;link&amp;gt;{{ site.url }}&amp;lt;/link&amp;gt;
    &amp;lt;atom:link href="{{ site.url }}/microblog.xml" rel="self" type="application/rss+xml" /&amp;gt;
    {% for post in site.microblog reversed limit:50 %}
      &amp;lt;item&amp;gt;
        &amp;lt;description&amp;gt;{{ post.content | xml_escape }}{% if post.external-url %}{% endif %}&amp;lt;/description&amp;gt;
        &amp;lt;pubDate&amp;gt;{{ post.date | date: "%a, %d %b %Y %H:%M:%S %z" }}&amp;lt;/pubDate&amp;gt;
        &amp;lt;link&amp;gt;{{ site.url }}{{ post.url }}&amp;lt;/link&amp;gt;
        &amp;lt;guid isPermaLink="true"&amp;gt;{{ site.url }}{{ post.url }}&amp;lt;/guid&amp;gt;
      &amp;lt;/item&amp;gt;
    {% endfor %}
  &amp;lt;/channel&amp;gt;
&amp;lt;/rss&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feed is the source for &lt;a href="http://micro.blog/xam"&gt;my micro.blog account&lt;/a&gt; as well.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating Microblog Posts
&lt;/h2&gt;

&lt;p&gt;So publishing works, we can manually create a new file in the &lt;code&gt;_microblog/&lt;/code&gt; directory and it will be published on the index-page, the microblog-page and the microblog-feed. Yeah!&lt;/p&gt;

&lt;p&gt;Creating a microblog post means to manually create a file at &lt;code&gt;_microblog/&amp;lt;YEAR&amp;gt;-&amp;lt;MONTH&amp;gt;-&amp;lt;DAY&amp;gt;-&amp;lt;TITLE&amp;gt;.md&lt;/code&gt;. In particular the &lt;code&gt;&amp;lt;TITLE&amp;gt;&lt;/code&gt; part is a bit unfortunate: Per @manton’s definition the a microblog &lt;a href="http://www.manton.org/2014/09/defining-a-microblog-post.html"&gt;doesn’t use titles for posts&lt;/a&gt;. Yet you can’t omit it, since otherwise you could only create one entry per day.&lt;/p&gt;

&lt;p&gt;So I wanted to have something quick like the &lt;code&gt;jekyll post "my-title"&lt;/code&gt; command. I decided to a add a &lt;code&gt;Makefile&lt;/code&gt; that can create a new microblog-file from a template and open it in my editor of choice right away — with an autogenerated title, so I don’t have to care about it.&lt;/p&gt;

&lt;p&gt;The template (at &lt;code&gt;templates/_microblog&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--------
layout: microblog
date: %CURRENT_DATE%
title: %POST_TITLE%
--------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;Makefile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Makefile
MICROBLOG_TEMPLATE := _templates/microblog
POST_DATE := $(shell date +%Y-%m-%d)
POST_TIME := $(shell date +%Y-%m-%d\ %T\ %z)
POST_TITLE := $(shell openssl rand 100000 | shasum | cut -c1-8)
POST_FILE := _microblog/$(POST_DATE)-$(POST_TITLE).md
.PHONY: new-microblog
new-microblog:
    @cat $(MICROBLOG_TEMPLATE) | \
    sed "s/%CURRENT_DATE%/$(POST_TIME)/g" | \
    sed "s/%POST_TITLE%/$(POST_TITLE)/g" &amp;gt; ${POST_FILE} &amp;amp;&amp;amp; \
    subl ${POST_FILE}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;make new-microblog&lt;/code&gt; on your shell will do the following and leave you with a new microblog post ready to publish:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the template from &lt;code&gt;_templates/microblog&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Replace the &lt;code&gt;%CURRENT_DATE%&lt;/code&gt; in the template with the current date and time&lt;/li&gt;
&lt;li&gt;Replace the &lt;code&gt;%POST_TITLE%&lt;/code&gt; with a randomized 8-characters string&lt;/li&gt;
&lt;li&gt;Save this at &lt;code&gt;_microblog/&amp;lt;CURRENT_DATE&amp;gt;-&amp;lt;RANDOMIZED_TITLE&amp;gt;.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open this file in vim. You might change this to the editor of your choice.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Where To Go From Here
&lt;/h2&gt;

&lt;p&gt;Setting everything up, I ended up learning a lot about the &lt;a href="https://www.w3.org/TR/micropub/"&gt;Micropub standard&lt;/a&gt; and &lt;a href="https://webmention.net/draft/"&gt;Webmentions&lt;/a&gt;. The &lt;a href="https://indieweb.org/"&gt;IndieWeb&lt;/a&gt; page is a great resource for this stuff. But in short, there is a whole set of specifications and standards defining the protocols to run your own micropub backend. And Webmentions are a neat way to let somebody when you referenced them.&lt;/p&gt;

&lt;p&gt;Yet these protocols need a dynamic webservice to actively work. That might look a bit counterintuitive to running a static blog, but on the &lt;a href="https://indieweb.org/Jekyll"&gt;indieweb wiki&lt;/a&gt; there already are a few ways to do so. But that’s for another weekend.&lt;/p&gt;

</description>
      <category>jekyll</category>
    </item>
    <item>
      <title>PHP Integration Tests Using the Built-in Server</title>
      <dc:creator>Max</dc:creator>
      <pubDate>Fri, 30 Mar 2018 15:42:17 +0000</pubDate>
      <link>https://dev.to/maxlmator/php-integration-tests-using-the-built-in-server-1k4e</link>
      <guid>https://dev.to/maxlmator/php-integration-tests-using-the-built-in-server-1k4e</guid>
      <description>&lt;p&gt;Microservices have plopped up everywhere and I have written a few of them at work by now. Given the limited scope I find microservices a pleasure to write tests for compared to most (legacy) monolith. In this post I want to share an approach on how to test microservices written in PHP using it's built-in server and some pitfalls we encountered so far.&lt;/p&gt;

&lt;p&gt;Let's assume we have a nice little microservice built with &lt;a href="https://www.slimframework.com/"&gt;Slim&lt;/a&gt;, &lt;a href="https://lumen.laravel.com/"&gt;Lumen&lt;/a&gt; or which ever framework you prefer. We have some routes that return JSON responses and accept various JSON payloads.&lt;/p&gt;

&lt;p&gt;We're able to run this application using PHP's built-in server by running for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ENVIRONMENT=production php -S 0.0.0.0:8080 -t public public/index.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case the &lt;code&gt;public/index.php&lt;/code&gt; is the entry file for any HTTP request, and the server is no reachable at &lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also you already have a &lt;a href="https://phpunit.de/"&gt;PHPUnit&lt;/a&gt; setup available which covers unit tests. For the sake of brevity we will skip the whole PHPUnit setup part and jump directly into writing tests against the built-in server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Basic Setup
&lt;/h2&gt;

&lt;p&gt;The goal is to write a test case where we might have a body payload which we want to send to specific endpoint and then check if the response has the HTTP status &lt;code&gt;200&lt;/code&gt; and the returned answer is a JSON containing a specific information. Like this:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Tests\Integration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ControllerTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseTest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testCorrectCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'field_one'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'some data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'field_two'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="s1"&gt;'apple'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s1"&gt;'banana'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="cd"&gt;/** @var \Psr\Http\Message\ResponseInterface $response */&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/api/myfunction'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'POST'&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;assertSame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStatusCode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$parsedResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBody&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="kc"&gt;true&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;assertArraySubset&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$parsedResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting part is to resolve the &lt;code&gt;$this-&amp;gt;dispatch&lt;/code&gt; part. We hand in the endpoint, the HTTP method and the payload and expect to retrieve a reponse object. So the &lt;code&gt;dispatch()&lt;/code&gt; function must actually send a HTTP request and return the response object. To extract this from the actual tests, a &lt;code&gt;BaseTest&lt;/code&gt; class is created:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Tests\Integration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Process\Process&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;GuzzleHttp\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;ENVIRONMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;HOST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9876&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Adjust this to a port you're sure is free&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setUpBeforeClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// The command to spin up the server&lt;/span&gt;
        &lt;span class="nv"&gt;$command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s1"&gt;'ENVIRONMENT=%s php -S %s:%d -t %s %s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ENVIRONMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nb"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/../../public'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nb"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/../../public/index.php'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Using Symfony/Process to get a handler for starting a new process&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$command&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Disabling the output, otherwise the process might hang after too much output&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;disableOutput&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Actually execute the command and start the process&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Let's give the server some leeway to fully start&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;usleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;tearDownAfterClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;ResponseInterface&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// STEP 2: Using Guzzle we send a request to the server&lt;/span&gt;
        &lt;span class="nv"&gt;$params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'body'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Creating a Guzzle Client with the base_uri, so we can use a relative&lt;/span&gt;
        &lt;span class="c1"&gt;// path for the requests.&lt;/span&gt;
        &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'base_uri'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'http://127.0.0.1:'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this to work you have to add these packages to your development dependencies:&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 --dev symfony/process
composer require --dev guzzlehttp/guzzle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's Happening Here?
&lt;/h3&gt;

&lt;p&gt;We're making use of PHPUnit's &lt;code&gt;setUpBeforeClass()&lt;/code&gt; and &lt;code&gt;tearDownAfterClass()&lt;/code&gt; function to control the lifetime of the local PHP server. The &lt;a href="https://github.com/symfony/process"&gt;symfony/process&lt;/a&gt; package gives us a nice handler on executing the PHP command on the local machine. We don't want to recreate the server for every single test, using one server per &lt;code&gt;TestCase&lt;/code&gt;-class is sufficient for our use case.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;dispatch()&lt;/code&gt; function we're creating a request using &lt;a href="https://github.com/guzzle/guzzle"&gt;guzzlehttp/guzzle&lt;/a&gt;. This is sent to server (using the same port as the local server) and it's &lt;code&gt;Response&lt;/code&gt; object is returned to the caller.&lt;/p&gt;

&lt;p&gt;Et voilà the &lt;code&gt;testCorrectCall&lt;/code&gt; is executed against a local PHP server running your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We ran into weird issues where tests would be stuck forever, adding &lt;code&gt;self::$process-&amp;gt;disableOutput();&lt;/code&gt; resolved this for us.&lt;/li&gt;
&lt;li&gt;If you have multiple classes inheriting from &lt;code&gt;BaseTest&lt;/code&gt; you might want to use different ports. We had issues where the ports were not yet released by the system. Swapping the &lt;code&gt;cont $port&lt;/code&gt; for a &lt;code&gt;static $port&lt;/code&gt; and either increasing or decreasing it, might help.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Combining Remote Tests with a Mocked Environment
&lt;/h2&gt;

&lt;p&gt;As noted above, most PHP frameworks come with a way to test them in a mocked environment – without spinning up a local PHP server. Our tests don't make any use of that ability so far.&lt;/p&gt;

&lt;p&gt;In an attempt to further enhance the test suite, we wanted to identify occasions where the application behaves differently when accessed directly to when it is accessed via HTTP. In fact, our initial trigger to use remote tests was a scenario where we only had test against a mocked environment and everything looked good in the tests, only to learn that our service would crash for the exact same calls when execute remotely (after being deployed of course).&lt;/p&gt;

&lt;p&gt;So here the solution we're currently using to run tests against both the remote server as well as a mocked environment:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Tests\Integration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;GuzzleHttp\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Psr\Http\Message\RequestInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Psr\Http\Message\ResponseInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Added to the part of BaseTest shown above&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kt"&gt;ResponseInterface&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$localResponse&lt;/span&gt; &lt;span class="o"&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;dispatchLocal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$remoteResponse&lt;/span&gt; &lt;span class="o"&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;dispatchRemote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&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;ensureLocalAndHttpIdentical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$localResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$remoteResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$remoteResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;dispatchLocal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;ResponseInterface&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// TODO Mock your application as necessary, so it can be executed and returns an instance of the ResponseInterface&lt;/span&gt;
        &lt;span class="nv"&gt;$req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$serverParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$body&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;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContainer&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'request'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$req&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&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;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;dispatchRemote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;ResponseInterface&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'body'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'base_uri'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'http://127.0.0.1:'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;ensureLocalAndHttpIdentical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ResponseInterface&lt;/span&gt; &lt;span class="nv"&gt;$localResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ResponseInterface&lt;/span&gt; &lt;span class="nv"&gt;$remoteResponse&lt;/span&gt;&lt;span class="p"&gt;)&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;assertSame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$localResponse&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStatusCode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;$remoteResponse&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStatusCode&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;assertEquals&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$localResponse&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBody&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$remoteResponse&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBody&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when we now use the &lt;code&gt;dispatch()&lt;/code&gt; function in any of our tests it will create two requests: one against the mocked application and an actual HTTP request against the local PHP server. As we don't want to test the properties of both requests individually, we compare the body and the response code int eh &lt;code&gt;ensureLocalAndHttpIdentical()&lt;/code&gt; function. Any differences here would cause the tests to fail. Then the &lt;code&gt;$remoteResponse&lt;/code&gt; is being returned to the actual test.&lt;/p&gt;

&lt;p&gt;This doesn't remove the need for unit tests. But it added a lot to my ease of mind when refactoring controllers or adding new features. Next for me will be add Mutation Testing to my palette of test approaches  (most likely with &lt;a href="https://github.com/infection/infection"&gt;Infection&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>php</category>
      <category>testing</category>
    </item>
    <item>
      <title>Maintaining Different Git Identities</title>
      <dc:creator>Max</dc:creator>
      <pubDate>Sun, 02 Jul 2017 15:08:10 +0000</pubDate>
      <link>https://dev.to/maxlmator/maintaining-different-git-identities</link>
      <guid>https://dev.to/maxlmator/maintaining-different-git-identities</guid>
      <description>&lt;p&gt;I like to have separate "identities" for my private and work stuff when using Git: Commits at work should be authored with my work email and commits in private projects with my private account. Until now I would always configure this per repository as soon as I noticed a commit done by the wrong email. &lt;/p&gt;

&lt;p&gt;As I was setting up my new computer and edited the global &lt;code&gt;.gitconfig&lt;/code&gt;, I wondered if there is a better way to keep this separate. Turns out there is one: With the &lt;a href="https://github.com/blog/2360-git-2-13-has-been-released"&gt;release of version 2.13&lt;/a&gt;, Git introduced &lt;a href="https://git-scm.com/docs/git-config#_conditional_includes"&gt;"Conditional Includes"&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;With these includes I can set a specific gitconfig-file to be include for all repositories within a specific location. As I store all my work projects within the folder &lt;code&gt;~/Work&lt;/code&gt;, I set the default user-config to be my private one and include the work-specific configfile for all Git repositories within that location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gitconfig

[user]
    name = Firstname Lastname
    email = &amp;lt;private email address&amp;gt;

[includeIf "gitdir:~/Work/"]
    path = .gitconfig-work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gitconfig-work

[user]
    name = Lastname, Firstname
    email = &amp;lt;work email address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The risk of being annoyed by wrongly associated commits is vastly smaller now — until I start checking out work projects to ~/Desktop/tmp for minor fixes. &lt;/p&gt;

&lt;p&gt;To check your configuration, make sure to be in a directory which is tracked by Git. Non-Git directories will always show the default configuration:&lt;br&gt;
&lt;/p&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;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/dev/justcurious 
&lt;span class="nv"&gt;$ &lt;/span&gt;git config user.email
&amp;lt;private email address&amp;gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Work/projectA
&lt;span class="nv"&gt;$ &lt;/span&gt;git config user.email
&amp;lt;work email address&amp;gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Work/not-a-repo
&lt;span class="nv"&gt;$ &lt;/span&gt;git config user.email
&amp;lt;private email address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>git</category>
    </item>
  </channel>
</rss>
