<?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: Joel Louzado</title>
    <description>The latest articles on DEV Community by Joel Louzado (@jlouzado).</description>
    <link>https://dev.to/jlouzado</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%2F9150%2F2016685.jpeg</url>
      <title>DEV Community: Joel Louzado</title>
      <link>https://dev.to/jlouzado</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jlouzado"/>
    <language>en</language>
    <item>
      <title>Level-Up as a Developer by Working with Legacy Codebases</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Wed, 06 Dec 2023 06:58:52 +0000</pubDate>
      <link>https://dev.to/jlouzado/level-up-as-a-developer-by-working-with-legacy-codebases-2e9l</link>
      <guid>https://dev.to/jlouzado/level-up-as-a-developer-by-working-with-legacy-codebases-2e9l</guid>
      <description>&lt;p&gt;Here's a list of topics and resources to use the next time you have a little down-time. Applying these skills will help you write more maintainable code. Over time you will also gain a reputation for being the kind of developer people turn to when they have a thorny problem to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functional Programming Basics
&lt;/h2&gt;

&lt;p&gt;Functional Programming is a vast subject, but you can start to see benefits from the understanding of a single concept: Pure Functions. Let's start with a simple definition 👇&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.freecodecamp.org/news/pure-function-vs-impure-function/" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ipERaFcA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.freecodecamp.org/news/content/images/2021/08/pure-function-vs-impure-function-codesweetly.png" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.freecodecamp.org/news/pure-function-vs-impure-function/" rel="noopener noreferrer" class="c-link"&gt;
          Pure vs Impure Functions in Functional Programming – What's the Difference?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Pure functions and impure functions are two programming terms you will often see in functional programming. One core difference between these two types of functions is whether or not they have side effects. In this article, you will learn what side effects are and we'll discuss the differences between pure
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--NR7BWmi---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.freecodecamp.org/universal/favicons/favicon.ico" width="48" height="48"&gt;
        freecodecamp.org
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This next video👇explains how to use it in your software. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: He refers to pure-functions as "calculations" and side-effects as "actions", so keep that in mind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/EqO4TcNLjl0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You will only learn by doing, so if you'd like to practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go through your current code-base&lt;/li&gt;
&lt;li&gt;Look for a Function where the side-effects and business-logic are mixed together

&lt;ul&gt;
&lt;li&gt;ideally you already understand the details of the function really well&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Separate out the Business Logic into a Pure-Function with just the "Calculations", and keep it separate from your side-effects.

&lt;ul&gt;
&lt;li&gt;Ensure your application still works.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you would like an example, here's code for an example ShoppingCart Class where you can add items and a discount is calculated before checkout:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/play?#code/PQKhCgAIUglBTADgJ3gZ3gOwC5sgQ0jQAsB7RRAS0wHNIBjfZbSAd0u2Mg-gFs98mACaQUpAG6Uh6BsXj0A1qQCuLAGbLM9bJVKZ8AGw4BPAHRQQwcPQP40eAMpkK1GgGEmLAN5RRySuL42PDcwfwAXETY-rQA2gC6kAC8kAkA3L4oAUEh2KTYhgD6WfTwkZjKvABG8MjJkAAMGb74QkIAkmEAFDy8kWjRrgA0fpSl5ZU1yACUkeKkUpA+kCuQnJRopr2biMokPWHTGatrxBumeQUGxf6lkADUKSXwx6vAwJAOUiHwamry2EiABlSDQaK5TiFWkIOLpMJBSGoCPDer4VvQ9GhSAZ4KYDKCugADTp8SAAcgAJF5egBfMkENrwISmSAAFXyhlG40gFKp602lyKzxphKOvhp4F89DkihU2C6s0g80WyzeHwAQntqOg8PjwfRIgBBCgGYwESAAJgaAFJIDC0BjNCxWHJ4ZxchyDFyQhsEeJapAAKwNBpohiYlj2x04er8i6em5jEIAPiDIcgAH5GqYLZBIk1JSd3p9vpBfv9tEaTcYIVGVDHBCI9eDaGG44Lrs9oCkAIyQAC0do20ewr3RmOxuL1RONiCMTJ5XjrTugkB7IZptuXOBZADFqJznpFeV52wnhaLmkWPl9pGW-gDIm5iEwW3R3Qw9nleLU22dNtKr7wG4X6kD+yAKleaolne5aPp8WAwrQ5oYpgaiUMgvBBHCZZYZQBh-ucGDCG4ejoZh2F6AAonhBiQeKhajIEwSyEBIEDGBtQKnMCwiKqKzFl8vDKLYLGAcgb6Qp+HHgWGqFYjieIEoSz6vhC9CgeBPJ8v+8ZXImpQimKKwSpk-jMSExFCKRaEYVhOjUbR3FKrxSxhoJlDCaJlmIRChCoeR9k4Xw+D4XJE6KdOABENmBZR8IhfhRBYNgUXGZAEqmcWVEAB74Lwc4hHs+A0GU1gRgwnj1Jg8CsJ8zhULQHjMPRjDMKY0IkrwXRRQACsgpBCMo2iQIaUUjAALCGYptdgHVtF1PX9YNw0sOq42WtNGSzaY0ryEoqj0UAA"&gt;Business Logic mixed with Side-Effects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/play?#code/PQKhCgAIUglBTADgJ3gZ3gOwC5sgQ0jQAsB7RRAS0wHNIBjfZbSAd0u2Mg-gFs98mACaQUpAG6Uh6BsXj0A1qQCuLAGbLM9bJVKZ8AGw4BPAHRQQwcPQP40eAMpkK1GgGEmLAN5RRySuL42PDcwfwAXETY-rQA2gC6kAC8kAkA3L4oAUEh2KTYhgD6WfTwkZjKvABG8MjJkAAMGb74QkIAkmEAFDy8kWjRrgA0fpSl5ZU1yACUkeKkUpA+kCuQnJRopr2biMokPWHTGatrxBumeQUGxf6lkADUKSXwx6vAwJAOUiHwamry2EiABlSDQaK5TiFWkIOLpMJBSGoCPDer4VvQ9GhSAZ4KYDKCugADTp8SAAcgAJF5egBfMkENrwISmSAAFXyhlG40gFKp602lyKzxphKOvhp4F89DkihU2C6s0g80WyzeHwAQntqOg8PjwfRIgBBCgGYwESAwtAYzQsKp2JkI+GcXIcgxc+BohiYliW604eqMAz0ZS2YIAEQ2fvl-IurpuY3gYs970+30gv3+2iNJuMEN9Kn9ghEevBtE9McF12e0BSAEZIABaC2RgvYV7ozHY3F6onGxBGB1U-M26CQWsNBo0gCkzatrZZADFqJznpFeV4K3HhaLmicU19pOm-gDIm5iExS3RnQw9nleLVy2dNtKL-A3LfSPfkArd2rU4eMxPT4sBhWhzQxTA1EoZBeCCOF01gygDEfc4MGENw9CgmC4L0ABRRCDB-cVJRWLJAmCWRX3fAZP1qBU5gWERVRWfdKF4EMcko5BL0hG8aK-T0IKxHE8QJQkzwvCFg342oeT5J9YyueNShFMUVglTJ-HIkI0KEDDIOg2CdDwgj6KVRilmTD4vnY0MdJAiFCAgrCjPgvh8CQwTOxEnsACJ9JcnD4XcpCiCwbBfLUyAJQ0lMAAVlFQSANC0YynVIBhDGDOzeOHf07QwEQ9F4yt3XAFLtHgwNspyCM5xtLpKzi24ykgCpqlqRV2qmSyWI+PtTXNAAmBoZzylhWDkJ05DWV13W4PAJFkgBWCdfFQbBEvSq5moTSAAD5IFWhpIAAfkaUwhsgSImnAWKPlwgAPfBeH7EI9nwGgymsb1MuYepMHgVhPmcKhaA8ZgiMYZhTGhEleC6XzmtIIRlG0SBDV8kYABYJzFaHsFhtp4cR5HUfR9UscgEaGnxzxTGleQlFUIigA"&gt;Business Logic separated into a Pure Function&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why would you want to do this though. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most bugs tend to be in the Business Logic &lt;/li&gt;
&lt;li&gt;If a Function or a Class logs to a DB or sends an email every time it's run, it becomes harder to test properly.&lt;/li&gt;
&lt;li&gt;If you can extract a Calculation into a Pure Function, it becomes easier to run.&lt;/li&gt;
&lt;li&gt;The easier it becomes to run, the easier it is to fix bugs.&lt;/li&gt;
&lt;li&gt;You can even write unit-tests for your Pure-Functions and run them automatically on every change, making it easier to catch &lt;a href="https://en.wikipedia.org/wiki/Software_regression"&gt;regressions&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;There's a few other skills I think make it easier to work with old code, I'm going to add those in shortly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TDD, for better-quality pure-functions&lt;/li&gt;
&lt;li&gt;C4 Architecture Diagrams, for standardized documentation&lt;/li&gt;
&lt;li&gt;Sequence Flow Diagrams in Mermaid, to get quicker feedback on code&lt;/li&gt;
&lt;li&gt;Trunk Based Development, to reduce operational overhead for small teams&lt;/li&gt;
&lt;li&gt;CodeScene, to manage the health of a codebase and pay-down tech-debt&lt;/li&gt;
&lt;li&gt;Approval Testing, when the original devs on a project aren't available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Leave me a comment or DM me on &lt;a href="//twitter.com/jlouzado"&gt;Twitter&lt;/a&gt; if you have any specific requests or questions.&lt;/p&gt;

</description>
      <category>resources</category>
      <category>tdd</category>
      <category>functional</category>
    </item>
    <item>
      <title>Publish to Dev.to via RSS</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Tue, 02 Feb 2021 13:27:02 +0000</pubDate>
      <link>https://dev.to/jlouzado/publish-to-dev-to-via-rss-27hi</link>
      <guid>https://dev.to/jlouzado/publish-to-dev-to-via-rss-27hi</guid>
      <description>&lt;p&gt;Ignore this one for now dear reader, just testing out the publish via RSS feature. 🙏&lt;/p&gt;

&lt;p&gt;Here's a cute puppy for your troubles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Lr2YomhIBU8LK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Lr2YomhIBU8LK/giphy.gif" alt="cute puppy on his back paddling his legs"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>guide</category>
      <category>publishing</category>
      <category>howto</category>
      <category>placeholder</category>
    </item>
    <item>
      <title>Create a "Series" from Markdown Editor</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Tue, 02 Feb 2021 13:23:03 +0000</pubDate>
      <link>https://dev.to/jlouzado/create-a-series-from-markdown-editor-dfn</link>
      <guid>https://dev.to/jlouzado/create-a-series-from-markdown-editor-dfn</guid>
      <description>&lt;p&gt;This is not anything new, but the instructions are a bit buried so I'm hoping that this write-up saves the next person the "duckduckgo-ing" and comment-reading I had to do.&lt;/p&gt;

&lt;p&gt;First, what are we talking about. By Series, I'm talking about the badge that appears at the top of certain posts. For example, take a series of Book Notes by &lt;a href="https://dev.to/danlebrero/"&gt;@danlebero&lt;/a&gt; the top of each post is decorated with links to the other posts in the series:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bB_a4oy_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rvkjgfgjcjerkt7wr4dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bB_a4oy_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rvkjgfgjcjerkt7wr4dg.png" alt="screenshot of the top of the first post in the series, showing the badge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to create a series, you can do so using the "Rich" editor as shown here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/dzhavat" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xice8zlq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--p4or78vo--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/184225/f6cc399a-70ec-4c28-bbb9-fec24f40bcf3.jpg" alt="dzhavat image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/dzhavat/a-short-guide-on-how-to-make-the-series-widget-on-dev-4o9f" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A short guide on how to “make” the series widget on DEV&lt;/h2&gt;
      &lt;h3&gt;Dzhavat Ushev ・ Sep 27 '19 ・ 2 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#meta&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Unfortunately, once you set the &lt;code&gt;series&lt;/code&gt; value via the rich-editor, it won't switch back to the Markdown editor even if you revert your settings. I quite prefer the writing &amp;amp; thinking in markup so this was quite a deal-breaker for me.&lt;/p&gt;

&lt;p&gt;After hunting around the comments, I found the answer in the last place I'd look: &lt;a href="https://dev.to/p/editor_guide#front-matter"&gt;The User Manual, in the &lt;code&gt;Front Matter&lt;/code&gt; section&lt;/a&gt;. Here's what the meta-data for this post looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--------
title: Create a "Series" from Markdown Editor
published: true
description: You ever wondered how people are creating a series of posts here on dev.to? Wonder no more
tags: howto, tutorial, guide
series: "Publishing on Dev.to"
--------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically, you just set the &lt;code&gt;series&lt;/code&gt; key in the header and the new post gets added to the series. &lt;/p&gt;

&lt;p&gt;Thank you for reading, let me know if this works for you and give it a ❤️ if it saved you some time so it's easier for others to find it. 🙏&lt;/p&gt;

</description>
      <category>howto</category>
      <category>tutorial</category>
      <category>guide</category>
    </item>
    <item>
      <title>Can Spaced-Repetition help improve your Retrospectives?</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Mon, 04 Jan 2021 10:58:48 +0000</pubDate>
      <link>https://dev.to/jlouzado/get-more-out-of-your-retrospectives-with-spaced-repetition-28mm</link>
      <guid>https://dev.to/jlouzado/get-more-out-of-your-retrospectives-with-spaced-repetition-28mm</guid>
      <description>&lt;p&gt;I think most people would agree that Retrospectives are a vital part of building a high-performing team and yet it's often (in my experience, at least) rushed so that the next Sprint can begin. If your team is already having healthy discussions during your Retrospectives then you're winning, but if the same kinds of errors happen Sprint-after-Sprint then maybe the Retro itself needs some improvement.&lt;/p&gt;

&lt;p&gt;With this post, I'm hoping to show that with a relatively small change a team can get a huge amount of value from the time they spend in Retrospectives. You're probably already capturing issues and ideas, from there it's about optimizing how they're evaluated and turned them into habits with the least wastage. If the system can also highlight successes as they happen that would be amazing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimum-Viable Retrospective
&lt;/h2&gt;

&lt;p&gt;In my experience, a good Retrospective balances two categories of items:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Previous Ideas&lt;/em&gt;, which will all be in various state of adoption, and&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;New Issues&lt;/em&gt; which are coming up all the time and need to be analyzed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We want to give both categories the appropriate time, without having to discuss every item in every meeting. In other words, it's about managing the team's &lt;em&gt;attention&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spaced-Repetition is an Attention-Manager
&lt;/h2&gt;

&lt;p&gt;A very popular technique for studying is to use Flash Cards in combination with Spaced-Repetition. The standard-version (also called the Leitner Method) can be implemented with physical boxes and cards as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take a number of boxes (about 7)

&lt;ul&gt;
&lt;li&gt;or one big box, with some separators. You get the idea.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;as you're learning a new topic, &lt;a href="https://www.wikihow.com/Write-Flash-Cards"&gt;make flash-cards&lt;/a&gt; for things you want to remember&lt;/li&gt;
&lt;li&gt;put the new cards in the first box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, when you sit down to study, review each box half as often as the previous one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the first box gets reviewed every day,&lt;/li&gt;
&lt;li&gt;second box gets reviewed every 2 days,&lt;/li&gt;
&lt;li&gt;third box gets reviewed every 4 days, &lt;/li&gt;
&lt;li&gt;and so on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each card, test yourself if you still remember it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you got it right, move the card to the next box

&lt;ul&gt;
&lt;li&gt;from the second box to the third, for example&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;if you got it wrong, move it all the way back to the first box.

&lt;ul&gt;
&lt;li&gt;sorry, I don't make the rules ¯_(ツ)_/¯&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason the review-interval doubles each time is because with each subsequent reminder the brain retains the memory for longer before it starts to fade. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--635YLoa3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kgepfgeoeted4cwn6hxm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--635YLoa3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kgepfgeoeted4cwn6hxm.png" alt="Graph of strenth-of-memory vs time, showing that recall-decay improves greatly after a single, well-timed revision "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After 3 or 4 revisions your brain gets the message and realizes that it's something really important, and so it gets committed to memory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ctY_4P5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m5ilh3jskssryr6ufx1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ctY_4P5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m5ilh3jskssryr6ufx1k.png" alt="Graph of strength-of-memory vs time showing successive revisions need decreasing frequency"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An Organization is really a bunch of Individuals, so the collective memory is only as strong as that of the weakest link. We can use the same system of Spaced-Repetition to automatically trigger a "remembering" of an old improvement and help a team to turn it into a habit much more easily.   &lt;/p&gt;

&lt;h2&gt;
  
  
  Applying Spaced-Repetition to a Retro
&lt;/h2&gt;

&lt;p&gt;This could be implemented with the same boxes and cards we've just seen, but if you're already using a tool like Trello you can use that as well. If you would like a ready-made template you can &lt;a href="https://trello.com/b/Fr3eSKnE/retrospective-template/joel_louzado/recommend"&gt;click here&lt;/a&gt; to see an example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Add the following columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CONFIG (where we'll set up our automation)&lt;/li&gt;
&lt;li&gt;Pending Review&lt;/li&gt;
&lt;li&gt;Review Weekly&lt;/li&gt;
&lt;li&gt;Review Fortnightly&lt;/li&gt;
&lt;li&gt;Review Monthly&lt;/li&gt;
&lt;li&gt;Review Every 2 Months, etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the &lt;a href="https://bridge24.com/blog/trello-card-repeater-power-up-tutorial/"&gt;Repeater Powerup&lt;/a&gt; and set up a Marker that automatically tells you which Columns are ready for review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each column needs one Marker, which could just be a card that says &lt;code&gt;Review Me!!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the card, and click &lt;code&gt;Repeat&lt;/code&gt; so that it gets repeated either weekly or fortnightly or whatever.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Refer the &lt;a href="https://trello.com/b/Fr3eSKnE/retrospective-template/joel_louzado/recommend"&gt;template&lt;/a&gt; if you want to see an example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We're assuming here that your Retrospectives are run once a week. If not, adjust the automation and the columns accordingly and keep in mind that each subsequent column should get reviewed half as often as the previous one.&lt;/p&gt;

&lt;p&gt;During the Sprint, team-members add items to the &lt;code&gt;Pending Review&lt;/code&gt; column&lt;/p&gt;

&lt;h3&gt;
  
  
  First 25% of the Retrospective
&lt;/h3&gt;

&lt;p&gt;When the Retrospective starts, collect any and all items that people want to discuss and put them in the &lt;code&gt;Pending Review&lt;/code&gt; column. The items in the first column are probably the newest, so they'll probably take longer to discuss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's say a card in &lt;code&gt;Pending Review&lt;/code&gt; reads: "Lots of bugs are being released to Production".&lt;/li&gt;
&lt;li&gt;The team decides it's time to introduce a Code Review Process.&lt;/li&gt;
&lt;li&gt;Make a new card titled "Code-Review every PR before merging it" and move it to the bottom of the &lt;code&gt;Every Week&lt;/code&gt; column.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remainder of the Retrospective
&lt;/h3&gt;

&lt;p&gt;For the remaining lists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For each card, ask the question "Did we remember to do this in the last Sprint".&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;YES&lt;/code&gt;, move the card one column to the Right.

&lt;ul&gt;
&lt;li&gt;For example, if the card was in the &lt;code&gt;Every 4 Weeks&lt;/code&gt; Column move it to &lt;code&gt;Every 8 Weeks&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;NO&lt;/code&gt;, move the card all the way back to the first column (&lt;code&gt;Every Week&lt;/code&gt;)

&lt;ul&gt;
&lt;li&gt;if a card is repeatedly falling back to the first column, maybe move it to &lt;code&gt;Pending Review&lt;/code&gt; so it can be discussed&lt;/li&gt;
&lt;li&gt;maybe the solution needs to be tweaked so that it better solves the problem&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Archive the Marker once all the cards in that column are done&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;After a Sprint or two you should start to see some positive changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Issues are raised more contextually because there's a way to gather them continuously throughout the Sprint.&lt;/li&gt;
&lt;li&gt;Meta-discussion during the Retrospective (especially about which Items to discuss should go down)&lt;/li&gt;
&lt;li&gt;Issues that get sorted out quickly become a highly-visible source of accomplishment so that the team can also see that progress is being made.&lt;/li&gt;
&lt;li&gt;Onboarding becomes simpler because the team's working-style is automatically getting documented as it evolves.

&lt;ul&gt;
&lt;li&gt;If anyone has a new idea they can also go back if anything similar has been tried before&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;If you're setting up a brand new team from scratch, I'd recommend &lt;a href="https://www.youtube.com/watch?v=-InKsQQY9Vk"&gt;Toyota Kata&lt;/a&gt; and &lt;a href="https://duckduckgo.com/?q=retrospective+antipatterns"&gt;Retrospective Antipatterns&lt;/a&gt; as starting points. The approach that's shared here is more to help existing teams that are feeling stuck to give their Processes &amp;amp; Thinking a bit of a shake-up. &lt;/p&gt;

&lt;p&gt;So what do you think? My thoughts on this topic are still evolving so if you enjoyed it or would like to discuss, I'm at &lt;a href="https://twitter.com/jlouzado"&gt;jlouzado&lt;/a&gt; on Twitter; that's probably the best way to reach me. &lt;/p&gt;

&lt;p&gt;Thank you so much for reading, see you in the next one. :) &lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/ncasenmare"&gt;Nicky Case&lt;/a&gt; for creating &lt;a href="https://ncase.me/remember/"&gt;how to remember anything&lt;/a&gt; which was my first introduction to Spaced-Repetition

&lt;ul&gt;
&lt;li&gt;also the source of the screenshots used in this article&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Andy Matushak's musing on &lt;a href="https://jlouzado.github.io/#Programmable%20Attention"&gt;Programmable Attention&lt;/a&gt; which inspired this implementation, and&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/DanLebrero"&gt;Dan Lebrero&lt;/a&gt; and &lt;a href="https://twitter.com/tusharmath"&gt;Tushar Mathur&lt;/a&gt; for reviews and advice on early drafts&lt;/li&gt;
&lt;li&gt;Cover by Braden Collum on UnSplash - &lt;a href="https://unsplash.com/photos/ttbCwN_mWic"&gt;Runners in a race&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>scrum</category>
      <category>sprint</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Do Stacked-PRs require re-review after merge?</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Sat, 14 Dec 2019 06:06:17 +0000</pubDate>
      <link>https://dev.to/jlouzado/do-stacked-prs-require-re-review-after-merge-522f</link>
      <guid>https://dev.to/jlouzado/do-stacked-prs-require-re-review-after-merge-522f</guid>
      <description>&lt;h2&gt;
  
  
  Scenario
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I'm working on a big feature that I know can be broken into two parts

&lt;ul&gt;
&lt;li&gt;these parts are, as is often the case, dependent on each other.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;I branch off &lt;code&gt;master&lt;/code&gt; and create branch &lt;code&gt;feat/part1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I finish coding part1, and create a PR with this branch

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;feat/part1&lt;/code&gt; -&amp;gt; &lt;code&gt;master&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;this is &lt;code&gt;PR-1&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;While I'm still checked out in &lt;code&gt;feat/part1&lt;/code&gt;, I create a new branch &lt;code&gt;feat/part2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I finish coding part 2 and create a second, "stacked" PR

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;feat/part2&lt;/code&gt; -&amp;gt; &lt;code&gt;feat/part1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;this is &lt;code&gt;PR-2&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's say both PRs get reviewed and approved. I now merge PR-2.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PR-1 now contains all the changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Question
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Can I assume that PR-1 is now approved and merge-able or do I need to re-review it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;As for why someone would do this, this technique of breaking up PRs is a way to breakup large changes into more manageable chunks&lt;/li&gt;
&lt;li&gt;That way the rest of the team can give feedback more easily.&lt;/li&gt;
&lt;li&gt;Can read more about it here: &lt;a href="https://graysonkoonce.com/stacked-pull-requests-keeping-github-diffs-small/"&gt;Stacked PRs To Keep Github Diffs Small | graysonkoonce.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ask</category>
      <category>help</category>
      <category>git</category>
      <category>codereview</category>
    </item>
    <item>
      <title>How would you manage spell-check of packages?</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Wed, 30 Oct 2019 13:58:33 +0000</pubDate>
      <link>https://dev.to/jlouzado/how-would-you-manage-spell-check-of-packages-2lco</link>
      <guid>https://dev.to/jlouzado/how-would-you-manage-spell-check-of-packages-2lco</guid>
      <description>&lt;p&gt;My npm package has custom words that trigger spell-check alerts unless whitelisted. I can add a whitelist for the &lt;a href="https://www.npmjs.com/package/cspell"&gt;cspell&lt;/a&gt; on my machine, but will everyone who imports my package need to do the same as well? &lt;/p&gt;

&lt;p&gt;How do I make life easier for someone who installs my package as a dependency.&lt;/p&gt;

</description>
      <category>ask</category>
      <category>javascript</category>
      <category>npm</category>
      <category>cspell</category>
    </item>
    <item>
      <title>Your Unit Tests Should Be Immutable</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Sat, 30 Mar 2019 14:01:38 +0000</pubDate>
      <link>https://dev.to/jlouzado/tdd-your-unit-tests-should-be-immutable-119m</link>
      <guid>https://dev.to/jlouzado/tdd-your-unit-tests-should-be-immutable-119m</guid>
      <description>&lt;h1&gt;
  
  
  Picture this...
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Your project has been following TDD from the very start&lt;/li&gt;
&lt;li&gt;You're tasked with refactoring a function (to improve performance, say)&lt;/li&gt;
&lt;li&gt;You make a relatively minor change, and run the tests&lt;/li&gt;
&lt;li&gt;Your tests for that unit pass, but then a bunch of unit tests in some random component fail!

&lt;ul&gt;
&lt;li&gt;"What the hell is happening, these components aren't even related!" I hear you say.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To fix it you will need to change those tests in those unrelated units, and that's a big problem. Your tests need to be &lt;em&gt;immutable to refactoring&lt;/em&gt; and the above scenario is a &lt;code&gt;Test Smell&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why is this a problem?
&lt;/h1&gt;

&lt;p&gt;There are lots of benefits to TDD, but one that doesn't get as much airtime is that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A good test-suite gives you &lt;strong&gt;confidence&lt;/strong&gt; about the behaviour of your system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However that confidence is NOT guaranteed by tooling, it comes from the fact that you followed TDD. You wrote a test, it failed, then you wrote some code and it passed. Therefore, that code works.&lt;/p&gt;

&lt;p&gt;That means that the only reason you trust your codebase is because you trust your fellow developers to have &lt;em&gt;also&lt;/em&gt; followed TDD. Which is to say, that relying on your test-suite is not a matter of Fact, but a matter of Trust.&lt;/p&gt;

&lt;p&gt;Hence once a test-suite exists, we need to protect our Trust in it by minimizing changes to it.&lt;/p&gt;

&lt;p&gt;Coming back to our hypothetical situation from earlier, Refactoring (by definition) is not supposed to be a change in behaviour. If you're now forced to update test-code in unrelated units, you now need to &lt;em&gt;manually&lt;/em&gt; validate those units and (all their usages) before trust is restored in the system.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reasons for Problem
&lt;/h1&gt;

&lt;p&gt;For example, your unit originally set an internal state's &lt;code&gt;canProceed&lt;/code&gt; and you refactored it to &lt;code&gt;shouldProceed&lt;/code&gt;. These other units are failing because they were asserting on the value of &lt;code&gt;canProceed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you go into those failing tests and update the tests with the new assumption it's &lt;em&gt;highly&lt;/em&gt; likely that an error will get made and you might assert &lt;code&gt;false&lt;/code&gt; instead of &lt;code&gt;true&lt;/code&gt; or any number of other issues. You might even accidentally delete a test (in more complex scenarios). The worst part of it is that your test suite can't save you from these mistakes because it can't self-test; the Light going Green doesn't mean anything if the test implementation is giving you a false-positive.&lt;/p&gt;

&lt;h1&gt;
  
  
  Desired Behaviour
&lt;/h1&gt;

&lt;p&gt;The only reason to change a test should be if the required behaviour of the system changes. Either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There's a bug in your implementation that you need to fix, or&lt;/li&gt;
&lt;li&gt;There's a requirement that's a &lt;a href="https://semver.org/"&gt;breaking change&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tests don't guarantee bug-free code, they're about enabling faster feedback.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In all other cases, we expect the tests to be &lt;code&gt;Immutable&lt;/code&gt; i.e. Refactoring should not require a change in tests.&lt;/p&gt;

&lt;h1&gt;
  
  
  Achieving Test Immutability
&lt;/h1&gt;

&lt;p&gt;Since we don't have a test-suite for our test-suite, there's increased pressure to follow clean-code guidelines while implementing it. Once tests are written the intention is that they should be encased in ember, so we should aim to get it right the first time.&lt;/p&gt;

&lt;p&gt;Here are some suggestions:&lt;/p&gt;

&lt;h2&gt;
  
  
  Name your tests explicitly
&lt;/h2&gt;

&lt;p&gt;Bad: &lt;code&gt;test('should set correct headers')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Good: &lt;code&gt;test('should set the 'device' header to 'mobile')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you're writing the test name and it's running a bit lengthy, you might be trying to test too many things or might have too many state-values to list out.&lt;/p&gt;

&lt;p&gt;That's okay, favour an explicit name over a short sentence. Atleast it's clear. And anyway, you can fix that in the next point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Domain-Language while naming your tests
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use terms relevant to your users
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Bad: &lt;code&gt;$1.00 - $2000.00 = No Interest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Good: &lt;code&gt;Loans of $2000 and below are interest-free&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Describe expected behaviour in the test name, rather than in the &lt;code&gt;expected&lt;/code&gt; result
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Passable:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$2001.00 Loan Amount&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;calculateInterest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$2001.00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="cm"&gt;/*actual*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$0.09&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="cm"&gt;/*expected*/&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;ul&gt;
&lt;li&gt;Better:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A loan of $2001.00 owes $0.09 interest&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;calculateInterest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$2001.00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="cm"&gt;/*actual*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$0.09&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="cm"&gt;/*expected*/&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;Your unit tests also serve as documentation; make them as readable as possible for another developer who might not have the context you have right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Group your tests semantically
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read up on &lt;a href="(https://lmws.net/describe-vs-context-in-rspec)"&gt;RSpec&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;describe&lt;/code&gt; to denote the behaviour you're testing,&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;context&lt;/code&gt; to group tests by common assumptions or world-states
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launch the rocket&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all ready&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should launch rocket&lt;/span&gt;&lt;span class="dl"&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;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not ready&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should do nothing&lt;/span&gt;&lt;span class="dl"&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;ul&gt;
&lt;li&gt;Your tests statements should ideally read like documentation,

&lt;ul&gt;
&lt;li&gt;This has the added benefit of making your tests easier to review&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Breaking things up in this way also avoids long test-names

&lt;ul&gt;
&lt;li&gt;it also becomes easier to locate and debug failing tests during refactoring&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Single Assert Per Test
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Once your test names are discrete, have only a single &lt;code&gt;assert&lt;/code&gt; per test&lt;/li&gt;
&lt;li&gt;If multiple asserts are "necessary", you're probably trying to check multiple things

&lt;ul&gt;
&lt;li&gt;the downside is that these extra things aren't documented in the test-name&lt;/li&gt;
&lt;li&gt;tomorrow those extra asserts might get removed because they don't look important&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;avoid all this drama, just keep a single assert per test.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Minimize data-sharing across tests
&lt;/h2&gt;

&lt;p&gt;You might be tempted to start defining common objects and reusing them across tests, resist that urge.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It might seem like you're following &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt; but it makes your tests less readable&lt;/li&gt;
&lt;li&gt;it might also inadvertently introduce bugs into your test code&lt;/li&gt;
&lt;li&gt;if something is really so generic that it can be included across tests, make a library out of it

&lt;ul&gt;
&lt;li&gt;and be sure to guarantee 100% test-coverage of any library you use.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Don't assert on an Object
&lt;/h2&gt;

&lt;p&gt;Take the following code as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createRequest&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;set correct headers&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_csrf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abcd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;__csrf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pqrst&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// cookies&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// params&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AAA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-CSRF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pqrst&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pwa&lt;/span&gt;&lt;span class="dl"&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;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&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;"This looks fine", I hear you say, "What's the Issue?". Well, this is basically just a hidden version of having multiple asserts per test.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here there's three asserts:

&lt;ul&gt;
&lt;li&gt;one for the &lt;code&gt;X-CSRF&lt;/code&gt; header,&lt;/li&gt;
&lt;li&gt;one for the &lt;code&gt;content-type&lt;/code&gt; header, and&lt;/li&gt;
&lt;li&gt;one for the &lt;code&gt;device&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;To make matters worse, the test title doesn't give you any information about what the desired output is.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refactor your tests to something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createRequest&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;headers&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should set X-CSRF header correctly&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;_csrf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abcd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;__csrf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pqrst&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;//cookies&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;//params&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pqrst&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-CSRF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should set `content-type` correctly&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="c1"&gt;//cookies&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;//params&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should set `device` header correctly&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="c1"&gt;//cookies&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;//params&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pwa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&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;h2&gt;
  
  
  Scrutinize your Testing-Code more than your Application Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Your tests basically contain all the information about the design of your new component

&lt;ul&gt;
&lt;li&gt;Not only it's behaviour, but it's interface and it's dependencies&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;If the testing code is solid, well written, and exhaustive, refactoring Application Code will be trivial!

&lt;ul&gt;
&lt;li&gt;If there's a gap in the tests, that's something that will only be felt in an integration test (or in Production)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;This is a Process thing and is up to the team on how to enforce it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Manage your branches well
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Be extra careful when resolving Merge-Conflicts in test-code&lt;/li&gt;
&lt;li&gt;Again, the test-code can't test itself.&lt;/li&gt;
&lt;li&gt;If a change has been made to an existing test, the fact that it passes doesn't prove anything.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Ultimately maintaining the test-suite is a matter of Discipline, Code-Guidelines and good Code-Review process as well as a reliable set of Team-mates in a trustful environment.&lt;/p&gt;

&lt;p&gt;As individual developers I claim that if we're going to be a craftsmen about anything, we should apply ourselves to the testing code. Our future selves will thank us for it.&lt;/p&gt;

&lt;p&gt;Good luck out there. :)&lt;/p&gt;

&lt;h1&gt;
  
  
  Further Reading
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://itnext.io/you-dont-know-tdd-691efe670094"&gt;You don't know TDD&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;This 4 part series dives deep while implementing the Money Lender example.&lt;/li&gt;
&lt;li&gt;TDD is endlessly fascinating; even solving compilation errors is sort of a &lt;a href="https://martinfowler.com/bliki/TestDrivenDevelopment.html"&gt;Red / Green / Refactor&lt;/a&gt; cycle&lt;/li&gt;
&lt;li&gt;This series of posts is truly something beautiful to witness, would highly recommend. :)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://spin.atomicobject.com/2014/12/09/typed-language-tdd-part1/"&gt;More Typing, Less Testing | TDD With Static Types&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Adding static-types to this discussion takes everything to overdrive.&lt;/li&gt;
&lt;li&gt;basically it add a &lt;code&gt;Add Types&lt;/code&gt; step into the &lt;a href="https://martinfowler.com/bliki/TestDrivenDevelopment.html"&gt;Red / Green / Refactor&lt;/a&gt; cycle&lt;/li&gt;
&lt;li&gt;types help create your interfaces with even more specificity.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://youtu.be/BSaAMQVq01E?t=2105"&gt;UncleBob Expecting Professionalism&lt;/a&gt; (35:05 - 41:40)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dzone.com/articles/unit-testing-smells-what-are-your-tests-telling-yo"&gt;Unit Testing Smells&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer20.com/tdd-done-right/"&gt;TDD Done Right - Tests Immutable to Refactor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally posted on &lt;a href="https://blog.patchcording.com/2019-03-24-tdd-immutable-tests/"&gt;blog.patchcording.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>tdd</category>
      <category>tutorial</category>
      <category>testing</category>
    </item>
    <item>
      <title>Is TDD just a gimmick?</title>
      <dc:creator>Joel Louzado</dc:creator>
      <pubDate>Sun, 24 Mar 2019 12:51:00 +0000</pubDate>
      <link>https://dev.to/jlouzado/is-tdd-just-a-gimmick-2mek</link>
      <guid>https://dev.to/jlouzado/is-tdd-just-a-gimmick-2mek</guid>
      <description>&lt;h2&gt;
  
  
  What's the big deal?
&lt;/h2&gt;

&lt;p&gt;Something that has radically improved the quality and maintainability of the software I've written over the past year has been &lt;code&gt;Test-Driven Development&lt;/code&gt; (TDD for short). My claim is that writing the test &lt;strong&gt;before&lt;/strong&gt; the implementation is not just a gimmick:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Unit tests produced by TDD guarantee code-coverage in a way that tests written post-implementation cannot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As developers I understand that there's a healthy amount of skepticism we all have so let's go through some of the common responses I get when people hear that claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe it does, but why should I care about code-coverage?
&lt;/h2&gt;

&lt;p&gt;Just to be clear, 100% code-coverage means that if a function is performing &lt;code&gt;N&lt;/code&gt; operations, each of them are covered by a unit-test. Put another way, if someone were to delete&lt;sup id="fnref1"&gt;1&lt;/sup&gt; a line of code at least one unit-test &lt;em&gt;should&lt;/em&gt; fail.&lt;/p&gt;

&lt;p&gt;If we have coverage we can have confidence, and with that confidence you get some effects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;effort to comprehend a piece of code will always grow more slowly than the complexity of that code, because:

&lt;ul&gt;
&lt;li&gt;there's always going to be at least one example of every potential usage, and&lt;/li&gt;
&lt;li&gt;you get an opportunity to play around with the code and see how it affects the test suite.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;refactoring code will be much easier and faster because feedback is so much quicker&lt;/li&gt;
&lt;li&gt;logical errors (bugs) will be much easier to spot and fix, since other people can read your tests and check if all the requirements are being fulfilled.&lt;/li&gt;
&lt;li&gt;changes to the codebase are guaranteed to not introduce regression bugs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So confidence (via code-coverage) is the whole game; you will see the above benefits in your codebase to the extent that the requirements are covered, simple as that.&lt;/p&gt;

&lt;h2&gt;
  
  
  But I could just write the function and then the tests and get the same coverage
&lt;/h2&gt;

&lt;p&gt;Almost everyone I've spoken to agrees that we need unit tests because we know bugs can creep into our code. Meanwhile unit-tests are also code, don't we need to guard against bugs there?&lt;/p&gt;

&lt;p&gt;Writing a test after the implementation leaves the possibility open that the test itself is buggy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you mean by a buggy test, how can a test have a bug?
&lt;/h2&gt;

&lt;p&gt;The purpose of a test is to check the correctness of the function. So anything that prevents it from doing that, is a bug. i.e. if a test isn't actually checking anything then it's not doing it's job.&lt;/p&gt;

&lt;p&gt;Let's use the example above; let's say I finished implementing &lt;code&gt;mul2&lt;/code&gt;, and then wrote the test below:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return the product&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mul2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice anything? The assertion statement is missing, but the actual test will pass&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. Here even though everything looks okay, the test itself is not trustworthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a ridiculous example, that would never happen!
&lt;/h2&gt;

&lt;p&gt;Well yes it's a bit silly, but it highlights a central problem with unit testing. Namely:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you know that the test you've written is correct?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Any alternative proposed to TDD &lt;strong&gt;must&lt;/strong&gt; be able to solve this problem or else it cannot be said to be viable.&lt;/p&gt;

&lt;p&gt;The fact that the test is written first solves this problem. If the test is correct, it &lt;em&gt;must&lt;/em&gt; fail.&lt;/p&gt;

&lt;p&gt;In the example above you expect it to fail, so you'll revisit the test-code when you see it's passing even if no code is present. The rules push you to prioritize confidence in the test first before starting on the change you want to make.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Logical Errors, TDD won't save me there
&lt;/h2&gt;

&lt;p&gt;TDD doesn't guarantee that your code is bug-free. It just guarantees that if a line is deleted that a test will fail. Therefore it's still your responsibility to write the correct tests. For example if the requirement was to multiply two numbers, but your tests are checking if the code adds the two together then your code is still wrong.&lt;/p&gt;

&lt;p&gt;In such a scenario, TDD helps in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it makes such an error easier to spot during code-review

&lt;ul&gt;
&lt;li&gt;since your &lt;code&gt;expected&lt;/code&gt; value will clearly be something different than the requirement, someone can flag it as an issue&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;once the error is spotted, it becomes easier to rewrite the bad test or to add tests for missing edge cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since refactoring is easier, this whole process happens much more quickly. And yes, while fixing one issue you're less likely to introduce a regression.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is all horribly complicated! I'm a pretty good programmer, I don't need all this
&lt;/h2&gt;

&lt;p&gt;That might be true, you might not need tests in order to produce good quality code. However, you're not the only person on your team. Also, you're probably not going to be on that team forever; tomorrow you might move on to another project or even to another company. What happens then?&lt;/p&gt;

&lt;p&gt;Writing tests is a way to communicate&lt;sup id="fnref3"&gt;3&lt;/sup&gt; the behaviour of the code without needing to write extensive documentation that no one will ever read (or maintain). Good-quality unit tests save an incredible amount of dev-hours, and can help a team to maintain a stable velocity as it grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  What exactly are good-quality tests?
&lt;/h2&gt;

&lt;p&gt;One key aspect of a "good" test would be that they are &lt;a href="https://dev.to/jlouzado/tdd-your-unit-tests-should-be-immutable-119m"&gt;immutable to refactoring&lt;/a&gt;. That means that once a test is written, it shouldn't change as long as the requirements don't change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, but how does that translate to "saved" dev-hours?
&lt;/h2&gt;

&lt;p&gt;One of hardest parts of building software is simply managing the communication overhead as the team scales. The number of connections between people is proportional to $N^2$ for $N$ members. So very quickly, it becomes almost impossible to keep everyone in sync if it requires talking to everyone about everything. Various solutions like "write documentation" or "write code that is so clear it doesn't need documentation" are all theoretically possible but are largely pipe-dreams. If it's possible to have a test suite for something, it's the ultimate safety-net and allows developers to make changes without worrying.&lt;/p&gt;

&lt;h2&gt;
  
  
  You say TDD is a timesaver, but updating old tests is a huge waste of time!
&lt;/h2&gt;

&lt;p&gt;If you're following TDD correctly, you shouldn't find yourself updating old tests. Once you write a test, they should be &lt;a href="https://dev.to/jlouzado/tdd-your-unit-tests-should-be-immutable-119m"&gt;immutable to refactoring&lt;/a&gt; i.e. it won't change as long as the API and the requirements haven't changed.&lt;/p&gt;

&lt;p&gt;If you find yourself doing TDD but also going back over old-tests a lot, then a couple of things might be going wrong:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Function's API needs improvement
&lt;/h3&gt;

&lt;p&gt;When you're writing that first test, spend more time designing your unit's signature to be extensible. Think of the &lt;a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle"&gt;Open-Closed Principle&lt;/a&gt;, but applied to a function instead of a class.&lt;/p&gt;

&lt;p&gt;We'll get into the specifics of writing that first test further down.&lt;/p&gt;

&lt;h3&gt;
  
  
  You're writing too much code too soon
&lt;/h3&gt;

&lt;p&gt;Let's say you're trying to implement an expression: $A+!B$ (A or not-B). The first would be:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return true if A is true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What should the implementation be? Your impulse might be to write the following:&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the least code required to make this test pass would simply be:&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;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sounds ridiculous for simple examples, but when writing complex algorithms it's common to fall into the trap of over-engineering. However, &lt;a href="https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction"&gt;no abstraction is better than the wrong one&lt;/a&gt; and being disciplined about writing minimal code helps us get all the examples working before trying to solve for other concerns like performance, reusability, maintainability, etc.&lt;/p&gt;

&lt;p&gt;In a way, TDD pushes us to focus on one thing at a time so that we can be completely focused on it. One test at a time, one solution at a time, and then refactor for one purpose at a time. When you're doing one thing, you don't have to hold everything in your mind since you know that the test suite has your back.&lt;/p&gt;

&lt;p&gt;For a more complex example check out &lt;a href="https://itnext.io/the-missing-practical-step-by-step-test-driven-development-a7140ca4b71"&gt;The Missing Practical Step in TDD&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Your tests are too specific, or too restrictive
&lt;/h3&gt;

&lt;p&gt;This might sound funny, but it's possible for tests to be overly specific. We've touched on this before, but tests should really be agnostic of implementation. In other words they should care about &lt;em&gt;behaviour&lt;/em&gt; and not be asserting on structure.&lt;/p&gt;

&lt;p&gt;The obvious example would be the test from the earlier section where we're asserting a DOM structure but there's other ways that a test can be too restrictive.&lt;/p&gt;

&lt;p&gt;Let's say you're building a &lt;a href="https://www.freecodecamp.org/news/an-introduction-to-the-flux-architectural-pattern-674ea74775c9/"&gt;Flux&lt;/a&gt;-like App (using something like React-Redux), and you need some code to emit an &lt;code&gt;Action&lt;/code&gt;. Your first test might be:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should fire Action-A1 when a X is true&lt;/span&gt;&lt;span class="dl"&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 your test might be:&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="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A1&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 write a new test:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should fire Action-A2 when X is true&lt;/span&gt;&lt;span class="dl"&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'll write the second test as follows:&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="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that now you're stuck; test1 and test2 are both mutually exclusive because something can't be strictly equal to two things at the same time. In this case, saying &lt;code&gt;strictEqual&lt;/code&gt; is overly specific; it's saying "this and only this is allowed to happen".&lt;/p&gt;

&lt;p&gt;What might be closer to your intent is to say "whatever else is also happening, I &lt;em&gt;also&lt;/em&gt; want this to happen". So you could rewrite your tests using some kind of &lt;code&gt;contains&lt;/code&gt; utility as such:&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="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now tomorrow if any number of actions are fired, your test is making sure that this action is also present. And if you've followed TDD so far, extra actions won't be fired from anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does that mean there any cases where one shouldn't or can't use TDD?
&lt;/h2&gt;

&lt;p&gt;For application development, almost everything is a good candidate for TDD. One exception is where it's not possible to write a test without being over-specific. For example there's little value in writing a test like &lt;code&gt;Assert that function returns &amp;lt;div&amp;gt;Hello World!&amp;lt;/div&amp;gt;&lt;/code&gt; and then having a function that returns &lt;code&gt;&amp;lt;div&amp;gt;Hello World!&amp;lt;/div&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;could&lt;/em&gt; do it, but then tomorrow if you need to return &lt;code&gt;&amp;lt;div&amp;gt;Hello &amp;lt;b&amp;gt;World!&amp;lt;/b&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; should the test really break? I mean, I've only added an enhancement, the old test should "technically" still be valid.&lt;/p&gt;

&lt;p&gt;The above example doesn't mean that all view-related things are automatically not eligible for TDD. To take an example of an App written in the &lt;a href="https://www.freecodecamp.org/news/an-introduction-to-the-flux-architectural-pattern-674ea74775c9/"&gt;Flux&lt;/a&gt; pattern, you might have a rock-solid reducer ready and waiting but then you might forget to actually fire an action from the view when a button is clicked. Packages like &lt;a href="https://github.com/testing-library/react-testing-library"&gt;react-testing-library&lt;/a&gt; are good for use-cases like that, and can provide coverage for your views too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Any others?
&lt;/h2&gt;

&lt;p&gt;Yes, if you're writing a new package, and there's two potential APIs that would both work equally fine but they both have different (say) performance implications then that might be a bad use-case for TDD. Tests can't help you choose between two different function signatures, for example. In such a case you're really out near the edge of software-development and you're in research mode. TDD will be of more use once you've explored the space sufficiently and sorted out the architecture.&lt;/p&gt;

&lt;p&gt;Speaking of architecture, structure your code so that more things are unit-testable, otherwise you end up with scenarios where you have to compulsively mock everything and you're testing "structure", rather than "behaviour"&lt;sup id="fnref4"&gt;4&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;I can't stress this enough though, almost everything related to Application Development can be done via TDD. As much as possible, irrespective of the structure of your application, extract your business logic into pure functions and TDD the heck out of it. You'll thank yourself later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your examples are a bit weird
&lt;/h2&gt;

&lt;p&gt;Well we've been talking about TDD so far but it's sort of a &lt;a href="https://medium.com/@fagnerbrack/wittgenstein-s-beetle-in-software-engineering-dcea89a5db92"&gt;Wittgenstein's Beetle&lt;/a&gt; where everyone has a thing in their box called a beetle and can only see their own box's contents. So then people might say "TDD is good" or "TDD is bad" and be talking about entirely different things.&lt;/p&gt;

&lt;p&gt;Here's what I mean when I'm talking about TDD:&lt;/p&gt;

&lt;p&gt;A quick recap of TDD's rules from &lt;a href="http://www.javiersaldana.com/articles/tech/refactoring-the-three-laws-of-tdd"&gt;Uncle Bob&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are not allowed to write any production code unless it is to make a failing unit test pass.&lt;/li&gt;
&lt;li&gt;You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.&lt;/li&gt;
&lt;li&gt;You are not allowed to write any more production code than is sufficient to pass the one failing unit test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, write only enough of a unit test to fail.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;RED&lt;/code&gt; phase&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Write only enough production code to make the failing unit test pass.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GREEN&lt;/code&gt; phase.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Repeat till all requirements are met, refactor as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice it might look like this. We'll take a simple example to start with. Say, I want to write a function &lt;code&gt;mul2&lt;/code&gt; that returns the product of two arguments:&lt;/p&gt;

&lt;p&gt;First create the test-file: &lt;code&gt;mul2.test.ts&lt;/code&gt; and start writing the test:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return the product&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mul2&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;As soon as this is written, the compiler will complain that &lt;code&gt;mul2&lt;/code&gt; doesn't exist. Only at this point do you actually create the &lt;code&gt;mul2.ts&lt;/code&gt; file and write:&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;const&lt;/span&gt; &lt;span class="nx"&gt;mul2&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="k"&gt;throw&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not implemented&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All you know is that it's a function, which is what you've declared. No implementation yet, no arguments either.&lt;/p&gt;

&lt;p&gt;Back to the test:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return the product&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mul2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler will complain: "Function doesn't accept values". Fair enough, now is a good time to think about the "API" of our function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are the order of the arguments,

&lt;ul&gt;
&lt;li&gt;important if the function might be curried&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Can any of them be null? do any of them have default values? What are their names?&lt;/li&gt;
&lt;li&gt;What's the return type of the function?
&lt;/li&gt;
&lt;/ul&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;const&lt;/span&gt; &lt;span class="nx"&gt;mul2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&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;b&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not implemented&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since it's just a simple function, the types are pretty basic but if there were more complex behaviour, here's where we would take care of that&lt;sup id="fnref5"&gt;5&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Back to the test, now we can add our assertion:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return the product&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mul2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test itself is now runnable. Run it, and it'll throw "Not Implemented" as we told it to. This is the point people skip to when they think of unit-tests, but it takes a lot of thinking even to get to this point; we're just so used to doing it we forget to account for it.&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;const&lt;/span&gt; &lt;span class="nx"&gt;mul2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&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;b&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that your test will pass, and you can start with the next test!&lt;/p&gt;

&lt;h2&gt;
  
  
  This way of writing tests seems super annoying
&lt;/h2&gt;

&lt;p&gt;Writing code this way is definitely a little unnatural at first, but it makes sure that nothing extraneous ever enters your code base. When people talk about Lean-Testing, and only writing the minimum tests required, this is really what that looks like; no more tests than necessary, no more code than needed.&lt;/p&gt;

&lt;p&gt;Over time your intuition for this style will grow and your compiler will come to feel like a helpful (if slightly pedantic) aide who just wants the best for you and your code. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Where would I go to learn more?
&lt;/h2&gt;

&lt;p&gt;If you're looking to read more about TDD, I'd highly recommend &lt;a href="https://itnext.io/you-dont-know-tdd-691efe670094"&gt;You Don't Know TDD&lt;/a&gt; which was what I used when I was first learning about this. It's a really rich resource and he deals with much more complex examples than I have here.&lt;/p&gt;

&lt;p&gt;In the meantime if you'd like to know how more about writing tests that don't break during refactoring, check out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dev.to/jlouzado/tdd-your-unit-tests-should-be-immutable-119m"&gt;Your Tests Should Be Immutable&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Feel free to hit me up on &lt;a href="https://twitter.com/jlouzado"&gt;Twitter&lt;/a&gt; if you have any questions and good luck out there. 🙏&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Assume the deletion was accidental, and in such a way that the code still compiles. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Run it in your IDE and check for yourself if you don't believe me. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;One caveat, don't try to communicate the "Why" of a change using tests. Tests are about behaviour, not purpose. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;This is similar to the previous example, where we don't want to write a test to guarantee a particular DOM structure. Check out &lt;a href="https://dev.to/danlebrero/the-tragedy-of-100-code-coverage"&gt;the tragedy of 100% code-coverage&lt;/a&gt; for more. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;If the typings are very complex, you might even want some way to develop &lt;em&gt;those&lt;/em&gt; using TDD, but that's another topic entirely. Check out something like &lt;a href="https://www.npmjs.com/package/typings-checker"&gt;typings-checker&lt;/a&gt; if you're interested. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
      <category>unittesting</category>
    </item>
  </channel>
</rss>
