<?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: dvallin</title>
    <description>The latest articles on DEV Community by dvallin (@dvallin).</description>
    <link>https://dev.to/dvallin</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%2F357732%2Fd61b7ce9-b228-4687-affd-2dc84615947a.png</url>
      <title>DEV Community: dvallin</title>
      <link>https://dev.to/dvallin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dvallin"/>
    <language>en</language>
    <item>
      <title>Test your React App with Context</title>
      <dc:creator>dvallin</dc:creator>
      <pubDate>Wed, 15 Apr 2020 12:47:55 +0000</pubDate>
      <link>https://dev.to/dvallin/test-your-react-app-with-context-4cn5</link>
      <guid>https://dev.to/dvallin/test-your-react-app-with-context-4cn5</guid>
      <description>&lt;p&gt;Have you ever struggled to test this little &lt;code&gt;fetch()&lt;/code&gt; call or this &lt;code&gt;window.location&lt;/code&gt; in your React App? The thing with those Web APIs is that you cannot mock them directly. Of course you can globally mock the fetch API during test setup &lt;a href="https://www.reactnativeschool.com/mocking-fetch-api-calls-when-using-jest"&gt;like this&lt;/a&gt; or use &lt;a href="https://www.npmjs.com/package/jest-fetch-mock"&gt;an npm package&lt;/a&gt; to do the same thing. But what to do with the next fancy API? I say you can solve the problem much easier and end up with a cleaner architecture at the same time by wrapping the APIs into a React.Context.&lt;/p&gt;

&lt;p&gt;First let us define a very thin wrapping layer of all APIs we need to use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Api&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockedApi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&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;You can create the Api in two ways. One in your production code with &lt;code&gt;createApi&lt;/code&gt; and one in your tests with &lt;code&gt;mockedApi&lt;/code&gt;. The problem is that you can't just invoke &lt;code&gt;fetch()&lt;/code&gt; wherever you like anymore. You first have to retrieve the Api object from somewhere. If you call the &lt;code&gt;createApi()&lt;/code&gt; method whenever you need the object, you still cannot replace the Api by a mock during testing. You need to somehow pass the object through your whole App and put it into the Props of all your Components. This is not very elegant and a lot of work!&lt;/p&gt;

&lt;p&gt;Luckily, React comes with a solution. You can create a &lt;a href="https://reactjs.org/docs/context.html"&gt;React.Context&lt;/a&gt; object, put your Api into it and consume this context wherever you need it.&lt;/p&gt;

&lt;p&gt;I do not like to use my API directly from my Components, so I first create Service objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Services&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UsersService&lt;/span&gt;
    &lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ContactsService&lt;/span&gt;
    &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RestService&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createServices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Services&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contacts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ContactsService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RestService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EntityService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entities&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;When testing these services you can easily wrap the Api and focus on the interaction with the Api. For a component to use these services you have to put them into a React.Context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Services&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AppWithContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createServices&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Services.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is exactly how you provide a &lt;a href="https://redux.js.org/basics/usage-with-react#indexjs"&gt;Redux Store&lt;/a&gt; to your App. Let us write something very similar to redux's &lt;a href="https://react-redux.js.org/api/connect"&gt;connect&lt;/a&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;injectServices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;WrappedComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Services&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WrappedComponent&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Services.Consumer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function takes a Component that has some Props &lt;code&gt;P &amp;amp; Services&lt;/code&gt; and returns a Component that has only Props &lt;code&gt;P&lt;/code&gt;. You can easily use it like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Services&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;OwnProps&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;injectServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and you can even put a connected Component into this function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatchToProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;OwnProps&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Callbacks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dipatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;onSave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dipatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createActionUsingService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;injectServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;stateToProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;dispatchToProps&lt;/span&gt;
    &lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&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;Now you can use the services even in your mapping function, which is probably exactly where you want them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you like this post, why not have a look at one of my other (probably more light-hearted) posts. This post was sponsored by &lt;a href="https://www.itemis.com/en/"&gt;itemis AG&lt;/a&gt;. That's the place were I work and drink.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>typescript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Of Dungeons, Dragons and SAT-Solvers</title>
      <dc:creator>dvallin</dc:creator>
      <pubDate>Wed, 01 Apr 2020 13:13:11 +0000</pubDate>
      <link>https://dev.to/dvallin/of-dungeons-dragons-and-sat-solvers-k00</link>
      <guid>https://dev.to/dvallin/of-dungeons-dragons-and-sat-solvers-k00</guid>
      <description>&lt;p&gt;I love to work on my &lt;a href="https://github.com/dvallin/tlb-js"&gt;roguelike game&lt;/a&gt; in my spare time. Of course there is no end in sight and it will probably not be playable for months or years to come. But on the way, I always encounter some interesting problems. Most of them can be easily solved with some monkey work, but a few call for logic programming and the sledgehammer that is &lt;a href="http://minisat.se/"&gt;MiniSat&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  A graph embedding problem appears
&lt;/h1&gt;

&lt;p&gt;Imagine you have procedurally generated a dungeon. So you basically generated a list of structures representing rooms of the dungeon and their connections (aka doors).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RoomId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Room&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RoomId&lt;/span&gt;
  &lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RoomId&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;Now you know that on the current level there should be some rooms filled with enemies and loot. There should also be a shop near the entrance. Next to the shop, a random encounter that gives a side quest. And a dragon that guards the treasure room.&lt;/p&gt;

&lt;p&gt;You start building descriptions for each of these structures. And try to fit them randomly into your dungeon. At first it is easy. Just decide for each room, what kind of filling it needs. A room near the entrance: Shop! A room somewhere inside the dungeon: Throw a d20, add some enemies, et voilà full dungeon. But then you try to fit the dragon in your dungeon. Now you have to look out, that there is a treasure room next to the dragon. And the treasure room should have only one entrance. Oh, and there should be only one shop. And not more than eight rooms filled with enemies...&lt;br&gt;
Your code is starting to become more and more tangled and complex.&lt;/p&gt;

&lt;p&gt;Let us step back for a moment and think about the problem in more abstract terms. The dungeon represents a graph &lt;em&gt;G&lt;/em&gt;. The nodes are rooms and the edges are the doors. The descriptions of room fillings are also a graph &lt;em&gt;H&lt;/em&gt;. The nodes are individual room fillings (e.g. a dragon, a treasure room, some enemies) and the edges bind them together. An edge between a dragon node and a treasure room node represents the restriction that they are directly connected.&lt;/p&gt;

&lt;p&gt;Now to fill the empty dungeon with interesting content you only have to find an embedding of &lt;em&gt;H&lt;/em&gt; in &lt;em&gt;G&lt;/em&gt;!&lt;/p&gt;
&lt;h1&gt;
  
  
  You shall &lt;del&gt;not&lt;/del&gt; SAT
&lt;/h1&gt;

&lt;p&gt;You might say that restating the problem with a graph does not solve anything. But it helps in viewing the problem as a mathematical one. At its core it is just the embedding problem and every additional rule adds restrictions on how this embedding should be done. So each rule reduces the pairs of nodes in &lt;em&gt;H&lt;/em&gt; and &lt;em&gt;G&lt;/em&gt; that are allowed in a correct embedding.&lt;/p&gt;

&lt;p&gt;A possible way to solve this problem is to represent it as a &lt;a href="https://en.wikipedia.org/wiki/Boolean_satisfiability_problem"&gt;boolean satisfiability problem&lt;/a&gt;. Yes this problem is NP-hard but there exist a lot of SAT-Solvers that can handle problems far larger than our little dungeon. The devs at &lt;a href="https://www.meteor.com/"&gt;meteor&lt;/a&gt; even packaged the famous &lt;a href="http://minisat.se/"&gt;MiniSat&lt;/a&gt; solver using &lt;a href="https://emscripten.org/"&gt;Emscripten&lt;/a&gt; on &lt;a href="https://www.npmjs.com/package/logic-solver"&gt;npm&lt;/a&gt; so you can solve SAT-Problems inside your browser!&lt;/p&gt;

&lt;p&gt;Now let us represent the problem in SAT using Typescript!&lt;/p&gt;

&lt;p&gt;First we introduce variables. We need a variable for each possible pair of nodes and write a little function that gives each &lt;em&gt;v in G&lt;/em&gt; and &lt;em&gt;w in H&lt;/em&gt; a unique name.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now for the actual rules of the embedding. The first rule is that each node in &lt;em&gt;H&lt;/em&gt; can only be mapped to one node in &lt;em&gt;G&lt;/em&gt;. That means if we have one dragon in &lt;em&gt;H&lt;/em&gt; there shall only be one dragon in &lt;em&gt;G&lt;/em&gt;. And if we need ten random ruffian-filled rooms, we need to put ten nodes in &lt;em&gt;H&lt;/em&gt; that represent that. As a logical expression this may look like this&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Cvw⇒⋀i≠vv∈H¬Ciw
  C_{vw} \Rightarrow \bigwedge\limits_{i \neq v}^{v \in H} \lnot C_{iw}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⇒&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;i&lt;/span&gt;&lt;span class="mrel mtight"&gt;&lt;span class="mrel mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="rlap mtight"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="inner"&gt;&lt;span class="mrel mtight"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="fix"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;⋀&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mrel mtight"&gt;∈&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;Written out this means: "If &lt;em&gt;v&lt;/em&gt; is mapped to &lt;em&gt;w&lt;/em&gt; then for all nodes &lt;em&gt;i&lt;/em&gt; (that are not &lt;em&gt;v&lt;/em&gt;) there is no mapping from &lt;em&gt;i&lt;/em&gt; to &lt;em&gt;w&lt;/em&gt;". For a SAT Solver to understand this rule, we need to transform it into &lt;a href="https://en.wikipedia.org/wiki/Conjunctive_normal_form"&gt;conjunctive normal form (CNF)&lt;/a&gt; first. Now with &lt;a href="https://en.wikipedia.org/wiki/Material_implication_(rule_of_inference)"&gt;material implication&lt;/a&gt;&lt;br&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;¬Cvw∨[⋀i≠vv∈H¬Ciw]
  \lnot C_{vw} \lor [ \bigwedge\limits_{i \neq v}^{v \in H} \lnot C_{iw} ]
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∨&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;i&lt;/span&gt;&lt;span class="mrel mtight"&gt;&lt;span class="mrel mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="rlap mtight"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="inner"&gt;&lt;span class="mrel mtight"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="fix"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;⋀&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mrel mtight"&gt;∈&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br&gt;
and with the law of distributivity&lt;br&gt;

&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;⋀i≠vv∈H(¬Ciw∨¬Cvw)
  \bigwedge\limits_{i \neq v}^{v \in H} ( \lnot C_{iw} \lor \lnot C_{vw} )
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;i&lt;/span&gt;&lt;span class="mrel mtight"&gt;&lt;span class="mrel mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="rlap mtight"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="inner"&gt;&lt;span class="mrel mtight"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="fix"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;⋀&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mrel mtight"&gt;∈&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∨&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br&gt;
we can reach &lt;em&gt;CNF&lt;/em&gt;. If you look closely at the above formulas you might notice that there is a trivial solution that satisfies them. When all variables are false! The formula expresses &lt;em&gt;at least once&lt;/em&gt; and we additionally assert&lt;br&gt;

&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;⋀v∈H[⋁w∈GCvw]
  \bigwedge\limits^{v \in H} [ 
  \bigvee^{w \in G} C_{vw} ]
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;⋀&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mrel mtight"&gt;∈&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;⋁&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;span class="mrel mtight"&gt;∈&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;v&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br&gt;
that for each node in &lt;em&gt;H&lt;/em&gt; there must be a mapping to a node in &lt;em&gt;G&lt;/em&gt; to make it &lt;em&gt;exactly one&lt;/em&gt;.

&lt;p&gt;Luckily, the &lt;em&gt;logic-solver&lt;/em&gt; package has already a bunch of helper functions to create common logical expressions and this one is &lt;em&gt;exactlyOne()&lt;/em&gt;. That means there is no need to put any more math formulas in this post 🤓.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// each w in H on exactly one v in G&lt;/span&gt;
  &lt;span class="nx"&gt;H&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Cvw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;G&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;createLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nx"&gt;solver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exactlyOne&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;Cvw&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;This looks simple enough and solving this problem by running &lt;code&gt;solver.solve()&lt;/code&gt; will even yield a solution! After mapping the variable assignments back to the graph embedding you realize that each node in &lt;em&gt;H&lt;/em&gt; is mapped to the exact same node in G. Which means that all enemies, shops and dragons are being put into the same room. That would mean no backtracking and yack shaving, and that is the whole point of dungeon crawling. So let us write an additional rule to achieve that!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// each v in G can map to at most one w in W&lt;/span&gt;
  &lt;span class="nx"&gt;G&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Cvw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;H&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;createLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nx"&gt;solver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;atMostOne&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;Cvw&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;This looks very similar to the rule we created above, except that we are now coming from nodes in &lt;em&gt;G&lt;/em&gt; to nodes in &lt;em&gt;H&lt;/em&gt; and use the &lt;em&gt;atMostOne()&lt;/em&gt; helper (we already derived the formula above). Each room of our dungeon now has at most one room mapped to it from &lt;em&gt;H&lt;/em&gt;. The solver will fill our dungeon and keep dragons separated from shopkeepers.&lt;/p&gt;

&lt;p&gt;Still the dragon is not sitting next to the treasure room, because we have yet to use the edges of &lt;em&gt;H&lt;/em&gt;! Let us try to put into code that the neighbourhoods in &lt;em&gt;H&lt;/em&gt; are also mapped to &lt;em&gt;G&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// all neighbours in H are mapped to neighbours in G&lt;/span&gt;
  &lt;span class="nx"&gt;H&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;G&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Cvw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;H&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;traverseEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;w&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="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;Cij&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nx"&gt;G&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;traverseEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;Cij&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&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="nx"&gt;solver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Cvw&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;Cij&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="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a lot going on here. The first two forEach statements are just to select each possible mapping of node pairs &lt;em&gt;v&lt;/em&gt; and &lt;em&gt;w&lt;/em&gt;. We use a simple function &lt;em&gt;traverseEdge&lt;/em&gt; to find neighbours of nodes. Then for each neighbour &lt;em&gt;j&lt;/em&gt; of &lt;em&gt;w&lt;/em&gt; in &lt;em&gt;H&lt;/em&gt; we create a new restriction. Now we look at each neighbour &lt;em&gt;i&lt;/em&gt; in &lt;em&gt;G&lt;/em&gt; of &lt;em&gt;v&lt;/em&gt;. And we can finally state that if there is a mapping from &lt;em&gt;v&lt;/em&gt; to &lt;em&gt;w&lt;/em&gt; there must be a mapping from &lt;em&gt;i&lt;/em&gt; to &lt;em&gt;j&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Oh, you can imagine the fun that went into testing that code!&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I presented only the bare essentials of my room embedder and a lot is still missing. There is for example no concept of an entrance to the dungeon and how &lt;em&gt;deep&lt;/em&gt; a room is inside of it. Also rooms might be too small for a dragon or not close enough to the shop. But we can always create new restrictions and modify existing ones to meet our changing needs.&lt;/p&gt;

&lt;p&gt;We can refine the solution on multiple levels. The first way is just to add more rules to the problem and to modify the graphs accordingly. But we can also extend the graph nodes with labels, remove nodes from &lt;em&gt;G&lt;/em&gt; or modify &lt;em&gt;H&lt;/em&gt;. It may also be a good idea to randomize the order of the rooms in &lt;em&gt;G&lt;/em&gt;. And a crucial one is to run multiple embedding phases. The first phase to add the must-haves of the level. Dragons, shops, treasures. With the second run you add additional content like side quests. And during the last passes you can add monsters and decorations that can fill the gaps between the more engaging and complex content.&lt;/p&gt;

&lt;p&gt;I guess, you can take it from here. Or get inspired to consider &lt;a href="https://en.wikipedia.org/wiki/Constraint_logic_programming"&gt;some logic programming&lt;/a&gt; for your own problems.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you had as much fun learning about SAT solvers as me writing down those formulas in latex. This post was sponsored by &lt;a href="https://www.itemis.com/en/"&gt;itemis AG&lt;/a&gt;. That's the place where I work and drink.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>typescript</category>
      <category>tutorial</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Little red failing test and other fables</title>
      <dc:creator>dvallin</dc:creator>
      <pubDate>Tue, 31 Mar 2020 13:35:24 +0000</pubDate>
      <link>https://dev.to/dvallin/little-red-failing-test-and-other-fables-8do</link>
      <guid>https://dev.to/dvallin/little-red-failing-test-and-other-fables-8do</guid>
      <description>&lt;p&gt;Instead of writing about my blogging habits during quarantine, I wrote some short fables about unit test methodology for you to read to your kids and/or cats.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Hare and the Hedgehog
&lt;/h1&gt;

&lt;p&gt;One Sunday morning about harvest time, just as the buckwheat was in bloom, the sun was shining brightly in heaven, the east wind was blowing warmly over the stupple-fields, the larks were singing in the air, the bees buzzing among the buckwheat, the people were all going in their Sunday clothes to church, and all creatures were happy, and the Hedgehog was happy too.&lt;/p&gt;

&lt;p&gt;The Hedgehog took a walk in the field, to visit his databases and look after his unit tests. When the Hedgehog caught sight of the Hare, he bade him a friendly good morning. But the Hare, who was in his own way a distinguished gentleman, did not return the Hedgehog’s greeting, but said to him, “How do you happen to be running about here in the morning?” - “I am going for a stroll” said the Hedgehog. “A stroll!” said the Hare with a smile. “It seems to me that you might use your legs for a better purpose.” This answer made the Hedgehog furiously angry, “You seem to imagine you can do more with your legs than I with mine.” - “That is just what I do think,” said the Hare. “That can be put to a test,” said the Hedgehog. “I wager that if we run a race, I will outstrip you.” To that the Hare agreed willingly for he was very confident in his quickness.&lt;/p&gt;

&lt;p&gt;The next day the Hedgehog reached the field where the Hare already waited for him. “Shall we start?” said the Hare. “Certainly,” said the Hedgehog. The hare counted, “Once, twice, thrice, and away!” and went of in a whirlwind down the field. The Hedgehog, however, only ran about three paces, and then he wrote a unit test, so he would not get lost in the high grass of the field. After another three paces, he stopped again to write another unit test. And so he went forth for quite some time. The Hare, however, must had been running in circles and to his disbelief met with the Hedgehog. “That cannot be done fairly,” he cried “I was ahead of you Hedgehog the whole time, I shall try to run even faster!” The Hare went of like the winds storm, so that he seemed to fly, but the Hedgehog did not change his pace.&lt;/p&gt;

&lt;p&gt;The Hare must had been running in circles many times, but never reached the top of the field. When the sun was already setting, the Hedgehog found the Hare lying dead in the middle of the field. The Hedghog, however finished the race quite before afternoon.&lt;/p&gt;

&lt;p&gt;The moral of this story, however, is, firstly, that no one, however great he may be, should permit himself to ignore test coverage for the sake of velocity.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Wolf and the Seven Features
&lt;/h1&gt;

&lt;p&gt;There once was a Wolf who had written a very efficient database layer for his use case. The database layer implemented all features that the Hare had demanded in his user story. Satisfied with himself the Wolf said: “I have implemented all seven features and I can see they are good. But still, I have to test them!” So he went forth and created a test data image for his use case. He added a row for when there are all piglets in wooden homes, and one row for when only one piglet is in a wooden home and the others are in a stone home. He added many more rows like this. And when he was finished he started to write his test. With a single test he covered all features at once! The Wolf said: “This is very elegant. I tested all seven features in one big gulp!”&lt;/p&gt;

&lt;p&gt;But then the Hare came and said: “Well done Wolf, you have implemented all seven features. But now I found out that there will never be all piglets in one home. You have to change your implementation!”. “No problem”, the wolf thought and quickly changed the database layer to fit the new needs. But lo! Now the test was broken and it was very hard to fix. The test tested all seven features at one stroke but now it tested features that were not correct anymore! Oh dear, what should the Wolf do now?&lt;/p&gt;

&lt;p&gt;When the clever Fox heard of the Hare's misery he came and said: “Wolf, why do you create a big test image? You can create exactly the data you need for each test! And write many small tests. One for each feature!” What a wonderful idea that was. The Wolf added just the case that there is one piglet in the wooden house and tested exactly this in a dedicated test. Now the tests even served as a documentation of the features the Wolf had implemented. When the Wolf showed this to the Hare, he was very satisfied and thanked the Wolf many times. As Customers always do when they see that a software developer did a good job.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Bear and the Grasshopper
&lt;/h1&gt;

&lt;p&gt;There once was a Bear who had written a very big and very cozy backend for himself. “This backend is a very good one for a big Bear like me. It will suit me very well, and now I shall sleep for the winter!”, the Bear said to himself. He gave a big yawn and fell asleep.&lt;/p&gt;

&lt;p&gt;But lo! A little Grasshopper jumped into the backend and hopped onto the Bears nose. This startled the Bear from his sleep and from the corner of his eyes he saw the Grasshopper jump away. “A bug in my backend! How can this be!”, the Bear growled with anger. He slammed his paw into the direction where he last saw the Grasshopper hop. “Let this be a lesson for you, little bug. And do not disturb my slumber again!”, the Bear growled and fell asleep once more.&lt;/p&gt;

&lt;p&gt;Some time passed, but then the little Grasshopper came back. He was just hiding behind another feature! He jumped into databases table and onto the belly of the Bear. This woke the Bear from his sleep again and made him more furious than the last time. He hit his paw against all the tables and even added debug logging to the controllers. But he could not catch the little bug.&lt;/p&gt;

&lt;p&gt;Then a Hedgehog who was disturbed by the noise came to the backend, “Bear, why do you make such a noise? Shouldn’t you be fast asleep?”. “There is a bug in my backend and I cannot catch it. When I look to the left it jumps to the right. And when I look here it jumps there.”, the Bear answered. The Hedgehog thought a moment for himself and finally said: “Bear you should write tests. Test everywhere you could see the bug and when you have tested all places he will be gone”. The Bear considered this and said, “Bears do not write tests and I do not see why this should help me. But I will do as you ask, for I am weary now and cannot sleep with a bug in my backend.“ And lo! After the Bear has written all his tests the Grasshopper had no place to hide anymore and was never seen again.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you had as much fun reading these stories as me writing them. This post was sponsored by &lt;a href="https://www.itemis.com/en/"&gt;itemis AG&lt;/a&gt;. That's the place were I work and drink.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>motivation</category>
      <category>writing</category>
      <category>jokes</category>
    </item>
  </channel>
</rss>
