<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ test driven development - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ test driven development - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 30 May 2026 16:32:00 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/test-driven-development/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Do Test-Driven Development with Svelte and Vitest – A Project-Based Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ By Sriram Thiagarajan Test Driven Development (TDD) is one of the best ways to make sure your code is high quality and works like it's supposed to work. It can also help you create reliable builds during continuous deployments.  In this post, we will... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-do-test-driven-development-with-svelte-and-vitest/</link>
                <guid isPermaLink="false">66d461492472e5ed2fa07bbd</guid>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TDD (Test-driven development) ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vite ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 19 Sep 2022 17:20:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/SvelteVitestTDDPoster.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sriram Thiagarajan</p>
<p>Test Driven Development (TDD) is one of the best ways to make sure your code is high quality and works like it's supposed to work. It can also help you create reliable builds during continuous deployments. </p>
<p>In this post, we will learn how to create a Svelte application using TDD methods.</p>
<h2 id="heading-what-were-building">What We're Building</h2>
<p>We are going to build a vertical tabs component where we can switch between three tabs. We are going to build this component by writing test cases first and developing the component functionality after that to make the tests more effective.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/FinalComponent-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Final implementation</em></p>
<h2 id="heading-prerequisite">Prerequisite</h2>
<p>I will explain all the steps needed to create an app and you can follow along with the code. It's great if you have basic programming knowledge and fundamental knowledge of HTML and CSS for this tutorial.</p>
<p>Also, you'll need to have Node.js installed. You can <a target="_blank" href="https://nodejs.org/en/">see how to do that here</a> if you don't have it already.</p>
<h2 id="heading-what-is-test-driven-development">What is Test-Driven Development?</h2>
<p>The basic idea of test-driven development, or TDD, is to write the test before you implement the actual functionality. This helps you clearly figure out what you're developing and how it works. </p>
<p>You first watch the test fail, and then you write the code to make it pass. This ensures that there are no false positive tests in your code.</p>
<p>TDD is a methodology you can apply to any programming language. It is more prevalent when developing backend applications that contain business logic that you can easily test. </p>
<p>The good news is, you can apply similar techniques to test your front-end applications as well.</p>
<h2 id="heading-three-stages-of-tdd">Three stages of TDD</h2>
<p>The three stages of TDD are:</p>
<ol>
<li>Red stage – Write the test and watch it fail</li>
<li>Green stage – Write the minimum code required to make the test pass</li>
<li>Refactor – Cleanup and refactor the code to make it more robust</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/TDDStages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Three stages of TDD</em></p>
<h2 id="heading-what-is-vitest">What is Vitest?</h2>
<p>Vitest is an up-and-coming testing framework which has similar functionality to Jest. </p>
<p>Since we are using Vite as our build tool for Svelte in this tutorial, Vitest has very good integration with Vite and offers a similar testing environment without needing extra configuration.</p>
<h2 id="heading-how-to-create-a-svelte-application">How to Create a Svelte Application</h2>
<p>We are going to create a Svelte application using Vite as the build tool. You can do that with this command:</p>
<pre><code>npm create vite@latest
</code></pre><p>This will create a new project, and you can follow the steps below to create and setup the project:</p>
<ol>
<li>Enter the name of the project. This will also create a new folder with the project name. In this example, I will add the project name as <code>svelte-tdd-vitest</code>.</li>
<li>You can select the framework in the next step. Let's choose <code>svelte</code> as the framework.</li>
<li>Then you can enter the variant of the framework. We can choose the <code>TypeScript</code> variant for this article. If you are not comfortable with TypeScript, you can also choose <code>JavaScript</code> in this option.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/ProjectInit.png" alt="Image" width="600" height="400" loading="lazy">
<em>Initialise Svelte project with Vite</em></p>
<p>You can then follow the helpful steps provided in the terminal to install the dependencies and start the application. Run the following command:</p>
<pre><code>cd svelte-tdd-vitest
npm install
npm run dev
</code></pre><p><code>npm install</code> will install the dependencies of the project. </p>
<p><code>npm run dev</code> will start the development server. You should see the app running in the port specified in the terminal.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/ViteServerStartCmd.png" alt="Image" width="600" height="400" loading="lazy">
<em>Vite Server started using npm run dev</em></p>
<p>Congrats, you can now see the starter app running in your browser. You can open the project in your favourite Code Editor and start working.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/SvelteViteStarter.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-set-up-vitest">How to Set Up Vitest</h2>
<p>You can add Vitest to the project right now as a dev dependency. This means that Vitest will not be packaged into the production build of the application since you will be running the test in your local environment.</p>
<pre><code>npm install -D vitest
</code></pre><p>Vitest can read the config of Vite inside the <code>vite.config.js</code> file and prepare the test environment similar to the build environment. This makes the test more reliable. So you can reuse the Vite config file and add more options for the configuration of Vitest.</p>
<p>You can also override the config for the Vitest by creating a new file called <code>vitest.config.js</code> in the project root. So now, create a new file called <code>vitest.config.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest/config'</span>
<span class="hljs-keyword">import</span> { svelte } <span class="hljs-keyword">from</span> <span class="hljs-string">'@sveltejs/vite-plugin-svelte'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">plugins</span>: [
    svelte({ <span class="hljs-attr">hot</span>: !process.env.VITEST }),
  ],
  <span class="hljs-attr">test</span>: {
    <span class="hljs-attr">environment</span>: <span class="hljs-string">'jsdom'</span>,
  }
})
</code></pre>
<p>There are a couple of configs we are adding to the file</p>
<ol>
<li>We are disabling Svelte's hot module reload when tests are running. </li>
<li>We are defining the environment for running the test as <code>jsdom</code>. It helps in mocking the DOM API and running the tests in a reliable method.</li>
</ol>
<p>In order to use the <code>jsdom</code> you need to add it as an Dev Dependency as well. So let's install that package using the terminal.</p>
<pre><code>npm install -D jsdom
</code></pre><p>After installation, let's add a couple of scripts to the <code>package.json</code> file to start the Vitest test from the <code>npm</code> command line:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    ...
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"vitest"</span>,
        <span class="hljs-attr">"coverage"</span>: <span class="hljs-string">"vitest run --coverage"</span>
}
</code></pre>
<h2 id="heading-how-to-create-the-first-test">How to Create the First Test</h2>
<p>You now have all the setup needed to write your first test. Create a new file called <code>sample.spec.ts</code> inside the <code>lib</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {describe, test, expect } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest'</span>;

describe(<span class="hljs-string">"Example File"</span>, <span class="hljs-function">() =&gt;</span> {
    test(<span class="hljs-string">"Sample test"</span>, <span class="hljs-function">() =&gt;</span> {
        expect(<span class="hljs-number">1</span> + <span class="hljs-number">3</span>).equal(<span class="hljs-number">4</span>);
    });
});
</code></pre>
<p>Let's break down the different functions used to create this test file:</p>
<ol>
<li><code>describe</code> – you use this to group similar test together and benchmark tests when generating your reports. It takes a name and a function that contains the group of tests.</li>
<li><code>test</code> – Represents a single test. It can contain multiple expectations within it. It is created by passing a name of the test and the function to run the test.</li>
<li><code>expect</code> – Represents the expression which you're testing.</li>
</ol>
<p>There are multiple different ways to write your test based on what you are testing. You can have a look at the complete API for Vitest in the <a target="_blank" href="https://vitest.dev/api/">official API Reference</a>.</p>
<p>Let's run the test using the following npm command:</p>
<pre><code>npm run test
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/09/NpmRunFirstTest.png" alt="Image" width="600" height="400" loading="lazy">
<em>Running the test</em></p>
<h2 id="heading-how-to-add-the-global-test-config">How to Add the Global Test Config</h2>
<p>You are going to be using the <code>describe</code>, <code>test</code>, and <code>expect</code> functions a lot in the test files and it might be verbose to import them in all the test files. So Vitest has a nice config where you can set these global imports and so you don't have to add them to each file. </p>
<p>So let's update the <code>vitest.config.js</code> file with this configuration:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  ...
  test: {
    ...
    globals: <span class="hljs-literal">true</span>
  }
})
</code></pre>
<p>After adding this <code>globals</code> equals true line in your config, you can now remove the imports in your spec file. </p>
<p>If you are using TypeScript, your TypeScript compiler will complain in your spec file. You can solve that by adding the following line to your <code>tsconfig.json</code> file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"extends"</span>: <span class="hljs-string">"@tsconfig/svelte/tsconfig.json"</span>,
  <span class="hljs-attr">"compilerOptions"</span>: {
    ...
    <span class="hljs-attr">"types"</span>: [<span class="hljs-string">"vitest/globals"</span>]
  },
}
</code></pre>
<p>Now your test can look like this. This is not a huge upgrade for this small file, but when you have lots of spec files, this config change is useful.</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">"Example File"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"Sample test"</span>, <span class="hljs-function">() =&gt;</span> {
        expect(<span class="hljs-number">1</span> + <span class="hljs-number">3</span>).equal(<span class="hljs-number">4</span>);
    });
});
</code></pre>
<h2 id="heading-how-to-create-a-svelte-component">How to Create a Svelte Component</h2>
<p>We will create a new svelte component called <code>VerticalTabs.svelte</code>. The requirements are to create a vertical tab component that can contain a few items and for the user to be able to select a particular tab to view its content in the right side.</p>
<p>The component will be divided into two parts. The left side displays all the tabs. The right side displays the content based on the tab.</p>
<p>Let's create the basic HTML and CSS styles needed for the component. We will add the functionality to switch tabs after writing the tests.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>First Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Second Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Third Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem aut deserunt veniam tempora deleniti quos reprehenderit natus. Animi, obcaecati dolorum, culpa, maiores maxime ullam soluta unde rerum nihil temporibus quibusdam!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-class">.vertical-tab-container</span> {
        <span class="hljs-attribute">display</span>: flex;
        <span class="hljs-attribute">flex-direction</span>: row;
        <span class="hljs-attribute">align-items</span>: center;
        <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid gray;
        <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
    }

    <span class="hljs-selector-class">.vertical-tab</span> {
        <span class="hljs-attribute">margin</span>: <span class="hljs-number">0px</span>;
        <span class="hljs-attribute">padding</span>: <span class="hljs-number">3rem</span>;
        <span class="hljs-attribute">list-style</span>: none;
        <span class="hljs-attribute">border-right</span>: <span class="hljs-number">1px</span> solid gray
    }

    <span class="hljs-selector-class">.vertical-tab</span> <span class="hljs-selector-tag">li</span> {
        <span class="hljs-attribute">margin</span>: <span class="hljs-number">2rem</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-selector-class">.vertical-tab-content</span> {
        <span class="hljs-attribute">flex</span>:<span class="hljs-number">1</span>
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>In this code, you are adding simple elements like an unordered list to display the list of tabs. You are styling it in the <code>&lt;style&gt;</code> tag which will be locally scoped CSS for this component.</p>
<p>Then, you are adding <code>&lt;h2&gt;</code> tag to display the tab heading and a paragraph tag <code>&lt;p&gt;</code> to show more dummy text for the tab. You're using <code>flex</code> to show the two items side by side and the property of <code>flex: 1</code> on the content will make that container take all the remaining available space to expand.</p>
<p>The component should look like the below image:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/VerticalTabInitial-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Vertical Tab initial</em></p>
<h2 id="heading-how-to-mount-the-svelte-component-in-test">How to Mount the Svelte Component in Test</h2>
<p>Now you need to create the first test for the component by mounting the svelte component and then checking to see if you can find the "First Tab" text in the component. </p>
<p>So create a new spec file called <code>VerticalTabs.spec.ts</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> VerticalTabs <span class="hljs-keyword">from</span> <span class="hljs-string">"./VerticalTabs.svelte"</span>;

describe(<span class="hljs-string">"VerticalTabs Component"</span>, <span class="hljs-function">() =&gt;</span> {

    test(<span class="hljs-string">"should render the component"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// Create a new container for the test</span>
        <span class="hljs-keyword">const</span> host = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>);

        <span class="hljs-comment">// Append the new container in the HTML body</span>
        <span class="hljs-built_in">document</span>.body.appendChild(host);

        <span class="hljs-comment">// Create an instance of the vertical tab</span>
        <span class="hljs-keyword">const</span> instance = <span class="hljs-keyword">new</span> VerticalTabs({ <span class="hljs-attr">target</span>: host });

        <span class="hljs-comment">// Check if the instance has value</span>
        expect(instance).toBeTruthy()

        <span class="hljs-comment">// Test if we can find the "First Tab Heading"</span>
        expect(host.innerHTML).toContain(<span class="hljs-string">"First Tab Heading"</span>)

    });

})
</code></pre>
<p>In order to mount the Svelte component, you need to first create a <code>div</code> container and attach that <code>div</code> to the <code>body</code> of the HTML document. Then you need to attach your component to the <code>div</code>. You can then test the <code>innerHTML</code> of the main container to see if you have the required content.</p>
<p>Now this test should pass since you have the <code>First Tab Heading</code> content displayed in the component.</p>
<p>Going through this long process in all the steps might prove to be difficult. So let's add another package to make the job easier. The package is <code>testing-library/svelte</code> and it provides more features to make the assertions easy and less verbose.</p>
<h2 id="heading-how-to-use-the-svelte-testing-library">How to Use the Svelte Testing Library</h2>
<p>First, you'll need to install the library:</p>
<pre><code>npm install -D @testing-library/svelte
</code></pre><p>Let's update the previous test to make it less verbose and let <code>testing-library</code> handle all the heavy lifting for us. You can use the <code>render</code> function to add the component to the testing page.</p>
<pre><code><span class="hljs-keyword">import</span> VerticalTabs <span class="hljs-keyword">from</span> <span class="hljs-string">"./VerticalTabs.svelte"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/svelte'</span>;

describe(<span class="hljs-string">"VerticalTabs Component"</span>, <span class="hljs-function">() =&gt;</span> {

    test(<span class="hljs-string">"should render the component"</span>, <span class="hljs-function">() =&gt;</span> {

        render(VerticalTabs);

        <span class="hljs-keyword">const</span> firstTabNode = screen.getByText(<span class="hljs-regexp">/First Tab Heading/i</span>)

        expect(firstTabNode).toBeTruthy()
    });

})
</code></pre><p>After the <code>render</code> function, add the component to the testing page. You can use the <code>screen</code> object imported from the library to query the nodes that are rendered.</p>
<p>There are multiple methods inside this object to make testing easy, and you will use one of the methods to get the text in the component.</p>
<p><code>getByText</code> will return the instance of a given text. You are expecting the node to contain some value.</p>
<p>There are three main ways to retrieve the element in the testing library, and each serves a different purpose:</p>
<ol>
<li>getByText – This will throw an error when the text is not found and the test will fail</li>
<li>queryByText – This will return null when the text is not found</li>
<li>findByText – This will also throw an error when the text is not found and you can use it when doing async tests where the element will take some time to appear/disappear</li>
</ol>
<p>You can find a useful summary of these helper functions in the <a target="_blank" href="https://testing-library.com/docs/queries/about">official docs page</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/QueriesSummary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Summary screenshot from Official docs of testing library</em></p>
<p>You can find more details on this API in this <a target="_blank" href="https://testing-library.com/docs/svelte-testing-library/api">official page</a>.</p>
<h2 id="heading-how-to-build-the-tab-switching-feature">How to Build the Tab Switching Feature</h2>
<p>We will start adding the feature to switch tabs in the component and test the component by writing the test first.</p>
<h3 id="heading-red-stage">Red stage</h3>
<p>Let's write a test the switch to a different tab on click of the "Second Tab" list item. </p>
<p>Since we don't have this functionality implemented, we will fail this test first and that's okay. Once we fail the test, we should write the logic to make it pass in the next step. </p>
<p>So let's write a failing test:</p>
<pre><code>test(<span class="hljs-string">"should switch tabs"</span>, <span class="hljs-keyword">async</span> () =&gt; {
        render(VerticalTabs);

        <span class="hljs-keyword">const</span> secondTabElement = screen.getByText(<span class="hljs-regexp">/Second Tab/i</span>);

        fireEvent.click(secondTabElement)

        <span class="hljs-keyword">await</span> screen.findByText(<span class="hljs-regexp">/Second Tab Heading/i</span>);
})
</code></pre><p>We are using the <code>fireEvent</code> from the testing library to simulate the click of the element. We can make the test <code>async</code> and <code>await</code> for the element since the text will change after the element is clicked.</p>
<p>You should have a failing test now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/TestFailing.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test failing unable to find the content</em></p>
<h3 id="heading-green-stage">Green stage</h3>
<p>Let's add the logic to change the tab in the Svelte component. We can do that easily by creating a <code>selectedIndex</code> variable and changing its value based on the selected tab.</p>
<pre><code>&lt;script lang=<span class="hljs-string">"ts"</span>&gt;
    <span class="hljs-keyword">let</span> selectedIndex = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">const</span> changeSecondTab = <span class="hljs-function">() =&gt;</span> {
        selectedIndex = <span class="hljs-number">1</span>;
    }
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>First Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeSecondTab()}&gt;Second Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Third Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span>&gt;</span>
        {#if selectedIndex == 0}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {:else if selectedIndex == 1}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Second Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {/if}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre><p><strong>Note: This is not the best implementation.</strong> It is only meant for showing that you can do minimal work to make the test pass. We will clean it up in the next stage</p>
<p>We have a method <code>changeSecondTab</code> that will change the <code>selectedIndex</code> value to 1 which will make the <code>#if</code> condition to change the tab. Even though it is not the best solution to handle all cases, we have a starting point.</p>
<p>Let's look at the test now. It should be working:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/TestPassed.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-refactor">Refactor</h3>
<p>Let's fix the implementation to make it more generic and have it work for all three tabs. We can also add an indicator to show which tab is currently selected.</p>
<pre><code class="lang-javascript">&lt;script lang=<span class="hljs-string">"ts"</span>&gt;
    <span class="hljs-keyword">let</span> selectedIndex = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">const</span> changeTab = <span class="hljs-function">(<span class="hljs-params">index: number</span>) =&gt;</span> {
        selectedIndex = index;
    }
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class:selected</span>=<span class="hljs-string">{selectedIndex</span> == <span class="hljs-string">0}</span> 
            <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeTab(0)}&gt;First Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class:selected</span>=<span class="hljs-string">{selectedIndex</span> == <span class="hljs-string">1}</span> 
            <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeTab(1)}&gt;Second Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class:selected</span>=<span class="hljs-string">{selectedIndex</span> == <span class="hljs-string">2}</span> 
            <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeTab(2)}&gt;Third Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span>&gt;</span>
        {#if selectedIndex == 0}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {:else if selectedIndex == 1}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Second Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {:else}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Third Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {/if}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    ...
    <span class="hljs-selector-class">.selected</span> {
        <span class="hljs-attribute">color</span>: blue;
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p>We have created a method <code>changeTab</code> that will be called on the click of each element and then change the <code>selectedIndex</code>. This will cause the <code>#if</code> logic to change the tab based on its value.</p>
<p>We also have <code>class:selected</code> followed by an expression and when the expression becomes true, the <code>selected</code> class is added to the element. So we have added one more CSS class and we made the text colour blue to show the selected tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/FinalComponent.png" alt="Image" width="600" height="400" loading="lazy">
<em>Finished vertical tabs component</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-375.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test after finishing refactor</em></p>
<p>We have now confirmed that the test is also passing after the refactor. You can continue this process to add more tests and features to your component.</p>
<h2 id="heading-how-to-add-animation">How to Add Animation</h2>
<p>Svelte makes it easy to add animation when content is changed. You can make use of the <code>transition</code> directive to add pre-built animation to your application.</p>
<p>So let's add a fly animation when the content changes. You can import the fly animation from <code>svelte/transition</code> and then add it to the element using <code>transition:fly</code>. This will add the default fly animation when the content flies out and new content flies in. Such a neat effect with just a single line of code!</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { fly } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/transition'</span>;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span> &gt;</span>
        {#if selectedIndex == 0}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">transition:fly</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {:else if selectedIndex == 1}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">transition:fly</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Second Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {:else}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">transition:fly</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Third Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {/if}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Animation brings life to your application and helps it stand out. I am a big fan of the simple animation transition system in Svelte.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you have learned how to create a new component using test-driven development methodology. Please share your feedback on this post and let me know your thoughts.</p>
<p>Thanks for reading! You can contact me on Twitter <a target="_blank" href="https://twitter.com/sriram_thiagar">@sriram_thiagar</a>. I regularly post articles on my blog <a target="_blank" href="https://www.eternaldev.com/">eternaldev.com</a> if you want to read more articles from me.</p>
<p>Hello everyone. I am Sriram, and I work as a Full Stack developer. I like to share my learning with others. I have been <a target="_blank" href="https://www.eternaldev.com/">blogging</a> for more than a year now on my website.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Test-Driven Development Tutorial – How to Test Your JavaScript and ReactJS Applications ]]>
                </title>
                <description>
                    <![CDATA[ Understanding test-driven development is an essential part of being a prolific software developer. Testing provides a solid platform for building reliable programs. This tutorial will show you all you need to implement test-driven development in your... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/test-driven-development-tutorial-how-to-test-javascript-and-reactjs-app/</link>
                <guid isPermaLink="false">66ba0e0ed14c87384322b685</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi Sofela ]]>
                </dc:creator>
                <pubDate>Tue, 26 Jul 2022 17:51:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/07/test-driven-development-tutorial-how-to-test-javascript-and-reactjs-app-codesweetly-battlecreek-coffee-roasters-i22gbC3gFm4-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Understanding test-driven development is an essential part of being a prolific software developer. Testing provides a solid platform for building reliable programs.</p>
<p>This tutorial will show you all you need to implement test-driven development in your JavaScript and React applications.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-test-driven-development">What Is Test-Driven Development?</a></li>
<li><a class="post-section-overview" href="#heading-javascript-example-of-a-test-driven-development-workflow">JavaScript Example of a Test-Driven Development Workflow</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-jest-as-a-test-implementation-tool">How to Use Jest as a Test Implementation Tool</a></li>
<li><a class="post-section-overview" href="#heading-important-stuff-to-know-about-using-es6-modules-with-jest">Important Stuff to Know about Using ES6 Modules with Jest</a></li>
<li><a class="post-section-overview" href="#heading-what-are-the-advantages-of-test-driven-development">What Are the Advantages of Test-Driven Development?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-unit-test-in-test-driven-development">What is a Unit Test in Test-Driven Development</a>?</li>
<li><a class="post-section-overview" href="#heading-what-is-an-integration-test-in-test-driven-development">What is an Integration Test in Test-Driven Development</a>?</li>
<li><a class="post-section-overview" href="#heading-what-is-an-end-to-end-test-in-test-driven-development">What is an End-to-End Test in Test-Driven Development</a>?</li>
<li><a class="post-section-overview" href="#heading-what-are-test-doubles-in-test-driven-development">What are Test Doubles in Test-Driven Development</a>?</li>
<li><a class="post-section-overview" href="#heading-quick-overview-of-test-driven-development-so-far">Quick Overview of Test-Driven Development So Far</a></li>
<li><a class="post-section-overview" href="#heading-how-to-test-react-components">How to Test React Components</a></li>
<li><a class="post-section-overview" href="#heading-test-runner-vs-react-component-testing-tool-whats-the-difference">Test Runner vs. React Component Testing Tool: What's the Difference?</a></li>
<li><a class="post-section-overview" href="#heading-project-how-react-testing-works">Project: How React Testing Works</a></li>
<li><a class="post-section-overview" href="#heading-overview">Overview</a></li>
</ol>
<p>So, without any further ado, let's get started by discussing what test-driven development means.</p>
<h2 id="heading-what-is-test-driven-development">What Is Test-Driven Development?</h2>
<p><strong>Test-driven development (TDD)</strong> is a coding practice where you write the result you want your program to produce before creating the program.</p>
<p>In other words, TDD requires you to pre-specify the output your intended program must produce to pass the test of functioning the way you envisioned.</p>
<p>So, in an effective test-driven development practice, you would first write tests that express the result you expect from your intended program.</p>
<p>Afterward, you would develop the program to pass the prewritten test.</p>
<p>For instance, suppose you wish to create an addition calculator. In such a case, the TDD approach will be like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/test-driven-development-tdd-workflow-diagram-codesweetly.png" alt="Test-driven development workflow diagram" width="600" height="400" loading="lazy">
<em>Test-driven development workflow diagram</em></p>
<ol>
<li>Write a test specifying the result you expect the calculator to produce to pass the test of being the program you had in mind.</li>
<li>Develop the calculator to pass the prewritten test.</li>
<li>Run the test to check whether the calculator passes or fails the test.</li>
<li>Refactor your test code (if necessary).</li>
<li>Refactor your program (if necessary).</li>
<li>Continue the cycle until the calculator matches your vision.</li>
</ol>
<p>Let's now see a JavaScript example of a TDD workflow.</p>
<h2 id="heading-javascript-example-of-a-test-driven-development-workflow">JavaScript Example of a Test-Driven Development Workflow</h2>
<p>The steps below will use a simple JavaScript program to show you how to approach TDD.</p>
<h3 id="heading-1-write-your-test">1. Write your test</h3>
<p>Write a test that specifies the result you expect your calculator program to produce:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">additionCalculatorTester</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (additionCalculator(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>) === <span class="hljs-number">10</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"✔ Test Passed"</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"❌ Test Failed"</span>);
  }
}
</code></pre>
<h3 id="heading-2-develop-your-program">2. Develop your program</h3>
<p>Develop the calculator program to pass the prewritten test:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">additionCalculator</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}
</code></pre>
<h3 id="heading-3-run-the-test">3. Run the test</h3>
<p>Run the test to check whether the calculator passes or fails the test:</p>
<pre><code class="lang-js">additionCalculatorTester();
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-ciui1u?devToolsHeight=33&amp;file=index.js"><strong>Try it on StackBlitz</strong></a></p>
<h3 id="heading-4-refactor-the-test">4. Refactor the test</h3>
<p>After you've confirmed that your program passed the prewritten test, it's time to check if there's any need to refactor it.</p>
<p>For instance, you could refactor <code>additionCalculatorTester()</code> to use a <a target="_blank" href="https://codesweetly.com/javascript-statement/#what-is-a-conditional-ternary-operator-in-javascript">conditional operator</a> like so:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">additionCalculatorTester</span>(<span class="hljs-params"></span>) </span>{
  additionCalculator(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>) === <span class="hljs-number">10</span> 
    ? <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"✔ Test Passed"</span>) 
    : <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"❌ Test Failed"</span>);
}
</code></pre>
<h3 id="heading-5-refactor-the-program">5. Refactor the program</h3>
<p>Let's also refactor the program's code to use an <a target="_blank" href="https://codesweetly.com/javascript-function-object#arrow-function-expression-in-javascript">arrow function</a>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> additionCalculator = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;
</code></pre>
<h3 id="heading-6-run-the-test">6. Run the test</h3>
<p>Rerun the test to ensure your program still works as intended.</p>
<pre><code class="lang-js">additionCalculatorTester();
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-xp732h?devToolsHeight=33&amp;file=index.js"><strong>Try it on StackBlitz</strong></a></p>
<p>Notice that in the examples above, we implemented TDD without using any libraries.</p>
<p>But you can also use powerful test-running tools like <a target="_blank" href="https://jasmine.github.io/">Jasmine</a>, <a target="_blank" href="https://mochajs.org/">Mocha</a>, <a target="_blank" href="https://github.com/substack/tape">Tape</a>, and <a target="_blank" href="https://jestjs.io/">Jest</a>, to make your test implementation faster, simpler, and more fun.</p>
<p>Let's see how to use Jest, for example.</p>
<h2 id="heading-how-to-use-jest-as-a-test-implementation-tool">How to Use Jest as a Test Implementation Tool</h2>
<p>Here are the steps you'll need to follow to get started using Jest as your test implementation tool:</p>
<h3 id="heading-step-1-get-the-right-node-and-npm-version">Step 1: Get the right Node and NPM version</h3>
<p>Make sure you have Node 10.16 (or greater) and NPM 5.6 (or greater) installed on your system.</p>
<p>You can get both by installing the latest LTS from the <a target="_blank" href="https://nodejs.org/en/">Node.js</a> website.</p>
<p>If you prefer to use Yarn, ensure you have <a target="_blank" href="https://yarnpkg.com/">Yarn 0.25 (or greater)</a>.</p>
<h3 id="heading-step-2-create-a-project-directory">Step 2: Create a project directory</h3>
<p>Create a new folder for your project.</p>
<pre><code class="lang-bash">mkdir addition-calculator-jest-project
</code></pre>
<h3 id="heading-step-3-navigate-to-your-project-folder">Step 3: Navigate to your project folder</h3>
<p>Using the command line, navigate to your project directory.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> path/to/addition-calculator-jest-project
</code></pre>
<h3 id="heading-step-4-create-a-packagejson-file">Step 4: Create a <code>package.json</code> file</h3>
<p>Initialize a <code>package.json</code> file for your project.</p>
<pre><code class="lang-bash">npm init -y
</code></pre>
<p>Or, if your <a target="_blank" href="https://codesweetly.com/package-manager-explained">package manager</a> is Yarn, run:</p>
<pre><code class="lang-bash">yarn init -y
</code></pre>
<h3 id="heading-step-5-install-jest">Step 5: Install Jest</h3>
<p>Install Jest as a development dependency package like so:</p>
<pre><code class="lang-bash">npm install jest --save-dev
</code></pre>
<p>Alternatively, if your package manager is Yarn, run:</p>
<pre><code class="lang-bash">yarn add jest --dev
</code></pre>
<h3 id="heading-step-6-make-jest-your-projects-test-runner-tool">Step 6: Make Jest your project's test runner tool</h3>
<p>Open your <code>package.json</code> file and add Jest to the <code>test</code> field.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jest"</span>
  }
}
</code></pre>
<h3 id="heading-step-7-create-your-project-file">Step 7: Create your project file</h3>
<p>Create a file that you will use to develop your program.</p>
<pre><code class="lang-bash">touch additionCalculator.js
</code></pre>
<h3 id="heading-step-8-create-your-test-file">Step 8: Create your test file</h3>
<p>Create a file that you will use to write your test cases.</p>
<pre><code class="lang-bash">touch additionCalculator.test.js
</code></pre>
<p><strong>Note:</strong> Your test file's name must end with <code>.test.js</code>—so that Jest can recognize it as the file containing your test code.</p>
<h3 id="heading-step-9-write-your-test-case">Step 9: Write your test case</h3>
<p>Open your test file and write some test code that specifies the result you expect your program to produce.</p>
<p><strong>Here's an example:</strong></p>
<pre><code class="lang-js"><span class="hljs-comment">// additionCalculator.test.js</span>

<span class="hljs-keyword">const</span> additionCalculator = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./additionCalculator"</span>);

test(<span class="hljs-string">"addition of 4 and 6 to equal 10"</span>, <span class="hljs-function">() =&gt;</span> {
  expect(additionCalculator(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>)).toBe(<span class="hljs-number">10</span>);
});
</code></pre>
<p>Here's what we did in the snippet above:</p>
<ol>
<li>We imported the <code>additionCalculator.js</code> project file into the <code>additionCalculator.test.js</code> test file.</li>
<li>We wrote a test case specifying that we expect the <code>additionCalculator()</code> program to output <code>10</code> whenever users provide <code>4</code> and <code>6</code> as its <a target="_blank" href="https://codesweetly.com/javascript-arguments">argument</a>.</li>
</ol>
<p><strong>Note:</strong></p>
<ul>
<li><a target="_blank" href="https://jestjs.io/docs/api#testname-fn-timeout"><code>test()</code></a> is one of Jest's global methods. It accepts three arguments:<ol>
<li>The name of the test (<code>"addition of 4 and 6 to equal 10"</code>).</li>
<li>A function containing the expectations you wish to test.</li>
<li>An optional timeout argument.</li>
</ol>
</li>
<li><a target="_blank" href="https://jestjs.io/docs/expect#expectvalue"><code>expect()</code></a> is a Jest method that lets you test the output of your code.</li>
<li><a target="_blank" href="https://jestjs.io/docs/expect#tobevalue"><code>toBe()</code></a> is a <a target="_blank" href="https://jestjs.io/docs/using-matchers">Jest matcher</a> function that enables you to compare <code>expect()</code>'s argument to primitive values.</li>
</ul>
<p>Suppose you run the test code now. The test would fail because you've not developed the program for which you created the test. So, let's do that now.</p>
<h3 id="heading-step-10-develop-your-program">Step 10: Develop your program</h3>
<p>Open your project file and develop a program to pass the prewritten test.</p>
<p><strong>Here's an example:</strong></p>
<pre><code class="lang-js"><span class="hljs-comment">// additionCalculator.js</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">additionCalculator</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-built_in">module</span>.exports = additionCalculator;
</code></pre>
<p>The snippet above created an <code>additionCalculator()</code> program and exported it with the <code>module.exports</code> statement.</p>
<h3 id="heading-step-11-run-the-test">Step 11: Run the test</h3>
<p>Run the prewritten test to check if your program passed or failed.</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>
</code></pre>
<p>Alternatively, you can use Yarn like so:</p>
<pre><code class="lang-bash">yarn <span class="hljs-built_in">test</span>
</code></pre>
<p>Suppose your project contains multiple test files, and you wish to run a specific one. In such a case, specify the test file as follow:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span> additionCalculator.test.js
</code></pre>
<p>Alternatively, you can use Yarn like this:</p>
<pre><code class="lang-bash">yarn <span class="hljs-built_in">test</span> additionCalculator.test.js
</code></pre>
<p>Once you've initiated the test, Jest will print a pass or fail message on your editor's console. The message will look similar to this:</p>
<pre><code class="lang-bash">$ jest
 PASS  ./additionCalculator.test.js
  √ addition of 4 and 6 to equal 10 (2 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.002 s
Ran all <span class="hljs-built_in">test</span> suites.
Done <span class="hljs-keyword">in</span> 7.80s.
</code></pre>
<p>If you prefer Jest to run your test automatically, add the <code>--watchAll</code> option to your <code>package.json</code>'s <code>test</code> field.</p>
<p><strong>Here's an example:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jest --watchAll"</span>
  }
}
</code></pre>
<p>After adding <code>--watchAll</code>, re-execute the <code>npm run test</code> (or <code>yarn test</code>) command to make Jest automatically begin rerunning your test whenever you save changes.</p>
<p><strong>Note:</strong> You can quit the watch mode by pressing the <strong>Q</strong> key on your keyboard.</p>
<h3 id="heading-step-12-refactor-the-test-code">Step 12: Refactor the test code</h3>
<p>So, now that you've confirmed that your program is working as intended, it's time to check if there's any need to refactor the test code.</p>
<p>For instance, suppose you realized that the <code>additionalCalculator</code> should allow users to add any number of digits. In that case, you can refactor your test code like so:</p>
<pre><code class="lang-js"><span class="hljs-comment">// additionCalculator.test.js</span>

<span class="hljs-keyword">const</span> additionCalculator = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./additionCalculator"</span>);

describe(<span class="hljs-string">"additionCalculator's test cases"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"addition of 4 and 6 to equal 10"</span>, <span class="hljs-function">() =&gt;</span> {
    expect(additionCalculator(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>)).toBe(<span class="hljs-number">10</span>);
  });

  test(<span class="hljs-string">"addition of 100, 50, 20, 45 and 30 to equal 245"</span>, <span class="hljs-function">() =&gt;</span> {
    expect(additionCalculator(<span class="hljs-number">100</span>, <span class="hljs-number">50</span>, <span class="hljs-number">20</span>, <span class="hljs-number">45</span>, <span class="hljs-number">30</span>)).toBe(<span class="hljs-number">245</span>);
  });

  test(<span class="hljs-string">"addition of 7 to equal 7"</span>, <span class="hljs-function">() =&gt;</span> {
    expect(additionCalculator(<span class="hljs-number">7</span>)).toBe(<span class="hljs-number">7</span>);
  });

  test(<span class="hljs-string">"addition of no argument provided to equal 0"</span>, <span class="hljs-function">() =&gt;</span> {
    expect(additionCalculator()).toBe(<span class="hljs-number">0</span>);
  });
});
</code></pre>
<p>Note that the <a target="_blank" href="https://jestjs.io/docs/api#describename-fn">describe()</a> method we used in the snippet above is optional code—it helps organize related test cases into groups.</p>
<p><code>describe()</code> accepts two arguments:</p>
<ol>
<li>A name you wish to call the test case group—for instance, <code>"additionCalculator's test cases"</code>.</li>
<li>A function containing your test cases.</li>
</ol>
<h3 id="heading-step-13-refactor-the-program">Step 13: Refactor the program</h3>
<p>So, now that you've refactored your test code, let's do the same for the <code>additionalCalculator</code> program.</p>
<pre><code class="lang-js"><span class="hljs-comment">// additionCalculator.js</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">additionCalculator</span>(<span class="hljs-params">...numbers</span>) </span>{
  <span class="hljs-keyword">return</span> numbers.reduce(<span class="hljs-function">(<span class="hljs-params">sum, item</span>) =&gt;</span> sum + item, <span class="hljs-number">0</span>);
}

<span class="hljs-built_in">module</span>.exports = additionCalculator;
</code></pre>
<p>Here's what we did in the snippet above:</p>
<ol>
<li>The <code>...numbers</code> code used JavaScript's <a target="_blank" href="https://codesweetly.com/javascript-rest-operator">rest operator</a> (<code>...</code>) to put the function's arguments into an array.</li>
<li>The <code>numbers.reduce((sum, item) =&gt; sum + item, 0)</code> code used JavaScript's <a target="_blank" href="https://codesweetly.com/javascript-reduce-method">reduce()</a> method to sum up all the items in the <code>numbers</code> array.</li>
</ol>
<h3 id="heading-step-14-rerun-the-test">Step 14: Rerun the test</h3>
<p>Once you've finished refactoring your code, rerun the test to confirm that your program still works as expected.</p>
<h3 id="heading-and-thats-it">And that's it!</h3>
<p>Congratulations! You've successfully used Jest to develop an addition calculator program using a test-driven development approach! 🎉</p>
<h2 id="heading-important-stuff-to-know-about-using-es6-modules-with-jest">Important Stuff to Know about Using ES6 Modules with Jest</h2>
<p>Jest does not currently recognize ES6 modules.</p>
<p>However, suppose you prefer to use ES6's import/export statements. In that case, do the following:</p>
<h3 id="heading-1-install-babel-as-a-development-dependency">1. Install Babel as a development dependency</h3>
<pre><code class="lang-bash">npm install @babel/preset-env --save-dev
</code></pre>
<p>Or, you can use Yarn:</p>
<pre><code class="lang-bash">yarn add @babel/preset-env --dev
</code></pre>
<h3 id="heading-2-create-a-babelrc-file-in-your-projects-root">2. Create a <code>.babelrc</code> file in your project's root</h3>
<pre><code class="lang-bash">touch .babelrc
</code></pre>
<h3 id="heading-3-open-the-babelrc-file-and-replicate-the-code-below">3. Open the <code>.babelrc</code> file and replicate the code below</h3>
<pre><code class="lang-json">{ <span class="hljs-attr">"presets"</span>: [<span class="hljs-string">"@babel/preset-env"</span>] }
</code></pre>
<p>The configuration above will now allow you to change step 9's <code>require()</code> statement from this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> additionCalculator = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./additionCalculator"</span>);
</code></pre>
<p>...to this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> additionCalculator <span class="hljs-keyword">from</span> <span class="hljs-string">"./additionCalculator"</span>;
</code></pre>
<p>Likewise, you can now also substitute step 10's <code>export</code> statement from this:</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = additionCalculator;
</code></pre>
<p>...to this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> additionCalculator;
</code></pre>
<p><strong>Note:</strong> Jest also specified similar instructions in their <a target="_blank" href="https://jestjs.io/docs/getting-started#using-babel">using Babel</a> documentation.</p>
<h3 id="heading-4-rerun-the-test">4. Rerun the test</h3>
<p>You can now rerun the test to confirm that your program still works!</p>
<p>So, now that we know what test-driven development is, we can discuss its advantages.</p>
<h2 id="heading-what-are-the-advantages-of-test-driven-development">What Are the Advantages of Test-Driven Development?</h2>
<p>Below are two main advantages of adopting test-driven development (TDD) in your programming workflow.</p>
<h3 id="heading-1-understand-your-programs-purpose">1. Understand your program's purpose</h3>
<p>Test-driven development helps you understand the purposes of your program.</p>
<p>In other words, since you write your test before the actual program, TDD makes you think about what you want your program to do.</p>
<p>Then, after you've documented the program's purposes using one or more tests, you can confidently proceed to create the program.</p>
<p>Therefore, TDD is a helpful way to jot down the specific results you expect your intended program to produce.</p>
<h3 id="heading-2-confidence-booster">2. Confidence booster</h3>
<p>TDD is a benchmark for knowing that your program is working as expected. It gives you the confidence that your program is working correctly.</p>
<p>Therefore, irrespective of any future development on your codebase, TDD provides an effective way to test if your program is still working appropriately.</p>
<p>Let's now discuss some popular TDD terms: "unit test," "integration test," "E2E," and "test doubles."</p>
<h2 id="heading-what-is-a-unit-test-in-test-driven-development">What is a Unit Test in Test-Driven Development?</h2>
<p>A <strong>unit test</strong> is a test you write to assess the functionality of an independent piece of a program. In other words, a unit test checks if a fully isolated unit of program is working as intended.</p>
<p>The test we wrote for step 10's <code>additionalCalculator</code> program is an excellent unit test example.</p>
<p>Step 10's <code>additionalCalculator()</code>'s test is a unit test because the program is an independent function that does not depend on any external code.</p>
<p>Note that a unit test's primary purpose is not to check for bugs. Instead, a unit test's core purpose is to check whether an independent piece of program (called unit) behaves as intended under various test cases.</p>
<h2 id="heading-what-is-an-integration-test-in-test-driven-development">What is an Integration Test in Test-Driven Development?</h2>
<p>An <strong>integration test</strong> assesses the functionality of a dependent piece of program. In other words, an integration test checks if a program—which depends on other code—is working as intended.</p>
<p>The test we wrote for step 13's <code>additionalCalculator</code> program is an excellent example of an integration test.</p>
<p>Step 13's <code>additionalCalculator()</code>'s test is an integration test because the program is a dependent function that depends on JavaScript's <a target="_blank" href="https://codesweetly.com/javascript-reduce-method">reduce()</a> method.</p>
<p>In other words, we used the prewritten test case to assess the integration of <code>additionalCalculator()</code> and <code>reduce()</code>.</p>
<p>Therefore, suppose JavaScript makes <code>reduce()</code> an obsolete method. In such a case, <code>additionalCalculator</code> will fail its test because of the <code>reduce()</code> method.</p>
<h2 id="heading-what-is-an-end-to-end-test-in-test-driven-development">What is an End-to-End Test in Test-Driven Development?</h2>
<p>An <strong>End-to-End (E2E) test</strong> assesses the functionality of a user interface. In other words, E2E checks if your user interface is working as intended.</p>
<p>Watch <a target="_blank" href="https://youtu.be/r9HdJ8P6GQI?t=1755">Max's YouTube video</a> for a good illustration of an End-to-End test.</p>
<h2 id="heading-what-are-test-doubles-in-test-driven-development">What are Test Doubles in Test-Driven Development?</h2>
<p><strong>Test doubles</strong> are the imitation objects used to mimic real dependencies like databases, libraries, networks, and APIs.</p>
<p>A test double allows you to bypass the natural objects on which your program depends. They let you test your code independently of any dependencies.</p>
<p>For instance, suppose you need to verify if an error detected in your app originates from an external API or your code.</p>
<p>But suppose the API's service is available only in production—not in the development environment. In that case, you've got two options:</p>
<ol>
<li>Wait until your app goes live—which could take months.</li>
<li>Clone the API so you can continue your test irrespective of the dependency's availability.</li>
</ol>
<p>Test doubles provide a helpful way to clone your program's dependencies so that your testing activities won't encounter any disruptions.</p>
<p>Typical examples of test doubles are dummy objects, mocks, fakes, and stubs. Let's discuss them below.</p>
<h3 id="heading-what-is-a-dummy-in-test-driven-development">What is a dummy in test-driven development?</h3>
<p>A <strong>dummy</strong> is a test double used to mimic the value of a specific dependency.</p>
<p>For instance, suppose your app depends on a third-party method that requires you to provide some arguments. In such a case, a dummy allows you to pass in pretend values to the parameters of that method.</p>
<h3 id="heading-what-is-a-mock-in-test-driven-development">What is a mock in test-driven development?</h3>
<p><strong>Mock</strong> is a test double used to mimic an external dependency without considering the responses the dependency may return.</p>
<p>For instance, suppose your app depends on a third-party API (for example, Facebook)—which you cannot access in the development mode. Mock allows you to bypass the API so that you can focus on testing your code regardless of the Facebook API's availability.</p>
<h3 id="heading-what-is-a-stub-in-test-driven-development">What is a stub in test-driven development?</h3>
<p>A <strong>stub</strong> is a test double used to mimic an external dependency while returning hand-coded values. You can use the returned value to assess your program's behavior with various test case responses from the dependency.</p>
<p>For instance, suppose your app depends on a third-party API (for example, Facebook)—which you cannot access in the development mode. Stub allows you to bypass the API while mimicking the exact values Facebook will return.</p>
<p>Therefore, stub helps you assess your program's behavior with various response scenarios.</p>
<h3 id="heading-what-is-a-fake-in-test-driven-development">What is a fake in test-driven development?</h3>
<p><strong>Fake</strong> is a test double used to create a working test implementation of an external dependency with dynamic values.</p>
<p>For instance, you can use fake to create a local database that allows you to test how a real database will work with your program.</p>
<h2 id="heading-quick-overview-of-test-driven-development-so-far">Quick Overview of Test-Driven Development So Far</h2>
<p>We've learned that test-driven development helps you jot down your program's behavior before creating the program.</p>
<p>We also saw a simple JavaScript test and used Jest as a test implementation tool.</p>
<p>Let's now see how to test React components.</p>
<h2 id="heading-how-to-test-react-components">How to Test React Components</h2>
<p>The two main tools you need to test your React components are:</p>
<ol>
<li>A test runner tool</li>
<li>A React component testing tool</li>
</ol>
<p>But what exactly is the difference between a test runner and a React component testing tool? Let's find out.</p>
<h2 id="heading-test-runner-vs-react-component-testing-tool-whats-the-difference">Test Runner vs. React Component Testing Tool: What's the Difference?</h2>
<p>Below are the differences between a test runner and a React component testing tool.</p>
<h3 id="heading-what-is-a-test-runner">What is a test runner?</h3>
<p>A <strong>test runner</strong> is a tool developers use to run a test script and print the test's results on the command line (CLI).</p>
<p>For instance, suppose you wish to run the test cases in your project's <code>App.test.js</code> test script. In such a case, you will use a test runner.</p>
<p>The test runner will execute <code>App.test.js</code> and print the test's results on the command line.</p>
<p>Typical examples of test runners are <a target="_blank" href="https://jasmine.github.io/">Jasmine</a>, <a target="_blank" href="https://mochajs.org/">Mocha</a>, <a target="_blank" href="https://github.com/substack/tape">Tape</a>, and <a target="_blank" href="https://jestjs.io/">Jest</a>.</p>
<h3 id="heading-what-is-a-react-component-testing-tool">What is a React component testing tool?</h3>
<p>A <strong>React component testing tool</strong> provides helpful APIs for defining a component's test cases.</p>
<p>For instance, suppose you need to test your project's <code>&lt;App /&gt;</code> component. In such a case, you will use a React component testing tool to define the component's test cases.</p>
<p>In other words, a React component testing tool provides the APIs for writing your component's test cases.</p>
<p>Typical examples are <a target="_blank" href="https://enzymejs.github.io/enzyme/">Enzyme</a> and the <a target="_blank" href="https://testing-library.com/docs/react-testing-library/intro">React Testing Library</a>.</p>
<p>So, now that we know what a test runner and React component testing tool are, let's use a mini-project to understand how React testing works.</p>
<h2 id="heading-project-how-react-testing-works">Project: How React Testing Works</h2>
<p>In the following steps, we will use <a target="_blank" href="https://en.wikipedia.org/wiki/Jest_(JavaScript_framework)">Jest</a> and the <a target="_blank" href="https://testing-library.com/docs/react-testing-library/intro">React Testing Library</a> (by Kent C. Dodds) to learn how React testing works.</p>
<p><strong>Note:</strong> The React official docs <a target="_blank" href="https://reactjs.org/docs/testing.html#tools">recommend</a> the Jest and React Testing Library combination for testing React components.</p>
<h3 id="heading-step-1-get-the-right-node-and-npm-version-1">Step 1: Get the right Node and NPM version</h3>
<p>Make sure that you have <a target="_blank" href="https://codesweetly.com/package-manager-explained#how-to-check-the-installed-node-version">Node 10.16</a> (or greater) and NPM 5.6 (or greater) installed on your system.</p>
<p>If you prefer to use Yarn, ensure you have Yarn 0.25 (or greater).</p>
<h3 id="heading-step-2-create-a-new-react-app">Step 2: Create a new React app</h3>
<p>Use NPM's <a target="_blank" href="https://create-react-app.dev/">create-react-app</a> package to create a new React app called <code>react-testing-project</code>.</p>
<pre><code class="lang-bash">npx create-react-app react-testing-project
</code></pre>
<p>Alternatively, you can use Yarn to configure your project like so:</p>
<pre><code class="lang-bash">yarn create react-app react-testing-project
</code></pre>
<h3 id="heading-step-3-go-inside-the-project-directory">Step 3: Go inside the project directory</h3>
<p>After the installation process, navigate into the project directory like so:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> react-testing-project
</code></pre>
<h3 id="heading-step-4-set-up-your-test-environment">Step 4: Set up your test environment</h3>
<p>Install the following test packages:</p>
<ul>
<li>jest</li>
<li>@testing-library/react</li>
<li>@testing-library/jest-dom</li>
<li>@testing-library/user-event</li>
</ul>
<p><strong>Note:</strong> If you've initialized your React project with <code>create-react-app</code> (step 2), you do not need to install any of the above packages. They come preinstalled and preconfigured in your <code>package.json</code> file.</p>
<p>Now, let's discuss the purpose of each of the above test packages.</p>
<h4 id="heading-what-is-jest">What is Jest?</h4>
<p><a target="_blank" href="https://www.npmjs.com/package/jest">jest</a> is the test runner tool we will use to run this project's test scripts and print the test results on the command line.</p>
<h4 id="heading-what-is-testing-libraryreact">What is @testing-library/react?</h4>
<p><a target="_blank" href="https://www.npmjs.com/package/@testing-library/react">@testing-library/react</a> is the React Testing Library which gives you the APIs you need to write test cases for your React components.</p>
<h4 id="heading-what-is-testing-libraryjest-dom">What is @testing-library/jest-dom?</h4>
<p><a target="_blank" href="https://www.npmjs.com/package/@testing-library/jest-dom">@testing-library/jest-dom</a> provides some set of custom Jest matchers for testing the DOM's state.</p>
<p><strong>Note:</strong> Jest already comes with lots of matchers, so using <code>jest-dom</code> is optional. <code>jest-dom</code> simply extends Jest by providing matchers that make your test more declarative, clear to read, and easy to maintain.</p>
<h4 id="heading-what-is-testing-libraryuser-event">What is @testing-library/user-event?</h4>
<p><a target="_blank" href="https://www.npmjs.com/package/@testing-library/user-event">@testing-library/user-event</a> provides the <code>userEvent</code> API for simulating users' interaction with your app on a web page.</p>
<p><strong>Note:</strong> <code>@testing-library/user-event</code> is a better alternative to the <a target="_blank" href="https://testing-library.com/docs/dom-testing-library/api-events/#fireevent">fireEvent</a> API.</p>
<h3 id="heading-step-5-clean-up-the-src-folder">Step 5: Clean up the <code>src</code> folder</h3>
<p>Delete all files inside the project directory's <code>src</code> folder.</p>
<h3 id="heading-step-6-create-your-code-files">Step 6: Create your code files</h3>
<p>Create the following files inside your project's <code>src</code> folder.</p>
<ul>
<li><code>index.js</code></li>
<li><code>App.js</code></li>
<li><code>App.test.js</code></li>
</ul>
<h3 id="heading-step-7-render-the-app-component">Step 7: Render the <code>App</code> component</h3>
<p>Open your <code>index.js</code> file and render the <code>App</code> component to the DOM like so:</p>
<pre><code class="lang-js"><span class="hljs-comment">// index.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;

<span class="hljs-comment">// Render the App component into the root DOM</span>
createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)).render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
</code></pre>
<h3 id="heading-step-8-write-your-test-case">Step 8: Write your test case</h3>
<p>Suppose you want your <code>App.js</code> file to render a <code>&lt;h1&gt;CodeSweetly Test&lt;/h1&gt;</code> element to the web page. In that case, open your <em>test script</em> and write some test code specifying the result you expect your <code>&lt;App /&gt;</code> component to produce.</p>
<p><strong>Here's an example:</strong></p>
<pre><code class="lang-js"><span class="hljs-comment">// App.test.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@testing-library/jest-dom"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;

test(<span class="hljs-string">"codesweetly test heading"</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  expect(screen.getByRole(<span class="hljs-string">"heading"</span>)).toHaveTextContent(<span class="hljs-regexp">/codesweetly test/i</span>);
});
</code></pre>
<p>Here are the main things we did in the test snippet above:</p>
<ol>
<li>We imported the packages needed to write our test case.</li>
<li><p>We wrote a test case specifying that we expect our <code>&lt;App /&gt;</code> component to render a heading element with a <code>"codesweetly test"</code> text.</p>
</li>
<li><p><a target="_blank" href="https://jestjs.io/docs/api#testname-fn-timeout"><code>test()</code></a> is one of Jest's global methods. We use it to run a test case. The method accepts three arguments:</p>
<ul>
<li>The name of the test (<code>"codesweetly test heading"</code>)</li>
<li>A function containing the expectations you wish to test</li>
<li>An optional timeout argument</li>
</ul>
</li>
<li><a target="_blank" href="https://testing-library.com/docs/react-testing-library/api/#render"><code>render()</code></a> is one of the React Testing Library APIs. We use it to render the component we wish to test.</li>
<li><a target="_blank" href="https://jestjs.io/docs/expect#expectvalue"><code>expect()</code></a> is a Jest method that lets you test the output of your code.</li>
<li><a target="_blank" href="https://testing-library.com/docs/queries/about/#screen"><code>screen</code></a> is a React Testing Library's object containing numerous methods for finding elements on a page.</li>
<li><a target="_blank" href="https://testing-library.com/docs/queries/about/#priority"><code>getByRole()</code></a> is one of the React Testing Library's query methods for finding elements on a page.</li>
<li><a target="_blank" href="https://github.com/testing-library/jest-dom#tohavetextcontent"><code>toHaveTextContent()</code></a> is one of <code>jest-dom</code>'s custom matchers that you can use to confirm the presence of a text content in a specific node.</li>
<li><code>/codesweetly test/i</code> is a <a target="_blank" href="https://codesweetly.com/javascript-regular-expression-object">regular expression</a> syntax that we used to specify a case-insensitive search for <code>codesweetly test</code>.</li>
</ol>
<p>Keep in mind that there are three alternative ways to write the above expect statement:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 1. Using jest-dom's toHaveTextContent() method:</span>
expect(screen.getByRole(<span class="hljs-string">"heading"</span>)).toHaveTextContent(<span class="hljs-regexp">/codesweetly test/i</span>);

<span class="hljs-comment">// 2. Using the heading's textContent property and Jest's toMatch() method:</span>
expect(screen.getByRole(<span class="hljs-string">"heading"</span>).textContent).toMatch(<span class="hljs-regexp">/codesweetly test/i</span>);

<span class="hljs-comment">// 3. Using React Testing Library's name option and jest-dom's toBeInTheDocument() method</span>
expect(screen.getByRole(<span class="hljs-string">"heading"</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/codesweetly test/i</span> })).toBeInTheDocument();
</code></pre>
<p><strong>Tip:</strong></p>
<p>Add a <code>level</code> option to the <code>getByRole()</code> method to specify your heading's level.</p>
<p><strong>Here's an example:</strong></p>
<pre><code class="lang-js">test(<span class="hljs-string">"codesweetly test heading"</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  expect(screen.getByRole(<span class="hljs-string">"heading"</span>, { <span class="hljs-attr">level</span>: <span class="hljs-number">1</span> })).toHaveTextContent(<span class="hljs-regexp">/codesweetly test/i</span>);
});
</code></pre>
<p>The <code>level: 1</code> option specifies an <code>&lt;h1&gt;</code> heading element.</p>
<p>Suppose you run the test code now. The test will fail because you've not developed the component for which you created the test. So, let's do that now.</p>
<h3 id="heading-step-9-develop-your-react-component">Step 9: Develop your React component</h3>
<p>Open your <code>App.js</code> file and develop the component to pass the prewritten test.</p>
<p><strong>Here's an example:</strong></p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>CodeSweetly Test<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>The <code>App</code> component, in the snippet above, renders a <code>&lt;h1&gt;</code> element containing the <code>"CodeSweetly Test"</code> text.</p>
<h3 id="heading-step-10-run-the-test">Step 10: Run the test</h3>
<p>Run the prewritten test to check if your program passed or failed.</p>
<pre><code class="lang-bash">npm <span class="hljs-built_in">test</span> App.test.js
</code></pre>
<p>Alternatively, you can use Yarn like so:</p>
<pre><code class="lang-bash">yarn <span class="hljs-built_in">test</span> App.test.js
</code></pre>
<p>Once you've initiated the test, Jest will print a pass or fail message on your editor's console. The message will look similar to this:</p>
<pre><code class="lang-bash">$ jest
 PASS  src/App.test.js
  √ codesweetly <span class="hljs-built_in">test</span> heading (59 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.146 s
Ran all <span class="hljs-built_in">test</span> suites related to changed files.
</code></pre>
<p><strong>Note:</strong> The <code>create-react-app</code> configured Jest in <a target="_blank" href="https://codesweetly.com/javascript-module-bundler/#what-is-webpack---progress---watch">watch mode</a> by default. Therefore, after running <code>npm test</code> (or <code>yarn test</code>), your currently opened terminal will continue to process the <code>test</code> command's activities. So, you won't be able to input any command on that terminal until you stop <code>test</code>'s execution. But you can open a new terminal window simultaneously with the one processing <code>test</code>. </p>
<p>In other words, use one terminal to run <code>test</code> and another to input commands.</p>
<h3 id="heading-step-11-run-the-application">Step 11: Run the application</h3>
<p>Take a look at your app in the browser by running:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>Or, if your <a target="_blank" href="https://codesweetly.com/package-manager-explained">package manager</a> is Yarn, run:</p>
<pre><code class="lang-bash">yarn start
</code></pre>
<p>Once you run the command above, your app will automatically open on your default browser.</p>
<h3 id="heading-step-12-refactor-the-test-code-1">Step 12: Refactor the test code</h3>
<p>Suppose you wish to change the heading's text when users click a button. In that case, you can simulate users' interaction with the button to confirm that it works as intended.</p>
<p><strong>Here's an example:</strong></p>
<pre><code class="lang-js"><span class="hljs-comment">// App.test.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> userEvent <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/user-event"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@testing-library/jest-dom"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;

describe(<span class="hljs-string">"App component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"codesweetly test heading"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    expect(screen.getByRole(<span class="hljs-string">"heading"</span>)).toHaveTextContent(<span class="hljs-regexp">/codesweetly test/i</span>);
  });

  test(<span class="hljs-string">"a codesweetly project heading"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);

    <span class="hljs-keyword">const</span> button = screen.getByRole(<span class="hljs-string">"button"</span>, { <span class="hljs-attr">name</span>: <span class="hljs-string">"Update Heading"</span> });

    userEvent.click(button);

    expect(screen.getByRole(<span class="hljs-string">"heading"</span>)).toHaveTextContent(<span class="hljs-regexp">/a codesweetly project/i</span>);
  });
});
</code></pre>
<p>Here are the main things we did in the test snippet above:</p>
<ol>
<li>We imported the packages needed to write our test case.</li>
<li>We wrote a test case specifying that we expect the <code>&lt;App /&gt;</code> component to render a heading element with a <code>"codesweetly test"</code> text.</li>
<li>We wrote another test case simulating users' interaction with the app's button element. In other words, we specified that whenever a user clicks the button, we expect <code>&lt;App /&gt;</code>'s heading to update to <code>"a codesweetly project"</code> text.</li>
</ol>
<p><strong>Note:</strong></p>
<ul>
<li><a target="_blank" href="https://jestjs.io/docs/api#describename-fn"><code>describe()</code></a> is one of Jest's global methods. It is optional code that helps organize related test cases into groups. <code>describe()</code> accepts two arguments:<ul>
<li>A name you wish to call the test case group—for instance, <code>"App component"</code>.</li>
<li>A function containing your test cases.</li>
</ul>
</li>
<li><a target="_blank" href="https://www.npmjs.com/package/@testing-library/user-event"><code>userEvent</code></a> is the React Testing Library's package containing several methods for simulating users' interaction with an app. For instance, in the snippet above, we used <code>userEvent</code>'s <code>click()</code> method to simulate a click event on the button element.</li>
<li>We rendered <code>&lt;App /&gt;</code> for each test case because React Testing Library unmounts the rendered components after each test. However, suppose you have numerous test cases for a component. In that case, use Jest's <a target="_blank" href="https://jestjs.io/docs/api#beforeeachfn-timeout"><code>beforeEach()</code></a> method to run <code>render(&lt;App /&gt;)</code> before each test in your file (or <code>describe</code> block).</li>
</ul>
<h3 id="heading-step-13-refactor-your-react-component">Step 13: Refactor your React component</h3>
<p>So, now that you've refactored your test code, let's do the same for the <code>App</code> component.</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [heading, setHeading] = useState(<span class="hljs-string">"CodeSweetly Test"</span>);

  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
    setHeading(<span class="hljs-string">"A CodeSweetly Project"</span>);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{heading}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>
        Update Heading
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Here are the main things we did in the snippet above:</p>
<ol>
<li><code>App</code>'s <code>heading</code> state got initialized with a <code>"CodeSweetly Test"</code> string.</li>
<li>We programmed a <code>handleClick</code> function to update the <code>heading</code> state.</li>
<li>We rendered a <code>&lt;h1&gt;</code> and <code>&lt;button&gt;</code> elements to the DOM.</li>
</ol>
<p>Note the following:</p>
<ul>
<li><code>&lt;h1&gt;</code>'s content is the <code>heading</code> state's current value.</li>
<li>Whenever a user clicks the button element, the <code>onClick()</code> event listener will trigger the <code>handleClick()</code> function. And <code>handleClick</code> will update <code>App</code>'s <code>heading</code> state to <code>"A CodeSweetly Project"</code>. Therefore, <code>&lt;h1&gt;</code>'s content will change to <code>"A CodeSweetly Project"</code>.</li>
</ul>
<h3 id="heading-step-14-rerun-the-test-1">Step 14: Rerun the test</h3>
<p>Once you've refactored your component, rerun the test (or check the actively running test) to confirm that your app still works as expected.</p>
<p>Afterward, check the browser to see your recent updates.</p>
<h3 id="heading-and-thats-it-1">And that's it!</h3>
<p>Congratulations! You've successfully used Jest and the React Testing Library to test a React component. 🎉</p>
<h2 id="heading-overview">Overview</h2>
<p>This article discussed how test-driven development works in JavaScript and ReactJS applications. </p>
<p>We also learned how to use Jest and the React Testing Library to make testing simpler and faster.</p>
<p>Thanks for reading!</p>
<h3 id="heading-and-heres-a-useful-reactjs-resource"><strong>And here's a useful ReactJS resource:</strong></h3>
<p>I wrote a book about React!</p>
<ul>
<li>It's beginner friendly ✔</li>
<li>It has live code snippets ✔</li>
<li>It contains scalable projects ✔</li>
<li>It has plenty of easy-to-grasp examples ✔</li>
</ul>
<p>The <a target="_blank" href="https://www.amazon.com/dp/B09KYGDQYW">React Explained Clearly</a> book is all you need to understand ReactJS.</p>
<p><a target="_blank" href="https://www.amazon.com/dp/B09KYGDQYW"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Twitter-React_Explained_Clearly-CodeSweetly-Oluwatobi_Sofela.jpg" alt="React Explained Clearly Book Now Available at Amazon" width="600" height="400" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Test-Driven Development with Integration Tests in .NET 5.0 ]]>
                </title>
                <description>
                    <![CDATA[ By Arjav Dave Test-Driven Development is a much-debated concept in the tech industry. Developers wonder whether they should practice TDD or not, how advantageous it is, and so on.  So what is Test-Driven Development, or TDD? Simply put, TDD dictates ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-tdd-with-integration-tests-in-net-5-0/</link>
                <guid isPermaLink="false">66d84decef84e4cc27cfbe21</guid>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 14 Apr 2021 17:37:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/04/tdd.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Arjav Dave</p>
<p>Test-Driven Development is a much-debated concept in the tech industry. Developers wonder whether they should practice TDD or not, how advantageous it is, and so on. </p>
<p>So what is Test-Driven Development, or TDD? Simply put, TDD dictates that you test your code before you push it to production.</p>
<p>Now, there are a number of opinions for what type of tests you should include in TDD. For example, should you include Unit Tests, Integration Tests, System Tests, or even UAT?</p>
<p>In this article, we will go through a real-world example that'll show you how to write integration tests in .NET 5.0 with a TDD methodology. </p>
<p>For writing tests, we will use the XUnit framework, since it is more extensive than the NUnit or MSTest testing frameworks. <a target="_blank" href="https://www.lambdatest.com/blog/nunit-vs-xunit-vs-mstest/">Here</a> is a good article if you want to learn more about the difference between these frameworks. </p>
<p>Secondly, VS Code has always been my choice of IDE, but you can use Visual Studio as well. </p>
<p>Let's start by laying out our project requirements.</p>
<h2 id="heading-project-requirements">Project Requirements</h2>
<p>TDD requires a very clear understanding of the scope of work. Without that clarity, all the test cases might not be covered.</p>
<p>Let's define what we mean by scope of work. We will be developing a patient admission system for a hospital.</p>
<h3 id="heading-business-requirements">Business Requirements</h3>
<ul>
<li>A hospital has X ICU rooms, Y Premium rooms, and Z General rooms.</li>
<li>ICU and Premium rooms can have a single patient at a time, while General rooms can have 2 patients. Each room has a room number.</li>
<li>On admitting, the patient has to provide name, age, gender, and phone number.</li>
<li>It is possible to search a patient via name or phone number.</li>
<li>The same patient cannot be admitted to multiple beds while they are still checked in.</li>
<li>A patient cannot be admitted if all the rooms are occupied.</li>
</ul>
<h3 id="heading-model-validation-rules">Model Validation Rules</h3>
<p>Based on the above requirements, there are two models we need to worry about, namely Patient and Room.</p>
<ul>
<li>A patient's age is between 0 and 150. The length of their name should be between 2 and 40 characters. Gender can be male, female, and other. Phone Number's length should be between 7 and 12 and it should all be digits.</li>
<li>Room type can be either "ICU", "Premium" or "General".</li>
</ul>
<h3 id="heading-test-cases-to-implement">Test Cases to implement</h3>
<p>Now, that we have defined our rules and requirements, let's start creating test cases. Since it's a basic CRUD application, we will mostly have integration tests.</p>
<h4 id="heading-patient-test-cases">Patient test cases</h4>
<ul>
<li>Do all the model validation tests.</li>
<li>Admit the same patient twice</li>
<li>Check out the same patient twice.</li>
<li>Admit the same patient to multiple rooms at the same time.</li>
<li>Search a patient with phone number and name.</li>
</ul>
<h2 id="heading-tdd-setup">TDD Setup</h2>
<p>In the above section we gathered our project requirements. Next we defined the models. Finally, we created the list of test cases which we will implement.</p>
<p>Open your terminal and run the below script to create and setup a new project.</p>
<pre><code>mkdir TDD
cd TDD
dotnet <span class="hljs-keyword">new</span> sln
dotnet <span class="hljs-keyword">new</span> webapi --name TDD
dotnet <span class="hljs-keyword">new</span> xunit --name TDD.Tests
cd TDD
dotnet add package Microsoft.EntityFrameworkCore --version <span class="hljs-number">5.0</span><span class="hljs-number">.5</span>
cd ../TDD.Tests
dotnet add reference ../TDD/TDD.csproj
dotnet add package Microsoft.EntityFrameworkCore --version <span class="hljs-number">5.0</span><span class="hljs-number">.5</span>
dotnet add package Microsoft.AspNetCore.Hosting --version <span class="hljs-number">2.2</span><span class="hljs-number">.7</span>
dotnet add package Microsoft.AspNetCore.Mvc.Testing --version <span class="hljs-number">5.0</span><span class="hljs-number">.5</span>
dotnet add package Microsoft.EntityFrameworkCore.InMemory --version <span class="hljs-number">5.0</span><span class="hljs-number">.5</span>
cd ..
dotnet sln add TDD/TDD.csproj
dotnet sln add TDD.Tests/TDD.Tests.csproj
code .
</code></pre><p>The above script creates a solution file named <em>TDD.sln</em>. Secondly, we create two projects for TDD and TDD.Tests. Then we add the dependencies for each project. Lastly, we add the projects to the solution and open the project in VS Code.</p>
<p>Before we start testing, we have a bit more setup to do. Basically, integration tests test the a specific module without mocking. So we will be mimicking our application via TestServer.</p>
<h3 id="heading-custom-webapplicationfactory">Custom WebApplicationFactory</h3>
<p>In order to mimic the TestServer, there is a class called <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.testing.webapplicationfactory-1?view=aspnetcore-5.0">WebApplicationFactory</a> (WAF) which bootstraps the application in memory.</p>
<p>In your <strong>TDD.Tests</strong> project create a file named <em>PatientTestsDbWAF.cs</em> with the following code.</p>
<pre><code>using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore;


namespace TDD.Tests
{
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PatientTestsDbWAF</span>&amp;<span class="hljs-title">lt</span></span>;TStartup&amp;gt; : WebApplicationFactory&amp;lt;TStartup&amp;gt; where TStartup : <span class="hljs-class"><span class="hljs-keyword">class</span>
    </span>{

        protected override IWebHostBuilder CreateWebHostBuilder()
        {
            <span class="hljs-keyword">return</span> WebHost.CreateDefaultBuilder()
                .UseStartup&amp;lt;TStartup&amp;gt;();
        }
        protected override <span class="hljs-keyword">void</span> ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(<span class="hljs-keyword">async</span> services =&amp;gt;
           {
               <span class="hljs-comment">// Remove the app's DbContext registration.</span>
               <span class="hljs-keyword">var</span> descriptor = services.SingleOrDefault(
                      d =&amp;gt; d.ServiceType ==
                          <span class="hljs-keyword">typeof</span>(DbContextOptions&amp;lt;DataContext&amp;gt;));

               <span class="hljs-keyword">if</span> (descriptor != <span class="hljs-literal">null</span>)
               {
                   services.Remove(descriptor);
               }

               <span class="hljs-comment">// Add DbContext using an in-memory database for testing.</span>
               services.AddDbContext&amp;lt;DataContext&amp;gt;(options =&amp;gt;
                  {
                      <span class="hljs-comment">// Use in memory db to not interfere with the original db.</span>
                      options.UseInMemoryDatabase(<span class="hljs-string">"PatientTestsTDD.db"</span>);
                  });
           });
        }
    }
}
</code></pre><p>We are removing the application's DbContext and adding an <strong>in memory</strong> DbContext. This is a necessary step since we don't want to interfere with the original database.</p>
<p>Secondly, we are initialising the database with some dummy data.</p>
<p>Since DataContext is a custom class, it will give compiler error. So we need to create it.</p>
<h3 id="heading-data-context">Data Context</h3>
<p>In your <strong>TDD project</strong>, create a file named <em>DataContext.cs</em> with the following code:</p>
<pre><code>using Microsoft.EntityFrameworkCore;

namespace TDD
{
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DataContext</span> : <span class="hljs-title">DbContext</span>
    </span>{
        public DataContext(DbContextOptions options) : base(options) { }

        <span class="hljs-comment">// For storing the list of patients and their state</span>
        public DbSet&amp;lt;Patient&amp;gt; Patient { get; set; }

        <span class="hljs-comment">// For the storying the rooms along with their types and capacity</span>
        public DbSet&amp;lt;Room&amp;gt; Room { get; set; }

        <span class="hljs-comment">// For logging which patients are currently admitted to which room</span>
        public DbSet&amp;lt;RoomPatient&amp;gt; RoomPatient { get; set; }

    }
}
</code></pre><p>Here Patient, Room, and RoomPatient are Entity classes with the required properties, which we will create next.</p>
<h3 id="heading-add-the-patient-property">Add the Patient property</h3>
<p>Again, in your <strong>TDD project</strong>, create a file named <em>Patient.cs</em> and paste in the code below:</p>
<pre><code>using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Patient</span>
    </span>{
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public <span class="hljs-built_in">String</span> Name { get; set; }

        public <span class="hljs-built_in">String</span> PhoneNumber { get; set; }

        public int Age { get; set; }

        public <span class="hljs-built_in">String</span> Gender { get; set; }
    }
}
</code></pre><h3 id="heading-add-the-room-property">Add the Room property</h3>
<p>Create another file named <em>Room.cs</em> with the following code:</p>
<pre><code>using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Room</span>
    </span>{
          [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public <span class="hljs-built_in">String</span> RoomType { get; set; }

        public int CurrentCapacity { get; set; }

        public int MaxCapacity { get; set; }
    }
}
</code></pre><h3 id="heading-add-the-roompatient-property">Add the RoomPatient property</h3>
<p>Create the last model file <em>RoomPatient.cs</em> with the following code:</p>
<pre><code>using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RoomPatient</span>
    </span>{
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        public int RoomId { get; set; }

        [ForeignKey(<span class="hljs-string">"RoomId"</span>)]
        public Room Room { get; set; }

        [Required]
        public int PatientId { get; set; }

        [ForeignKey(<span class="hljs-string">"PatientId"</span>)]
        public Patient Patient { get; set; }
    }
}
</code></pre><p>Now you shouldn't be getting any more compiler errors.</p>
<p>Lastly, remove the <em>WeatherForecast.cs</em> and <em>WeatherForecastController.cs</em> files.</p>
<p>Go to your terminal in VS Code and run the below command:</p>
<pre><code>cd TDD.Tests
dotnet test
</code></pre><p>You will see a nice green result which says that one test has passed.</p>
<p><img src="https://arjavdave.com/wp-content/uploads/2021/04/Test_Success_1-1024x211.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test Success</em></p>
<h3 id="heading-create-the-patient-controller">Create the Patient Controller</h3>
<p>Unfortunately .NET doesn't provide a way to directly test the models in itself. So we will have to create a controller to test it.</p>
<p>Go ahead and create a <em>PatientController.cs</em> file in the Controllers folder in <strong>TDD project</strong> with the below code:</p>
<pre><code>using Microsoft.AspNetCore.Mvc;

namespace TDD.Controllers
{
    [Route(<span class="hljs-string">"api/[controller]"</span>)]
    [ApiController]
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PatientController</span> : <span class="hljs-title">Controller</span>
    </span>{
        [HttpPost]
        public IActionResult AddPatient([FromBody] Patient Patient)
        {
            <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Insert the patient into db</span>
            <span class="hljs-keyword">return</span> Created(<span class="hljs-string">"/patient/1"</span>, Patient);
        }
    }
}
</code></pre><p>We created an API to add a patient. In order to test our model we will call this API.</p>
<p>That's all we need to start testing.</p>
<h2 id="heading-model-validation-tests">Model Validation Tests</h2>
<p>Since we've setup the basic code for testing, let's write a test that fails. We will start our testing with the model validation tests.</p>
<h3 id="heading-failing-red-state">Failing (Red) State</h3>
<p>Let's create a new file named <em>PatientTests.cs</em> in your <strong>TDD.Tests project</strong> and delete the file named <em>UnitTest1.cs</em>. Copy the below code into your file:</p>
<pre><code>using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Testing;
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace TDD.Tests
{
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PatientTests</span> : <span class="hljs-title">IClassFixture</span>&amp;<span class="hljs-title">lt</span></span>;PatientTestsDbWAF&amp;lt;Startup&amp;gt;&amp;gt;
    {
        <span class="hljs-comment">// HttpClient to call our api's</span>
        private readonly HttpClient httpClient;
        public WebApplicationFactory&amp;lt;Startup&amp;gt; _factory;

        public PatientTests(PatientTestsDbWAF&amp;lt;Startup&amp;gt; factory)
        {
            _factory = factory;

            <span class="hljs-comment">// Initiate the HttpClient</span>
            httpClient = _factory.CreateClient();
        }

        [Theory]
        [InlineData(<span class="hljs-string">"Test Name 2"</span>, <span class="hljs-string">"1234567891"</span>, <span class="hljs-number">20</span>, <span class="hljs-string">"Male"</span>, HttpStatusCode.Created)]
        [InlineData(<span class="hljs-string">"T"</span>, <span class="hljs-string">"1234567891"</span>, <span class="hljs-number">20</span>, <span class="hljs-string">"Male"</span>, HttpStatusCode.BadRequest)]
        [InlineData(<span class="hljs-string">"A very very very very very very loooooooooong name"</span>, <span class="hljs-string">"1234567891"</span>, <span class="hljs-number">20</span>, <span class="hljs-string">"Male"</span>, HttpStatusCode.BadRequest)]
        [InlineData(<span class="hljs-literal">null</span>, <span class="hljs-string">"1234567890"</span>, <span class="hljs-number">20</span>, <span class="hljs-string">"Invalid Gender"</span>, HttpStatusCode.BadRequest)]
        [InlineData(<span class="hljs-string">"Test Name"</span>, <span class="hljs-string">"InvalidNumber"</span>, <span class="hljs-number">20</span>, <span class="hljs-string">"Male"</span>, HttpStatusCode.BadRequest)]
        [InlineData(<span class="hljs-string">"Test Name"</span>, <span class="hljs-string">"1234567890"</span>, <span class="hljs-number">-10</span>, <span class="hljs-string">"Male"</span>, HttpStatusCode.BadRequest)]
        [InlineData(<span class="hljs-string">"Test Name"</span>, <span class="hljs-string">"1234567890"</span>, <span class="hljs-number">20</span>, <span class="hljs-string">"Invalid Gender"</span>, HttpStatusCode.BadRequest)]
        [InlineData(<span class="hljs-string">"Test Name"</span>, <span class="hljs-string">"12345678901234444"</span>, <span class="hljs-number">20</span>, <span class="hljs-string">"Invalid Gender"</span>, HttpStatusCode.BadRequest)]
        public <span class="hljs-keyword">async</span> Task PatientTestsAsync(<span class="hljs-built_in">String</span> Name, <span class="hljs-built_in">String</span> PhoneNumber, int Age, <span class="hljs-built_in">String</span> Gender, HttpStatusCode ResponseCode)
        {
            <span class="hljs-keyword">var</span> scopeFactory = _factory.Services;
            using (<span class="hljs-keyword">var</span> scope = scopeFactory.CreateScope())
            {
                <span class="hljs-keyword">var</span> context = scope.ServiceProvider.GetService&amp;lt;DataContext&amp;gt;();

                <span class="hljs-comment">// Initialize the database, so that </span>
                <span class="hljs-comment">// changes made by other tests are reset. </span>
                <span class="hljs-keyword">await</span> DBUtilities.InitializeDbForTestsAsync(context);

                <span class="hljs-comment">// Arrange</span>
                <span class="hljs-keyword">var</span> request = <span class="hljs-keyword">new</span> HttpRequestMessage(HttpMethod.Post, <span class="hljs-string">"api/patient"</span>);

                request.Content = <span class="hljs-keyword">new</span> StringContent(JsonSerializer.Serialize(<span class="hljs-keyword">new</span> Patient
                {
                    Name = Name,
                    PhoneNumber = PhoneNumber,
                    Age = Age,
                    Gender = Gender
                }), Encoding.UTF8, <span class="hljs-string">"application/json"</span>);

                <span class="hljs-comment">// Act</span>
                <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> httpClient.SendAsync(request);

                <span class="hljs-comment">// Assert</span>
                <span class="hljs-keyword">var</span> StatusCode = response.StatusCode;
                Assert.Equal(ResponseCode, StatusCode);
            }
        }
    }
}
</code></pre><p>The <code>[Theory]</code> attribute allows us to mention different parameters for our tests. Because of this, we don't have to write different tests for all the combinations.</p>
<p>Also, DBUtilities is a utility class to reinitialise the database to its initial state. This might seem trivial when we have 1 or 2 tests, but it becomes critical as we add more tests.</p>
<h3 id="heading-dbutilities-class">DBUtilities class</h3>
<p>The DBUtilities class will initialise your database with 1 patient and 3 different type of rooms.</p>
<p>Create a file named <em>DBUtilities.cs</em> in your <strong>TDD.Tests</strong> project with the below code:</p>
<pre><code>using System.Threading.Tasks;

namespace TDD.Tests
{
    <span class="hljs-comment">// Helps to initialise the database either from the WAF for the first time</span>
    <span class="hljs-comment">// Or before running each test.</span>
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DBUtilities</span>
    </span>{

        <span class="hljs-comment">// Clears the database and then,</span>
        <span class="hljs-comment">//Adds 1 Patient and 3 different types of rooms to the database</span>
        public <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task InitializeDbForTestsAsync(DataContext context)
        {
            context.RoomPatient.RemoveRange(context.RoomPatient);
            context.Patient.RemoveRange(context.Patient);
            context.Room.RemoveRange(context.Room);

            <span class="hljs-comment">// Arrange</span>
            <span class="hljs-keyword">var</span> Patient = <span class="hljs-keyword">new</span> Patient
            {
                Name = <span class="hljs-string">"Test Patient"</span>,
                PhoneNumber = <span class="hljs-string">"1234567890"</span>,
                Age = <span class="hljs-number">20</span>,
                Gender = <span class="hljs-string">"Male"</span>
            };
            context.Patient.Add(Patient);

            <span class="hljs-keyword">var</span> ICURoom = <span class="hljs-keyword">new</span> Room
            {
                RoomType = <span class="hljs-string">"ICU"</span>,
                MaxCapacity = <span class="hljs-number">1</span>,
                CurrentCapacity = <span class="hljs-number">1</span>
            };
            context.Room.Add(ICURoom);

            <span class="hljs-keyword">var</span> GeneralRoom = <span class="hljs-keyword">new</span> Room
            {
                RoomType = <span class="hljs-string">"General"</span>,
                MaxCapacity = <span class="hljs-number">2</span>,
                CurrentCapacity = <span class="hljs-number">2</span>
            };
            context.Room.Add(GeneralRoom);

            <span class="hljs-keyword">var</span> PremiumRoom = <span class="hljs-keyword">new</span> Room
            {
                RoomType = <span class="hljs-string">"Premium"</span>,
                MaxCapacity = <span class="hljs-number">1</span>,
                CurrentCapacity = <span class="hljs-number">1</span>
            };
            context.Room.Add(PremiumRoom);

            <span class="hljs-keyword">await</span> context.SaveChangesAsync();
        }
    }
}
</code></pre><p>Go ahead and run the <strong>dotnet test</strong> command again and you will see 1 passed and 4 failed tests. This is because the 4 tests were expecting BadRequest but were getting a Created result.</p>
<p><img src="https://arjavdave.com/wp-content/uploads/2021/04/failed_tests-1024x195.png" alt="Image" width="600" height="400" loading="lazy">
<em>Failing (Red) State</em></p>
<p>Let's fix it!</p>
<h3 id="heading-success-green-state">Success (Green) State</h3>
<p>In order to fix these we need to add attributes to our <em>Patient.cs</em> class.</p>
<p>Update the <em>Patient.cs</em> file as below:</p>
<pre><code>using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Patient</span> : <span class="hljs-title">IValidatableObject</span>
    </span>{
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        [StringLength(<span class="hljs-number">40</span>, MinimumLength = <span class="hljs-number">2</span>, ErrorMessage = <span class="hljs-string">"The name should be between 2 &amp;amp; 40 characters."</span>)]
        public <span class="hljs-built_in">String</span> Name { get; set; }

        [Required]
        [DataType(DataType.PhoneNumber)]
        [RegularExpression(@<span class="hljs-string">"^(\d{7,12})$"</span>, ErrorMessage = <span class="hljs-string">"Not a valid phone number"</span>)]
        public <span class="hljs-built_in">String</span> PhoneNumber { get; set; }

        [Required]
        [Range(<span class="hljs-number">1</span>, <span class="hljs-number">150</span>)]
        public int Age { get; set; }

        [Required]
        public <span class="hljs-built_in">String</span> Gender { get; set; }

        public <span class="hljs-built_in">Boolean</span> IsAdmitted { get; set; }

        public IEnumerable&amp;lt;ValidationResult&amp;gt; Validate(ValidationContext validationContext)
        {
            <span class="hljs-comment">// Only Male, Female or Other gender are allowed</span>
            <span class="hljs-keyword">if</span> (Gender.Equals(<span class="hljs-string">"Male"</span>, System.StringComparison.CurrentCultureIgnoreCase) == <span class="hljs-literal">false</span> &amp;amp;&amp;amp;
                Gender.Equals(<span class="hljs-string">"Female"</span>, System.StringComparison.CurrentCultureIgnoreCase) == <span class="hljs-literal">false</span> &amp;amp;&amp;amp;
                Gender.Equals(<span class="hljs-string">"Other"</span>, System.StringComparison.CurrentCultureIgnoreCase) == <span class="hljs-literal">false</span>)
            {
                <span class="hljs-keyword">yield</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ValidationResult(<span class="hljs-string">"The gender can either be Male, Female or Other"</span>);
            }

            <span class="hljs-keyword">yield</span> <span class="hljs-keyword">return</span> ValidationResult.Success;
        }
    }
}
</code></pre><p>Here, we have added the required attributes. We have also implemented the <em>IValidatableObject</em> interface so that we can verify the <em>Gender</em>.</p>
<p>Time to run the <strong>dotnet test</strong> command. You will see a nice green line saying 5 tests passed.</p>
<p><img src="https://arjavdave.com/wp-content/uploads/2021/04/Tests_passed_2-1024x244.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can add more edge case scenarios in the <em>InlineData</em> to test the Patient model validation tests thoroughly.</p>
<h2 id="heading-duplicate-patient-test">Duplicate Patient Test</h2>
<p>We shall now create a test which fails when we try to add a duplicate patient.</p>
<h3 id="heading-failing-red-test">Failing (Red) Test</h3>
<p>Create another test in your class <em>PatientTests.</em> Add the below code:</p>
<pre><code>[Fact]
public <span class="hljs-keyword">async</span> Task PatientDuplicationTestsAsync()
{
    <span class="hljs-keyword">var</span> scopeFactory = _factory.Services;
    using (<span class="hljs-keyword">var</span> scope = scopeFactory.CreateScope())
    {
        <span class="hljs-keyword">var</span> context = scope.ServiceProvider.GetService&amp;lt;DataContext&amp;gt;();
        <span class="hljs-keyword">await</span> DBUtilities.InitializeDbForTestsAsync(context);

        <span class="hljs-comment">// Arrange</span>
        <span class="hljs-keyword">var</span> Patient = <span class="hljs-keyword">await</span> context.Patient.FirstOrDefaultAsync();

        <span class="hljs-keyword">var</span> Request = <span class="hljs-keyword">new</span> HttpRequestMessage(HttpMethod.Post, <span class="hljs-string">"api/patient"</span>);
        Request.Content = <span class="hljs-keyword">new</span> StringContent(JsonSerializer.Serialize(Patient), Encoding.UTF8, <span class="hljs-string">"application/json"</span>);

        <span class="hljs-comment">// Act</span>
        <span class="hljs-keyword">var</span> Response = <span class="hljs-keyword">await</span> httpClient.SendAsync(Request);

        <span class="hljs-comment">// Assert</span>
        <span class="hljs-keyword">var</span> StatusCode = Response.StatusCode;
        Assert.Equal(HttpStatusCode.BadRequest, StatusCode);
    }
}
</code></pre><p>We have used a <code>[Fact]</code> attribute instead of the <code>[Theory]</code> attribute here since we don't want to test the same method with different parameters. Instead, we want to make the same request twice.</p>
<p>Run <strong>dotnet test</strong> to run our newly created test. The test will fail with the message <em>Assert.Equal() Failure</em>. Time to fix it.</p>
<h3 id="heading-success-green-test">Success (Green) Test</h3>
<p>To fix the failing test we need to add the implementation for the AddPatient method in <em>PatientController.cs</em>. Update the file's code as below:</p>
<pre><code>using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace TDD.Controllers
{
    [Route(<span class="hljs-string">"api/[controller]"</span>)]
    [ApiController]
    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PatientController</span> : <span class="hljs-title">Controller</span>
    </span>{
        private readonly DataContext _context;

        public PatientController(DataContext context)
        {
            _context = context;
        }
        [HttpPost]
        public <span class="hljs-keyword">async</span> Task&amp;lt;IActionResult&amp;gt; AddPatientAsync([FromBody] Patient Patient)
        {
            <span class="hljs-keyword">var</span> FetchedPatient = <span class="hljs-keyword">await</span> _context.Patient.FirstOrDefaultAsync(x =&amp;gt; x.PhoneNumber == Patient.PhoneNumber);
            <span class="hljs-comment">// If the patient doesn't exist create a new one</span>
            <span class="hljs-keyword">if</span> (FetchedPatient == <span class="hljs-literal">null</span>)
            {
                _context.Patient.Add(Patient);
                <span class="hljs-keyword">await</span> _context.SaveChangesAsync();
                <span class="hljs-keyword">return</span> Created($<span class="hljs-string">"/patient/{Patient.Id}"</span>, Patient);
            }
            <span class="hljs-comment">// Else throw a bad request</span>
            <span class="hljs-keyword">else</span>
            {
                <span class="hljs-keyword">return</span> BadRequest();
            }
        }
    }
}
</code></pre><p>Run the <strong>dotnet test</strong> again and you will see that the tests have passed.</p>
<h2 id="heading-important-notes">Important Notes</h2>
<p>As you add more models/domains like Doctors, Staff, Instruments and so on, you will have to create more tests. Make sure to have a different WAF, utility wrappers, and different test files for each of them.</p>
<p>Secondly, the tests in the same file do not run in parallel. But the tests from different files do run in parallel. Therefore, each WAF should have a different database name so that data is not misconfigured.</p>
<p>Lastly, the connections to the original database still need to be setup in the main project.</p>
<h2 id="heading-how-to-write-good-tests">How to write good tests</h2>
<p>The thought process for creating tests for all scenarios is similar.</p>
<p>That is, you should first identify the requirements. Then, set up a skeleton of methods and classes without implementation. Write tests to verify the implementation. Finally, refactor as needed and rerun the tests.</p>
<p>This tutorial didn't include authentication and authorisation for APIs. You can <a target="_blank" href="https://arjavdave.com/2021/03/31/net-5-setup-authentication-and-authorisation/">read here</a> on how to set that up.</p>
<p>Since I didn't cover all the test cases here, I have created a <a target="_blank" href="https://github.com/shenanigan/tdd-demo">repository on Github</a>. It covers the implementation for all the test cases if you want to have a look.</p>
<p>You can find the <a target="_blank" href="https://github.com/shenanigan/tdd-demo">project here</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In order for TDD to be effective you really need to have a clear idea of what the requirements are. If the requirements keep on changing, it'll become very difficult to maintain the tests as well as the project.</p>
<p>TDD mainly covers unit, integration, and functional tests. You will still have to do UAT, Configuration, and Production testing before you go live.</p>
<p>Having said that, TDD is really helpful in making your project bug free. Secondly, it boosts your confidence for the implementation. You will be able to change bits and pieces of your code as long as the tests pass. Lastly, it provides a better architecture for your project.</p>
<p><a target="_blank" href="https://arjavdave.com/">Check out more tutorials on .NET here.</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Test-Driven Development, Functions, and React Components ]]>
                </title>
                <description>
                    <![CDATA[ By TK This article is part of my studies on how to build sustainable and consistent software. In this post, we will talk about the thinking behind the testing driven development and how to apply this knowledge to simple functions, web accessibility, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/tdd-functions-and-react-components/</link>
                <guid isPermaLink="false">66d852c00e7fa84787a1cd5f</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 30 Apr 2020 17:18:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/tdd.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By TK</p>
<p>This article is part of my studies on how to build sustainable and consistent software. In this post, we will talk about the thinking behind the testing driven development and how to apply this knowledge to simple functions, web accessibility, and React components, mostly with Jest and React Testing Library.</p>
<p>Automated tests are a big part of software development. It gives us, developers, confidence to ship code to be there, but we increase the confidence that the software will be up and running and working appropriately.</p>
<p>I began my software career in the Ruby community writing tests from the first day I learned the language. The Ruby (and Rails) community was always strong in the testing automation area. It helped shape my mindset on how to write good software.</p>
<p>So using Ruby and Rails, I did a lot of backend stuff like background jobs, data structure modeling, API building, and so on. In this scope, the user is always one: the developer user. If building an API, the user would be the developer that's consuming the API. If building the models, the user would be the developer that will use this model.</p>
<p>Now doing a lof of frontend stuff too, after 1 intense year of building PWAs using mostly React and Redux, at first some thoughts came to my mind:</p>
<ul>
<li>TDD is impossible when building UI stuff. How do I know if it is a div or span?</li>
<li>Testing can be "complex". Should I shallow or should I mount? Test everything? Ensure every div should be the right place?</li>
</ul>
<p>So I started re-thinking about these testing practices and how to make it productive.</p>
<p>TDD is possible. If I'm wondering if I should expect a div or a span, I'm probably testing the wrong thing. Remember: tests should give us the confidence to ship, not necessarily to cover every bit or implementation details. We will dive into this topic later!</p>
<p>I want to build tests that:</p>
<ul>
<li>Ensure the software works appropriately</li>
<li>Give the confidence to ship code to production</li>
<li>Make us think about software design</li>
</ul>
<p>And tests that make software:</p>
<ul>
<li>Easy to maintain</li>
<li>Easy to refactor</li>
</ul>
<h2 id="heading-testing-driven-development">Testing Driven Development</h2>
<p>TDD shouldn't be complex. It is just a process of 3 steps:</p>
<ul>
<li>Make a test</li>
<li>Make it run</li>
<li>Make it right</li>
</ul>
<p>We start writing a simple test to cover how we expect the software works. Then we make the first implementation of the code (class, function, script, etc). Now the software is behaving. It works as expected. Time to make it right. Time to make it better.</p>
<p>The goal is a clean code that works. We solve the "that works" problem first and then make the code clean.</p>
<p>It is pretty simple. And it should be. I didn't say it is easy. But it is simple, straightforward, just 3 steps. Every time you exercise this process of writing tests first, code after, and then refactoring, you feel more confident.</p>
<p>One good technique when writing your tests first is to think about use cases and simulate how it should be used (as a function, component, or used by a real user).</p>
<h2 id="heading-functions">Functions</h2>
<p>Let's apply this TDD thing into simple functions.</p>
<p>Some time ago I was implementing a draft feature for a real estate registration flow. Part of the feature was to show a modal if the user had a not finished real estate. The function we will implement is the one that answers if the user has at least one real estate draft.</p>
<p>So first step: writing the test! Let's think of the use cases of this function. It always responds a boolean: true or false.</p>
<ul>
<li>Has no unsaved real estate draft: <code>false</code></li>
<li>Has at least one unsaved real estate draft: <code>true</code></li>
</ul>
<p>Let's write the tests that represent this behavior:</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'hasRealEstateDraft'</span>, <span class="hljs-function">() =&gt;</span> {
  describe(<span class="hljs-string">'with real estate drafts'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns true'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> realEstateDrafts = [
        {
          <span class="hljs-attr">address</span>: <span class="hljs-string">'São Paulo'</span>,
          <span class="hljs-attr">status</span>: <span class="hljs-string">'UNSAVED'</span>
        }
      ];

      expect(hasRealEstateDraft(realEstateDrafts)).toBeTruthy();
    });
  });

  describe(<span class="hljs-string">'with not drafts'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns false'</span>, <span class="hljs-function">() =&gt;</span> {
      expect(hasRealEstateDraft([])).toBeFalsy();
    });
  });
});
</code></pre>
<p>We wrote the tests. But when running it, it shows go red: 2 broken tests because we do not have the function implemented yet.</p>
<p>Second step: make it run! In this case, it is pretty simple. We need to receive this array object and return if it has or hasn't at least one real estate draft.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> hasRealEstateDraft = <span class="hljs-function">(<span class="hljs-params">realEstateDrafts</span>) =&gt;</span> realEstateDrafts.length &gt; <span class="hljs-number">0</span>;
</code></pre>
<p>Great! Simple function. Simple tests. We could go to step 3: make it right! But in this case, our function is really simple and we've already got it right.</p>
<p>But now we need the function to get the real estate drafts and pass it to the <code>hasRealEstateDraft</code>.</p>
<p>Which use case we can think of?</p>
<ul>
<li>An empty list of real estates</li>
<li>Only saved real estates</li>
<li>Only unsaved real estates</li>
<li>Mixed: save and unsaved real estates</li>
</ul>
<p>Let's write the tests to represent it:</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'getRealEstateDrafts'</span>, <span class="hljs-function">() =&gt;</span> {
  describe(<span class="hljs-string">'with an empty list'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns an empty list'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> realEstates = [];

      expect(getRealEstateDrafts(realEstates)).toMatchObject([]);
    });
  });

  describe(<span class="hljs-string">'with only unsaved real estates'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns the drafts'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> realEstates = [
        {
          <span class="hljs-attr">address</span>: <span class="hljs-string">'São Paulo'</span>,
          <span class="hljs-attr">status</span>: <span class="hljs-string">'UNSAVED'</span>
        },
        {
          <span class="hljs-attr">address</span>: <span class="hljs-string">'Tokyo'</span>,
          <span class="hljs-attr">status</span>: <span class="hljs-string">'UNSAVED'</span>
        }
      ];

      expect(getRealEstateDrafts(realEstates)).toMatchObject(realEstates);
    });
  });

  describe(<span class="hljs-string">'with only saved real estates'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns an empty list'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> realEstates = [
        {
          <span class="hljs-attr">address</span>: <span class="hljs-string">'São Paulo'</span>,
          <span class="hljs-attr">status</span>: <span class="hljs-string">'SAVED'</span>
        },
        {
          <span class="hljs-attr">address</span>: <span class="hljs-string">'Tokyo'</span>,
          <span class="hljs-attr">status</span>: <span class="hljs-string">'SAVED'</span>
        }
      ];

      expect(getRealEstateDrafts(realEstates)).toMatchObject([]);
    });
  });

  describe(<span class="hljs-string">'with saved and unsaved real estates'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns the drafts'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> realEstates = [
        {
          <span class="hljs-attr">address</span>: <span class="hljs-string">'São Paulo'</span>,
          <span class="hljs-attr">status</span>: <span class="hljs-string">'SAVED'</span>
        },
        {
          <span class="hljs-attr">address</span>: <span class="hljs-string">'Tokyo'</span>,
          <span class="hljs-attr">status</span>: <span class="hljs-string">'UNSAVED'</span>
        }
      ];

      expect(getRealEstateDrafts(realEstates)).toMatchObject([{
        <span class="hljs-attr">address</span>: <span class="hljs-string">'Tokyo'</span>,
        <span class="hljs-attr">status</span>: <span class="hljs-string">'UNSAVED'</span>
      }]);
    });
  });
});
</code></pre>
<p>Great! We run the tests. It doesn't work.. yet! Now implement the function.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> getRealEstatesDrafts = <span class="hljs-function">(<span class="hljs-params">realEstates</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> unsavedRealEstates = realEstates.filter(<span class="hljs-function">(<span class="hljs-params">realEstate</span>) =&gt;</span> realEstate.status === <span class="hljs-string">'UNSAVED'</span>);
  <span class="hljs-keyword">return</span> unsavedRealEstates;
};
</code></pre>
<p>We simply filter by the real estate status and return it. Great, the tests are passing, the bar is green! And the software is behaving, but we can make it better: step 3!</p>
<p>What about extracting the anonymous function within the <code>filter</code> function and make the <code>'UNSAVED'</code> be represented by an enum?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> STATUS = {
  <span class="hljs-attr">UNSAVED</span>: <span class="hljs-string">'UNSAVED'</span>,
  <span class="hljs-attr">SAVED</span>: <span class="hljs-string">'SAVED'</span>,
};

<span class="hljs-keyword">const</span> byUnsaved = <span class="hljs-function">(<span class="hljs-params">realEstate</span>) =&gt;</span> realEstate.status === STATUS.UNSAVED;

<span class="hljs-keyword">const</span> getRealEstatesDrafts = <span class="hljs-function">(<span class="hljs-params">realEstates</span>) =&gt;</span> realEstates.filter(byUnsaved);
</code></pre>
<p>The tests are still passing and we have a better solution.</p>
<p>One thing to have in mind here: I isolated the data source from the logic. What does it mean? We get the data from local storage (data source), but we test only the functions responsible to the logic to get drafts and see if it has at least one draft. The functions with the logic, we ensure that it works and it is clean code.</p>
<p>If we get the <code>localStorage</code> inside our functions, it becomes hard to test. So we separate the responsibility and make the tests easy to write. Pure functions are easier to maintain and simpler to write tests.</p>
<h2 id="heading-react-components">React Components</h2>
<p>Now let's talk about React components. Back to the introduction, we talked about writing tests that test implementation details. And now we will see how we can make it better, more sustainable, and have more confidence.</p>
<p>A couple of days ago I was planning to build the new onboarding information for the real estate owner. It is basically a bunch of pages with the same design, but it changes the icon, title, and description of the pages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/ui.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>I wanted to build just one component: <code>Content</code> and pass the information needed to render the correct icon, title, and description. I would pass <code>businessContext</code> and <code>step</code> as props and it would render the correct content to the onboarding page.</p>
<p>We don't want to know if we will render a div or paragraph tag. Our test needs to ensure that for a given business context and step, the correct content will be there. So I came with these use cases:</p>
<ul>
<li>The first step of the rental business context</li>
<li>Last step of the rental business context</li>
<li>The first step of the sales business context</li>
<li>Last step of the sales business context</li>
</ul>
<p>Let's see the tests:</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'Content'</span>, <span class="hljs-function">() =&gt;</span> {
  describe(<span class="hljs-string">'in the rental context'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> defaultProps = {
      <span class="hljs-attr">businessContext</span>: BUSINESS_CONTEXT.RENTAL
    };

    it(<span class="hljs-string">'renders the title and description for the first step'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">0</span>;
      <span class="hljs-keyword">const</span> { getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Content</span> {<span class="hljs-attr">...defaultProps</span>} <span class="hljs-attr">step</span>=<span class="hljs-string">{step}</span> /&gt;</span></span>);

      expect(getByText(<span class="hljs-string">'the first step title'</span>)).toBeInTheDocument();
      expect(getByText(<span class="hljs-string">'the first step description'</span>)).toBeInTheDocument();
    });

    it(<span class="hljs-string">'renders the title and description for the forth step'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">3</span>;
      <span class="hljs-keyword">const</span> { getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Content</span> {<span class="hljs-attr">...defaultProps</span>} <span class="hljs-attr">step</span>=<span class="hljs-string">{step}</span> /&gt;</span></span>);

      expect(getByText(<span class="hljs-string">'the last step title'</span>)).toBeInTheDocument();
      expect(getByText(<span class="hljs-string">'the last step description'</span>)).toBeInTheDocument();
    });
  });

  describe(<span class="hljs-string">'in the sales context'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> defaultProps = {
      <span class="hljs-attr">businessContext</span>: BUSINESS_CONTEXT.SALE
    };

    it(<span class="hljs-string">'renders the title and description for the first step'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">0</span>;
      <span class="hljs-keyword">const</span> { getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Content</span> {<span class="hljs-attr">...defaultProps</span>} <span class="hljs-attr">step</span>=<span class="hljs-string">{step}</span> /&gt;</span></span>);

      expect(getByText(<span class="hljs-string">'the first step title'</span>)).toBeInTheDocument();
      expect(getByText(<span class="hljs-string">'the first step description'</span>)).toBeInTheDocument();
    });

    it(<span class="hljs-string">'renders the title and description for the last step'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">6</span>;
      <span class="hljs-keyword">const</span> { getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Content</span> {<span class="hljs-attr">...defaultProps</span>} <span class="hljs-attr">step</span>=<span class="hljs-string">{step}</span> /&gt;</span></span>);

      expect(getByText(<span class="hljs-string">'the last step title'</span>)).toBeInTheDocument();
      expect(getByText(<span class="hljs-string">'the last step description'</span>)).toBeInTheDocument();
    });
  });
});
</code></pre>
<p>We have one <code>describe</code> block for each business context and an <code>it</code> block for each step. I also created an accessibility test to ensure the component we are building is accessible.</p>
<pre><code class="lang-javascript">it(<span class="hljs-string">'has not accessibility violations'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> props = {
    <span class="hljs-attr">businessContext</span>: BUSINESS_CONTEXT.SALE,
    <span class="hljs-attr">step</span>: <span class="hljs-number">0</span>,
  };

  <span class="hljs-keyword">const</span> { container } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Content</span> {<span class="hljs-attr">...props</span>} /&gt;</span></span>);
  <span class="hljs-keyword">const</span> results = <span class="hljs-keyword">await</span> axe(container);

  expect(results).toHaveNoViolations();
});
</code></pre>
<p>Now we need to make it run! Basically, the UI part of this component is just the icon, the title, and the description. Something like:</p>
<pre><code class="lang-javascript">&lt;Fragment&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/Fragment&gt;
</code></pre>
<p>We just need to build the logic to get all these correct data. As I have the <code>businessContext</code> and the <code>step</code> in this component, I wanted to just do something like</p>
<pre><code class="lang-javascript">content[businessContext][step]
</code></pre>
<p>And it gets the correct content. So I built a data structure to work that way.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> onboardingStepsContent = {
  <span class="hljs-attr">alugar</span>: {
    <span class="hljs-number">0</span>: {
      <span class="hljs-attr">Icon</span>: Home,
      <span class="hljs-attr">title</span>: <span class="hljs-string">'first step title'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'first step description'</span>,
    },
    <span class="hljs-comment">// ...</span>
  },
  <span class="hljs-attr">vender</span>: {
    <span class="hljs-number">0</span>: {
      <span class="hljs-attr">Icon</span>: Home,
      <span class="hljs-attr">title</span>: <span class="hljs-string">'first step title'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'first step description'</span>,
    },
    <span class="hljs-comment">// ...</span>
  },
};
</code></pre>
<p>It's just an object with the first keys as the business context data and for each business context, it has keys that represent each step of the onboarding. And our component would be:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Content = <span class="hljs-function">(<span class="hljs-params">{ businessContext, step }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> onboardingStepsContent = {
    <span class="hljs-attr">alugar</span>: {
      <span class="hljs-number">0</span>: {
        <span class="hljs-attr">Icon</span>: Home,
        <span class="hljs-attr">title</span>: <span class="hljs-string">'first step title'</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">'first step description'</span>,
      },
      <span class="hljs-comment">// ...</span>
    },
    <span class="hljs-attr">vender</span>: {
      <span class="hljs-number">0</span>: {
        <span class="hljs-attr">Icon</span>: Home,
        <span class="hljs-attr">title</span>: <span class="hljs-string">'first step title'</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">'first step description'</span>,
      },
      <span class="hljs-comment">// ...</span>
    },
  };

  <span class="hljs-keyword">const</span> { Icon, title, description } = onboardingStepsContent[businessContext][step];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Fragment</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Fragment</span>&gt;</span></span>
  );
};
</code></pre>
<p>It works! Now let's make it better. I wanted to make the get content more resilient. What if it receives a step that doesn't exist for example? These are the use cases:</p>
<ul>
<li>The first step of the rental business context</li>
<li>Last step of the rental business context</li>
<li>The first step of the sales business context</li>
<li>Last step of the sales business context</li>
<li>Inexistent step of the rental business context</li>
<li>Inexistent step of the sales business context</li>
</ul>
<p>Let's see the tests:</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'getOnboardingStepContent'</span>, <span class="hljs-function">() =&gt;</span> {
  describe(<span class="hljs-string">'when it receives existent businessContext and step'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns the correct content for the step in "alugar" businessContext'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> businessContext = <span class="hljs-string">'alugar'</span>;
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">0</span>;

      expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({
        <span class="hljs-attr">Icon</span>: Home,
        <span class="hljs-attr">title</span>: <span class="hljs-string">'first step title'</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">'first step description'</span>,
      });
    });

    it(<span class="hljs-string">'returns the correct content for the step in "vender" businessContext'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> businessContext = <span class="hljs-string">'vender'</span>;
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">5</span>;

      expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({
        <span class="hljs-attr">Icon</span>: ContractSign,
        <span class="hljs-attr">title</span>: <span class="hljs-string">'last step title'</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">'last step description'</span>,
      });
    });
  });

  describe(<span class="hljs-string">'when it receives inexistent step for a given businessContext'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'returns the first step of "alugar" businessContext'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> businessContext = <span class="hljs-string">'alugar'</span>;
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">7</span>;

      expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({
        <span class="hljs-attr">Icon</span>: Home,
        <span class="hljs-attr">title</span>: <span class="hljs-string">'first step title'</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">'first step description'</span>,
      });
    });

    it(<span class="hljs-string">'returns the first step of "vender" businessContext'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> businessContext = <span class="hljs-string">'vender'</span>;
      <span class="hljs-keyword">const</span> step = <span class="hljs-number">10</span>;

      expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({
        <span class="hljs-attr">Icon</span>: Home,
        <span class="hljs-attr">title</span>: <span class="hljs-string">'first step title'</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">'first step description'</span>,
      });
    });
  });
});
</code></pre>
<p>Great! Now let's build our <code>getOnboardingStepContent</code> function to handle this logic.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> getOnboardingStepContent = <span class="hljs-function">(<span class="hljs-params">{ businessContext, step }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> content = onboardingStepsContent[businessContext][step];

  <span class="hljs-keyword">return</span> content
    ? content
    : onboardingStepsContent[businessContext][<span class="hljs-number">0</span>];
};
</code></pre>
<p>We try to get content. If we have it, just return it. If we don't have it, return the first step of the onboarding.</p>
<p>Neat! But we can improve it. What about using the <code>||</code> operator? No need to assign to a variable, no need to use a ternary.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> getOnboardingStepContent = <span class="hljs-function">(<span class="hljs-params">{ businessContext, step }</span>) =&gt;</span>
  onboardingStepsContent[businessContext][step] ||
  onboardingStepsContent[businessContext][<span class="hljs-number">0</span>];
</code></pre>
<p>If it finds the content, just return it. If it didn't find, return the first step of the given business context.</p>
<p>Now our component is only UI.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Content = <span class="hljs-function">(<span class="hljs-params">{ businessContext, step }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> {
    Icon,
    title,
    description,
  } = getOnboardingStepContent({ businessContext, step });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Fragment</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Fragment</span>&gt;</span></span>
  );
};
</code></pre>
<hr>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p>I like to think deeply about the tests I'm writing. And I think all developers should too. It does need to give us the confidence to ship more code and have a bigger impact on the market we are working on.</p>
<p>Like all code, when we write smelly and bad tests, it influences other developers to follow the "pattern". It gets worse in bigger companies. It scales badly. But we are always able to stop, reflect on the status quo, and take action to make it better.</p>
<p>I shared some resources I found interesting reading and learning. If you want to get a great introduction to TDD, I really recommend TDD by example, a book from Kent Beck.</p>
<p>I will write more about tests, TDD, and React. And how we can make our software more consistent and feel safe when shipping code to production.</p>
<h2 id="heading-dependencies">Dependencies</h2>
<ul>
<li><a target="_blank" href="https://github.com/nickcolley/jest-axe">jest-axe</a>: jest matchers for testing accessibility</li>
<li><a target="_blank" href="https://github.com/testing-library/react-testing-library">testing-library/react-testing-library</a>: testing utilities to help test react</li>
<li><a target="_blank" href="https://github.com/testing-library/jest-dom">testing-library/jest-dom</a>: jest matchers to test the state of the DOM</li>
</ul>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://BeginnerJavaScript.com/friend/LEANDRO">Beginner JavaScript Course</a></li>
<li><a target="_blank" href="https://ReactForBeginners.com/friend/LEANDRO">React for Beginners Course</a></li>
<li><a target="_blank" href="https://AdvancedReact.com/friend/LEANDRO">Advanced React Course</a></li>
<li><a target="_blank" href="https://ES6.io/friend/LEANDRO">ES6 Course</a></li>
<li><a target="_blank" href="https://www.educative.io/courses/the-road-to-learn-react?aff=x8bV">The Road to learn React</a></li>
<li><a target="_blank" href="https://www.educative.io/courses/javascript-fundamentals-before-learning-react?aff=x8bV">JavaScript Fundamentals Before Learning React</a></li>
<li><a target="_blank" href="https://www.educative.io/courses/reintroducing-react-v16-beyond?aff=x8bV">Reintroducing React: V16 and Beyond</a></li>
<li><a target="_blank" href="https://www.educative.io/courses/advanced-react-patterns-with-hooks?aff=x8bV">Advanced React Patterns With Hooks</a></li>
<li><a target="_blank" href="https://www.educative.io/courses/practical-redux">Practical Redux</a></li>
<li><a target="_blank" href="https://mbsy.co/lFtbC">JavaScript Course by OneMonth</a></li>
<li><a target="_blank" href="https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530">Test Driven Development by example book by Kent Beck</a></li>
<li><a target="_blank" href="https://www.amazon.com/Testable-JavaScript-Ensuring-Reliable-Code/dp/1449323391/ref=sr_1_8?dchild=1&amp;keywords=testing+javascript&amp;qid=1585274935&amp;s=books&amp;sr=1-8">Testable Javascript book by Mark Ethan Trostler</a></li>
<li><a target="_blank" href="https://github.com/tk-notes/blog/tree/master/tdd-functions-and-react-components">Blog post source code</a></li>
<li><a target="_blank" href="https://medium.com/hackernoon/testing-react-with-jest-axe-and-react-testing-library-accessibility-34b952240f53">Testing React applications with jest, jest-axe, and react-testing-library</a></li>
<li><a target="_blank" href="https://blog.sapegin.me/all/react-testing-3-jest-and-react-testing-library/">Modern React testing, part 3: Jest and React Testing Library</a></li>
<li><a target="_blank" href="https://accessibility.blog.gov.uk/2017/02/24/what-we-found-when-we-tested-tools-on-the-worlds-least-accessible-webpage/">What we found when we tested tools on the world’s least-accessible webpage</a></li>
<li><a target="_blank" href="https://kentcdodds.com/blog/testing-implementation-details">Testing Implementation Details</a></li>
<li><a target="_blank" href="https://alterclass.io/?ref=5ec57f513c1321001703dcd2">Learn React by building an App</a></li>
</ul>
<p>You can other articles like this <a target="_blank" href="https://leandrotk.github.io/tk/2020/03/closure-currying-and-cool-abstractions/index.html">on my blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A practical introduction to Test Driven Development ]]>
                </title>
                <description>
                    <![CDATA[ By Luca Piccinelli Test Driven Development is hard! This is the untold truth about it. These days you read a ton of articles about all the advantages of doing Test Driven Development (TDD). And you probably hear a lot of talks at tech conferences tha... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/practical-tdd-test-driven-development-84a32044ed0b/</link>
                <guid isPermaLink="false">66c35cb6258ebfc3dc8f1f74</guid>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 01 Jan 2019 16:34:33 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*Yd-MlvHYafduLBLFkSgH4Q.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Luca Piccinelli</p>
<h4 id="heading-test-driven-development-is-hard-this-is-the-untold-truth-about-it">Test Driven Development is hard! This is the untold truth about it.</h4>
<p>These days you read a ton of articles about all the advantages of doing Test Driven Development (TDD). And you probably hear a lot of talks at tech conferences that tell you to “Do the tests!”, and how cool it is to do them. </p>
<p>And you know what? Unfortunately, they are right (not necessarily about the “cool” part, but about the useful part). <strong>Tests are a MUST</strong>! The typical advantages we list when it comes to talking about TDD are real:</p>
<ul>
<li>You write better software</li>
<li>You have protection from breaking the world when new features are introduced</li>
<li>Your software is self documented</li>
<li>You avoid over-engineering</li>
</ul>
<p>Even if I’ve always agreed with these advantages, <strong>there was a time when I thought that I didn’t need TDD to write good and maintainable software.</strong> Of course, now I know I was wrong, but why did I have this idea despite the shiny magic of the pros? The reason is just one: and let me ask Rihanna to say it for me…</p>
<h3 id="heading-the-cost"><strong>The Cost!</strong></h3>
<p>It costs a lot! Probably someone is thinking “<em>but it costs even more if you don’t do the tests</em>” — and this is right, too. But these two costs come at different times:</p>
<ul>
<li>you do TDD ➡ you have a cost <strong>now</strong>.</li>
<li>You don’t do TDD ➡ you will have a cost <strong>in the future</strong>.</li>
</ul>
<p>So, how do we come out of this impasse?</p>
<p>The most effective way to get something done is doing it as naturally as possible. The nature of people is to be lazy (here software developers are the best performers) and greedy, so you have to find your way of <strong>reducing the costs now</strong>. It’s easy to say, but so hard to do!</p>
<p>Here I will share my experience and what has worked for me in turning the benefit/cost ratio to my favour.</p>
<p>But before I do that, let’s analyze some typical difficulties in applying TDD.</p>
<h3 id="heading-are-you-able-to-test-the-sum-of-two-numbers">Are you able to test the sum of two numbers?</h3>
<p>Generally speaking, theory is not optional; you have to master it in order to master the practice. However trying to apply at once all the theoretical knowledge you’ve previously acquired could have the following effect:</p>
<p>The typical theory lesson on TDD starts with something like this:</p>
<p>And here you are like</p>
<p>Then comes this:</p>
<ul>
<li>red ➡ green ➡ refactor cycle</li>
<li>unit, acceptance, regression, integration tests</li>
<li>mocking, stubs, fakes</li>
<li>if you are lucky (or maybe unlucky ?), someone will tell you about contract testing</li>
<li>and if you are very lucky (or maybe very unlucky ?) you will touch legacy codebase refactoring</li>
</ul>
<p>The going gets tough, but you are an experienced developer and all these concepts are not that hard to handle for you. Then class ends; you go home, and throughout the next days you diligently do some code katas to fix the concepts just learned. So far so good.</p>
<h4 id="heading-the-struggle-is-real">The struggle is real</h4>
<p>Next comes a real world project, with real deadlines and real timing costs — but you are motivated to apply your shiny new TDD. You start thinking about the architecture of your software and start writing tests for the first class and the class itself — let’s call it <strong>Class1</strong>.</p>
<p>Now you think about the first user of Class1, let’s call it <strong>UsageOfAClass,</strong> and again you test and write it. Class1 is a collaborator of UsageOfAClass, so are you going to mock it? Ok let’s mock it. But what about real interactions of Class1 and UsageOfAClass? Maybe you should test them all as well? Let’s do it.</p>
<p>At this point, inside of you, you start hearing a little voice that says “<em>I</em> <em>would develop much faster if I didn’t have to write these tests…</em>”. You don’t listen to this evil voice and proceed straight to the next test.</p>
<p><strong>Class2</strong> is going to be used by UsageOfAClass and it persists itself inside a Db. So, do we have to test Class2, its interaction with UsageOfAClass, and the persistence in the Db? But wait… did anyone mention how to cope with I/O testing during the TDD theory class?</p>
<p>The theory behind TDD is not that hard to understand, but applying it to the real world can be really complex if you don’t approach it the right way.</p>
<h3 id="heading-just-do-it">Just do it</h3>
<p>We should always keep in mind that theory must be bent to our needs and not the contrary.</p>
<p>The main goal is to get the job done. So my advice is, <strong>just do it</strong>!</p>
<p><strong>Start simple and just do your task up to the end.</strong> Then, when you get stuck in some theoretical mind loop like:</p>
<ul>
<li>is this a unit or an integration test?</li>
<li>here should I mock it or not?</li>
<li>oh crap, here I should write a new collaborator, so a brand new suite of infinite unit tests just to write “hey, banana”…</li>
</ul>
<p>just forget about theory for a while and take a step forward. Just do it as it comes!</p>
<p>Once you are done with your task, have a look back at your work. <strong>Looking back</strong> at the completed job, it will be much easier to analyze what would have been the right thing to do.</p>
<h3 id="heading-practical-tdd">Practical TDD</h3>
<p>Just do it. By the way, I think this is also the right approach to TDD.</p>
<p>What was wrong in how we built Class1, Class2 and UsageOfAClass? <strong>The approach.</strong></p>
<p>This is a bottom-up approach:</p>
<ul>
<li>analyze the problem</li>
<li>figure out an architecture</li>
<li>start building it from unit components</li>
</ul>
<p>This approach is the best friend of <strong>over-engineering</strong>. You typically build the system in order to prevent changes that you think will come in the future, without knowing if they actually will. Then when some requirement changes, it typically happens in a way that doesn’t fit your structure, no matter how good it is.</p>
<p>For me <strong>the key to drastically reducing the immediate cost</strong> of writing with TDD has been to take a top-down approach:</p>
<ol>
<li>bring a user story</li>
<li>write a very simple test of a use case</li>
<li>make it run</li>
<li>go back to step 2 until all use cases are complete</li>
</ol>
<p>While doing this process, don’t worry too much about architecture, clean code (well, remember at least to use decent variables names) or any kind of complication that is not currently needed. Just do what you know you need <strong>now</strong>, up to the end.</p>
<p><strong>Tests of the story clearly state what are the current and known requirements.</strong></p>
<p>Once you are done, take a look at your big ball of spaghetti mud code, get over the shame, and look deeper at what you have done:</p>
<ul>
<li>it works! And tests prove it.</li>
<li>All the system is there, <strong>and just what is actually needed to get the job done</strong>.</li>
</ul>
<p>Now you have an overview of all the parts of your system, so you can refactor with the knowledge of the domain that you couldn’t have had when you started from scratch. And tests will make sure that nothing will break while refactoring.</p>
<h3 id="heading-refactoring">Refactoring</h3>
<p>The best way for me to start to refactor is to identify areas of responsibility and separate them in private methods. This step helps identify responsibilities and their inputs and outputs.</p>
<p>After that, classes of collaborators are almost there and you just need to move them into different files.</p>
<p>As you proceed, first write tests for the classes that pop out from the process and iterate until you are satisfied with the result. And remember, if you get stuck somewhere, just do it! If you do something bad, once you are done you will have more information on how to get over the mistake the next time you face it. <strong>Getting the job done is the priority</strong>, to the best of your current abilities.</p>
<p>This way, if you analyze your errors to learn from them, you will also refine your abilities.</p>
<h3 id="heading-the-next-user-story">The next user story</h3>
<p>Continue developing your product following these steps:</p>
<ul>
<li>take a story</li>
<li>make it work completely in a “test — code” cycle.</li>
<li>refactor</li>
</ul>
<p>While adding features you will continue to change your software and maybe even its structure. But as the system grows, the cost of change will maintain a linear growth thanks to the two main features of TDD:</p>
<ul>
<li>architecture discovery (that helps to control the complexity)</li>
<li>protection from breaking changes</li>
</ul>
<p>The system will not be over-engineered, as architecture is going to emerge as stories get completed. You don’t think about what could be future requirements; if you end up needing it, then the cost to implement it will be low.</p>
<h4 id="heading-what-can-make-it-go-wrong">What can make it go wrong?</h4>
<p>The size of the story. What you build up to the end must be the right size. Not too big (otherwise it will take too much time to get any feedback) or too small (otherwise you won’t have the overview).</p>
<p>What if the story is too big? Split it up in pieces that can be built from the start to the end.</p>
<h3 id="heading-whats-next">What’s next?</h3>
<p>In the next article I will give a practical example of the concepts I explained here. We will implement, step by step, the <a target="_blank" href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata">Bowling Game kata</a> starting from an acceptance test.</p>
<p>It is not a real world problem, but it has enough complexity to see how TDD can help in handling it.</p>
<p>Please share your opinion and suggestions about this article. Do you agree with me or do you think that all this is a bunch of rubbish? Let me know what you think in comments; it would be very nice to start a conversation on TDD and share our experiences.</p>
<p>I want to thank <a target="_blank" href="https://www.freecodecamp.org/news/practical-tdd-test-driven-development-84a32044ed0b/undefined">Matteo Baglini</a> for helping me to find my way through a practical approach to software development and TDD.</p>
<p>Thank you for reading!</p>
<p>Cover image courtesy of <a target="_blank" href="https://testsigma.com/blog/ai-driven-test-automation/">testsigma</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A quick introduction to test driven development with Jest ]]>
                </title>
                <description>
                    <![CDATA[ By Nicolas Mitchell This article is a simple walkthrough of how to apply Test Driven Development (TDD) principles to a JavaScript exercise using Jest. Intro After a few years of experience developing on my own personal projects, I recently decided to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-quick-introduction-to-test-driven-development-with-jest-cac71cb94e50/</link>
                <guid isPermaLink="false">66c343154f7405e6476b0168</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 25 Jun 2018 21:18:39 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*0jCUKud4CkbbmNrFDzIQZw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Nicolas Mitchell</p>
<p>This article is a simple walkthrough of how to apply Test Driven Development (TDD) principles to a JavaScript exercise using Jest.</p>
<h3 id="heading-intro">Intro</h3>
<p>After a few years of experience developing on my own personal projects, I recently decided to become a Full-Stack developer.</p>
<p>This new situation encouraged me to start thinking about practices that I’ve neglected until now, such as testing my code.</p>
<p>That is why I wanted to start my journey through Test Driven Development. I’ve decided to share my first steps here with you.</p>
<h3 id="heading-the-exercise">The exercise</h3>
<p>I decided to start with the first Osherove TDD kata. You can access the full exercise <a target="_blank" href="http://osherove.com/tdd-kata-1/">here</a>.</p>
<p>The goal is to deliver a function that takes a string entry (<code>"1, 2, 3"</code> for instance) and returns the sum of all numbers.</p>
<p>Our project will have the following structure:</p>
<pre><code>js-kata-jest/
</code></pre><pre><code>├─ src/
</code></pre><pre><code>  └─ kata.js
</code></pre><pre><code>├─ test/
</code></pre><pre><code>  └─ kata.test.js
</code></pre><pre><code>└─ package.json
</code></pre><h3 id="heading-setting-up-the-test-environment">Setting up the test environment</h3>
<p>First we have to set up the test environment. As a React developer, I decided to go with <a target="_blank" href="https://facebook.github.io/jest/">Jest</a>. You may use any other testing library of your choice.</p>
<h4 id="heading-installing-jest-dev-dependency">Installing Jest dev dependency</h4>
<pre><code>yarn add --dev jest
</code></pre><p>or with <a target="_blank" href="https://www.npmjs.com/">npm</a>:</p>
<pre><code>npm install --save-dev jest
</code></pre><h4 id="heading-activating-jest-on-your-code-editor">Activating Jest on your code editor</h4>
<p>I am using Atom as a code editor, and installed the <a target="_blank" href="https://atom.io/packages/tester-jest">tester-jest</a> package. This allowed me to run my tests on save for any <code>*.test.js</code> file.</p>
<h3 id="heading-test-driven-development">Test Driven Development</h3>
<p>The theory behind TDD is quite simple, and revolves around 3 steps:</p>
<ol>
<li>Writing a test for a small part of a functionality and checking that this new test is failing (Red step)</li>
<li>Writing the code that makes the test pass, then checking that your previous test and the new one are successful (Green step)</li>
<li>Refactoring the code to make sure it is clear, understandable, and behaves well with the previous functionalities</li>
</ol>
<p>In the next part, we are going to go into detail for each of these steps.</p>
<h3 id="heading-solving-the-exercise">Solving the exercise</h3>
<h4 id="heading-first-loop">First loop</h4>
<p>First, we want to handle the case where our <code>add</code> function is given an empty string or one with a single element.</p>
<ol>
<li><p><strong>Writing the tests</strong></p>
</li>
<li><p>The first test checks that an empty string returns 0</p>
</li>
<li>The second checks that a single element string returns the provided element</li>
</ol>
<p><strong>2. Writing the code</strong></p>
<ul>
<li>First we return 0 by default</li>
<li>Then we provide an <code>if</code> statement that handles the parsing of a single provided element</li>
</ul>
<p>Here is the final code:</p>
<p><strong>3. Refactoring the code</strong></p>
<p>As it is our first functionality, we can skip this step for now — but we will soon return to it. ;)</p>
<h4 id="heading-second-loop">Second loop</h4>
<p>We will now handle the case where the string contains multiple elements:</p>
<ol>
<li><strong>Writing the tests</strong></li>
</ol>
<p>The new test makes sure that calculation of a multiple element string was done correctly:</p>
<p><strong>2. Writing the code</strong></p>
<ul>
<li>First we create a new <code>if</code> statement on purpose to be sure that our first two tests affect the new solution</li>
<li>Second we create a new array from the entry string, using the <code>,</code> as a separator</li>
<li>Finally, we parse each element of the newly created array to calculate the sum</li>
</ul>
<p>Here is the final code:</p>
<p><strong>3. Refactoring the code</strong></p>
<p>As we can see above, there are several problems within our code:</p>
<ul>
<li>the two if statement shouldn’t be decorrelated, as adding one or more to zero should behave the same.</li>
<li>the separator value is drowned in the code. This adds complexity if we want to change to a <code>;</code> separator, for instance.</li>
<li>a large part of our code is located in an <code>if</code> statement. We could reverse the logic to extract our main code from it.</li>
</ul>
<p>So we can add a new <code>separator</code> variable, which will decide on the separator type. We can also merge the two <code>if</code> statement into one, and then reverse the logic.</p>
<p>We can now run our test again before moving on to the next loop.</p>
<h4 id="heading-third-loop">Third loop</h4>
<p>We can now handle the declaration of new separators and avoid the entry of negative numbers.</p>
<ol>
<li><p><strong>Writing the tests</strong></p>
</li>
<li><p>The first new test focuses on a single separator within the default values.</p>
</li>
<li>The second will make sure that we can configure a new separator directly within the input.</li>
<li>The third one will check that an error is thrown when a negative value is passed as an entry.</li>
</ol>
<p><strong>2. Writing the code</strong></p>
<ul>
<li>First, we replace the <code>separator</code> string by a <code>separators</code> array, where we add the <code>\n</code> value.</li>
<li>Second, we introduce a new separator search through a regular expression. That will be added to the previous array.</li>
<li>We can now join the previous array elements to split the string with them.</li>
<li>We filter the resulting array to remove all non-number elements.</li>
<li>We add a new array, <code>negatives</code>, that will spot negative values within the entry.</li>
<li>If the <code>negatives</code> array isn’t empty, throw an error.</li>
</ul>
<p>Here is the final code:</p>
<p><strong>3. Refactoring the code</strong></p>
<p>We now have two new possible optimizations:</p>
<ul>
<li>We are using the regular expression twice, and are willing to change it easily. We can extract it within a new <code>const regexp</code>.</li>
<li>We calculate <code>parseInt(list[i])</code>several times, so we should store the value only once to speed up the <code>for</code> loop.</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We can now run our tests again to make sure that all our expected functionalities are still working.</p>
<p>You may now continue on your own as well. Check out the definitive version of the kata with all tests passing <a target="_blank" href="https://github.com/nclsmitchell/js-kata-jest">here</a>.</p>
<p>Feel free to reach me on Twitter if you have any questions or comments <a target="_blank" href="https://twitter.com/nclsmitchell">@nclsmitchell</a> or through Medium :)</p>
<p>Thanks for your reading, and please clap for me if you like this post.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Great RSpec-tations: why I love test-driven development ]]>
                </title>
                <description>
                    <![CDATA[ By Arit Amana When I first wrote about Test-Driven Development, I thought I was in love with the concept… but that was just the flirting stage. Now I’ve fallen head-over-Louboutins, girlfriend! ? The efficiency gains from not needing to fire my app u... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/great-rspec-tations-test-driven-development-16c86f2ccf7c/</link>
                <guid isPermaLink="false">66c34bf25ced6d98e4bd32f8</guid>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby on Rails ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ women in tech ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 23 May 2018 23:57:01 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*OvF5QBJTAjMURU4G2BSWNA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Arit Amana</p>
<p>When I first <a target="_blank" href="https://code.likeagirl.io/what-done-looks-like-test-driven-development-e9b0eaa38836">wrote about Test-Driven Development</a>, I thought I was in love with the concept… but that was just the flirting stage. Now I’ve fallen head-over-Louboutins, girlfriend! ?</p>
<p>The efficiency gains from not needing to fire my app up for testing are just the beginning. Developing my apps with <a target="_blank" href="http://rspec.info/">RSpec</a> forces me to really think about how I’m defining and structuring my code. Furthermore, every time my tests fail, they faithfully supply tips and clues that help me troubleshoot what’s missing, broken or redundant. Now that’s a metaphor for life in general… but I digress. ?</p>
<p>I’m creating an online chess app <a target="_blank" href="https://code.likeagirl.io/no-longer-the-lone-coding-wolf-4fb52360b808">as part of an agile development team</a>, and this week, I was tasked with building the <strong>move_to!(x,y)</strong> method. This should move a chess piece (called <strong>pawn</strong> from now on) to the chessboard square at location <strong>(x,y)</strong>.</p>
<p>If an opponent’s piece (called <strong>king</strong> from now on) occupies (x,y), pawn should capture it. If pawn’s brother-in-arms occupies (x,y), the method should raise an error message and pawn should go nowhere.</p>
<p>Note: move_to!(x,y) doesn’t consider whether the moves or captures are valid. Other methods will do this.</p>
<p>I configured <a target="_blank" href="https://github.com/thoughtbot/factory_bot">FactoryBot</a> to generate instances of a chess game. Each chess piece has the following relevant attributes: <strong>:location_x</strong>, <strong>:location_y</strong>, <strong>:white</strong> (a boolean; <strong>true</strong> = white color), <strong>:game_id</strong>, and <strong>:notcaptured</strong> (a boolean; <strong>false</strong> = the piece has been captured). My first test determined if pawn (currently on 0,0) moved to an empty square (7,7):</p>
<p>Next, I began writing the <strong>move_to!(x,y)</strong> method, then ran my test:</p>
<pre><code>arit (master) chessapp $ rspec spec/models/piece_spec.rb
</code></pre><pre><code>.
</code></pre><pre><code>Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0.43495</span> seconds (files took <span class="hljs-number">15.68</span> seconds to load)
</code></pre><pre><code><span class="hljs-number">1</span> example, <span class="hljs-number">0</span> failures
</code></pre><p>Yes! No errors. ?? Next, I wrote a test to determine whether pawn stayed put if its destination was occupied by a friendly piece (we’ll call it ro<strong>ok):</strong></p>
<p>Why aren’t I testing the values of <strong>rook.notcaptured</strong>, <strong>rook.location_x</strong> and <strong>rook.location_y</strong>? Well, the rook IS the friendly-piece in question, but what we’re actually testing is whatever piece (if any) is <strong>found by and saved in the <em>destination</em> variable</strong>. Now to flesh out the method:</p>
<p>My tests passed again! ?? Feeling very confident, I moved on to the third test: to determine if the opponent’s king was captured and whether pawn took its place:</p>
<p>I also completed the method:</p>
<p>But when I ran my tests, I received the following error:</p>
<pre><code>arit (master *) chessapp $ rspec spec/models/piece_spec.rb
</code></pre><pre><code>..F
</code></pre><pre><code>Failures:
</code></pre><pre><code><span class="hljs-number">1</span>) Piece captures opponent<span class="hljs-string">'s piece on destination, then assumes that position</span>
</code></pre><pre><code>Failure/<span class="hljs-built_in">Error</span>: expect(destination.notcaptured).to be <span class="hljs-literal">false</span>
</code></pre><pre><code>expected <span class="hljs-literal">false</span>
</code></pre><pre><code>got <span class="hljs-literal">true</span>
</code></pre><pre><code># ./spec/models/piece_spec.rb:<span class="hljs-number">104</span>:<span class="hljs-keyword">in</span> <span class="hljs-string">`block (2 levels) in &lt;top (required)&gt;'</span>
</code></pre><pre><code>Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0.21787</span> seconds (files took <span class="hljs-number">4.83</span> seconds to load)
</code></pre><pre><code><span class="hljs-number">1</span> example, <span class="hljs-number">1</span> failure
</code></pre><pre><code>Failed examples:
</code></pre><pre><code>rspec ./spec/models/piece_spec.rb:<span class="hljs-number">95</span> # Piece captures opponent<span class="hljs-string">'s piece on destination, then assumes that position</span>
</code></pre><p>Wha??? <strong>destination.notcaptured</strong> was not updated? Why? I re-read my method over and over. Nothing seemed to be missing or broken (and, really, just how much could I get wrong in 11 lines of code?).</p>
<p>After deciding to make like a ? and review my rspec test sloooowwly, it occurred to me that the d<strong>estination</strong> variable was expected to change. The move_to!(x,y) method had updated its l<strong>ocation_x, location_y</strong> and n<strong>otcaptured</strong> attributes.</p>
<p>Then it hit me — I needed to RELOAD <strong>destination</strong> from the database back into RSpec. Then my three tests passed beautifully:</p>
<p>Test-Driven Development has permanently impacted my coding practice, and I relished the opportunity to turn the rest of my teammates unto it. TDD is lightweight, efficient, safe, revealing, and it helps me produce higher-quality code the first … well, okay… in as little time as possible! ?</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
