<?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: Marko Bjelac</title>
    <description>The latest articles on DEV Community by Marko Bjelac (@mbjelac).</description>
    <link>https://dev.to/mbjelac</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%2F104381%2Fc54e8f6a-69e3-413f-b64d-8f212121b84e.jpeg</url>
      <title>DEV Community: Marko Bjelac</title>
      <link>https://dev.to/mbjelac</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mbjelac"/>
    <language>en</language>
    <item>
      <title>Socrates Deutschland 2025</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Mon, 21 Jul 2025 22:27:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/socrates-deutschland-2025-2h11</link>
      <guid>https://dev.to/mbjelac/socrates-deutschland-2025-2h11</guid>
      <description>&lt;p&gt;My colleague &amp;amp; me were on the &lt;a href="https://www.socrates-conference.de/home" rel="noopener noreferrer"&gt;Socrates un-conference&lt;/a&gt; in Soltau, Germany.&lt;/p&gt;

&lt;p&gt;This was our 2nd Socrates, as we were both at the &lt;a href="https://dev.to/mbjelac/socrates-uk-2024-1d9m"&gt;UK version last year&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Comparison with the UK conference is not very interesting: There were more people than in the UK (this is usually the biggest Socrates by far) and the hotel was new, built specifically for conferences &amp;amp; gatherings. Other than that the venue type was similar and the people were as smart, as kind &amp;amp; as inviting as in the UK.&lt;/p&gt;

&lt;p&gt;Comparison with other conferences and life experiences in general is close to impossible. The German Socrates is as radical as the UK Socrates in more than one aspect.&lt;/p&gt;

&lt;h1&gt;
  
  
  🔪 Aspects
&lt;/h1&gt;

&lt;p&gt;Socrates is a complex endeavour and describing it is difficult. Hence I will do the engineering thing and analyse it. This means chopping it up into pieces (calling them “aspects” to sound like I know what I’m doing) so I can better understand it.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Professional
&lt;/h2&gt;

&lt;p&gt;I met a bunch of very very &lt;em&gt;very&lt;/em&gt; smart people! These people know a lot &amp;amp; love to talk and to teach about various software crafting and other skills. Their accessibility is the most radical thing. You just ask someone to show you something or talk to you about something and they’ll eagerly accommodate you.&lt;/p&gt;

&lt;p&gt;For example, I was on a session describing a mad form of TDD (MAD-TDD) and that evening I realise that the way we do BDD at my current project has some resemblances. At lunch the next day I ask the speaker would he pair with me on an idea related to mad TDD. At dinner that day we pair on a small experiment and I am now ready to explore MAD-BDD!&lt;/p&gt;

&lt;p&gt;Everyone’s schedule is full and everyone wants to get to the next session or play a board game, but they’ll all make room in their schedule for you and go out of their way to teach (and with that, to learn) about anything you ask.&lt;/p&gt;

&lt;p&gt;There is more patience accumulated at Socrates than at 7 kindergarten-teacher conferences. 🍼&lt;/p&gt;

&lt;h2&gt;
  
  
  👫 Social
&lt;/h2&gt;

&lt;p&gt;Some issues can’t be explained by Clean Code or any other technical book. A lot of sessions and conversations were about agility. Put differently, they were about the social systems which are created to build software. These systems are complex and seldom optimal. Agility as a term is warily used nowadays (walking on eggshells 🐣) however there is an understanding that the original idea was OK. Some attendees are extremely experienced in navigating those systems and gave the rest of us very valuable advice.&lt;/p&gt;

&lt;p&gt;Also, managers are apparently not evil. 🤷&lt;/p&gt;

&lt;h2&gt;
  
  
  🌍 Worldly
&lt;/h2&gt;

&lt;p&gt;The world is being eaten by software. This is old news. We can’t do anything about it but we can try to ensure the software systems we create do not enforce injustice. Or can we?&lt;/p&gt;

&lt;p&gt;Is it inevitable that companies grow to treat their employees like resources?&lt;/p&gt;

&lt;p&gt;Is there any viable alternative to the already established techno-feudalism of the ultra-rich?&lt;/p&gt;

&lt;p&gt;Now, &lt;em&gt;that’s&lt;/em&gt; heavy subject matter. So heavy in fact that I skipped one of those sessions to listen to escape room 🔒 building skills - metaphorically and literally escaping, heh heh.&lt;/p&gt;

&lt;p&gt;However, I did attend a couple of those sessions, the last one having dark but towards the end also some lighter notes which left a tiny spark of optimism in me. 🌈&lt;/p&gt;

&lt;h2&gt;
  
  
  🍭 Playful
&lt;/h2&gt;

&lt;p&gt;Socrates would not be Socrates without some serious silliness. Most of us there are engineers after all.&lt;/p&gt;

&lt;p&gt;Among these unconventional activities (ha! as if others were conventional) there were&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;billiards 🎱&lt;/li&gt;
&lt;li&gt;board games 🎲&lt;/li&gt;
&lt;li&gt;volleyball 🏐&lt;/li&gt;
&lt;li&gt;table-top roleplaying games 🧙 (only one but that was awesome)&lt;/li&gt;
&lt;li&gt;programming robots 🤖&lt;/li&gt;
&lt;li&gt;intentionally destroying a codebase by refactoring 🧨&lt;/li&gt;
&lt;li&gt;and petting a very nice dog called Luca 🐕&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sober or not 🍺, long conversations about wildly amusing &amp;amp; diverse topics were to be found in every corridor.&lt;/p&gt;

&lt;p&gt;I went to sleep late every night, reluctant to leave the conversations. But I wanted to get some sleep for the next day. However, lying in bed I couldn’t fall asleep because my mind was excitedly racing through the events of the day. After I finally fell asleep I would awake the next morning 1.5 hours before the alarm clock, my body still tired but my mind yelling: “Come on, lets go on the ride again, and again, and again!” 🎢&lt;/p&gt;

&lt;p&gt;Now at home, after I finally got a night or two of decent sleep I fall into the daily routine again. While going about regular tasks I smile when a memory from the past couple of days pops up and waves to me in passing.&lt;/p&gt;

&lt;h1&gt;
  
  
  🥳 In closing
&lt;/h1&gt;

&lt;p&gt;Socrates was (again) a warm and inspiring experience. I felt at home with people whom I (mostly) met for the first time in my life. This is what every conference should look like. This is how people should communicate, learn and teach, always.&lt;/p&gt;

&lt;p&gt;While waiting for the next year’s Socrates I will not be idle. I will try to spread the experience by organising monthly meetups in Zagreb and any other close-by city that will take me.&lt;/p&gt;

&lt;p&gt;What meetups? These meetups: &lt;a href="https://www.meetup.com/zagreb-software-crafters/" rel="noopener noreferrer"&gt;https://www.meetup.com/zagreb-software-crafters/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;To wrap this up, I would like to thank:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conference organisers, the most selfless beings on the planet: Accept a big 💋 from me!&lt;/li&gt;
&lt;li&gt;All the other attendees: Stay as kind &amp;amp; inclusive as you've been at Soltau! I hope to see you all next year!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rb7abhjh7y6hwsys5iw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rb7abhjh7y6hwsys5iw.jpg" alt="The quirky crowd of Socrates DE 2025" width="800" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>conference</category>
    </item>
    <item>
      <title>Cost of Change in Forests &amp; Deserts</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Tue, 01 Apr 2025 22:24:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/cost-of-change-in-forests-deserts-3dfl</link>
      <guid>https://dev.to/mbjelac/cost-of-change-in-forests-deserts-3dfl</guid>
      <description>&lt;p&gt;I have been watching Dave Farley's &lt;a href="https://www.youtube.com/@ModernSoftwareEngineeringYT" rel="noopener noreferrer"&gt;MSE channel&lt;/a&gt;, which prompted me to leaf through his book &lt;a href="https://www.oreilly.com/library/view/modern-software-engineering/9780137314942/" rel="noopener noreferrer"&gt;Modern Software Engineering&lt;/a&gt;. I read it a year ago, but as I leafed through it again I discovered I had penned thoughts next to some paragraphs.&lt;/p&gt;

&lt;p&gt;Leafing through to find more interesting stuff which I hadn't annotated, I found this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;... Dan [&lt;a href="https://dannorth.net/" rel="noopener noreferrer"&gt;North&lt;/a&gt;] described the difference between waterfall and agile thinking as, effectively, a problem in economics. Waterfall thinking is promulgated on the assumption that change gets more expensive as time goes on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;small&gt;-- Chapter 4, Working Iteratively, Iteration as a Defensive Design Strategy, p.46&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Dave goes on to explain how in this view, the core difference between waterfall and agile is the &lt;em&gt;cost of change&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This is visually represented with cost/time diagrams (redrawn here with minor additions):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjqk4luq94n8z7ts8g9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjqk4luq94n8z7ts8g9u.png" alt="Waterfall vs. Agile cost-of-change diagrams depicting how in the Waterfall model cost of change starts very low and grows slowly but then picks up speed and never stops growing, while in the Agile model cost starts rising quickly but then levels off" width="781" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the Waterfall model does not require any coding practices which keep the codebase maintainable, we get 2 effects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Starting things from scratch is very fast, as we only spend time on coding the thing we need&lt;/li&gt;
&lt;li&gt;Each change is more expensive than the one before as we do not "waste" time refactoring, writing tests or coding in pairs/mobs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This strongly reminds me of Beth &amp;amp; Kent Beck's excellent metaphor, &lt;a href="https://tidyfirst.substack.com/p/forest-and-desert" rel="noopener noreferrer"&gt;the Forest and the Desert&lt;/a&gt;. When Beth &amp;amp; Kent talk about the Forest, they mention a much more relaxed working environment. There is no stress. Work flows naturally, with no overtime and no rushing. Developers have the time to rest, exchange ideas or invest in the practices which help keep things where they are (i.e. the Forest). It seems to me that the cost of change in the forest is constant.&lt;/p&gt;

&lt;p&gt;Conversely, things are much more stressful in the Desert. As the cost of change is rising all the time, deadlines slip, rushing is ubiquitous and there is no time to do activities which would help alleviate these problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfj4s1ksrrkac6g0xs0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfj4s1ksrrkac6g0xs0c.png" alt="Same diagram as above, only Waterfall-&amp;gt;Desert, Agile-&amp;gt;Forest" width="770" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While working in the Desert is possible, and indeed much more common today, I strongly prefer working in the Forest. I like to rest in the shade.&lt;/p&gt;

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

&lt;p&gt;I believe the effect is related to Martin Fowler's &lt;a href="https://martinfowler.com/bliki/DesignStaminaHypothesis.html" rel="noopener noreferrer"&gt;Design Stamina Hypothesis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For another, also excellent, description of Forest/Desert, see Beth &amp;amp; Kent's &lt;a href="https://www.youtube.com/watch?v=nt6m8qtRbz0" rel="noopener noreferrer"&gt;talk at Øredev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cost-of-change diagrams re-purposed with permission from Dave Farley.&lt;/p&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@alingavriliuc?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Alin Gavriliuc&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-small-tree-in-the-middle-of-a-desert-pJeNSIEzHs8?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Emergent test pyramid</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Tue, 11 Feb 2025 20:44:58 +0000</pubDate>
      <link>https://dev.to/mbjelac/emergent-test-pyramid-4cc</link>
      <guid>https://dev.to/mbjelac/emergent-test-pyramid-4cc</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://www.pexels.com/photo/pyramid-of-gray-stones-in-water-9379813/" rel="noopener noreferrer"&gt;Samuel Bourgeot&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Follow the principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Test each thing at the lowest possible level.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, do test &lt;em&gt;all&lt;/em&gt; the things (interactions between things are also things).&lt;/p&gt;

&lt;p&gt;This will naturally lead to a test pyramid emerging:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9r3bzrgqk0n3jw76ifk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9r3bzrgqk0n3jw76ifk.png" alt="Basic test pyramid" width="668" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;End-to-end (E2E) tests: Hard to write, slow &amp;amp; unreliable.&lt;/p&gt;

&lt;p&gt;Acceptance tests: Describe features, hard to write without a framework, not so fast.&lt;/p&gt;

&lt;p&gt;Unit tests: Testing small pieces of data processing code, easy to write, very fast.&lt;/p&gt;

&lt;p&gt;This gets you to the sweet spot between just enough coverage, number of tests to write and speed of test execution. It also allows easier refactoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Writing automated tests is hard. To make it easier I advise you to test before the code is implemented. This is also known as test-first development. Add a bit of thoughtful pacing &amp;amp; cleaning up and you get test-&lt;em&gt;driven&lt;/em&gt; development. With a bit of experience with software architecture &amp;amp; paying attention to the ease (or lack thereof) of writing tests you get test-driven &lt;em&gt;design&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;All these are for another article, albeit related.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://martinfowler.com/bliki/TestPyramid.html" rel="noopener noreferrer"&gt;test pyramid&lt;/a&gt; is a well-documented concept. The benefits are real. You can cover all or almost all functionality of your software with keeping tests to a minimum &amp;amp; at the same time allowing for lots of refactoring without breaking any tests.&lt;/p&gt;

&lt;p&gt;Here's how to get there: When developing your software, take small steps and try to adhere to the principles described below. Always know where you are in the codebase and act accordingly.&lt;/p&gt;

&lt;p&gt;I know, sounds mysterious. It isn't. Read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onion architecture
&lt;/h2&gt;

&lt;p&gt;The architecture of your system is going to impact your writing of automated tests. The Onion architecture is by far the best suited architecture for thoroughly-tested systems.&lt;/p&gt;

&lt;p&gt;There are several variations of this and I warmly suggest you read &lt;a href="https://www.thoughtworks.com/insights/blog/architecture/demystify-software-architecture-patterns" rel="noopener noreferrer"&gt;this article&lt;/a&gt; which explains them all but also summarises the key points.&lt;/p&gt;

&lt;p&gt;I like the name "onion architecture" best because the name itself hints at what the architecture looks like.&lt;/p&gt;

&lt;p&gt;Here is a diagram of my approach to this architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyt50xrtlte9qvd0s0zc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyt50xrtlte9qvd0s0zc.png" alt="Onion architecture, my variant" width="377" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Only 2 test layers needed
&lt;/h2&gt;

&lt;p&gt;This architecture enables me to have just 2 types (or layers) of functional tests:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Acceptance tests&lt;/li&gt;
&lt;li&gt;Unit tests&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are also integration tests but let's ignore them in this article.&lt;/p&gt;

&lt;p&gt;Here is a similar diagram, but with tests:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lfo3jm83s3ufpznl2jc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lfo3jm83s3ufpznl2jc.png" alt="Onion architecture, my variant, with tests" width="452" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Acceptance tests
&lt;/h3&gt;

&lt;p&gt;These tests have 2 main purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Describe a feature&lt;/li&gt;
&lt;li&gt;Verify all wiring between services and all their collaborators is correct&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Unit tests
&lt;/h3&gt;

&lt;p&gt;These are the widely known small &amp;amp; focused tests. They test only one class (sometimes just a function). The class ideally should not have any collaborators as this complicates tests with test doubles. They are very fast to execute, typically under 10ms per test.&lt;/p&gt;

&lt;h3&gt;
  
  
  A DB digression
&lt;/h3&gt;

&lt;p&gt;In my variation of the architecture the database is included in acceptance tests. Queries contain business logic. Acceptance tests should capture behaviour since they cover whole features, not just interactions between classes.&lt;/p&gt;

&lt;p&gt;However, notice that the DAO classes have low-level tests. These are similar to unit tests as they focus on small pieces of code with no collaborators. They are not unit tests "by the book" since they use the database. However, they function in the same way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If someone breaks a query (which is likely since queries tend to get complex) we will immediately know where the problem is because the query's test will fail. &lt;/li&gt;
&lt;li&gt;They enable us to test-drive SQL (or whatever query language is used). We could test-drive with a database &amp;amp; an SQL client, but this way we have a test as an executable document that the query does what it's supposed to. Also, some ORM libraries have their own abstractions over SQL and test-driving is only possible this way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conversely, notice that controllers are not covered by acceptance nor unit tests. This is because they don't (shouldn't) contain any business logic. They are glue code and should be tested separately (see last section of this article).&lt;/p&gt;

&lt;h2&gt;
  
  
  Top-down
&lt;/h2&gt;

&lt;p&gt;While designing your software, always remember what type of code constructs are available and which you are focused on currently.&lt;/p&gt;

&lt;p&gt;This architecture is perfect for a top-down development approach. The approach has the least cognitive load (i.e. it takes up smaller head-space).&lt;/p&gt;

&lt;p&gt;For each feature:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write acceptance tests which describe a feature

&lt;ul&gt;
&lt;li&gt;do not focus on a particular class; acceptance tests should be separated from the app's classes by abstraction layers so they can focus on behaviour of the system&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Implement service classes as needed, defining their collaborators &amp;amp; wiring them (piping input &amp;amp; output data between them to get the result)&lt;/li&gt;
&lt;li&gt;Avoid implementing collaborators:

&lt;ul&gt;
&lt;li&gt;externals (adapters, see diagram) should be interfaces or abstract classes to be implemented later&lt;/li&gt;
&lt;li&gt;internals (logic or DAOs) should be implemented with stubs (methods returning dummy data or better yet, throwing "TODO" errors)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Test-drive internals' implementation with unit tests&lt;/li&gt;
&lt;li&gt;Wire the acceptance test to the SUT (System Under Test), that is - the service class

&lt;ul&gt;
&lt;li&gt;write test doubles to implement externals (don't use mocking libs ... another article)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Work on all the pieces until acceptance tests pass&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repeat for next feature and so on.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;very&lt;/em&gt; important principle:&lt;/p&gt;

&lt;h3&gt;
  
  
  What can go down, should
&lt;/h3&gt;

&lt;p&gt;Extract, extract, extract. Whenever you spot a piece of logic, arithmetic or data transformation in the service, try to extract it into a class or function which can then be unit tested.&lt;/p&gt;

&lt;p&gt;The number of execution paths through a service (counting only the service code, not collaborators) should be forced down to a minimum.&lt;/p&gt;

&lt;p&gt;With that we can do this:&lt;/p&gt;

&lt;h3&gt;
  
  
  What can be tested down, should
&lt;/h3&gt;

&lt;p&gt;Code paths going through a service's collaborators should be tested only in unit tests of those collaborators.&lt;/p&gt;

&lt;p&gt;The only thing tested in acceptance tests should be wiring of collaborators.&lt;/p&gt;

&lt;h2&gt;
  
  
  The benefits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Benefit 1: Fast tests
&lt;/h3&gt;

&lt;p&gt;By forcing most of the logic &lt;em&gt;and&lt;/em&gt; testing down into the unit level, we maximise the amount of test coverage done by fast tests. Overall, test-coverage is not lowered but total duration of test execution is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefit 2: Easy refactoring
&lt;/h3&gt;

&lt;p&gt;By not having any tests between the lowest layer of unit tests &amp;amp; the highest layer of acceptance test, we make it easier to refactor services &amp;amp; their usage of collaborators.&lt;/p&gt;

&lt;p&gt;Maybe a service has multiple sub-services which talk to units. Maybe one does and the other doesn't.&lt;/p&gt;

&lt;p&gt;All this is subject to change as the developer's understanding of the system grows but also when the customer's requirements shift &amp;amp; evolve.&lt;/p&gt;

&lt;p&gt;Refactoring is an activity which shouldn't modify functionality, so why should it cause us to modify our functional tests?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lkukdhk4wt481oneo4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lkukdhk4wt481oneo4s.png" alt="Diagram of service &amp;amp; logic classes with separation of benefits" width="707" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The 3rd test layer
&lt;/h2&gt;

&lt;p&gt;Acceptance &amp;amp; unit tests do not cover deployment configuration nor the deployment process itself.&lt;/p&gt;

&lt;p&gt;A 3rd test layer is needed. These tests are end-to-end tests. They are slow &amp;amp; tricky to write, typically testing through a web UI or a public HTTP API.&lt;/p&gt;

&lt;p&gt;The good thing is, we need just a few of them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a33k0n6gfc81h56yse3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a33k0n6gfc81h56yse3.png" alt="Deployed app &amp;amp; configuration points" width="657" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After we deploy our app there are some things we need to verify to be sure everything works. These are marked on the diagram as red dots:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is our app reachable from the outside world?&lt;/li&gt;
&lt;li&gt;Did the deployment process successfully deploy the latest version?&lt;/li&gt;
&lt;li&gt;Are configuration variables set to correct values?

&lt;ul&gt;
&lt;li&gt;Like the ones used for connecting to the database, 3rd party &amp;amp; platform services.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These tests should be written after a new red dot comes up. Since the app should be deployed as soon as possible from the start of the project, end-to-end tests can be added continuously as the system grows.&lt;/p&gt;

&lt;p&gt;They are of course ran against a deployed app on a testing or staging environment, the configuration of which needs to be as close to production as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Emergence
&lt;/h2&gt;

&lt;p&gt;The emerging test pyramid:&lt;/p&gt;

&lt;p&gt;Unit tests: lots of them (counting individual methods, not classes) because we're covering &lt;em&gt;all&lt;/em&gt; possible execution paths through units.&lt;/p&gt;

&lt;p&gt;Acceptance tests: fewer, because we're covering one or two paths through a service&lt;/p&gt;

&lt;p&gt;End-to-end tests: very few because we're covering only points of configuration&lt;/p&gt;

&lt;h2&gt;
  
  
  To be continued
&lt;/h2&gt;

&lt;p&gt;This assumes only one piece of deployed software. What about apps with multiple pieces communicating through APIs? Doesn't that require more end-to-end tests to cover all the API communication?&lt;/p&gt;

&lt;p&gt;No. Use &lt;a href="https://dev.to/mbjelac/frontendbackend-contract-testing-14ki"&gt;API tests&lt;/a&gt; for that.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>bdd</category>
      <category>testing</category>
      <category>agile</category>
    </item>
    <item>
      <title>Engineering vs. crafting</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Thu, 06 Feb 2025 20:16:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/engineering-vs-crafting-393n</link>
      <guid>https://dev.to/mbjelac/engineering-vs-crafting-393n</guid>
      <description>&lt;p&gt;Cover photo by myself - my kids made holiday honey-cookies&lt;/p&gt;




&lt;p&gt;Last year Dave Farley &lt;a href="https://www.youtube.com/watch?v=yHCds5IbKa4" rel="noopener noreferrer"&gt;published a segment&lt;/a&gt; from one of his Engineering room interviews with Emily Bache.&lt;/p&gt;

&lt;p&gt;It was somewhat provocatively titled:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What Is A Software Engineer? | Craftsmanship Movement Was A "Step Backwards"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yet another scenario which goes like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;a minority struggles to become a majority&lt;/li&gt;
&lt;li&gt;everyone else ignores them&lt;/li&gt;
&lt;li&gt;during the struggle the minority fractures and starts bickering amongst themselves, creating several even smaller minorities&lt;/li&gt;
&lt;li&gt;everyone else ignores them even more&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The minority I'm referring to are programmers (i.e. people making and modifying code for a living) who are doing their jobs with the highest level of quality possible. What is quality and what is possible are topics for themselves but this is the gist.&lt;/p&gt;

&lt;p&gt;The programming-as-craft concept was more or less completely described a while ago by Bob Martin's post &lt;a href="https://blog.cleancoder.com/uncle-bob/2011/01/17/software-craftsmanship-is-about.html" rel="noopener noreferrer"&gt;What Software Craftsmanship is about&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dave's approach is that software engineering is not craft because it brings something else to the discipline. I have not figured out what. Software-as-craft does not imply the absence of TDD, BDD, continuous integration, deployment, delivery or any other "engineering-like" practice.&lt;/p&gt;

&lt;p&gt;To take a step backwards (or rather, tilt our heads), what is art?&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://en.wiktionary.org/wiki/art" rel="noopener noreferrer"&gt;multiple definitions&lt;/a&gt;. Among those listed I think this one is closest to the context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(countable) Skillful creative activity, usually with an aesthetic focus.&lt;br&gt;
&lt;em&gt;She's mastered the art of programming.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The examples gives it away I admit - programming &lt;em&gt;can be&lt;/em&gt; art.&lt;/p&gt;

&lt;p&gt;So can engineering.&lt;/p&gt;

&lt;p&gt;This is surely art:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6bh93rczrbou26v4928.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6bh93rczrbou26v4928.jpg" alt="Vincent Van Gogh: Café Terrace at Night, 1888. COURTESY WIKIMEDIA COMMONS" width="391" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm sure most people will agree that this is also art:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aavn16f6im9nw5433u6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aavn16f6im9nw5433u6.jpg" alt="Chrysler Building spire, Manhattan, by Carol Highsmith" width="263" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, there is a huge difference. Buildings also have a type of art seldom visible to most people. The building's structure &amp;amp; infrastructure are very complex feats of engineering. They required a lot of thought, planning, collaboration &amp;amp; quality of work which can be thought of as huge pieces of art. They are even more magnificent than a painting (or an architect's drawing) because they involve hard work &amp;amp; skill invested by a lot of individuals. My point is, categories are often fuzzy.&lt;/p&gt;

&lt;p&gt;Programming &lt;em&gt;can be&lt;/em&gt; art.&lt;/p&gt;

&lt;p&gt;Programming &lt;em&gt;can be&lt;/em&gt; craft.&lt;/p&gt;

&lt;p&gt;Programming &lt;em&gt;can be&lt;/em&gt; engineering.&lt;/p&gt;

&lt;p&gt;Programming can also be &lt;em&gt;none&lt;/em&gt; of the above. It can be a sloppy mess.&lt;/p&gt;

&lt;p&gt;The important thing is that today most of programming is neither art nor craft nor engineering. It is a sloppy mess, hastily put together to meet a deadline and to make money quickly (mostly not going to the programmers themselves).&lt;/p&gt;

&lt;p&gt;Here is a helpful diagram to paint the picture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcbevb9r9491oxuguytw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcbevb9r9491oxuguytw.png" alt="Types of code vs. number of developers categorized by developer type; demonstrating the irrelevance of distinguishing between software crafters &amp;amp; engineers" width="569" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of bickering about esoteric categories, we should put our energy and imagination to work on how to reduce the number of slop-pushers and increase the number of crafters &lt;em&gt;and&lt;/em&gt; engineers.&lt;/p&gt;

</description>
      <category>navelgazing</category>
      <category>agile</category>
      <category>tdd</category>
    </item>
    <item>
      <title>SoCraTes UK 2024</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Wed, 25 Sep 2024 08:13:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/socrates-uk-2024-1d9m</link>
      <guid>https://dev.to/mbjelac/socrates-uk-2024-1d9m</guid>
      <description>&lt;p&gt;My colleague Ivana &amp;amp; I went to &lt;a href="https://socratesuk.org/" rel="noopener noreferrer"&gt;SoCraTes UK&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;This is an &lt;strong&gt;&lt;em&gt;un&lt;/em&gt;&lt;/strong&gt;conference, meaning almost all things are &lt;strong&gt;&lt;em&gt;un&lt;/em&gt;&lt;/strong&gt;like regular developer conferences.&lt;/p&gt;

&lt;p&gt;But what &lt;em&gt;is&lt;/em&gt; an unconference?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no schedule (up front)&lt;/li&gt;
&lt;li&gt;There are no talks (there is talking though)&lt;/li&gt;
&lt;li&gt;The amount of interaction with everyone there is &lt;em&gt;through the roof&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here we go…&lt;/p&gt;

&lt;h2&gt;
  
  
  Glowing hula hoops
&lt;/h2&gt;

&lt;p&gt;Before we leave for England, I browse the &lt;a href="https://github.com/SoCraTesUK/socrates-uk/wiki" rel="noopener noreferrer"&gt;unconference github wiki pages&lt;/a&gt; and in the Arrivals page I spot a person named Corinna saying she is coming to London and would someone join her for the train &amp;amp; taxi ride to the event. I contact her through Slack, and the 3 of us meet in London &amp;amp; grab lunch together, after which we proceed to the unconference by train &amp;amp; taxi. We get to know each other &amp;amp; talk about our geeky stuff but also various other things.&lt;/p&gt;

&lt;p&gt;In other words - we start the unconference even before we get there! 👍&lt;/p&gt;

&lt;p&gt;The first day is informal. It’s a chance for introducing yourself, meeting people &amp;amp; chatting.&lt;/p&gt;

&lt;p&gt;The unconference attendees are very diverse, but everyone is at ease and open to conversation. After the first dinner, Mervi performs a dance with glowing hula hoops for just a couple of us on a whim. Here is a trimmed video:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/1012357923" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The diversity of the attendants is not a hindrance. It is rather the opposite - it brings richness &amp;amp; depth to the unconference because it is contrasted with a shared interest for software craft (and testing). In short, the interest for producing high-quality code and how to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open space
&lt;/h2&gt;

&lt;p&gt;On Friday morning we attend the unconference opening session. We are (re)introduced to &lt;a href="https://openspaceworld.org/wp2/what-is/" rel="noopener noreferrer"&gt;Open Space technology&lt;/a&gt;. In short, it is a set of guidelines designed to create environments which encourage collaboration.&lt;/p&gt;

&lt;p&gt;It starts with a “marketplace” where anyone who wants takes a big-format post-it and writes a topic and their name on it. The topic can be something they know about or something they want to know about. Then all the people who have written a topic stand in line and one by one shortly explain to the crowd what the topic is about.&lt;/p&gt;

&lt;p&gt;After you have explained your topic, you go to the adjacent room and you paste the post-it on the wall with a location-time grid so everyone knows where &amp;amp; when the topic will be discussed. This proves to be tricky for me because I don’t want to paste my topic at the same time of another topic that is interesting to me. But time &amp;amp; space are constrained so you have to make some decision here.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2scrfykzdv3crl9uahf.jpeg" alt="Friday sessions" width="800" height="600"&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxi5am8sh2ursk3p01ar.jpeg" alt="Saturday sessions" width="800" height="600"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Friday sessions&lt;/td&gt;
&lt;td&gt;Saturday sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you have more topics, you move to the end of the line and on your next turn explain your next topic and so on.&lt;/p&gt;

&lt;p&gt;At the end of each day there we reflect on the day’s sessions. This is again done in groups where each group discusses where they have been and what they have learned. Mingling among groups is encouraged in the same way as for all the other discussions.&lt;/p&gt;

&lt;p&gt;These reflection sessions are a great idea because I find out what has been going on in the sessions I missed, I get to talk to people I haven't had a chance to talk to yet and they relax the crowd after the wind-up of the day, just in time for dinner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sessions
&lt;/h2&gt;

&lt;p&gt;Here are descriptions of most of the sessions I attended.&lt;/p&gt;

&lt;h3&gt;
  
  
  Confidence in Software Engineers
&lt;/h3&gt;

&lt;p&gt;Confidence is a complex topic. We do a lot of unpacking.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confidence in presentation: not having the ability to speak or present your ideas with confidence, although you are confident in them&lt;/li&gt;
&lt;li&gt;Confidence in execution: not having the ability to decide which way to go as you are not certain where you will end up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A feedback like “You have low confidence” is counter-productive and will lower the dev’s confidence even more. Be supportive &amp;amp; see who needs to change the most - the dev or her environment?&lt;/p&gt;

&lt;p&gt;Also with gender taken into account, women usually appear less confident than men simply because men will “fake it until you make it”, having no problem to say they know something when they only heard a term once, while women will be honest about their experience. So, should women also fake it until they make it or should men stop doing that?&lt;/p&gt;

&lt;p&gt;Another interesting perspective is that we value existing experience more than the ability to learn. The former is easier to measure, but the latter is much more important.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problematic XP Practices
&lt;/h3&gt;

&lt;p&gt;The central theme of the session is a list of contentious (often argued about) XP practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trunk-based development&lt;/li&gt;
&lt;li&gt;pairing&lt;/li&gt;
&lt;li&gt;monorepos&lt;/li&gt;
&lt;li&gt;no estimates&lt;/li&gt;
&lt;li&gt;no projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately (for me) most of the time was spent on discussing monorepos &amp;amp; no estimates. This depends on the crowd - that’s how Open space works.&lt;/p&gt;

&lt;p&gt;I was most interested in the “no projects” topic. The gist is that this doesn’t mean projects should not be used at all. It means that developers shouldn’t set project-related goals, but instead should focus on the product. The product is much more important, while the project is just one of the tools to help product delivery.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you do BDD?
&lt;/h3&gt;

&lt;p&gt;I suggest this topic in the morning. I hope I can gather various experiences and distill what are the core practices which make good BDD workflows.&lt;/p&gt;

&lt;p&gt;This turns out to be one of the best knowledge exchanges I have ever participated in, as both Seb Rose &amp;amp; Nat Pryce 😍 join in and cut through the less-relevant stuff like tooling &amp;amp; syntax to the core of what is BDD. I try to capture it on a flipchart and annotate it that evening:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8dix0eodmm5lj0i2l29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8dix0eodmm5lj0i2l29.png" alt="My " width="500" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also my &lt;a href="https://github.com/SoCraTesUK/socrates-uk/wiki/2024-Sessions#how-do-you-use-bdd" rel="noopener noreferrer"&gt;notes&lt;/a&gt; from the session on the unconference github wiki.&lt;/p&gt;

&lt;h3&gt;
  
  
  Android Java Mobbing
&lt;/h3&gt;

&lt;p&gt;After all these “heavy thinking” sessions it is a bit refreshing to participate in a technical hands-on session. Anita has started building a chess game for Android in Java and she wants help with cleaning up the code.&lt;/p&gt;

&lt;p&gt;We help her convert it to Kotlin, fix the build configuration &amp;amp; start on refactoring the code.&lt;/p&gt;

&lt;p&gt;Stuff left for later is replacing the current presentation library with Jetpack Compose, and also separating game logic from presentation logic so it can be thoroughly covered with tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote XP
&lt;/h3&gt;

&lt;p&gt;In this group we discuss how XP practices transfer to remote work.&lt;/p&gt;

&lt;p&gt;XP has traditionally been designed around physical presence of all people required to do the work, so this is sometimes challenging when none of the people are in the office.&lt;/p&gt;

&lt;p&gt;The discussions are in-depth so we only have time to cover 2 XP practices (informative workspace &amp;amp; sit together), but I remember these suggestions for remote XP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The team dashboard will not be visible at all times (everyone having an extra monitor is complicated) so some alerting system can be put in place (Slack was proposed) so that everyone in the team knows when to look at the dashboard to see what has changed

&lt;ul&gt;
&lt;li&gt;The team dashboard traditionally displays the current build status, but also any other information important to the current project&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;For solo work, a whole-day video call can be set up to which all solo workers connect. Although they do solo stuff, they can easily just ask anyone for help. The problem of spacial audio (you want to overhear a conversation, but not listen to it as you would in a normal call) software was proposed like Gather Town.

&lt;ul&gt;
&lt;li&gt;I raised the problem of headsets being too hard on your ears if worn all the time. The response was that you should use the laptop’s speakers &amp;amp; microphone (even if it has less quality).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  BDD reboot
&lt;/h3&gt;

&lt;p&gt;This was a session organised by Seb Rose. It helped me put together all the bits &amp;amp; pieces I gathered from the previous BDD session but also from the last decade of my searching for a working BDD workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrszeqijy72o6oef8tpu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrszeqijy72o6oef8tpu.jpg" alt="BDD workflow" width="800" height="1062"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am pleasantly surprised to find out my team was almost on the correct path. We will try out some improvements though.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing UI components
&lt;/h3&gt;

&lt;p&gt;Esko showed us how his team test-drives UI components. The approach is quite different than what I've used but the environments (client, requirements, etc.) are different so it’s hard to say whether our approach is really better. However, we do have interesting discussions about testing in general.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example mapping
&lt;/h3&gt;

&lt;p&gt;This is a workshop to plug the last holes in my understanding of practical BDD. It does not go as well as I expect, but still I’m glad to have tried it. Besides, I bought books on BDD in the morning, one of which explains example mapping so I’m confident I can pick it up from there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://leanpub.com/b/bddbooks" rel="noopener noreferrer"&gt;The books are available on Leanpub.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Impact mapping
&lt;/h3&gt;

&lt;p&gt;I suggested an Impact mapping session hoping several people were going to show us how it works in the real world. Alas, only one person from the assembled group did it 5 years ago. Nevertheless, they proceed to explain it to the whole group. I was surprised more people didn’t hear about it before but also at so many people attending the session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Me showcasing my hobby project
&lt;/h3&gt;

&lt;p&gt;A fun session happens when I offer to showcase my hobby project. It’s made using TDD &amp;amp; it’s a game. Both of these things cause interest, and I get some good feedback about the game and my artwork.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software ball ⚽
&lt;/h3&gt;

&lt;p&gt;This was planned for Friday morning but ended up being moved to Saturday. This was great because I would have missed it otherwise.&lt;/p&gt;

&lt;p&gt;This is a very geeky ball game where participants throw a ball to each other representing execution of a program. The participants and the game facilitator try to agree on a set of instructions for each participant (a “node”) so the ball will travel according to the specifications with as few instructions as possible.&lt;/p&gt;

&lt;p&gt;I liked it very much as it’s both fun, challenging &amp;amp; encourages physical activity in the open.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other sessions
&lt;/h3&gt;

&lt;p&gt;Time-space constraints being what they are on Earth, I missed most of the sessions. However it was clear that the session topics were very diverse. From autism &amp;amp; imposter syndrome through clean code practices all the way to specific hands-on tinkering with Excel, Bash, build scripts etc.&lt;/p&gt;

&lt;p&gt;There were also many other discussions during meals, walks, drinks &amp;amp; evening board games. We were talking to each other a lot, since we were all together from 8-9 in the morning until midnight or even later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dyj21r3yegr0grqxor9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dyj21r3yegr0grqxor9.jpg" alt="TDD board game" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Playing TDD, the board game. Yes, it was very late. 😜&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterglow
&lt;/h2&gt;

&lt;p&gt;During the unconference retrospective Mervi thought of the term &lt;em&gt;afterglow&lt;/em&gt; to describe our state after the unconference due to the fond memories we created together.&lt;/p&gt;

&lt;p&gt;In the days &amp;amp; weeks following the unconference I’m sure I’ll be buzzing with ideas &amp;amp; thoughts.&lt;/p&gt;

&lt;p&gt;However, I think I will also be reflecting on the experience of the interactions I had, the kindness, curiosity, inclusivity &amp;amp; warmth. &lt;/p&gt;

&lt;p&gt;I am deeply grateful to all participants. Thank you for the afterglow! ❤️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hk7yjid3gaquu65ko2b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hk7yjid3gaquu65ko2b.jpg" alt="SoCraTes UK 2024 group photo" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>conference</category>
      <category>unconference</category>
      <category>craft</category>
    </item>
    <item>
      <title>TDD is cheaper</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Thu, 11 Jan 2024 23:47:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/tdd-is-cheaper-3i6a</link>
      <guid>https://dev.to/mbjelac/tdd-is-cheaper-3i6a</guid>
      <description>&lt;p&gt;Cover image: Scene from Modern Family, Phil: "Slow is smooth &amp;amp; smooth is fast!"&lt;/p&gt;

&lt;p&gt;Tim Ottinger posted this article: &lt;a href="https://www.industriallogic.com/blog/do-they-hate-writing-tests/" rel="noopener noreferrer"&gt;Do They Hate Writing Tests?&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As always, concise &amp;amp; to the point. I had the same experience with all 3 types of code: Old legacy, new legacy &amp;amp; test-driven.&lt;/p&gt;

&lt;p&gt;What I found very revealing in the article is this list of new-legacy activities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write a bunch of code (being very careful, of course)&lt;/li&gt;
&lt;li&gt;Edit it until it will compile.&lt;/li&gt;
&lt;li&gt;Debug it until it gets the right answers.&lt;/li&gt;
&lt;li&gt;Look it over for other errors and correct them.&lt;/li&gt;
&lt;li&gt;Send it off to code review&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is what I think the TDD list of activities looks like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test-drive the code (no need to be careful, tests watch your back)&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Edit it until it will compile.&lt;/del&gt; &lt;em&gt;for TDD-ers working in compiled languages, compile fail is a failing test, so we don't have more than one line compile failures and we fix it immediately&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Debug it until it gets the right answers.&lt;/del&gt; &lt;em&gt;we test-drive, so bugs are few and far between (like, maybe 1 per month or less)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Look it over for other errors and correct them.&lt;/del&gt; &lt;em&gt;no need no errors - all tests ever written are run often (faster ones more often) so nothing is broken for more than a couple of minutes&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Send it off to code review &lt;em&gt;... sure, we can do that (but check out &lt;a href="https://martinfowler.com/bliki/RefinementCodeReview.html" rel="noopener noreferrer"&gt;Refinement Code Review&lt;/a&gt; by Martin Fowler)&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ah, sorry, I'll remove the superfluous items:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test-drive the code&lt;/li&gt;
&lt;li&gt;Send it off to code review&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hmmm, this list seems smaller than the new-legacy list. Could it be that &lt;del&gt;writing code using TDD&lt;/del&gt; designing your system driven by tests is more efficient, thus cheaper? Remember, the most expensive thing in IT is the developer hour.&lt;/p&gt;

&lt;p&gt;I've heard first-hand accounts of TDD projects being FOUR (4) times as efficient as non-TDD projects.&lt;/p&gt;

&lt;p&gt;Granted, TDD takes practice, but doesn't everything?&lt;/p&gt;

</description>
      <category>tdd</category>
    </item>
    <item>
      <title>Github Actions output to if expression</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Tue, 19 Dec 2023 22:55:02 +0000</pubDate>
      <link>https://dev.to/mbjelac/github-action-output-to-if-expression-and-how-to-test-it-531i</link>
      <guid>https://dev.to/mbjelac/github-action-output-to-if-expression-and-how-to-test-it-531i</guid>
      <description>&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@wimarys?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Wim Arys&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-very-large-group-of-stone-structures-in-a-park-gDlpMyInsak?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I wanted a CI pipeline job to fail if some numeric output was larger than 0.&lt;/p&gt;

&lt;p&gt;The pipeline is set up in Github Actions and the job has a step which has a numeric output. I just had to give an &lt;code&gt;id&lt;/code&gt; to the step to be able to reference it's outputs with Github Action contexts like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;${{ steps.stepId.outputs.outputName }}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The next step would check the output value, compare it to 0 and &lt;code&gt;exit 1&lt;/code&gt; if it is larger. Then I remembered steps (as well as jobs) have an &lt;code&gt;if&lt;/code&gt; section which takes in an expression. I knowe you no longer have to put &lt;code&gt;${{&lt;/code&gt; &amp;amp; &lt;code&gt;}}&lt;/code&gt; around the expression but I wasn't sure if it would work simply like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if: steps.myStep.outputs.myOutput &amp;gt; 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When I'm not sure of something, I like to test it. I often test pieces of Github Actions by making a new workflow, pushing it to &lt;code&gt;master&lt;/code&gt; and trying it out on Github.&lt;/p&gt;

&lt;p&gt;Here is my workflow for testing how can a job's step output be used in an &lt;code&gt;if&lt;/code&gt; expression of a subsequent step:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;I wanted to test it with different values so I used &lt;code&gt;workflow_dispatch&lt;/code&gt;'s inputs to give my workflow a custom parameter for testing.&lt;/p&gt;

&lt;p&gt;I ran the workflow with several numbers and confirmed it works.&lt;/p&gt;

&lt;p&gt;I also found &lt;a href="https://github.com/orgs/community/discussions/25871" rel="noopener noreferrer"&gt;the answer&lt;/a&gt; on the Github forum, but it would have been nice if Github Actions documentation had some easy-to-reach example for this.&lt;/p&gt;

&lt;p&gt;I could have also probably gotten the answer even faster from an LLM prompt.&lt;/p&gt;

&lt;p&gt;In any case, it is nice to be able to test your code, wherever you got it from.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Edit:&lt;/em&gt; When you have your test workflow, no need to push it to &lt;code&gt;master&lt;/code&gt; &amp;amp; test it on Github. You can use &lt;a href="https://github.com/nektos/act?tab=readme-ov-file#overview----" rel="noopener noreferrer"&gt;act&lt;/a&gt; to test Github Action workflows locally.&lt;/p&gt;

</description>
      <category>ci</category>
    </item>
    <item>
      <title>JS Date: The Timezone Tantrum</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Mon, 13 Nov 2023 22:44:44 +0000</pubDate>
      <link>https://dev.to/mbjelac/js-date-the-timezone-tantrum-nji</link>
      <guid>https://dev.to/mbjelac/js-date-the-timezone-tantrum-nji</guid>
      <description>&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@lucian_alexe?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Lucian Alexe&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/brown-wooden-framed-analog-clock-f2xfTOv0p9Y?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;We had a subtle bug in our UI code which involved the wrong time offset being applied when date &amp;amp; time were input around the DST change.&lt;/p&gt;

&lt;p&gt;Without going into the ghastly details, the underlying cause was we used the dreaded &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date" rel="noopener noreferrer"&gt;JS Date&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In our defence, we &lt;em&gt;had&lt;/em&gt; to use it as it was the output type from a 3rd party widget.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://softwaresauna.com/" rel="noopener noreferrer"&gt;Software Sauna&lt;/a&gt;, we like to test stuff. Much more than that, we like to test stuff &lt;em&gt;in isolation&lt;/em&gt;. We believed we tested our component in isolation, until we learned that &lt;a href="https://stackoverflow.com/a/15171030/1093343" rel="noopener noreferrer"&gt;JS Date is coupled to the OS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5waiwh0sk0esaykjs84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5waiwh0sk0esaykjs84.png" alt="Isolated component test &amp;amp; test with Date breaking the isolation" width="580" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could control the DST flip by setting the test's input time to the appropriate time of year (summer/winter). However we couldn't control the timezone. We had to adjust the expected data &lt;em&gt;in the test&lt;/em&gt; 🤢 using the same library which the production code used (&lt;a href="https://momentjs.com/" rel="noopener noreferrer"&gt;momentjs&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;How would it work on CI? - we asked ourselves. Well, even better, CI is always on UTC so it wouldn't be bothered with it.&lt;/p&gt;

&lt;p&gt;After some thought we concluded this was a &lt;strong&gt;bad thing&lt;/strong&gt;. If users' &lt;em&gt;browsers&lt;/em&gt; were in a timezone, so should the UI tests!&lt;/p&gt;

&lt;p&gt;We needed to set the timezone to our UI test CI job!&lt;/p&gt;

&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;p&gt;Thankfully, since we use &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;Github actions&lt;/a&gt; for CI this was just a matter of finding an action that suited us.&lt;/p&gt;

&lt;p&gt;We set up Sze Ying's action &lt;a href="https://github.com/szenius/set-timezone" rel="noopener noreferrer"&gt;set-timezone&lt;/a&gt; and that's it!&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; Only the UI/frontend tests job should have this. Your server should be in UTC and so should the backend tests job.&lt;/p&gt;

</description>
      <category>date</category>
      <category>time</category>
      <category>javascript</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Frontend/backend contract testing</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Fri, 10 Nov 2023 09:00:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/frontendbackend-contract-testing-14ki</link>
      <guid>https://dev.to/mbjelac/frontendbackend-contract-testing-14ki</guid>
      <description>&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@othentikisra?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;israel palacio&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/two-square-blue-led-lights-ImcUkZ72oUs?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Contract testing is a known concept. It is nicely described in the &lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html#ContractTests" rel="noopener noreferrer"&gt;Contract Tests&lt;/a&gt; section of the excellent article "The Practical Test Pyramid" by &lt;a href="https://www.hamvocke.com/" rel="noopener noreferrer"&gt;Ham Vocke&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Takeaway points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test consumer &amp;amp; producer &lt;em&gt;together&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Test &lt;em&gt;only&lt;/em&gt; the contract layers, without the behaviour of either the consumer or producer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At &lt;a href="https://softwaresauna.com/" rel="noopener noreferrer"&gt;Software Sauna&lt;/a&gt; we developed a similar approach, albeit with some modifications to fit our own flow of developing web apps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We do not test on the HTTP layer - tests interact with a domain-specific layer which hides the data transport infrastructure (here called &lt;em&gt;API functions&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;We do not setup test-double behaviour on the producer side. Rather, we expose test utility endpoints and drive test double behaviour from tests directly so both input &amp;amp; expected data are visible in test.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The web app
&lt;/h2&gt;

&lt;p&gt;Software Sauna predominantly produces web apps &amp;amp; not distributed systems, so most of contracts we deal with are those between the web UI usually called &lt;em&gt;frontend&lt;/em&gt; &amp;amp; the behaviour &amp;amp; busines logic of the app usually called &lt;em&gt;backend&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The frontend communicates with the backend by sending HTTP requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4bgbugveifbgn4f9g4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4bgbugveifbgn4f9g4i.png" alt="Frontend -&amp;gt; HTTP -&amp;gt; Backend" width="459" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We want readable &amp;amp; maintainable code, so we slice our frontend &amp;amp; backend codebases into abstraction layers. This results in &lt;em&gt;&lt;a href="https://wiki.c2.com/?SoftwareSeam" rel="noopener noreferrer"&gt;seams&lt;/a&gt;&lt;/em&gt; throughout the codebases, enabling us to have tests on relevant scopes.&lt;/p&gt;

&lt;p&gt;One such seam is between code that implements behaviour (does stuff) &amp;amp; code that deals with HTTP communication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp1ocdetrr8309bfnirl0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp1ocdetrr8309bfnirl0.png" alt="Seams in frontend &amp;amp; backend codebases" width="602" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can look at the frontend's API-related layer, the HTTP channel &amp;amp; backend's API-related layer as a single component - the &lt;em&gt;contract&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5aw05xqd77vfj4e5pjdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5aw05xqd77vfj4e5pjdy.png" alt="Frontend logic -&amp;gt; Contract -&amp;gt; Backend logic" width="416" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The contract has one responsibility, that is to transfer data from frontend to backend &amp;amp; back.&lt;/p&gt;

&lt;p&gt;However, other things related to this communication are also part of it, like authentication, authorisation, throttling, etc.&lt;/p&gt;

&lt;p&gt;Here is an example of a web app stack with the contract components in more detail:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rbtk3wb5l1mvsrsw38t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rbtk3wb5l1mvsrsw38t.png" alt="Web app stack with marked scope of API tests" width="651" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To test the contract, we just replace the frontend &amp;amp; backend behaviours with tests &amp;amp; &lt;a href="https://martinfowler.com/bliki/TestDouble.html" rel="noopener noreferrer"&gt;test doubles&lt;/a&gt;, respectively:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i6kuk8hdqwkug16ne6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i6kuk8hdqwkug16ne6u.png" alt="Frontend test -&amp;gt; Contract -&amp;gt; Backend test double" width="412" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example test
&lt;/h2&gt;

&lt;p&gt;Every API test has two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Frontend test&lt;/li&gt;
&lt;li&gt;Backend test double replacing the actual service&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The test in the example tests the API function &lt;code&gt;getUsers()&lt;/code&gt;, which will be called by components who want to display a list of the system's users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Line 9:&lt;/em&gt; Log in as a specific user. This tests both frontend &amp;amp; backend authentication implementation &amp;amp; config. It is practical to create a single dummy user for each user role in the app.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Line 16:&lt;/em&gt; Stub the method labelled &lt;code&gt;get-users&lt;/code&gt; with some test data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Line 18:&lt;/em&gt; Call the API function which should result in a method call to the appropriate backend service (actually test double).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Line 20:&lt;/em&gt; Assert that the stubbed data is returned from the API function.&lt;/p&gt;

&lt;p&gt;There is also an example of an unauthorised call to show that we can test the backend's authorisation config.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test double
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This example uses Spring to auto-wire services (actually, their test doubles) into the DI context.&lt;/p&gt;

&lt;p&gt;The method labels (as string parameters in the &lt;code&gt;withMethod&lt;/code&gt; calls) have to match string parameters in frontend-side calls to &lt;code&gt;setStubbing&lt;/code&gt; &amp;amp; &lt;code&gt;failWith&lt;/code&gt;. If they don't, the tests will fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spying
&lt;/h2&gt;

&lt;p&gt;Sometimes we want to know if the desired arguments were passed to the backend method.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Our backend test double acts both as a stub and a spy, enabling the frontend test to check returned values &amp;amp; also check that the correct arguments were sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other stuff
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testing error handling
&lt;/h3&gt;

&lt;p&gt;Similar to stubbing values, we can tell the backend test double that a method should fail. This allows us to test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;backend mapping of failures (i.e. exceptions) to HTTP error responses&lt;/li&gt;
&lt;li&gt;frontend handling of errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Part of error handling was already shown in the example for unauthorised calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test-driving the API layer
&lt;/h3&gt;

&lt;p&gt;This approach allows the API layers to be implemented within a TDD workflow.&lt;/p&gt;

&lt;p&gt;We test-drive a UI component. The component requires data from the backend. As this is crossing the seam, we test-drive the implementation using a test double to replace the API function.&lt;/p&gt;

&lt;p&gt;That test double defines the API function signature.&lt;/p&gt;

&lt;p&gt;Then we can test-drive the API function itself, by providing a test-double on the backend side, which in turn defines the service method signature.&lt;/p&gt;

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

&lt;p&gt;During our usage of this pattern in Software Sauna, we have found that it completely eliminates common errors like request/response structure definition discrepancies, but also harder to find errors buried in URL path &amp;amp; header definitions, error handling, authentication &amp;amp; authorisation setup.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>contracttesting</category>
    </item>
    <item>
      <title>Give me 0.5x developers or give me death!</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Sat, 11 Feb 2023 23:36:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/give-me-05x-developers-or-give-me-death-31h0</link>
      <guid>https://dev.to/mbjelac/give-me-05x-developers-or-give-me-death-31h0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Slow is smooth &amp;amp; smooth is fast.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How does one become a 10x developer?
&lt;/h2&gt;

&lt;p&gt;Here's &lt;del&gt;my opinion&lt;/del&gt; the Truth:&lt;/p&gt;

&lt;p&gt;Mikey is a 10x developer. Mikey is that guy who started the project. He knows every little detail, architecture decision &amp;amp; helper method. The entire codebase fits in his head. He started in Heaven, i.e. working alone. Unfortunately software is too big these days &amp;amp; time is money so his boss hired more developers. To work on HIS code. Mikey is trying his best to hold the code together, gatekeeping left &amp;amp; right (he's &lt;em&gt;the&lt;/em&gt; pull request reviewer), making sure his vision is kept pristine &amp;amp; unsoiled. The other developers can't onboard as fast as the boss wants. They don't know their way around the code nearly as well as Mikey does. The boss says Mikey's churning out 10 times more stuff than them. They're helping but thank goodness we have Mikey on board - a 10x developer who is saving this project.&lt;/p&gt;

&lt;p&gt;This is a myth. Mikey &lt;em&gt;appears&lt;/em&gt; fast because he started the project, or has been so long on it he might as well been there from the start. Mikey takes shortcuts. Mikey rushes stuff. This makes him appear even faster. However, this is only good if you want to keep Mikey as the single developer on the project. New people take time to get acquainted with the code, with Mikey's decisions, patterns &amp;amp; conventions. Worse, since Mikey took many shortcuts, the codebase is convoluted &amp;amp; unreadable. There are no tests. Mikey refactors seldom if ever ("Gotta churn out those features!", "Have no time to clean up now, I can always do it later..."). Other developers either take their time putting things in order, writing tests &amp;amp; refactoring, or don't take time for this, instead trying to churn out features, breaking things &amp;amp; fixing them - taking even more time.&lt;/p&gt;

&lt;p&gt;In reality, Mikey is probably as good as any other developer (all of us are) not better or worse. Churning out rushed code alone for a long time warps Mikey's mind &amp;amp; he becomes stuck to his codebase, thinking this is the best there can be. Mikey develops a blind spot and can't see he's slowing down. Mikey is slowing down because he's breaking stuff all the time, or having trouble putting in features which use existing code (often just copy-pasting the code &amp;amp; modifying that).&lt;/p&gt;

&lt;p&gt;The charade breaks down when you put Mikey on a different project or confront him with lack of built-in quality in "his" project.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what to do?
&lt;/h2&gt;

&lt;p&gt;How do we develop software without getting caught in a code quagmire?&lt;/p&gt;

&lt;p&gt;The solution is absurd: 0.5x developers&lt;/p&gt;

&lt;p&gt;These guys are 2 times &lt;em&gt;slower&lt;/em&gt;! How's that gonna help?&lt;/p&gt;

&lt;p&gt;Well, they're slower because for every line of feature code they write, 3 lines of test code goes in. For every 5 minutes of typing, another 5 minutes goes into discussion with their team mates.&lt;/p&gt;

&lt;p&gt;They squander engineer hours (i.e. the client's money) on setting up continuous delivery pipelines, architecture &amp;amp; test patterns, attending exploration testing sessions, writing acceptance tests before the first line of feature code is even written &amp;amp; insane stuff like that.&lt;/p&gt;

&lt;p&gt;They're slower. Because they take the time to make their work smooth. Which in turn makes them faster.&lt;/p&gt;

&lt;p&gt;For every test not written, skipped refactoring or good practice ignored, there is an undeterminable length of time waiting silently in some dark corner of the project's uncertain future. Time spent in debugging, reworking existing code or just plain bashing one's head against the desk.&lt;/p&gt;

&lt;p&gt;No, I say give me &lt;em&gt;half&lt;/em&gt;-x developers. They're faster.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>tdd</category>
      <category>bdd</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Proud to be a Grug</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Wed, 04 Jan 2023 00:36:00 +0000</pubDate>
      <link>https://dev.to/mbjelac/proud-to-be-a-grug-4fc0</link>
      <guid>https://dev.to/mbjelac/proud-to-be-a-grug-4fc0</guid>
      <description>&lt;p&gt;This is a review of an article (calling itself a guide, or is it a manifesto?): &lt;a href="https://grugbrain.dev/" rel="noopener noreferrer"&gt;The Grug Brained Developer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First off, I agree with a staggering majority of statements!  &lt;/p&gt;

&lt;p&gt;Also I highly applaud it's writing style (hello &lt;a href="https://en.wikipedia.org/wiki/Pygmy_(novel)" rel="noopener noreferrer"&gt;Pygmy&lt;/a&gt;) - the broken, stripped-down 1sentence=1paragraph English makes it strangely more readable than most IT texts (or maybe it's very late).&lt;/p&gt;

&lt;p&gt;I broke this down into three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;✅ I like 100% for things which ... I like 100% with short explanations why&lt;/li&gt;
&lt;li&gt;🤷 Neither here nor there for things which I think the author didn't clearly state their position on or possibly I didn't understand it&lt;/li&gt;
&lt;li&gt;🫤 not 100% for mixed stuff which I have serious doubts about and I dig into it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's go.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ I like 100%
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-complexity" rel="noopener noreferrer"&gt;Complexity&lt;/a&gt; in no unclear terms asserts that "complexity spirit demon" is bad. That's it. 100% correct. No point in musing about accidental vs. intentional complexity. It's all bad.&lt;/p&gt;

&lt;p&gt;Saying &lt;a href="https://grugbrain.dev/#grug-on-saying-no" rel="noopener noreferrer"&gt;No&lt;/a&gt; &amp;amp; &lt;a href="https://grugbrain.dev/#grug-on-saying-ok" rel="noopener noreferrer"&gt;OK&lt;/a&gt; are very nice descriptions of the ideal &amp;amp; realistic tools to handle the complexity problem. I like the 80/20 (although don't take the numbers seriously) rule &amp;amp; especially not dumping the &lt;em&gt;entire&lt;/em&gt; truth on non-techies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-factring-your-code" rel="noopener noreferrer"&gt;Factoring&lt;/a&gt;, aside from the nice touch of accuracy in calling it factoring without the superfluous re, has very valuable advice in not taking it too far - you don't yet know in what direction the code will go and you're in danger of factoring yourself out of readability.&lt;/p&gt;

&lt;p&gt;Similarly &lt;a href="https://grugbrain.dev/#grug-on-refactoring" rel="noopener noreferrer"&gt;Refactoring&lt;/a&gt; and &lt;a href="https://grugbrain.dev/#grug-on-chestertons-fence" rel="noopener noreferrer"&gt;Chesterton&lt;/a&gt; are very nice, although I have a feeling the author separated "factoring" &amp;amp; "refactoring" to two pretty different contexts (improving code locally &amp;amp; globally, respectively) the examples (J2EE &amp;amp; OSGi) &amp;amp; advice are dead-on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-microservices" rel="noopener noreferrer"&gt;Microservices&lt;/a&gt; tells it succinctly, reminding me of the question: If you can't factor your codebase properly, what makes you think putting network calls in the mix will improve things?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-type-systems" rel="noopener noreferrer"&gt;Type systems&lt;/a&gt; section is a nice warning to not go too far with them. We're not researching new branches of maths here, we're trying to build software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-dry" rel="noopener noreferrer"&gt;DRY&lt;/a&gt; is explained very well, also &lt;a href="https://grugbrain.dev/#grug-on-closures" rel="noopener noreferrer"&gt;closures&lt;/a&gt;, &lt;a href="https://grugbrain.dev/#grug-on-concurrency" rel="noopener noreferrer"&gt;concurrency&lt;/a&gt; &amp;amp; &lt;a href="https://grugbrain.dev/#grug-on-optimizing" rel="noopener noreferrer"&gt;optimising&lt;/a&gt;, all of which are aspects of tackling complexity which can get out of hand (i.e. become complex themselves).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-apis" rel="noopener noreferrer"&gt;APIs&lt;/a&gt; section is OK, albeit a bit specific while being unclear at the same time. Is the author not happy with Java APIs? So is &lt;em&gt;this&lt;/em&gt; author! Switch to Typescript &amp;amp; Kotlin! 😉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-parsing" rel="noopener noreferrer"&gt;Parsing&lt;/a&gt; is also touched upon in this (apparently very broad) guide. I almost put it in Neither here nor there, but gave it a 2nd read and liked it: Basically, complexity is the enemy (again). Keep it simple.&lt;/p&gt;

&lt;p&gt;In the end of the guide, &lt;a href="https://grugbrain.dev/#grug-on-fads" rel="noopener noreferrer"&gt;fads&lt;/a&gt;, &lt;a href="https://grugbrain.dev/#grug-on-fold" rel="noopener noreferrer"&gt;FOLD&lt;/a&gt; &amp;amp; &lt;a href="https://grugbrain.dev/#grug-on-imposter-syndrom" rel="noopener noreferrer"&gt;impostor syndrome&lt;/a&gt; are pretty accurate descriptions of issues in developer psychology.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤷 Neither here nor there
&lt;/h2&gt;

&lt;p&gt;The bit about &lt;a href="https://grugbrain.dev/#grug-on-agile" rel="noopener noreferrer"&gt;Agile&lt;/a&gt; has nothing really of note ... The Agile concept has a &lt;em&gt;lot&lt;/em&gt; of potential. If done right it can completely transform people and companies they work in for the better. Tech practices like automated testing (and test-first practices like TDD) can seriously help in this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-soc" rel="noopener noreferrer"&gt;Separation of concerns&lt;/a&gt; is in my view misrepresented by an erroneous example of separating HTML, CSS &amp;amp; JS while the proposed solution (Locality of behaviour) is &lt;em&gt;actually&lt;/em&gt; what SoC &lt;em&gt;is&lt;/em&gt;. So, we basically agree on the principle but not the naming which I don't care about anyway.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://grugbrain.dev/#grug-on-visitor-pattern" rel="noopener noreferrer"&gt;visitor pattern&lt;/a&gt; has only "bad" with link to the Wikipedia article, so not much to go on here ... for what it's worth, I don't see much use for the pattern in modern languages and architectures.&lt;/p&gt;

&lt;p&gt;The section on &lt;a href="https://grugbrain.dev/#grug-on-front-end-development" rel="noopener noreferrer"&gt;frontend development&lt;/a&gt; reminds me of a simplified take of a mostly-backend developer. Today's frontends are apps in themselves &amp;amp; and their complexity is simply the result of mounting user expectations arising from explosion of app users with the majority of them being quite non-tech.&lt;/p&gt;

&lt;h2&gt;
  
  
  🫤 not 100%
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://grugbrain.dev/#grug-on-testing" rel="noopener noreferrer"&gt;Testing&lt;/a&gt; section I like the non-mocking part.&lt;/p&gt;

&lt;p&gt;Also I &lt;em&gt;kind&lt;/em&gt; of like &amp;amp; agree with the "small, well curated end-to-end test suite" + "integration test sweet spot" &lt;em&gt;if&lt;/em&gt; by "integration tests" the author means deployable-level (backend-only, frontend-only) acceptance tests which don't focus on implementation details but on behaviour.&lt;/p&gt;

&lt;p&gt;However, using them with a lot of debugger action is just a sign of missing unit tests (which is clear from the other parts of the section). Having good unit tests (and lots of them, especially on backend, which the author is apparently at home in) is a life-saver when writing acceptance tests since the acceptance tests can also be narrow and focused - as they should, since they're harder to write and slower to execute.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grugbrain.dev/#grug-on-tools" rel="noopener noreferrer"&gt;Tools&lt;/a&gt; is basically a call for debugging. To me frequent debugging is a sign of missing unit tests (see previous paragraph) and shows room for improvement in your testing strategy.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://grugbrain.dev/#grug-on-expression-complexity" rel="noopener noreferrer"&gt;Expression complexity&lt;/a&gt; section is just a specific example of an "optimise code for debugging" strategy, although the specific "good" example strikes me as more readable than the "bad" one. Nevertheless, I wouldn't recommend optimising your code for anything other than readability.&lt;/p&gt;

&lt;p&gt;Likewise, &lt;a href="https://grugbrain.dev/#:~:text=grug%20be%20frank-,Logging,-grug%20huge%20fan" rel="noopener noreferrer"&gt;logging&lt;/a&gt; is also an example of trying to improve things where unit tests (and possibly "integration" tests, or rather acceptance tests) are lacking. A well-tested deployable has to have logging only for input &amp;amp; output traffic. Logging "all major logical branches within code (if/for)" is just crazy.&lt;/p&gt;

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

&lt;p&gt;I like Grug. They're headed mostly in the right direction regarding principles and mindset. Unfortunately, automated testing is hard to get right but when you do the payback is more than handsome!&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>testing</category>
      <category>articlereview</category>
    </item>
    <item>
      <title>How to run your tests with a single keystroke</title>
      <dc:creator>Marko Bjelac</dc:creator>
      <pubDate>Wed, 09 Nov 2022 23:34:42 +0000</pubDate>
      <link>https://dev.to/mbjelac/how-to-run-your-tests-with-a-single-keystroke-2e94</link>
      <guid>https://dev.to/mbjelac/how-to-run-your-tests-with-a-single-keystroke-2e94</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@johnnyboylee?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Johnny Briggs&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;What is the point of going through the trouble to set all this up? I will try to briefly explain the reason I like to set up my test runs in this way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test-driven development
&lt;/h3&gt;

&lt;p&gt;TDD is a practice which has many variations. The canonical "red, green, refactor" variation is an oft quoted one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Red: Write the tests, they fail (compile fail also counts)&lt;/li&gt;
&lt;li&gt;Green: Implement the code which the tests test, tests pass&lt;/li&gt;
&lt;li&gt;Refactor: Clean up the code (both implementation &amp;amp; tests), presumably running the tests again to see if you broke something while refactoring&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a very short &amp;amp; simple description which doesn't get into details, some of which can be important. One of which is the prediction step:&lt;/p&gt;

&lt;p&gt;1a. Red: Write the tests&lt;br&gt;
1b. Red: Try to &lt;em&gt;predict&lt;/em&gt; the &lt;em&gt;result&lt;/em&gt; of their failure&lt;br&gt;
1c. Red: Run tests&lt;br&gt;
1d. Red: Compare the actual failure result to your prediction&lt;br&gt;
1e. Red: If they differ, either fix your understanding of the tests or fix the tests&lt;/p&gt;

&lt;p&gt;There are other variations including or excluding this one.&lt;/p&gt;

&lt;p&gt;In general, I find that if the developer writes code &lt;em&gt;with&lt;/em&gt; tests (before, after or in-between), this is enough to get the test-driven benefit: The tests guide the code/design leading to just enough code being written in a readable, decoupled manner which makes it easy to understand &amp;amp; modify.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time
&lt;/h3&gt;

&lt;p&gt;To get this benefit, time is of importance. The time window within which both tests &amp;amp; implementation are written has to be small because the human short-term memory can hold only so much information and for a finite, often short, amount of time.&lt;/p&gt;

&lt;p&gt;This leads to two requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your tests have to run very fast&lt;/li&gt;
&lt;li&gt;You have to run your tests often&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Writing fasts tests is a skill to be practiced &amp;amp; perfected but is out of scope of this article. However, I assure you it is possible to do, even for higher level non-unit tests.&lt;/p&gt;

&lt;p&gt;Running tests often is easier to do when the process of running them is simple. The simplest process I can think of is a single keypress.&lt;/p&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;In this part of the article the theory ends and practice begins. The example is very specific and I leave it to you to extract the principles and apply it to your set of tools if needed.&lt;/p&gt;

&lt;p&gt;We will be using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/idea/" rel="noopener noreferrer"&gt;Intellij Idea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Intellij plugin &lt;a href="https://plugins.jetbrains.com/plugin/9448-run-configuration-as-action" rel="noopener noreferrer"&gt;Run Configuration as Action&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Create a test configuration
&lt;/h3&gt;

&lt;p&gt;Create an Intellij &lt;a href="https://www.jetbrains.com/help/idea/run-debug-configuration.html" rel="noopener noreferrer"&gt;Run Configuration&lt;/a&gt; to run your tests.&lt;/p&gt;

&lt;p&gt;Try it out - run it by selecting it in the Run Configuration drop-down menu and clicking Run button.&lt;/p&gt;

&lt;p&gt;When you're happy with it, give it a nice name you'll remember, like &lt;code&gt;unit tests&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Configure action keyboard shortcut
&lt;/h3&gt;

&lt;p&gt;Go to &lt;code&gt;Preferences&lt;/code&gt; / &lt;code&gt;Keymap&lt;/code&gt; / &lt;code&gt;Plugins&lt;/code&gt; / &lt;code&gt;Run Configuration as Action&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Scroll down until you find an entry &lt;code&gt;Run 'unit tests'&lt;/code&gt; (you may have to restart Intellij for it to show up in the list).&lt;/p&gt;

&lt;p&gt;Select it, right-click and choose &lt;code&gt;Add Keyboard Shortcut&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Enter keyboard shortcut, i.e. &lt;code&gt;F10&lt;/code&gt;. Sort out any conflicts how you see fit.&lt;/p&gt;

&lt;p&gt;Press your shortcut to see if the configuration runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Diversify
&lt;/h3&gt;

&lt;p&gt;On a more complex project (e.g. multiple stack layers of a web application) there can be multiple run configurations for varying types of tests. Create each one with a different name and set up a different keyboard shortcut for each.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;F10&lt;/code&gt; Backend unit tests&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F9&lt;/code&gt; Frontend unit tests&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+F10&lt;/code&gt; Backend integration tests (testing adapter code with external services)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way you can selectively run only one type of tests, according to the part of your system you are working on.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>intellij</category>
    </item>
  </channel>
</rss>
