<?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[ Quality Assurance - 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[ Quality Assurance - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 30 May 2026 08:55:59 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/quality-assurance/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your First Dynamic Performance Test in Apache JMeter ]]>
                </title>
                <description>
                    <![CDATA[ As a QA engineer, I have always found performance testing to be one of the most exciting and underrated parts of software testing. Yes, functional testing is important, but it’s of little use if users have to wait for 5 seconds for each page to load.... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-your-first-dynamic-performance-test-in-apache-jmeter/</link>
                <guid isPermaLink="false">6900f3ca65a053299e38eab3</guid>
                
                    <category>
                        <![CDATA[ Scale Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Performance Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ jmeter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mah Noor ]]>
                </dc:creator>
                <pubDate>Tue, 28 Oct 2025 16:48:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761335397152/cb105a44-4c18-4998-9ffb-d520df0e6510.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a QA engineer, I have always found performance testing to be one of the most exciting and underrated parts of software testing. Yes, functional testing is important, but it’s of little use if users have to wait for 5 seconds for each page to load.</p>
<p>For me personally, there is a deep satisfaction that comes with seeing your product come alive under load to find out how it’ll actually work in production when thousands of users will be using it.</p>
<p>Performance testing is about discovering how your system performs under real-world pressure in terms of load, concurrency, and throughput. One of the key aspects of performance testing is ensuring that the APIs can endure the expected load. You can do this using tools like Apache JMeter and K6.</p>
<p>In this tutorial, we’ll explore how you can build your first end-to-end performance test in Apache JMeter. You will be learning to create a test suite that is dynamic (the test can be run with any test data) and that’s one-click executable (the test execution can be done through the GUI as well as the CLI).</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-introduction-to-apache-jmeter">Introduction to Apache JMeter</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-create-a-new-test-plan">Step 1: Create a New Test Plan</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-configure-the-thread-group">Step 2: Configure the Thread Group</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-add-http-request-defaults">Step 3: Add HTTP Request Defaults</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-add-a-csv-data-set-config-dynamic-input">Step 4: Add a CSV Data Set Config (Dynamic Input)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-add-the-http-request-sampler">Step 5: Add the HTTP Request Sampler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-add-a-json-extractor">Step 6: Add a JSON Extractor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-add-an-assertion">Step 7: Add an Assertion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-8-add-listeners">Step 8: Add Listeners</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-9-run-your-test">Step 9: Run Your Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-10-chain-another-request-optional">Step 10: Chain Another Request (Optional)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-11-analyze-the-results">Step 11: Analyze the Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pro-tips">Pro Tips</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-folder-structure">Example Folder Structure:</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start, make sure you have:</p>
<ul>
<li><p><a target="_blank" href="https://jmeter.apache.org/download_jmeter.cgi"><strong>Apache JMeter (5.5 or above)</strong></a> installed.</p>
</li>
<li><p><a target="_blank" href="https://www.java.com/en/download/manual.jsp"><strong>Java 8 or later</strong></a> configured on your system.</p>
</li>
</ul>
<p>You can check if JMeter is installed by running the command below:</p>
<pre><code class="lang-plaintext">jmeter -v
</code></pre>
<p><strong>Note:</strong> This tutorial will use the <a target="_blank" href="https://jsonplaceholder.typicode.com/">JSONPlaceholder</a> public API. You’ll learn how you can get a post_id and use it in a chain request to get user details.</p>
<p>Let’s get started.</p>
<h2 id="heading-introduction-to-apache-jmeter">Introduction to Apache JMeter</h2>
<p>Apache JMeter is an open-source API load and stress testing tool. It’s a powerful testing tool that supports a wide range of protocols, including HTTP, HTTPS, FTP, JDBC, SOAP, and REST.</p>
<p>JMeter helps you answer critical questions about your APIs, like:</p>
<ul>
<li><p>How does my API perform under heavy load?</p>
</li>
<li><p>What’s the maximum number of users it can handle before it starts failing?</p>
</li>
<li><p>Which requests or endpoints are slowing things down?</p>
</li>
</ul>
<p>Let’s go through the step-by-step process of building a dynamic load testing suite with JMeter.</p>
<h3 id="heading-step-1-create-a-new-test-plan">Step 1: Create a New Test Plan</h3>
<p>Once JMeter opens, you’ll see an empty Test Plan. Think of this as your main workspace, which holds everything: Test configuration, users, requests, assertions, and results.</p>
<p>Right-click on <strong>Test Plan → Add → Threads (Users) → Thread Group</strong> to add a thread group. A thread group is essentially a test suite containing our test cases.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761045558747/ad3a2fe3-de59-420f-ba9d-1a36323e1d9e.png" alt="Add Thread Group" width="1920" height="1009" loading="lazy"></p>
<h3 id="heading-step-2-configure-the-thread-group">Step 2: Configure the Thread Group</h3>
<p>To configure the thread group, fill out the following input fields:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Setting</td><td>Value</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>Number of Threads (Users)</td><td>5</td><td>This represents the number of concurrent users. In this case, it will be ‘5’</td></tr>
<tr>
<td>Ramp-up Period (seconds)</td><td>10</td><td>This means the time it takes the threads to reach the maximum value.</td></tr>
<tr>
<td>Loop Count</td><td>2</td><td>This specifies the number of times you want your thread group executed.</td></tr>
</tbody>
</table>
</div><p>You’ve now created a small, controlled load test of 10 total requests (5 users × 2 loops).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049951497/8221336c-5f10-4161-81fa-d0ad27c7164f.png" alt="Thread Group" class="image--center mx-auto" width="1920" height="982" loading="lazy"></p>
<h3 id="heading-step-3-add-http-request-defaults">Step 3: Add HTTP Request Defaults</h3>
<p>When you’re creating a suite of 100s of APIs, you don’t need to add your request details to all the API samplers in JMeter. JMeter lets you set it once globally by using a config element called HTTP Request Defaults. To add this element, follow the steps below:</p>
<ol>
<li><p>Right-click on <strong>Thread Group → Add → Config Element → HTTP Request Defaults.</strong></p>
</li>
<li><p>Enter the following:</p>
<ul>
<li><p><strong>Protocol:</strong> <code>https</code></p>
</li>
<li><p><strong>Server Name or IP:</strong> <a target="_blank" href="http://jsonplaceholder.typicode.com"><code>jsonplaceholder.typicode.com</code></a></p>
</li>
</ul>
</li>
</ol>
<p>This means all requests in this test will automatically use this base URL.</p>
<h3 id="heading-step-4-add-a-csv-data-set-config-dynamic-input">Step 4: Add a CSV Data Set Config (Dynamic Input)</h3>
<p>In real projects, APIs rarely use static inputs. Take as an example a login API that you want to run for 100 concurrent users. In a real-world scenario, every login request will have a different username and password.</p>
<p>To replicate this on JMeter, you need to run your test for 100 different login credentials. This means that your test should be <strong>test data-driven</strong>. We can build a data-driven test in JMeter using a <strong>CSV file</strong>:</p>
<ol>
<li><p>Create a file named <code>data.csv</code> with the following content:</p>
<pre><code class="lang-plaintext"> post_id
 1
 2
 3
 4
 5
</code></pre>
</li>
<li><p>Save it in your JMeter project folder.</p>
</li>
<li><p>In JMeter, right-click on <strong>Thread Group → Add → Config Element → CSV Data Set Config.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761048312824/4558aae4-23c8-446d-89d0-237aca29619d.png" alt="Add CSV Data Set Config" class="image--center mx-auto" width="1169" height="974" loading="lazy"></p>
</li>
<li><p>Fill in the following fields:</p>
<ul>
<li><p><strong>Filename:</strong> <code>data.csv</code></p>
</li>
<li><p><strong>Variable Names:</strong> <code>post_id</code></p>
</li>
<li><p><strong>Recycle on EOF:</strong> <code>True</code></p>
</li>
<li><p><strong>Stop thread on EOF:</strong> <code>False</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761048167041/eae27f5c-6e23-4c7d-8890-b3eb5943bb66.png" alt="CSV Data Set Config" class="image--center mx-auto" width="1437" height="642" loading="lazy"></p>
</li>
</ul>
</li>
</ol>
<p>Now each user will pick a new <code>post_id</code> for every iteration from the CSV file.</p>
<h3 id="heading-step-5-add-the-http-request-sampler">Step 5: Add the HTTP Request Sampler</h3>
<p>Now let’s add the actual API call we'll test under load. To do this, follow the steps below:</p>
<ol>
<li><p>Right-click on <strong>Thread Group → Add → Sampler → HTTP Request.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761051865320/92bf89d0-616c-4d07-9531-3985265e07d7.png" alt="Add an HTTP Request" class="image--center mx-auto" width="1920" height="1017" loading="lazy"></p>
</li>
<li><p>Rename it to <strong>Get Post Data.</strong></p>
</li>
<li><p>Set the following fields:</p>
<ul>
<li><p><strong>Method:</strong> GET</p>
</li>
<li><p><strong>Path:</strong> <code>/posts/${post_id}</code></p>
</li>
</ul>
</li>
</ol>
<p>Here <code>${post_id}</code> dynamically takes its value from your CSV file. The Protocol and Server IP fields will automatically get data from the ‘HTTP Request default’ config element that we added in Step #3.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049282841/a420139c-4622-4d7a-ac7d-4308bb9a1dbc.png" alt="Add a GET Request" class="image--center mx-auto" width="1920" height="904" loading="lazy"></p>
<h3 id="heading-step-6-add-a-json-extractor">Step 6: Add a JSON Extractor</h3>
<p>When the API returns a response, we can extract a value (like <code>userId</code>) from it and use it later. This is used to implement an end-to-end flow where data is gotten (with GET) from an API and sent to the next POST/DELETE API.</p>
<p>For our API, below is the example response:</p>
<pre><code class="lang-plaintext">{
  "userId": 1,
  "id": 3,
  "title": "fugiat veniam minus",
  "body": "This is an example post body"
}
</code></pre>
<p>To extract <code>userId</code>:</p>
<ol>
<li><p>Right-click on <strong>Get Post Data → Add → Post Processors → JSON Extractor.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761051791176/b7888a78-efbb-48d3-8aba-fcd21edfd8f2.png" alt="Add JSON Extractor" class="image--center mx-auto" width="1920" height="1018" loading="lazy"></p>
</li>
<li><p>Set the variables below in the JSON Extractor:</p>
<ul>
<li><p><strong>Name:</strong> Extract User ID</p>
</li>
<li><p><strong>Variable Name:</strong> <code>user_id</code></p>
</li>
<li><p><strong>JSON Path Expression:</strong> <code>$.userId</code></p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049324410/8a163733-8925-4557-9ace-124b08167f8e.png" alt="JSON Extractor" class="image--center mx-auto" width="1920" height="971" loading="lazy"></p>
<p>Now you can use <code>${user_id}</code> in the next request, making your test fully dynamic.</p>
<h3 id="heading-step-7-add-an-assertion">Step 7: Add an Assertion</h3>
<p>Assertions help you verify that your API responds correctly even under load. You can assert on the API response code, response time, or even the response payload. To add an assertion, follow the steps below:</p>
<ol>
<li><p>Right-click <strong>Get Post Data → Add → Assertions → Response Assertion.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049384591/a0293eef-74a0-4d55-b0c4-232d5c5eaa0c.png" alt="Add Response Assertion" class="image--center mx-auto" width="1920" height="1020" loading="lazy"></p>
</li>
<li><p>Configure as:</p>
<ul>
<li><p><strong>Response Field to Test:</strong> <em>Response Code –</em> This will add an assertion for the response code.</p>
</li>
<li><p><strong>Pattern Matching Rules:</strong> <em>Contains</em></p>
</li>
<li><p><strong>Pattern to Test:</strong> 200</p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050184412/5a52f600-74f6-48c7-a975-7e39df47afdb.png" alt="Add Response Assertion" class="image--center mx-auto" width="1920" height="1017" loading="lazy"></p>
<p>This ensures JMeter only counts the request as successful if the word <code>fugiat</code> appears in the response.</p>
<h3 id="heading-step-8-add-listeners">Step 8: Add Listeners</h3>
<p>We’ll add listeners to display our test results in different forms, such as visually or in a summary. Let’s add two essential ones:</p>
<ol>
<li><p><strong>View Results Tree</strong>: to view and debug individual requests.</p>
</li>
<li><p><strong>Summary Report</strong>: to view performance metrics like response time, error rate, and throughput.</p>
</li>
</ol>
<p>Add them via <strong>Thread Group → Add → Listener → [Choose Listener]</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049568483/0daa916c-503d-4f91-ad17-1d2bd29a9f72.png" alt="Add Listener in JMeter" class="image--center mx-auto" width="1920" height="1020" loading="lazy"></p>
<h3 id="heading-step-9-run-your-test">Step 9: Run Your Test</h3>
<p>Hit the green <strong>Start</strong> button at the top. JMeter will start sending requests to your API using the dynamic post IDs from your CSV file.</p>
<p>As the test runs:</p>
<ul>
<li><p>Green checkmarks in <strong>View Results Tree</strong> mean successful responses.</p>
</li>
<li><p>Assertion failures will appear in red.</p>
</li>
<li><p><strong>Summary Report</strong> will aggregate key metrics.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050151356/d8c72408-cf91-4c9d-8663-0a65b6943f5b.png" alt="JMeter View Results Tree" class="image--center mx-auto" width="1920" height="1013" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050211424/532dd999-b870-4cf8-ad1e-1a692119b0e0.png" alt="JMeter Summary Report" class="image--center mx-auto" width="1920" height="1024" loading="lazy"></p>
<h3 id="heading-step-10-chain-another-request-optional">Step 10: Chain Another Request (Optional)</h3>
<p>Let’s take it one step further: we’ll use the extracted <code>user_id</code> from the first response to get user details from the <a target="_blank" href="https://jsonplaceholder.typicode.com/users">GET users call</a>. To do this, follow the steps below:</p>
<ol>
<li><p>Right-click <strong>Thread Group → Add → Sampler → HTTP Request.</strong></p>
</li>
<li><p>Rename to <strong>Get User Details.</strong></p>
</li>
<li><p>Set:</p>
<ul>
<li><p><strong>Method:</strong> GET</p>
</li>
<li><p><strong>Path:</strong> <code>/users/${user_id}</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050384264/dcc1c333-4e06-4dd9-8dca-9af823fedabd.png" alt="GET Users API" class="image--center mx-auto" width="1920" height="1015" loading="lazy"></p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050365937/736b9954-6d01-45a6-8c16-f6d2ceb60e10.png" alt="Test Execution in JMeter" class="image--center mx-auto" width="1920" height="1021" loading="lazy"></p>
<h3 id="heading-step-11-analyze-the-results">Step 11: Analyze the Results</h3>
<p>Once the test completes, open the <strong>Summary Report</strong>. You’ll see:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Metric</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Sample Count</strong></td><td>Number of total requests sent</td></tr>
<tr>
<td><strong>Average</strong></td><td>Mean response time per request</td></tr>
<tr>
<td><strong>Min/Max</strong></td><td>Fastest and slowest response times</td></tr>
<tr>
<td><strong>Error %</strong></td><td>Percentage of failed requests</td></tr>
<tr>
<td><strong>Throughput</strong></td><td>Requests handled per second</td></tr>
</tbody>
</table>
</div><p>If your error percentage is 0% and throughput is stable, your system handled the load well.</p>
<h3 id="heading-pro-tips">Pro Tips</h3>
<ul>
<li><p><strong>Parameterize everything.</strong> Use multiple CSVs for realistic test flows (users, IDs, tokens).</p>
</li>
<li><p><strong>Add timers</strong> (like <em>Constant Timer</em>) to simulate think time between user actions.</p>
</li>
<li><p><strong>Use Assertions wisely.</strong> Don’t add extra assertions; focus on key validations such as response time and API status code.</p>
</li>
<li><p><strong>Generate HTML reports using the command below:</strong></p>
<pre><code class="lang-plaintext">  jmeter -n -t test-plan.jmx -l results.jtl -e -o report
</code></pre>
</li>
</ul>
<h3 id="heading-example-folder-structure">Example Folder Structure:</h3>
<p>Follow the folder structure below for an organized test suite.</p>
<pre><code class="lang-plaintext">performance-test/
├── data.csv
├── test-plan.jmx
└── results/
    ├── summary.csv
    └── report.html
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Performance testing is an essential element of a production readiness checklist for any product. It helps you ensure that your product can handle the expected user load and scale gracefully.</p>
<p>This guide is your first step towards writing end-to-end performance test cases and bridging the gap between being a functional test engineer and a full-stack QA Engineer who understands both quality and scalability.</p>
<p>I hope you found this tutorial helpful. If you want to stay connected or learn more about performance testing, follow me on <a target="_blank" href="https://www.linkedin.com/in/mah-noorqa/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write QA Documentation That Will Actually Work ]]>
                </title>
                <description>
                    <![CDATA[ Imagine developing a complex software product without taking any action to protect against errors. Human error and unexpected code combinations can cause a wide range of defects. This is where quality assurance (QA) documentation comes in.  Usually, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-qa-documentation-that-will-actually-work/</link>
                <guid isPermaLink="false">66be14ba0c9c630f4d48debb</guid>
                
                    <category>
                        <![CDATA[ documentation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oleh Romanyuk ]]>
                </dc:creator>
                <pubDate>Mon, 17 Jun 2024 18:29:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/How-to-Write-QA-Documentation-That-Will-Actually-Work.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Imagine developing a complex software product without taking any action to protect against errors. Human error and unexpected code combinations can cause a wide range of defects. This is where quality assurance (QA) documentation comes in. </p>
<p>Usually, a QA tester creates a report after discovering a bug. The next step is that they send a report to the bug handler. Basically, a bug handler is a developer that fixes a bug according to the detailed report. The bug handler ensures a clean and efficient QA process and makes it easier to have a clean conversation between the fixers and the testers. </p>
<p>But you might be wondering – why do we need QA documentation?</p>
<p>QA testing is essential in IT products today. Tight deadlines, unique skill sets within the organization, and the demand to develop products stress the need for a structured methodology. QA documentation guides testers through levels of clarity and overall coverage. </p>
<p>I've written this article to make your life a bit easier. So here it is, your ultimate guide on how to write software QA documentation that will work.</p>
<h3 id="heading-this-is-what-well-cover">This is what we'll cover:</h3>
<ul>
<li><a class="post-section-overview" href="#heading-make-a-test-plan-and-a-test-progress-report">Make a Test Plan and a Test Progress Report</a></li>
<li><a class="post-section-overview" href="#heading-create-test-cases">Create Test Cases</a></li>
<li><a class="post-section-overview" href="#heading-defect-reports">Defect Reports</a></li>
<li><a class="post-section-overview" href="#heading-useful-tips-for-defect-report-writing">Useful Tips for Defect Report Writing</a></li>
<li><a class="post-section-overview" href="#heading-submit-a-defect-report">Submit a Defect Report</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-make-a-test-plan-and-a-test-progress-report">Make a Test Plan and a Test Progress Report</h2>
<p>Developing great software requires a thorough and documented approach to testing. Everything begins in the development phase with a complete checkout plan as a template for the entire QA process. It outlines the general requirements, defines the followed route, identifies the necessary assets, and sets a simple timeline for achieving the objectives.</p>
<h3 id="heading-draw-up-a-roadmap-before-you-start">Draw up a roadmap before you start</h3>
<p>Before you start implementing your test plan, take some time to think about the big picture. Ask yourself:</p>
<p><em>What problem does this software solve?</em> As soon as you understand the main purpose of the software, you'll be able to manage the checkout process and identify the features that are most important to your goals. </p>
<p>I promise that once you see that you can do this, you quickly prioritize your efforts. They are based primarily on the importance of the functionality and its impact on the user.</p>
<h3 id="heading-create-a-plan">Create a plan</h3>
<p>The test plan is the central part of the QA technique. The test plan should contain the following key elements:</p>
<ul>
<li><strong>Imaginary test</strong>: Clearly identify the expected impact of the payment method. Will it confirm that core functionality is running smoothly, or will it alert you to capability gaps?</li>
<li><strong>Test method</strong>: Outline how the test will be performed. Will you do targeted testing, useless testing, or a mix of the two?</li>
<li><strong>Resource allocation</strong>: Identify the equipment and technology required to perform a complete control. What control framework will you use? Are specific hardware or software configurations required for proper control?</li>
<li><strong>Timetable and remaining dates</strong>: Establish a realistic timetable for the trial. Set clear deadlines to keep the project on track.</li>
</ul>
<h3 id="heading-understand-the-why-and-how">Understand the 'why' and 'how'</h3>
<p>A well-developed roadmap will ensure that key issues are addressed throughout the improvement approach:</p>
<ul>
<li><strong>Acceptance requirements</strong>: Clear fail/success criteria should be defined for all control cases. So, criteria allow the customer to understand that the product is high quality and ready for the end-user.</li>
<li><strong>Resource management</strong>: Identify the assets required for the testing. This includes preferred machines, copies of software in various forms, required expertise, and more.</li>
<li><strong>Team dynamics</strong>: Ensure that simple roles and tasks are defined within the test team. Who is responsible for particular test cases? Who documents bugs and who talks to developers?</li>
<li><strong>Time management</strong>: I advise setting realistic checkout times, taking into account project deadlines and the availability of useful help.</li>
</ul>
<p>The test progress report is another part of the QA documentation, similar to the test plan, but with additional data on current progress. This document allows you and your development team to monitor project progress and identify any organizational issues.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/test-plan-and-progress-report-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A test plan and a progress report</em></p>
<h2 id="heading-create-test-cases">Create Test Cases</h2>
<p>Think of each test case as a detailed recipe for finding potential defects in the functionality of a software program. By following these "recipes" and evaluating the expected and actual results, defects can be accurately identified and addressed before preventive action is taken. </p>
<p>Each test case acts as an independent unit, outlining the steps required to evaluate a particular element of a software program. </p>
<p>Below is a breakdown of the key elements that make up a well-defined test case Here is my step-by-step guide for creating test cases:</p>
<ul>
<li><strong>ID</strong>: This is an identifier field to help distinguish between test cases and track them easily.</li>
<li><strong>Priority</strong>: This indicates the severity of the test case based on the functionality of the program and its impact on the normal overall performance of the known software program application.</li>
<li><strong>Test Requirements</strong>: These are requirements for testing software successfully, this can include reference documents also.</li>
<li><strong>Software Module</strong>: This shows the feature under testing. It also refers to the software requirements specifications (SRS) document explaining the software feature in detail.</li>
<li><strong>Test Context</strong>: This details the test plan to clarify how the daily tests will be carried out. It also identifies the test data required for a successful case study and includes unique and important statistical information.</li>
<li><strong>Expected Output</strong>: This describes the expected output to be displayed if the test is successful.</li>
<li><strong>Actual output</strong>: This indicates the actual result in the event of failure and shows the developer the errors in the application module of the software program.</li>
<li><strong>Comment</strong>: This is an optional section where the tester can give a description of the observations or add additional records.</li>
</ul>
<p>All QAs typically include the above elements, but can also be designed specifically for the task selected by the QA group. Also, each control case follows a lifecycle that defines the phases of creation, testing (pass, fail), completion, and so on. </p>
<p>In the next section, we’ll check out another important element of QA documentation: the defect report.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/test-cases.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test cases</em></p>
<h2 id="heading-defect-reports">Defect Reports</h2>
<p>Defect reporting is an important element of QA documentation. Issue tracking is the detailed reporting of sudden problems that arise in a software product. Careful documentation of these issues lays the groundwork for a complex and bug-free final product. </p>
<p>Sounds simple, right? Yes, but only until you start documenting.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/bug-task.png" alt="Image" width="600" height="400" loading="lazy">
<em>A defect report</em></p>
<p>The bug report consists of the following sections: Identifier, Summary, Description, Steps to Reproduce, Reproducibility, Severity, Priority, Environment, and Attachments.</p>
<ul>
<li><strong>Identifier</strong>: Each software program problem is assigned a completely unique identifier that acts like a customized nameplate. This makes the QA documentation less complicated to navigate and allows verbal communication between the installer, tester, and project manager (PM).</li>
<li><strong>Summary:</strong> This is an opportunity to provide brief and informative answers to three basic questions: What was the problem? Where did the problem appear? Under what specific conditions did the problem appear?</li>
<li><strong>Explanation:</strong> Examine the failure log in more detail. Summarize the identified action (the result completed) and check it against the planned action (the predicted end result). Including a link to the app requirements of the software program can serve as a useful reference element.</li>
<li><strong>Reproduction method</strong> (STR): This phase should be considered as a step-by-step recipe for reproducing the defect. It should be strict and cover all the steps that caused the problem. Skipping critical steps can make it difficult for you to reproduce the problem and cause delays.</li>
<li><strong>Reproducibility:</strong> In this section, you clarify if the bug appears every time you follow the STR. You should use numbers to show approximate chances, for example, 7 times out of 10.</li>
<li><strong>Severity</strong>: Here you explain how much harm the bug may bring to the project. Essentially, this is a measure of the severity of the technical disruption that a bug will cause to the whole project. Remember that problems that are known to be minor can grow and cause you extreme problems throughout the software.</li>
<li><strong>Priority</strong>: Each error log assigns a problem priority that indicates its urgency. Common priorities are letters (A: highest priority, Z: highest priority), numbers (1: highest priority, 9: highest priority), or descriptive terms (high, medium, low).</li>
<li><strong>Environment</strong>: Specify the gadget or browser model in which the bug appeared. This will help you to put the problem in context and narrow down a valid cause.</li>
<li><strong>Attachments</strong>: If possible, enrich the documentation with screenshots, screen recordings, console log documents, and others. This will help to provide visual documentation of the error.</li>
</ul>
<p>My structure provides detailed information, so you can empower developers to effectively diagnose, address, and eliminate any software bugs. In this way, leading to more user-friendly and robust products. </p>
<p>Now, in the next section, we'll see some useful tips you can use for defect report writing.</p>
<h3 id="heading-useful-tips-for-defect-report-writing">Useful Tips for Defect Report Writing</h3>
<ol>
<li>Write a sufficient summary. It does not matter if it is long or short. What matters is that it should be clear.</li>
<li>Have a look at the summary and the description. Do they look pretty much the same? You must have forgotten to outline the expected and actual results in the description and to add the link to the requirements.</li>
<li>Capture the issue with the help of a screenshot. It may save you and the development team a lot of time. Sometimes one glance at the picture is just enough to understand the situation.</li>
<li>Before reporting the issue, try to reproduce it at least 3 times to be sure that it exists.</li>
<li>Report the issue ASAP and notify your project manager or product owner if the issue is major.</li>
<li>Check for grammar mistakes in your QA documentation so you're not taken down by the grammar police.</li>
<li>However comical it sounds, make sure that the issue is not a feature – review the documentation again!</li>
<li>Do not miss any important information in your Steps to Reproduce.</li>
</ol>
<h2 id="heading-submit-a-defect-report">Submit a Defect Report</h2>
<p>The final and one of the most important elements of QA documentation is the defect report. You may understand it covers the entire lifecycle of a problem, from its initial discovery to its final closure. </p>
<p>Let's now examine the key areas of this process:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/defect-report-lifecycle.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>a defect report lifecycle</em></p>
<p>We'll go over the defect report lifestyle piece by piece:</p>
<h3 id="heading-problem-reporting">Problem Reporting:</h3>
<p>This adventure begins with the careful compilation and submission of a report on the entire program. This serves as a roadmap for developers and provides a clear assessment of the problem.</p>
<h3 id="heading-triage-and-tasks">Triage and tasks:</h3>
<p>The task manager or technical lead takes on the role of gatekeeper at this stage. They carefully compare the files. If the file contains enough elements to work with, it is assigned to the developer and repaired. However, if the file is missing essential elements, it may be rejected for further improvement.</p>
<h3 id="heading-bug-fixing">Bug fixing:</h3>
<p>The assigned developer takes the initiative and works diligently to eliminate the annoying bug.</p>
<h3 id="heading-verification-and-completion">Verification and completion:</h3>
<p>Once the developer claims to have fixed the problem, it's your turn as QA. Carefully verify the fix by retesting the functionality in question. If everything works as it should, you are done. </p>
<p>The documentation has come to a happy end. Ideally, this will happen within a reasonable period of one to two weeks.</p>
<h3 id="heading-reboot-and-keep-going">Reboot and keep going:</h3>
<p>But it is not always that simple. If it is known that bugs are still being made in the validation system, there is no need to despair! </p>
<p>Re-open the bug documentation and send it to the developers for further attention. Sometimes the process of fixing bugs is repetitive and requires patience. But by being careful and effective, you can guarantee that all bug reports will eventually reach their final destination, resulting in a more polished and reliable software application product.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Quality Assurance is a process you simply cannot avoid. Each airplane prior to departure undergoes a technical check. If there is any issue, the aircraft is grounded until the problem is solved. The same goes for any software. </p>
<p>But QA documentation is not always "write and ignore". At some point in the software development lifecycle, QA documentation needs to be continually updated and improved as requirements change, new features are introduced, and feedback is received from deployment and production use.</p>
<p>There are also a growing number of styles that use synthetic intelligence and machine learning to partially automate the creation of QA documentation. </p>
<p>For example, natural language processing (NLP) is used to analyze requirements documents and generate draft control examples. Test bots can use NLP to interpret and routinely execute directed test cases. Predictive evaluation can also be used to identify the most dangerous areas of a software program that require more detailed control.</p>
<p>While these strategies are still new and not mature enough to replace human testers, they can help with growth and augment manual exploration, especially for large and complex builds. By making QA documentation a collaborative and ongoing hobby, your team can deliver better software faster and with fewer defects.</p>
<h3 id="heading-do-you-need-to-improve-the-quality-of-your-software">Do you need to improve the quality of your software?</h3>
<p>My company KeenEthics provides solid <a target="_blank" href="https://coventit.com/services/custom-software-development">development and quality assurance services</a>. In case you need an estimate for a similar project, feel free to <a target="_blank" href="https://coventit.com/contact-us">get in touch</a><em>.</em> </p>
<p>If you have enjoyed the article, you should continue with <a target="_blank" href="https://coventit.com/blog/How-IT-Outsourcing-Saves-Costs">How IT Outsourcing Saves Costs for Your Company</a> and <a target="_blank" href="https://coventit.com/blog/risks-of-it-outsourcing">Avoiding Pitfalls in IT Outsourcing: Tips for Minimizing Risks</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Become a Quality Assurance Engineer – QA Engineer Career Guide ]]>
                </title>
                <description>
                    <![CDATA[ A Quality Assurance (QA) Engineer is someone who tests software products throughout the whole development process. They ensure that the product meets high quality standards before releasing it to the public. But how do you become a QA Engineer? In th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-become-a-quality-assurance-engineer-qa-engineer-career-guide/</link>
                <guid isPermaLink="false">66b8d96857c651c38343a9a0</guid>
                
                    <category>
                        <![CDATA[ career advice ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jessica Wilkins ]]>
                </dc:creator>
                <pubDate>Mon, 16 May 2022 15:33:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/05/thisisengineering-raeng-1oYSrlQrpY4-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A Quality Assurance (QA) Engineer is someone who tests software products throughout the whole development process. They ensure that the product meets high quality standards before releasing it to the public.</p>
<p>But how do you become a QA Engineer? In this article, I will talk about the qualifications and process for becoming a QA engineer.</p>
<h2 id="heading-what-is-quality-assurance-and-quality-control">What is Quality Assurance and Quality Control?</h2>
<p>When a product is being built, stakeholders have expectations and requirements. It is important that there is a process put in place to ensure that those high quality standards are being adhered to and mistakes in the product development are spotted and reported.</p>
<p>Quality Assurance focuses more on proactive processes while Quality Control focuses more on reactive corrections that need to be made. </p>
<p>Quality control also focuses on inspection and testing whereas Quality Assurance involves documentation, audits, and management.</p>
<h2 id="heading-core-skills-needed-for-becoming-a-good-qa-engineer">Core skills needed for becoming a good QA engineer</h2>
<h3 id="heading-attention-to-detail">Attention to detail</h3>
<p>The role of a QA engineer involves being detail-oriented and thorough in order to spot issues or discrepancies in quality standards set for the product.</p>
<h3 id="heading-good-communication">Good communication</h3>
<p>QA engineers will be communicating with stakeholders, management, and developers for the product. Effective and clear communication between all parties involved is really important for the development process of a product.</p>
<h3 id="heading-good-time-management">Good time management</h3>
<p>Since a QA engineer will have to balance multiple tasks throughout the day, it is important to have strong time management skills to ensure that you stay productive and are able to meet your deadlines.</p>
<h3 id="heading-problem-solving-skills">Problem solving skills</h3>
<p>Throughout the life cycle of a product, issues will arise. It is important that QA engineers have strong problem solving skills and are able to develop a plan to solve those issues.</p>
<h3 id="heading-strong-listening-skills">Strong listening skills</h3>
<p>A good QA engineer not only needs to be able to communicate but also listen to their development team, management, and stakeholders to ensure the successful launch of the product.</p>
<h3 id="heading-the-ability-to-write-a-test-plan">The ability to write a test plan</h3>
<p>A test plan is a document detailing the objectives and testing processes that will be applied to the software product. QA engineers will work with other developers and stakeholders to develop this testing strategy.</p>
<h3 id="heading-an-understanding-of-test-automation-tools-and-manual-testing-practices">An understanding of test automation tools and manual testing practices</h3>
<p>It is helpful for QA engineers to be familiar with different automated testing tools like Selenium. They will also need to know how to effectively manually test products in order to identify bugs.</p>
<h3 id="heading-strong-understanding-of-the-software-development-life-cycle">Strong understanding of the Software Development Life Cycle</h3>
<p>A good QA engineer should understand the full life cycle of software products in order to effectively plan and test them.</p>
<p>Here are the 7 phases of the <a target="_blank" href="https://www.freecodecamp.org/news/get-a-basic-understanding-of-the-life-cycles-of-software-development/">Software Development Life Cycle</a>:</p>
<ol>
<li>Planning Stage</li>
<li>Analysis Stage</li>
<li>Design Stage</li>
<li>Software Development Stage</li>
<li>Software Testing Stage</li>
<li>Implementation and Integration</li>
<li>Operations and Maintenance Stage</li>
</ol>
<h2 id="heading-do-you-need-to-learn-how-to-code-become-a-qa-engineer">Do you need to learn how to code become a QA engineer?</h2>
<p>Learning programming fundamentals can help QA engineers build automated test suites to save time on manual testing and provide a better understanding of the development implementations by the software developers.</p>
<p>Some widely used programming languages to learn would be Java, C#, JavaScript, and Python.</p>
<p>Choose one language to learn to get an understanding of the programming fundamentals.</p>
<h2 id="heading-do-you-need-a-computer-science-degree-to-become-a-qa-engineer">Do you need a Computer Science degree to become a QA engineer?</h2>
<p>Having a Computer Science degree can help you when it comes to finding your first Quality Assurance job because a lot of employers still prefer a degree. If you have the time and money to pursue that path, that can be a viable option.</p>
<p>Other options would be to go to a bootcamp or teach yourself through online resources. If you are considering a bootcamp, please read through this <a target="_blank" href="https://www.freecodecamp.org/news/coding-bootcamp-handbook/">helpful resource</a> first.</p>
<h2 id="heading-do-you-need-certifications-to-become-a-good-qa-engineer">Do you need certifications to become a good QA engineer?</h2>
<p>QA certifications can help boost your resume and knowledge base. A lot of these certifications do require that you have degree from an accredited university or a few years of experience.</p>
<p>Here are some QA certifications you can look into:</p>
<ul>
<li>Certified Associate in Software Testing (CAST)</li>
<li>Certified Test Engineer (CSTE)</li>
<li>Certified Software Quality Analyst (CSQA)</li>
</ul>
<h2 id="heading-how-to-get-a-job-as-a-qa-engineer">How to get a job as a QA engineer</h2>
<p>Once you have learned programming, testing, and QA fundamentals then you can start looking for junior level positions. Make sure to build out a strong résumé and prepare for the QA interview questions using free online interview guides.</p>
<p>If you are self taught, it would help to have a little bit of experience through small contract work. If you are in a degree program, students will have access to internship opportunities and other career resources.</p>
<h2 id="heading-salaries-for-qa-engineers">Salaries for QA engineers</h2>
<p>Salaries for QA engineers will range depending on experience and location. The average base US salary according to <a target="_blank" href="<https://www.payscale.com/research/US/Job=Quality_Assurance_(QA)_Engineer/Salary>">payscale</a> is $72,000.</p>
<p>I hope you enjoyed this article and best of luck on your software journey.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Test Your Apps using Jest, Testing Library, Cypress, and Supertest ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! In this article we're going to talk about testing. I'll give you a good overview of what testing is and an introduction of how you can implement it on your JavaScript projects. We'll use four very popular tools – Jest, Testing library, C... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/test-a-react-app-with-jest-testing-library-and-cypress/</link>
                <guid isPermaLink="false">66d45f22264384a65d5a9528</guid>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react testing library ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Mon, 25 Apr 2022 17:13:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/pexels-rodolfo-clix-1366942.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone! In this article we're going to talk about testing. I'll give you a good overview of what testing is and an introduction of how you can implement it on your JavaScript projects. We'll use four very popular tools – Jest, Testing library, Cypress and Supertest.</p>
<p>First we're going to talk about what testing is, why is it a good idea to test our code, and the different kinds of tests that can be implemented.</p>
<p>Then we're going to introduce each of the tools we will be using, and finally we'll give practical examples for vanilla JS code, a front-end React app, and a back-end Node app.</p>
<p>Andiamo via!</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-testing-and-why-is-it-valuable">What is testing and why is it valuable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-different-types-of-tests">Different types of tests</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-manual-vs-automated-testing">Manual vs Automated testing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-functional-vs-non-functional-testing">Functional vs Non-functional testing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-unit-vs-integration-testing-vs-end-to-end-testing">Unit vs Integration vs End-to-end testing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-white-box-vs-black-box-vs-grey-box-testing">White box vs Black box vs Grey box testing</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-test">When to test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-our-toolset">Our toolset</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-jest">What is Jest</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-testing-library">What is Testing library</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-cypress">What is Cypress</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-supertest">What is Supertest</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-roundup">Tools roundup</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-vanilla-js-code">How to test vanilla JS code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-a-front-end-react-app-with-jest-and-react-testing-library">How to test a front-end React app with Jest and React testing library</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-a-front-end-react-app-with-cypress">How to test a front-end React app with Cypress</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-a-back-end-node-app">How to test a back-end Node app</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrap-up">Wrap up</a></p>
</li>
</ul>
<h1 id="heading-what-is-testing-and-why-is-it-valuable">What is Testing and Why is it Valuable</h1>
<p>Testing is the practice of checking if a piece of software runs as expected. This is often recognized as QA or quality assurance, and aims to reduce to a bare minimum the amount of bugs that get to production.</p>
<p>We test software to identify errors, gaps or missing requirements and fix those things before shipping code to production.</p>
<p>Testing our code thoroughly improves our project's reliability, saves us later bug-fixing time and hence reduces costs, and improves the chance of our customer being fully satisfied with our product.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/BvIJ1M5-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=u6QfIXgjwGQ&amp;t=6s">Here's a nice short video by Fireship</a> introducing some of the concepts we'll talk about later.</p>
<h1 id="heading-different-types-of-tests">Different Types of Tests</h1>
<p>Testing practices can be classified in different types according to many factors. Personally I think there's a lot of mumbo jumbo about this topic, with hundreds of terms that often refer to very similar things. So let's keep it simple and review only the most popular terms and what they mean.</p>
<p>This will help clarify the many ways in which a software can be tested and better understand the tools we're going to present later on.</p>
<h3 id="heading-manual-vs-automated-testing">Manual vs Automated testing</h3>
<p>Depending on the tools we use to test our software, we can classify testing into <strong>manual</strong> or <strong>automated testing</strong>.</p>
<p><strong>Manual testing</strong> is the practice of "clicking around" and manually checking all the features our product has, simulating what an actual user would do.</p>
<p><strong>Automated testing</strong> is done through code, writing programs that check how our application runs.</p>
<p>There're many testing frameworks and libraries we can use for this. When it comes to functional testing (we're going to see what that means in a sec), most libraries work in a similar way:</p>
<ul>
<li><p>First we <strong>define</strong> what piece of code we want to test.</p>
</li>
<li><p>Then we provide that piece of code some sort of <strong>input</strong> or execute an <strong>action</strong> on it.</p>
</li>
<li><p>Then we define what that piece of code <strong>should do</strong> given the input/action we performed.</p>
</li>
<li><p>And finally we will <strong>compare</strong> what that piece of code actually did against what we said it should do.</p>
</li>
</ul>
<p>If it did what we said it should, the test passed. If it didn't, it failed.</p>
<h3 id="heading-functional-vs-non-functional-testing">Functional vs Non-functional testing</h3>
<p><strong>Functional</strong> testing refers to the actual <strong>features of our product</strong>. For example, if we have a blog platform, functional testing should assure the users can create new articles, edit those articles, browse through articles written by other people, and so on.</p>
<p><strong>Non-functional</strong> testing refers to anything that's <strong>not strictly related to the core features</strong> of our product. And that again can be classified into different categories, for example:</p>
<ul>
<li><p><strong>Stress testing</strong> checks how infrastructure responds to heavy usage.</p>
</li>
<li><p><strong>Security testing</strong> checks if an application is vulnerable to common hacking attacks.</p>
</li>
<li><p><strong>Accessibility testing</strong> checks if an application is coded in a way that is accessible for people with different disabilities.</p>
</li>
</ul>
<h3 id="heading-unit-vs-integration-testing-vs-end-to-end-testing">Unit vs Integration testing vs End-to-end testing</h3>
<p>Another way to classify testing is depending how broad or comprehensive it is.</p>
<p><strong>Unit testing</strong> aims to test individual functions, methods or small chunks of code in an independent way. In unit testing, small pieces of code are checked in an isolated way.</p>
<p><strong>Integration testing</strong> checks how individual pieces of code interact with each other and work together. In integration testing, we put pieces together and see if they interact correctly.</p>
<p><strong>End-to-end testing</strong>, also known as E2E, executes programs in a simulated environment that emulates actual user behavior. Having a website as an example, our code would open in an actual browser and all the features would be executed in the same way a user would use them. E2E testing is a lot like manual testing in that sense, but fully automated.</p>
<p>E2E testing is the most broad or comprehensive type of these three, as it evaluates whole features and behaviors, not specific parts of our code.</p>
<h3 id="heading-white-box-vs-black-box-vs-grey-box-testing">White box vs Black box vs Grey box testing</h3>
<p>The last classification we're going to see depends on how much our tests focus on implementation details or user experience.</p>
<p>Let's say we have a simple website with a button that, when it gets clicked, it opens a modal. In our code, the button has a click event listener that executes a function. That function changes the CSS class of our modal HTML element, and that gets the modal rendered in the screen.</p>
<p>We talk about "<strong>white box</strong>" testing when we test <strong>implementation details</strong>. Following the example, under this paradigm we could test that the button click executes the corresponding function, and that after the function execution, the CSS class of our modal element is changed accordingly.</p>
<p>Another way to do this is to forget about implementation all together and just check if the modal is rendered after the button click. We don't care what the CSS class is, or if the corresponding function is executed or not. We just focus on testing <strong>what the user should perceive.</strong> That's "<strong>black box</strong>" testing.</p>
<p>And, as you may have guessed, "grey box" testing is just a combination of the previous two.</p>
<p>One last thing to mention here is that these different types of tests aren't necessarily mutually exclusive. I mean, they can and often are implemented at the same time on the same projects.</p>
<p>It's very common to have both manual and automated testing, functional and non-functional testing, unit and E2E testing ... The idea will always be to try to anticipate and solve the greatest possible number of problems in reasonable time and effort.</p>
<h1 id="heading-when-to-test">When to Test</h1>
<p>This may seem like a simple question at first, but there are actually different approaches to this, too.</p>
<p>Some people like to test their app once it's been fully developed. Others like to write tests at the same time they code the application, and test each feature as it's being developed.</p>
<p>Others like to write tests first before anything else, defining in this way the minimum requirements for the program to accomplish. And then they code the app in a way that passes those tests as fast as possible (this is called <a target="_blank" href="https://en.wikipedia.org/wiki/Test-driven_development">test driven development or TDD</a>).</p>
<p>Once you have an app or a whole feature developed, and you have a test suite in place (a test suite is a group of tests that check a particular feature or an entire app), another common practice is to run your tests each time you make any kind of modification to the codebase, to verify nothing gets broken.</p>
<p>Lastly, if you have a <a target="_blank" href="https://en.wikipedia.org/wiki/CI/CD">CI/CD</a> system in place, it's common to automate the execution of tests before any deployment. So that if any test fails, the deployment is stopped and some kind of alert is dispatched (which of course is always better than seeing your app catch fire on prod 🔥😱).</p>
<p>Same as with test types, it's common to test applications at different times. Each company normally has its own testing schedule or practice to follow, tailored to their needs.</p>
<h1 id="heading-our-toolset">Our Toolset</h1>
<p>Ok, now that we have a clearer idea of what testing is and the types of tests we can perform, let's review the tools we're going to use in our examples.</p>
<p>As mentioned before, there are a lot of different libraries to choose to run our tests. I chose these four because they are some of the most popular when it comes to JavaScript apps, but know there are more options out there. I'll be naming alternatives for most of the tools we'll use in case you'd like to investigate more. 😉</p>
<h2 id="heading-what-is-jest">What is Jest</h2>
<p><a target="_blank" href="https://jestjs.io/">Jest</a> is a JavaScript test-runner. A test-runner is a piece of software that allows you to run tests to evaluate your app. It's an open-source project maintained by Meta (formerly Facebook), and was first open-sourced in 2014.</p>
<p>Side comment: Every time I say "test runner" I picture this. Am I the only one? 🤔</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/8gTI-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Test runner, not Blade runner!</em></p>
<p>Anyway...you can use Jest in projects that use <a target="_blank" href="https://babeljs.io/">Babel</a>, <a target="_blank" href="https://www.typescriptlang.org/">TypeScript</a>, <a target="_blank" href="https://nodejs.org/en/">Node.js</a>, <a target="_blank" href="https://reactjs.org/">React</a>, <a target="_blank" href="https://angular.io/">Angular</a>, <a target="_blank" href="https://vuejs.org/">Vue.js</a>, <a target="_blank" href="https://svelte.dev/">Svelte</a> and other technologies too. You can install Jest through NPM just like any library and it requires very little configuration to start off.</p>
<p>Jest comes installed by default when setting up React apps with <a target="_blank" href="https://create-react-app.dev/">create-react-app</a>.</p>
<p>Jest is often also called a testing framework, as it comes with many other built-in features besides just running tests (which is not the case with all test runners). Some of those features are:</p>
<ul>
<li><p><strong>Assertion library:</strong> Jest comes with a lot of built-in functions and methods you can use to assert your code (asserting basically means checking if a piece of code behaves like it's expected).</p>
</li>
<li><p><strong>Snapshot testing:</strong> Jest allows you to use snapshots, which are a way of capturing a large object and storing it in memory so you can later on compare it with something else.</p>
</li>
<li><p><strong>Code coverage:</strong> Jest allows you to get code coverage reports of your tests. These reports show what percentage of your code is currently being tested, and you can even see the exact lines of code that aren't currently being covered.</p>
</li>
<li><p><strong>Mocking library:</strong> Jest also works like a mocking library in the sense that it allows you to mock data (like a function or a module) and use that in your tests.</p>
</li>
</ul>
<p>Some well known alternatives to Jest are <a target="_blank" href="https://mochajs.org/">Mocha</a>, <a target="_blank" href="https://jasmine.github.io/">Jasmine</a>, and <a target="_blank" href="https://karma-runner.github.io/latest/index.html">Karma</a>.</p>
<p>Here's <a target="_blank" href="https://www.youtube.com/watch?v=SyHzgcFefBk">a nice little video</a> explaining what Jest is.</p>
<h2 id="heading-what-is-testing-library">What is Testing Library?</h2>
<p>Testing library is not a test runner, but a set of utilities that will work together with a test runner like Jest or Mocha. This utilities are tools we can use to test our code easily and with a deeper focus on user experience (black box testing).</p>
<p>Testing library was developed by <a target="_blank" href="https://kentcdodds.com/">Kent C Dodds</a> (who also happens to be one of the best JS teachers on earth, so I recommend that you follow him).</p>
<p>Quoting <a target="_blank" href="https://testing-library.com/">the official docs:</a></p>
<blockquote>
<p><em>"The Testing Library family of libraries is a very light-weight solution for testing without all the implementation details.</em></p>
<p><em>The main utilities it provides involve querying for nodes similarly to how users would find them. In this way, testing-library helps ensure your tests give you confidence in your UI code."</em></p>
</blockquote>
<p>In plain English, with the testing library we can test UI elements (like a paragraph, a button, a div...) instead of testing the code responsible for rendering the UI.</p>
<p>The principle behind the library is:</p>
<blockquote>
<p><em>"The more your tests resemble the way your software is used, the more confidence they can give you."</em></p>
</blockquote>
<p>... and that's exactly what we mean by "black box" testing. 😉</p>
<p>The testing library is actually a <strong>set of libraries</strong>, each created to achieve the same objective but adapted to work with different technologies such as React, Angular, Vue, Svelte, React Native and more... That's why you might hear "React-testing-library" or "Vue-testing-library". It's the same thing but adapted to work with different technologies.</p>
<p>React-testing-library comes installed by default when setting up React apps with <a target="_blank" href="https://create-react-app.dev/">create-react-app</a>.</p>
<p>An alternative to testing library is <a target="_blank" href="https://enzymejs.github.io/enzyme/">Enzyme</a> (a UI testing set of utilities developed by Airbnb).</p>
<h2 id="heading-what-is-cypress">What is Cypress?</h2>
<p>Cypress is an open source test-runner that allows you to execute your projects in an automated browser, in the same way a user would.</p>
<p>With Cypress, we can program what the browser will do (like visit a URL, click a button, complete and submit a form...) and check that each action is matched with the corresponding response.</p>
<p>What's sweet about this is that the testing resembles A LOT to what the user will experience. And since the whole point of making software is the user, the closer we are to their perspective, the closer we should be to catching the most meaningful bugs in our code. (Plus it's really cool to see an automated browser go through your entire app in just a few seconds... 🤓)</p>
<p>Another nice feature of Cypress is "time travel". On Cypress's automated browser we can see all the test's we've written, and simply hover over them to see a graphical snapshot of its result. It's a very useful thing to better understand what's breaking and when.</p>
<p>Even though it can be used for unit and integration testing, Cypress is mostly used for end-to-end testing as it can easily evaluate complete features in a matter of seconds.</p>
<p>You can use Cypress to test anything that runs in a browser, so you can easily implement it on React, Angular, Vue, and so on.</p>
<p>Unlike Jest and React-Testing-Library, Cypress doesn't come pre-installed with create-react-app. But we can easily install it with NPM or your package manager of choice.</p>
<p>Some alternatives to Cypress are <a target="_blank" href="https://www.selenium.dev/">Selenium</a> and <a target="_blank" href="https://pptr.dev/">Puppeteer</a>.</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=BQqzfHQkREo">Here's a sweet video by Fireship explaining what Cypress is and how it works.</a></p>
<p>Side comment: ...and every time I talk about Cypress <a target="_blank" href="https://www.youtube.com/watch?v=BV3CYz34ziE">this plays in my mind</a>. 😎</p>
<h2 id="heading-what-is-supertest">What is Supertest?</h2>
<p><a target="_blank" href="https://github.com/visionmedia/supertest">Supertest</a> is a library that simulates HTTP requests. It's super handy to test back-end Node apps together with Jest (as we will see in the coming examples).</p>
<h3 id="heading-tools-roundup">Tools roundup</h3>
<p>As a quick round-up about this topic:</p>
<ul>
<li><p>Jest is the library that we'll use to write and run tests for JavaScript.</p>
</li>
<li><p>Testing library works together with Jest, and provides us with functions and methods to test the UI directly, forgetting about the code behind it.</p>
</li>
<li><p>Cypress runs your app in a simulated browser and checks if actions performed in the UI respond as expected.</p>
</li>
<li><p>Supertest is a library that mocks HTTP requests and it can be used together with Jest to test back-end apps.</p>
</li>
</ul>
<p>Now let's begin with the fun part ...</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/giphy-2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Let the testing begin!!</em></p>
<h1 id="heading-how-to-test-vanilla-js-code">How to Test Vanilla JS Code</h1>
<p>Ok, let's start by testing some simple vanilla JS code. The idea here is to see how we can implement Jest in our project and learn the basics of how it works.</p>
<p>Let's start by creating a new directory in our machine and creating a Node app with <code>npm init -y</code>. Then install Jest by running <code>npm i -D jest</code> (<code>-D</code> saves it as a development dependency).</p>
<p>Now you should see something like this in your <code>package.json</code> file: <code>"devDependencies": { "jest": "^27.5.1" }</code> .</p>
<p>And speaking about it, in your <code>package.json</code>, replace your <code>test</code> script with <code>"test": "jest"</code>. This will allow us to later run our tests by running <code>npm test</code>. ;)</p>
<p>Your entire <code>package.json</code> file should look something like this:</p>
<pre><code class="lang-plaintext">{
  "name": "vanillatesting",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "jest": "^27.5.1"
  }
}
</code></pre>
<p>Cool, we're all set to write some JS we can actually test! Create an <code>index.js</code> file and put this code in it:</p>
<pre><code class="lang-plaintext">// index.js
function isPalindrome(string) {
    // O(n)
    // Put a pointer at each extreme of the word and iterate "inwards"
    // At each iteration, check if the pointers represent equal values
    // If this condition isn't accomplished, the word isn't a palindrome
    let left = 0
    let right = string.length-1

    while (left &lt; right) {
        if (string[left] === string[right]) {
            left += 1
            right -= 1
        }
        else return false
    }

    return true
}
</code></pre>
<p>This function is a <a target="_blank" href="https://en.wikipedia.org/wiki/Palindrome">palindrome</a> checker. It receives a string as parameter, and returns <code>true</code> if the string is a palindrome and <code>false</code> if it's not. (This is a classic technical interview question btw, but that's stuff for another article.🤫)</p>
<p>See that we're exporting the function too. Side comment: If you'd like to know more about this and how JS modules work, I recently wrote <a target="_blank" href="https://www.freecodecamp.org/news/modules-in-javascript">an article</a> about it.</p>
<p>Great, so now let's test this function and see if it works as expected. Let's create a file called <code>index.test.js</code>.</p>
<p>This file is where we'll write our tests. The suffix we're using (<code>.test.js</code>) is important here, as Jest will automatically identify the <code>.test</code> files and execute them when we order Jest to test our project.</p>
<p>Jest also identifies files with the <code>.spec</code> suffix, like <code>index.spec.js</code> (for "specification", which refers to the requirements of your project). Personally I prefer <code>.test</code> as it feels more explicit to me, but both work the same.</p>
<p>Now let's write our first tests! Put this within your <code>index.test.js</code> file.</p>
<pre><code class="lang-plaintext">// index.test.js
isPalindrome = require('./index.js')

test('neuquen is palindrom', () =&gt; {
    expect(isPalindrome("neuquen")).toBe(true)
})

test('bariloche is not palindrom', () =&gt; {
    expect(isPalindrome("bariloche")).toBe(false)
})
</code></pre>
<p>Let's recap what we're actually doing:</p>
<ol>
<li><p>Require the function we want to test: <code>isPalindrome = require('./index.js')</code></p>
</li>
<li><p>The <code>test()</code> function is provided by Jest and within it we will put the code we want Jest to execute.</p>
</li>
<li><p><code>test()</code> takes two parameters. The first is a test description, which is a distinctive name that will show on our console when the test is run. We'll see an example in a sec.</p>
</li>
<li><p>The second parameter is a callback, which contains the actual testing code.</p>
</li>
<li><p>Within this callback we're calling the <code>expect()</code> function (also provided by Jest). <code>expect()</code> takes our function as parameter, which itself is receiving a parameter we made up.</p>
</li>
<li><p>Last, we chain the <code>.toBe()</code> function (provided by Jest too) and as parameter we pass it the value we expect <code>isPalindrome()</code> to return for each case. ("neuquen" is a palindrome so our function should return <code>true</code>, and "bariloche" is not, so it should return <code>false</code>.)</p>
</li>
</ol>
<p>One of the things I like the most about Jest is how easy it is to set it up. Another thing I like a lot is how self explanatory its syntax is. Notice that we can easily understand what our tests will evaluate by just reading them.👌</p>
<p>Now let's try this! If we run <code>npm test</code> in our console, we should get the following:</p>
<pre><code class="lang-plaintext">// console
&gt; jest PASS 
./index.test.js
✓ neuquen is palindrom (1 ms)
✓ bariloche is not palindrom

Test Suites: 1 passed, 1
total Tests:       2 passed, 2
total Snapshots:   0
total Time:        0.244 s
Ran all test suites.
</code></pre>
<p>Congratulations, you just passed your first Jest test ever.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/mr-miyagi-nod-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/lets-get-this-party-started-yeah-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To see how a failing test looks too, let's change our function by editing the <code>return</code> lines.</p>
<pre><code class="lang-plaintext">// index.js
function isPalindrome(string) {
    // O(n)
    // Put a pointr at each extreme of the word and iterate "inwards"
    // At each iteration, check if the pointers represent equal values
    // If this condition isn't accomplished, the word isn't a palindrome
    let left = 0
    let right = string.length-1

    while (left &lt; right) {
        if (string[left] === string[right]) {
            left += 1
            right -= 1
        }
        else return 1
    }

    return 2
}
</code></pre>
<p>Now you should get something like this:</p>
<pre><code class="lang-plaintext">// console
&gt; vanillatesting@1.0.0 test
&gt; jest

 FAIL  ./index.test.js
  ✕ neuquen is palindrom (4 ms)
  ✕ bariloche is not palindrom

  ● neuquen is palindrom

    expect(received).toBe(expected) // Object.is equality

    Expected: true
    Received: 2

      3 | // describe('isPalindrome function', () =&gt; {
      4 |   test('neuquen is palindrom', () =&gt; {
    &gt; 5 |     expect(isPalindrome("neuquen")).toBe(true)
        |                                     ^
      6 |   })
      7 |
      8 |   test('bariloche is not palindrom', () =&gt; {

      at Object.&lt;anonymous&gt; (index.test.js:5:37)

  ● bariloche is not palindrom

    expect(received).toBe(expected) // Object.is equality

    Expected: false
    Received: 1

       7 |
       8 |   test('bariloche is not palindrom', () =&gt; {
    &gt;  9 |     expect(isPalindrome("bariloche")).toBe(false)
         |                                       ^
      10 |   })
      11 | // })
      12 |

      at Object.&lt;anonymous&gt; (index.test.js:9:39)

Test Suites: 1 failed, 1 total
Tests:       2 failed, 2 total
Snapshots:   0 total
Time:        0.28 s, estimated 1 s
Ran all test suites.
</code></pre>
<p>See that you get a nice description of what tests failed and at which point they failed. In our case they failed when we asserted (checked) the return values.</p>
<p>This is very useful and we should always pay attention to these descriptions, as some times our tests may fail because they're not written correctly. And we don't normally write tests for our tests, yet... 😅 So when you see a failing test, first check that it's working as expected and then go review your actual code.</p>
<p>Now let's add and test another function to show some more Jest features:</p>
<pre><code class="lang-plaintext">// index.js
function twoSum(nums, target) {
    // O(n)
    // Iterate the array once
    // At each iteration, calculate the value needed to get to the target, which is target - currentValue
    // If the neededValue exists in the array, return [currentValue, neededValue], else continue iteration
    for (let i = 0; i &lt; nums.length; i++) {
        const neededNum = target - nums[i]
        if (nums.indexOf(neededNum) !== -1 &amp;&amp; nums.indexOf(neededNum) !== i) return [nums[i], nums[nums.indexOf(neededNum)]]
    }
    return false
}

module.exports = { isPalindrome, twoSum }
</code></pre>
<p>This is another classic interview question. The function takes two parameters, an array of numbers and a target value number. What it does is to identify if there are two numbers in the array that add up to the second parameter value. If the two values exist in the array, it returns them in an array, and if they don't, it returns false.</p>
<p>Now let's write some tests for this:</p>
<pre><code class="lang-plaintext">({ isPalindrome, twoSum } = require('./index.js'))

...

test('[2,7,11,15] and 9 returns [2, 7]', () =&gt; {
    expect(twoSum([2,7,11,15], 9)).toEqual([2,7])
})

test('[3,2,4] and 6 returns [2, 4]', () =&gt; {
    expect(twoSum([3,2,4], 6)).toEqual([2,4])
})

test('[3,2,4] and 10 returns false', () =&gt; {
    expect(twoSum([3,2,4], 10)).toBe(false)
})
</code></pre>
<p>See that the structure is almost the same, except we're using a different <strong>matcher</strong> in two of the tests, <code>toEqual()</code>.</p>
<p><strong>Matchers</strong> are the functions Jests provides us with to evaluate values. There are many types of matchers that can be used for many different occasions.</p>
<p>For example, <code>.toBe()</code> is used to evaluate primitives like strings, numbers, or booleans. <code>toEqual()</code> is used to evaluate objects (which covers pretty much everything else in Javascript).</p>
<p>If you need to compare the return value with a number you could use <code>.toBeGreaterThan()</code> or <code>toBeGreaterThanOrEqual()</code> and so on...</p>
<p>To see a full list of the available matchers, <a target="_blank" href="https://jestjs.io/docs/using-matchers">check the docs</a>.</p>
<p>If we run our tests now, we will get the following:</p>
<pre><code class="lang-plaintext">&gt; vanillatesting@1.0.0 test
&gt; jest

 PASS  ./index.test.js
  ✓ neuquen is palindrom (2 ms)
  ✓ bariloche is not palindrom
  ✓ [2,7,11,15] and 9 returns [2, 7] (1 ms)
  ✓ [3,2,4] and 6 returns [2, 4]
  ✓ [3,2,4] and 10 returns false (1 ms)

Test Suites: 1 passed, 1 total
Tests:       5 passed, 5 total
Snapshots:   0 total
Time:        0.256 s, estimated 1 s
Ran all test suites.
</code></pre>
<p>That's cool, but our tests results look a bit messy. And as our tests suite grows, it will probably be harder to identify each separate result.</p>
<p>To help us with this, Jest provides us with a <code>describe()</code> function, which we can use to group tests together and show results in a more schematic way. We can use it like this:</p>
<pre><code class="lang-plaintext">({ isPalindrome, twoSum } = require('./index.js'))

describe('isPalindrome function', () =&gt; {
  test('neuquen is palindrom', () =&gt; {
    expect(isPalindrome("neuquen")).toBe(true)
  })

  test('bariloche is not palindrom', () =&gt; {
    expect(isPalindrome("bariloche")).toBe(false)
  })
})

describe('twoSum function', () =&gt; {
  test('[2,7,11,15] and 9 returns [2, 7]', () =&gt; {
    expect(twoSum([2,7,11,15], 9)).toEqual([2,7])
  })

  test('[3,2,4] and 6 returns [2, 4]', () =&gt; {
    expect(twoSum([3,2,4], 6)).toEqual([2,4])
  })

  test('[3,2,4] and 10 returns false', () =&gt; {
    expect(twoSum([3,2,4], 10)).toBe(false)
  })
})
</code></pre>
<p>The first parameter is the description we want to show for the given group of tests, and the second is a callback that contains our tests. Now if we run <code>npm test</code> again, we get this 😎:</p>
<pre><code class="lang-plaintext">// console
&gt; vanillatesting@1.0.0 test
&gt; jest

 PASS  ./index.test.js
  isPalindrome function
    ✓ neuquen is palindrom (2 ms)
    ✓ bariloche is not palindrom
  twoSum function
    ✓ [2,7,11,15] and 9 returns [2, 7] (1 ms)
    ✓ [3,2,4] and 6 returns [2, 4]
    ✓ [3,2,4] and 10 returns false

Test Suites: 1 passed, 1 total
Tests:       5 passed, 5 total
Snapshots:   0 total
Time:        0.216 s, estimated 1 s
Ran all test suites.
</code></pre>
<h1 id="heading-how-to-test-a-front-end-react-app-with-jest-and-react-testing-library">How to Test a Front-end React App with Jest and React Testing Library</h1>
<p>Now that we know the basics of Jest, let's hop on to see how we can combine it with Testing library to test a React app.</p>
<p>For this we're going to use a dead simple example. Just a page with random text, a button that toggles another piece of text, a text input, and a button that toggles the rendering of the input.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/Recording-2022-04-23-at-21.11.24.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Take into account we'll be using <a target="_blank" href="https://create-react-app.dev/">create-react-app</a> to create this app (which has Jest and Testing library installed by default). If you're not using create-react-app, you might need to install both libraries and add some extra config.</p>
<p>We're not going to see any React code here, we're just going to focus on the tests.</p>
<p>The folder structure of our project is the following:</p>
<pre><code class="lang-plaintext">&gt; src
    &gt; components
        - About.jsx
    - App.jsx
    - Index.js
    - setupTests.js
</code></pre>
<p>The <code>setupTests.js</code> file is important here. It's created by default with create-react-app with this content:</p>
<pre><code class="lang-plaintext">// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
</code></pre>
<p>It globally imports the <code>jest-dom</code> library provided by Testing library, which gives us additional Jest matchers we can use to test the DOM (like <code>toHaveTextContent(), toBeInTheDocument()</code>, etc).</p>
<p>We're going to see examples in a bit, but know that some of the functions and matchers we'll use come from here.</p>
<p>Regarding our tests files, the common practice is to have a different test file for each component we're testing.</p>
<p>Regarding where to place them, two common practices are to have them all together in a single folder, like <code>__tests__</code> or similar, or to have each test file in the same folder as the component it's testing.</p>
<p>I prefer the later as I'll often be hopping from the component code to the test code, and it's nice to have them nearby. But trully it doesn't matter. As long as we use the <code>.test</code> or <code>.spec</code> suffixes, Jest will identify and run the files anyway.</p>
<p>Having created our tests files, our folder structure should look like this:</p>
<pre><code class="lang-plaintext">&gt; src
    &gt; components
        - About.jsx
        - About.test.jsx
    - App.jsx
    - Index.js
    - setupTests.js
</code></pre>
<p>Cool! Let's start by testing our <code>About</code> component.</p>
<p>First lets test that it's rendering correctly, like this:</p>
<pre><code class="lang-plaintext">// About.test.jsx
import { render, screen } from '@testing-library/react'
import About from './About'

describe('About', () =&gt; {

  test('About renders correctly', () =&gt; {
    render( &lt;About/&gt; )
    expect(screen.getByText("I'm the about page!")).toBeInTheDocument()
  })

})
</code></pre>
<ul>
<li>See that we start by importing two things from Testing library: <code>import { render, screen } from '@testing-library/react'</code>.</li>
</ul>
<p>The <code>render</code> function takes a React component as a parameter and it will render it so we can test it.</p>
<p><code>screen</code> is an object that comes with lots of queries we can use to test the UI directly, skipping implementation details and focusing on what the user will actually see.</p>
<ul>
<li><p>Then we import our <code>About</code> component: <code>import About from './About'</code></p>
</li>
<li><p>We use the <code>describe</code> and <code>test</code> Jest functions previously mentioned.</p>
</li>
<li><p>We render the <code>About</code> component: <code>render( &lt;About/&gt; )</code></p>
</li>
<li><p>We use the <code>expect</code> Jest function, and as a parameter we use the <code>screen</code> object provided by Testing library. We use its <code>getByText</code> query, which scans the React component for the text we pass as parameter.</p>
</li>
<li><p>To end, we use the Testing library's <code>.toBeInTheDocument()</code> matcher, which just checks if the previous query result is being rendered.</p>
</li>
</ul>
<p>Then we can test that the "Switch state" toggle button works correctly, like this:</p>
<pre><code class="lang-plaintext">// About.test.jsx
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import About from './About'

describe('About', () =&gt; {

  ...

  test('Switch state works correctly', async () =&gt; {
    render( &lt;About/&gt; )

    expect(screen.getByText("It's on!")).toBeInTheDocument()
    userEvent.click(screen.getByText('Switch state'))
    expect(screen.getByText("It's rolling!")).toBeInTheDocument()
    userEvent.click(screen.getByText('Switch state'))
    expect(screen.getByText("It's on!")).toBeInTheDocument()
  })

})
</code></pre>
<p>See that we import an additional utility called <code>userEvent</code>. This is an object that contains many methods we can use to simulate user fired events, like clicks, hovers, writting in an input, and so on.</p>
<ul>
<li><p>We first check that the default string is rendered: <code>expect(screen.getByText("It's on!")).toBeInTheDocument()</code></p>
</li>
<li><p>Then we simulate a click and check that the string changes in the screen:</p>
</li>
</ul>
<pre><code class="lang-plaintext">userEvent.click(screen.getByText('Switch state'))
expect(screen.getByText("It's rolling!")).toBeInTheDocument()
</code></pre>
<ul>
<li>And last we simulate another click and check that the string reverses back to default:</li>
</ul>
<pre><code class="lang-plaintext">userEvent.click(screen.getByText('Switch state'))
expect(screen.getByText("It's on!")).toBeInTheDocument()
</code></pre>
<p>To finish, we're going to write another test to verify that the text input and its toggle work correctly.</p>
<pre><code class="lang-plaintext">import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import About from './About'

describe('About', () =&gt; {

  ...

  test('Input works correctly', async () =&gt; {
    render( &lt;About/&gt; )

    userEvent.type(screen.getByTestId("testInput"), "Testing the test")
    userEvent.click(screen.getByText("Print input"))

    expect(screen.getByText("Testing the test")).toBeInTheDocument()

    userEvent.click(screen.getByText("Print input"))
    expect(screen.queryByText("Testing the test")).not.toBeInTheDocument()
  })


})
</code></pre>
<ul>
<li><p>Again we use the <code>userEvent</code> to simulate text being writen into our input element: <code>userEvent.type(screen.getByTestId("testInput"), "Testing the test")</code></p>
</li>
<li><p>Then we simulate a click on the toggle button, and check for the input text to be in the document:</p>
</li>
</ul>
<pre><code class="lang-plaintext">userEvent.click(screen.getByText("Print input"))
expect(screen.getByText("Testing the test")).toBeInTheDocument()
</code></pre>
<ul>
<li>And we close by simulating another click and checking that the test is no longer present:</li>
</ul>
<pre><code class="lang-plaintext">userEvent.click(screen.getByText("Print input"))
expect(screen.getByText("Testing the test")).toBeInTheDocument()
</code></pre>
<p>You can see how nice the utilities provided by Testing libraries are, and how easy it is to combine them with Jest. 🤓</p>
<p>We can run this specific test file by running <code>npm test -- About.test.jsx</code> and this is the result we get:</p>
<pre><code class="lang-plaintext">// console
PASS  src/components/About.test.jsx
  About
    ✓ About renders correctly (34 ms)
    ✓ Switch state works correctly (66 ms)
    ✓ Input works correctly (67 ms)

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        0.997 s, estimated 1 s
Ran all test suites matching /About.test.jsx/i.
</code></pre>
<p>The last Jest feature I'd like to show you is <strong>test coverage</strong>. You can obtain a coverage report by running <code>npm test -- --coverage</code>.</p>
<p>This will run your tests normally and at the end of the results report you should see something like this:</p>
<pre><code class="lang-plaintext">// console
...

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |      75 |      100 |   85.71 |      70 |                   
 src            |       0 |      100 |       0 |       0 |                   
  App.jsx       |       0 |      100 |       0 |       0 | 7                 
  App.t.js      |       0 |        0 |       0 |       0 |                   
  index.js      |       0 |      100 |     100 |       0 | 5-6               
 src/components |     100 |      100 |     100 |     100 |                   
  About.jsx     |     100 |      100 |     100 |     100 |                   
----------------|---------|----------|---------|---------|-------------------
</code></pre>
<p>In the report we can see that our <code>About.jsx</code> component is completely covered, but our <code>App.jsx</code> and <code>index.js</code> files are not being tested.</p>
<p>This feature is very handy when working on big projects and you want to quickly know if most of your code is being tested correctly.</p>
<h1 id="heading-how-to-test-a-front-end-react-app-with-cypress">How to Test a Front-end React App with Cypress</h1>
<p>We've talked a lot about Jest, so now let's take a look at how we can test our app using Cypress.</p>
<p>We'll start off by installing Cypress by running <code>npm i -D cypress</code>.</p>
<p>This should add this to our <code>package.json</code>:</p>
<pre><code class="lang-plaintext">"devDependencies": {
    "cypress": "^9.5.4"
}
</code></pre>
<p>Then we'll run <code>npx cypress open</code>. This will open the Cypress browser, and create a <code>cypress</code> directory within our project. Within this directory you'll find examples, documentation, and config options.</p>
<p>You'llo also find an "integration" folder, in which we have to put our tests. So let's create our <code>About.test.js</code> file in that folder and replicate the same test examples we've seen with Jest:</p>
<pre><code class="lang-plaintext">// About.test.js
describe('AboutPage', () =&gt; {
    it('Renders correctly', () =&gt; {
        cy.visit('http://localhost:3000/about')
        cy.contains("I'm the about page!")
    })

    it('switch btn toggles text', () =&gt; {
        cy.contains("It's on!")
        cy.get('.switchBtn').click()
        cy.contains("It's rolling!")
        cy.get('.switchBtn').click()
        cy.contains("It's on!")
    })

    it('Input works correctly', () =&gt; {
        cy.get(".testInput").type("Testing the test")
        cy.get('.printInputBtn').click()
        cy.contains("Testing the test")

        cy.get('.printInputBtn').click()
        cy.contains("Testing the test").should('not.exist')
    })
})
</code></pre>
<ul>
<li><p>The <code>describe</code> function works the same as in jest.</p>
</li>
<li><p><code>it()</code> is the same as the <code>test()</code> function we've previously seen.</p>
</li>
<li><p>In the first test we tell the browser to visit our app's URL and check that the corresponding text is rendered:</p>
</li>
</ul>
<pre><code class="lang-plaintext">cy.visit('http://localhost:3000/about')
cy.contains("I'm the about page!")
</code></pre>
<ul>
<li>Then we check that the default toggle text is rendered, simulate a click and check that it changes accordingly:</li>
</ul>
<pre><code class="lang-plaintext">cy.contains("It's on!")
cy.get('.switchBtn').click()
cy.contains("It's rolling!")
cy.get('.switchBtn').click()
cy.contains("It's on!")
</code></pre>
<ul>
<li>And to end we simulate a text input, simulate a click, and check that the input text is rendered:</li>
</ul>
<pre><code class="lang-plaintext">cy.get(".testInput").type("Testing the test")
cy.get('.printInputBtn').click()
cy.contains("Testing the test")

cy.get('.printInputBtn').click()
cy.contains("Testing the test").should('not.exist')
</code></pre>
<p>The syntaxt is slightly different than Jest, but the idea and structure are pretty much the same.🤙</p>
<p>Now if we run <code>npx cypress open</code> again, a window should open with this content:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/2022-04-23_22-30.png" alt="2022-04-23_22-30" width="600" height="400" loading="lazy"></p>
<p>We can click on "Run integration spec" and our test will run automatically in the mock browser. After the tests have run, on the left panel we'll see the results:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/2022-04-23_22-31.png" alt="2022-04-23_22-31" width="600" height="400" loading="lazy"></p>
<p>We can open those results to see each step the test executed. If we hover over each step, we'll see it executed in the browser in real time. A real sweet feature of Cypress.👌👌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/2022-04-23_22-34.png" alt="2022-04-23_22-34" width="600" height="400" loading="lazy"></p>
<p>As you can see, it's very easy to set up tests with Cypress. And if you're already familiar with Jest, you can quickly pick it up as the syntax is not that different.</p>
<p>If you're wondering if it makes sense to use both Jest and Cypress as test runners in the same project, <a target="_blank" href="https://stackoverflow.com/questions/66217682/should-i-use-both-cypress-and-jest-together">I think this stack-overflow answe</a>r sums it up quite nicely.</p>
<h1 id="heading-how-to-test-a-back-end-node-app">How to Test a Back-end Node App</h1>
<p>Now that we have a basic understanding of the ways we can tests a front-end app, let's cross the river and see how we can use similar tools to test a back end app.</p>
<p>For this we'll use a simple Node and Express API with just 3 endpoints.</p>
<p>Create a directory and run <code>npm init -y</code> to create a Node app. Run <code>npm i express</code> to install Express, and then run <code>npm i -D jest supertest</code> to install both Jest and Supertest as development dependencies.</p>
<p>Inside your <code>package.json</code>, add <code>"scripts": { "test": "jest" }</code>. Your entire <code>package.json</code> should look like this:</p>
<pre><code class="lang-plaintext">{
  "dependencies": {
    "express": "^4.17.3"
  },
  "devDependencies": {
    "jest": "^27.5.1",
    "supertest": "^6.2.2"
  },
    "scripts": {
    "test": "jest"
  }
}
</code></pre>
<p>Then create an <code>app.js</code> file and put this code in it:</p>
<pre><code class="lang-plaintext">// app.js
/* Import and initialize express */
const express = require('express')
const app = express()
const server = require('http').Server(app)
/* Global middlewares */
app.use(express.json())

/* Endpoint 1 */
app.get('/', async (req, res) =&gt; {

    try {
        res.status(200).json({ greeting: "Hello there!" })
    } catch (err) {
        res.status(500).send(err)
    }
})

/* Endpoint 2 */
app.get('/isPalindrome', async (req, res) =&gt; {

    try {
        const string = req.body.string
        let result = true        
        let left = 0
        let right = string.length-1

        while (left &lt; right &amp;&amp; result) {
            if (string[left] === string[right]) {
                left += 1
                right -= 1
            }
            else result = false
        }

        res.status(200).json({ result: result })

    } catch (err) {
        res.status(500).send(err)
    }
})

/* Endpoint 3 */
app.get('/twoSum', async (req, res) =&gt; {

    try {
        const nums = JSON.parse(req.body.nums)
        const target = JSON.parse(req.body.target)

        let result = false

        for (let i = 0; i &lt; nums.length; i++) {
            const neededNum = target - nums[i]
            if (nums.indexOf(neededNum) !== -1 &amp;&amp; nums.indexOf(neededNum) !== i) result = [nums[i], nums[nums.indexOf(neededNum)]]
        }

        res.status(200).json({ result: result })

    } catch (err) {
        res.status(500).send(err)
    }
})

/* Export server object */
module.exports = server

/* Initialize server */
server.listen(3001, () =&gt; console.log('Server is listening.') )
server.on('error', error =&gt; console.error(error) )
</code></pre>
<p>As you can see, endpoint 1 just returns a greeting message. Endpoint 2 and 3 are adaptations of the functions we've seen in our vanilla JS examples. They now receive the parameters within the request and the return values go in the response. 😉</p>
<p>Now the testing! Create an <code>app.test.js</code> file and put this code within it:</p>
<pre><code class="lang-plaintext">// app.test.js
const supertest = require('supertest') // Import supertest
const server = require("./app") // Import the server object
const requestWithSupertest = supertest(server) // We will use this function to mock HTTP requests

afterEach(done =&gt; { // afterEach function is provided by Jest and executes once all tests are finished
    server.close() // We close the server connection once all tests have finished
    done()
})

test('GET "/" returns greeting', async () =&gt; {
    const res = await requestWithSupertest.get('/')
    expect(res.status).toEqual(200)
    expect(res.type).toEqual(expect.stringContaining('json'))
    expect(res.body).toEqual({ greeting: "Hello there!" })
})

describe("/isPalindrome", () =&gt; {
    test('GET "/isPalindrome" neuquen returns true', async () =&gt; {
        const res = await requestWithSupertest.get('/isPalindrome').set('Content-type', 'application/json').send({ "string":"neuquen" })
        expect(res.status).toEqual(200)
        expect(res.type).toEqual(expect.stringContaining('json'))
        expect(res.body).toEqual({ result: true })
    })

    test('GET "/isPalindrome" bariloche returns true', async () =&gt; {
        const res = await requestWithSupertest.get('/isPalindrome').set('Content-type', 'application/json').send({ "string":"bariloche" })
        expect(res.status).toEqual(200)
        expect(res.type).toEqual(expect.stringContaining('json'))
        expect(res.body).toEqual({ result: false })
    })
})

describe("/twoSum", () =&gt; {
    test('GET "/twoSum" [2,7,11,15] and 9 returns [7, 2]', async () =&gt; {
        const res = await requestWithSupertest.get('/twoSum').set('Content-type', 'application/json').send({ "nums":"[2,7,11,15]", "target": "9" })
        expect(res.status).toEqual(200)
        expect(res.type).toEqual(expect.stringContaining('json'))
        expect(res.body).toEqual({ result: [7, 2] })
    })

    test('GET "/twoSum" [3,2,4] and 6 returns [4, 2]', async () =&gt; {
        const res = await requestWithSupertest.get('/twoSum').set('Content-type', 'application/json').send({ "nums":"[3,2,4]", "target": "6" })
        expect(res.status).toEqual(200)
        expect(res.type).toEqual(expect.stringContaining('json'))
        expect(res.body).toEqual({ result: [4, 2] })
    })

    test('GET "/twoSum" [3,2,4] and 10 returns false', async () =&gt; {
        const res = await requestWithSupertest.get('/twoSum').set('Content-type', 'application/json').send({ "nums":"[3,2,4]", "target": "10" })
        expect(res.status).toEqual(200)
        expect(res.type).toEqual(expect.stringContaining('json'))
        expect(res.body).toEqual({ result: false })
    })
})
</code></pre>
<p>Let's analyze what we're doing:</p>
<ul>
<li><p>We mock the request with <code>requestWithSupertest.get('/')</code></p>
</li>
<li><p>Then we "break" the <code>res</code> object in pieces and assert each part of it:</p>
<ul>
<li><p>Check the response status: <code>expect(res.status).toEqual(200)</code></p>
</li>
<li><p>Check the response format: <code>expect(res.type).toEqual(expect.stringContaining('json'))</code></p>
</li>
<li><p>Check the response body content: <code>expect(res.body).toEqual({ greeting: "Hello there!" })</code></p>
</li>
</ul>
</li>
</ul>
<p>The other tests are really similar, except we're sending data in the mock requests bodies, like this:</p>
<pre><code class="lang-plaintext">const res = await requestWithSupertest.get('/isPalindrome').set('Content-type', 'application/json').send({ "string":"bariloche" })
</code></pre>
<p>As you can see, testing in this way is really simple once you're familiar with Jest. We just need a little help by Supertest to mock the HTTP request and the rest is just asserting the response. 👏👏</p>
<p>We can run our tests with <code>npm test</code> and we should get the following response:</p>
<pre><code class="lang-plaintext">// console
 PASS  ./app.test.js
  ✓ GET "/" returns greeting (46 ms)
  /isPalindrome
    ✓ GET "/isPalindrome" neuquen returns true (18 ms)
    ✓ GET "/isPalindrome" bariloche returns true (3 ms)
  /twoSum
    ✓ GET "/twoSum" [2,7,11,15] and 9 returns [7, 2] (4 ms)
    ✓ GET "/twoSum" [3,2,4] and 6 returns [4, 2] (3 ms)
    ✓ GET "/twoSum" [3,2,4] and 10 returns false (2 ms)

Test Suites: 1 passed, 1 total
Tests:       6 passed, 6 total
Snapshots:   0 total
Time:        0.552 s, estimated 1 s
Ran all test suites.
</code></pre>
<h1 id="heading-wrap-up">Wrap up</h1>
<p>And that's it! We've covered the basics of four very popular tools that will allow you to test both the front-end and back-end of your JS apps.</p>
<p>Of course there's much more to all the tools we've seen and many features we haven't covered. But the idea was to give you an introduction so you can take your first steps in the testing world.</p>
<p>As always, I hope you enjoyed the article and learned something new. If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">linkedin</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">twitter</a>.</p>
<p>Cheers and see you in the next one! =D</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/goodbye-bye--1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Risk-Based Testing: A Balanced & Effective Approach To Testing ]]>
                </title>
                <description>
                    <![CDATA[ By Rashmi Sharma Stakeholders are always pushing searching for faster solutions. Project managers are rushing products to the delivery table. And there is isn't necessarily anything wrong with doing it this way. But it can be challenging for QA testi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/risk-based-testing-a-balanced-effective-approach-to-testing/</link>
                <guid isPermaLink="false">66d460c9c7632f8bfbf1e493</guid>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 25 Feb 2021 15:58:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/02/photo-1574790398664-0cb03682ed1c--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Rashmi Sharma</p>
<p>Stakeholders are always pushing searching for faster solutions. Project managers are rushing products to the delivery table. And there is isn't necessarily anything wrong with doing it this way.</p>
<p>But it can be challenging for QA testing teams who have to embrace this super quick timetable, and then convince the developer team to get onboard.</p>
<p>Software teams know how badly test management teams want to reach deadlines when they are coping with constant shifts and changes.</p>
<p>In this scenario, all blame falls on the test team, who might quickly become a convenient target when production bugs are shipped. And any delays regarding specifications and implementation in the upstream software development lifecycle (SDLC) phase will make matters worse. </p>
<p>Beyond that, the demands of the stakeholders who want the product available ASAP add fuel to the fire. All of this puts the testing team under immense pressure.</p>
<p>A QA team must have a rational and empirical response to this challenge. The answer to this problem lies in <a target="_blank" href="https://www.kualitee.com/test-management/best-test-management-tools-must-used-2019/">risk-based testing (RBT)</a> which can help the testing team deliver on their deadlines. </p>
<p>Your test team can save a ton of effort with the RBT strategy, and it produces great savings while delivering the project on time.</p>
<h2 id="heading-what-is-risk-based-testing-rbt-basics">What is Risk-Based Testing? RBT Basics</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/dm.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In risk-based test management, you find the greatest market threats (that would have a detrimental effect on the enterprise as defined by the consumer) early in the development cycle and then you can counter them by taking preventive steps.</p>
<p>These market threats may include increased costs, consumer disappointment, poor user interface, and lost customers. And RBT can help you mitigate them by conducting testing in such a way that, even if a customer gets an error, they can go on using the application (and the organization isn't greatly affected).</p>
<p>RBT involves testing that's performed on the basis of product risks. It's useful in helping you discover how likely a specific feature or capability is to fail in final output/production. It'll also help you determine this failure's effect on the company in terms of cost and other damages, well ahead of time. And it does this by using a prioritization strategy for test cases.</p>
<p>So Risk-Based evaluation works by prioritizing the testing of a product or software's functionality, components, and features. This prioritization is based on the risk of the possibility of failure in the development of the feature or functionality and its effect on clients.</p>
<h2 id="heading-how-to-assess-risk-with-rbt">How to Assess Risk with RBT</h2>
<p>RBT includes risk management and test prioritization depending on the risk factor of each test. The risk factor is the result of the likelihood and possible effect of future risk. </p>
<p>But how are we able to come up with those values? To allocate a risk factor to a specific risk, here are three requirements to consider.</p>
<h3 id="heading-code-complexity">Code Complexity</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/complexity.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Cyclomatic Complexity</em></p>
<p>The more ambiguous code is, the more likely flaws will be discovered. Simply put, it is more likely that more complicated code contains glitches. The reverse is also true: the cleaner and simpler the code, the less likely it is to contain errors.</p>
<p>The problem then is how you should calculate code complexity. One measure is <a target="_blank" href="https://www.tutorialspoint.com/software_testing_dictionary/cyclomatic_complexity.htm">cyclomatic complexity</a> which refers to the number of potential paths. The minimal number of test cases you require to thoroughly test a feature is determined by that number. In fact, code with high cyclomatic complexity, which may expand the number of errors, can be more difficult to read.</p>
<h3 id="heading-churn-or-number-of-modifications-to-the-code">Churn or number of modifications to the code</h3>
<p>Churn here implies the number of modifications that a specified file or module experiences. An application area that developers alter more frequently is more likely to have bugs than one which they hardly ever touch.</p>
<p>A great example of this is an application for e-commerce that has been in development for many years. The software team is likely to make frequent adjustments to the offers, introduce new features, and try experiments to boost purchases. The affected sections of the code shift regularly and are thus more likely to produce errors.</p>
<p>When <a target="_blank" href="https://dzone.com/articles/code-churn-a-magical-metric-for-software-quality">churn</a> is significant, extensive testing should be proposed for risk-based planning: more UI tests, more unit tests, more integration tests, and so on.</p>
<h3 id="heading-criticality">Criticality</h3>
<p>Criticality involves the calculation of a <a target="_blank" href="https://techbeacon.com/app-dev-testing/how-slash-high-cost-defects">software defect's</a> influence on your application. Criticality is not spread equally through a codebase. Many systems are expected to have a high-critical code core on which the remainder of the application relies. </p>
<p>If the code does not perform properly, several parts of the software could be compromised and it would probably create defects. If it applies to safety-related software, a critical flaw may cause data loss, sensitive data disclosure, and maybe even endanger lives.</p>
<p>When measuring the effect portion of the risk factor, criticality may be useful.</p>
<p>If a bug arises in the application's most important environment, the effects could be much more extreme than if it existed in some area that included utility code only.</p>
<p>We rely on our algorithms in our test management frameworks to classify site components. If web components can not be detected by the algorithm and related core code, the UI checks if our customers will make mistakes or fail, creating frustration, reworks, service calls, and a lack of faith in our solution. </p>
<p>Worse still, if false positives are generated by our application, it will interrupt the CI/CD process and impede the implementation of a legitimate application.</p>
<h2 id="heading-smart-testing-is-the-solution">Smart Testing Is the Solution</h2>
<p>Software development companies need a better strategy when it comes to software testing than "just test everything." Not all code is equal, not all threats are credible, and not all bugs trigger equal harm. </p>
<p>In order to make informed decisions about how to distribute capital and test them more effectively, tech companies must take these RBT considerations into account.</p>
<p>If you want to remain on top of your Risk-Based Software Testing, you can check out <a target="_blank" href="https://www.kualitee.com/">Kualitee</a> – we're a software testing and information security company.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Google Does Code Reviews – Quality Assurance Tips from Google's Documentation ]]>
                </title>
                <description>
                    <![CDATA[ A code review, sometimes called code Quality Assurance, is the practice of having other people check your code after you write it.  Code reviews bring many benefits to the process of writing and delivering software: Ensures consistency through your ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-google-taught-me-about-code-reviews/</link>
                <guid isPermaLink="false">66bc55edda80a491ea5a5f5f</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google ]]>
                    </category>
                
                    <category>
                        <![CDATA[ QA ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kealan Parr ]]>
                </dc:creator>
                <pubDate>Thu, 14 Jan 2021 18:09:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/01/Google.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A code review, sometimes called code Quality Assurance, is the practice of having other people check your code after you write it. </p>
<p>Code reviews bring many benefits to the process of writing and delivering software:</p>
<ul>
<li>Ensures consistency through your codebase.</li>
<li>Teaches all members of the review (helps knowledge transfer).</li>
<li>Builds contextual awareness regarding what might affect other parts of the team</li>
<li>Helps avoid breaking builds</li>
<li>Casts fresh eyes over a code change to search for optimisations and simplifications in the change.</li>
<li>Promotes quality and helps make sure no one forgot or missed anything.</li>
</ul>
<p>Google has 1,918 repositories on <a target="_blank" href="https://github.com/google">their GitHub</a> across multiple languages, and even more that aren't open source.</p>
<p>One of their codebases is shared by over 25,000 Googlers, and typically has <a target="_blank" href="https://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository/fulltext">40,000 commits</a> daily (16,000 human changes, and 24,000 by automated systems). Each day it has to serve around 800,000 queries per second during peak times.</p>
<p>Google has published their engineering practices, so let's see how they review code at their scale, with so many commits a day.</p>
<p>Google refers to changes in their codebases as <strong>CLs</strong> standing for change lists. It's just a unit of work / piece of code going through review. </p>
<h1 id="heading-how-to-prepare-for-code-reviews">How to Prepare for Code Reviews</h1>
<p>Firstly, before you even think about the code review process, try and focus on <strong>who</strong> will do the review. Try to pick a subject matter expert. Pick someone who is familiar with this codebase or area of the codebase. </p>
<p>Sometimes this may even mean having different people review different parts of the code. But less <a target="_blank" href="https://sback.it/publications/icse2018seip.pdf">than 25% of code review's at Google have more than one reviewer.</a></p>
<p>Getting someone to respond in a timely manner is also important. To avoid bottle necks and overloading individuals, just CC reviewers onto the change to review it at their convenience if they want to.</p>
<h1 id="heading-how-to-run-fast-code-reviews">How to Run Fast Code Reviews</h1>
<p>Code reviews should be completed quickly. The <strong>maximum</strong> length of time for a review should be one business day.</p>
<p>Why the urgency? I've personally had QA's sometimes take weeks or longer.</p>
<ul>
<li><strong>It becomes a blocker.</strong> Although the author of the code moves onto new work, new changes start to form a back log, and the delays can build up to weeks or months.</li>
<li><strong>Developers feel frustrated.</strong> If the reviewer asks for major changes but only responds every 3 days, it is frustrating for the developer working on that change. But with quick responses, whenever you require explanation of exactly what you need to do, the frustration fades away.</li>
<li><strong>Code quality can degrade.</strong> If your reviews are always slow, developers are less likely to do code clean ups, refactoring work or general code improvement ("If my reviewer won't reply for 4 days what's even the point?"), and the code quality submitted in the reviews is more likely to go down.</li>
</ul>
<p>The main reason code reviews can be fast is because they're small. Rather than sending a 1,000 line CL, they're separated into multiple CL's – pushing 10 smaller changes of 100 lines for example.</p>
<p>Google also has emergencies where code changes have to be made quickly to resolve major problems in production. In these cases, code quality is relaxed. This review should immediately become the reviewers first priority. There are some examples of emergencies Google has faced <a target="_blank" href="https://www.freecodecamp.org/news/what-is-a-software-post-mortem/">here</a> if you're curious.</p>
<h2 id="heading-googles-code-review-standards">Google's Code Review Standards</h2>
<p>The key rule Google emphasizes is:</p>
<p><strong>Reviewers should generally approve a change once it definitely improves the overall code health, even if it isn't perfect.</strong></p>
<p>The key point Google seem to be making is that perfect code doesn't exist. If it makes it <strong>better</strong>, that is enough. </p>
<p>It's definitely a balancing act between something being better, and <strong>how</strong> much better it could be. If you could add more feedback to make significant improvements, there may need to be more work done on the code.</p>
<h2 id="heading-what-googlers-look-for-in-code-reviews">What Googlers Look for in Code Reviews</h2>
<p>When doing code reviews, Google focuses on these elements according to their <a target="_blank" href="https://google.github.io/eng-practices/review/reviewer/looking-for.html">engineering practices documentation</a>:</p>
<blockquote>
<p><strong>Design</strong>: Is the code well-designed and appropriate for your system? Does this change belong in your codebase, or in a library? Does it integrate well with the rest of your system?  </p>
<p><strong>Functionality</strong>: Does the code behave as the author likely intended? Is the way the code behaves good for its users? Mostly, we expect developers to test CLs well-enough that they work correctly by the time they get to code review.   </p>
<p><strong>Complexity</strong>: Could the code be made simpler? Would another developer be able to easily understand and use this code when they come across it in the future? Is it over-engineered for its current use case?  </p>
<p><strong>Tests</strong>: Does the code have correct and well-designed automated tests? Will the tests actually fail when the code is broken? Will they start producing false positives? Does each test make simple and useful assertions?  </p>
<p><strong>Naming</strong>: Did the developer choose clear names for variables, classes, methods, etc.?  </p>
<p><strong>Comments</strong>: Are the comments clear and useful? Ensure where sensible comments explain <strong>why</strong> something is being done, rather than how.  </p>
<p><strong>Style &amp; Consistency</strong>: Does the code follow our <a target="_blank" href="http://google.github.io/styleguide/">style guides</a>?  </p>
<p><strong>Documentation</strong>: Did the developer also update relevant documentation?</p>
</blockquote>
<p>Google has style guides for multiple languages like <a target="_blank" href="https://google.github.io/styleguide/cppguide.html">C++</a>, <a target="_blank" href="https://google.github.io/swift/">Swift</a>, <a target="_blank" href="https://google.github.io/styleguide/htmlcssguide.html">HTML/CSS</a>, <a target="_blank" href="https://google.github.io/styleguide/lispguide.xml">Lisp</a>, <a target="_blank" href="https://google.github.io/styleguide/jsguide.html">JavaScript</a> and <a target="_blank" href="https://google.github.io/styleguide/">more.</a></p>
<p>Having a document that everyone can refer to helps standardise the code. It also helps clarify what the expectations are in the review process.</p>
<h2 id="heading-how-googlers-review-code">How Googlers Review Code</h2>
<p>There is a three-stage process for code review in Google's engineering practices. Here's a list of things you'd need to cover if you were to review:</p>
<ol>
<li>Get a high level overview of the change</li>
<li>Examine the main parts of the change</li>
<li>Look through the rest of the code, in a sensible order</li>
</ol>
<p>Let's go over each step in more detail.</p>
<h2 id="heading-1-get-a-high-level-overview-of-the-code-change">1. Get a High Level Overview of the Code Change</h2>
<p>Look at the code change's description/summary. Does it all make sense? For example, if someone is changing a codebase that is being deleted next week, push back on the change <em>courteously,</em> and explain why the change doesn't look needed anymore. </p>
<p>It's inefficient if people are spending time on work that isn't actually needed, so have a look at your development life cycle and see why this might be happening. The earlier you can catch these issues the better.</p>
<p>In order to get a high level overview of the code, you may want to briefly scan the code components to see how it all works together. </p>
<p>If you see a serious architectural problem or something majorly wrong, you should share your observations immediately at this stage. Even if you don't have time to review every single other element of the review. Reviewing the rest may well even end up being a waste of time if the architectural problems are severe enough. </p>
<p>Aside from this, there are 2 major reasons why you should send your review comments immediately: </p>
<ul>
<li>Googlers will often email a change, and then immediately start new work based on that change. If the change in review need serious adjustments, they may be building on something that needs to be significantly changed.</li>
<li>Big changes to the CL may take a while to finish. Developers all have deadlines and it's courteous to try and help them meet them by letting them start rework as soon as possible.</li>
</ul>
<h2 id="heading-2-examine-the-main-parts-of-the-code-change">2. Examine the Main Parts of the Code Change</h2>
<p>Once you have had an overview, review the "main" parts of the change.</p>
<p>Find the file or files that are central to the CL. Often, there is one file that has the largest number of changes, and it’s the major piece of the CL.</p>
<p>Spend most of your focus reviewing these pieces. This provides context to all the smaller pieces, and generally makes it faster to review. </p>
<p>If the CL is too large for you to get a good overview and understand the flow, it's a good sign the developer should be splitting up their CL into smaller changes.</p>
<h2 id="heading-3-look-through-the-rest-of-the-code-in-a-sensible-order">3. Look Through the Rest of the Code, in a Sensible Order</h2>
<p>Once you have a good overview of the change, it's time to drill down into the details and go file by file. </p>
<p>Each reviewer generally does this differently. Some go in the order that the version control presents to them and some pick a particular order. Choose what makes sense to you. It's important to just review <strong>everything</strong>, and miss nothing.</p>
<h3 id="heading-review-every-line-of-code">Review Every Line of Code</h3>
<p>Don't miss or skim important details. Sometimes there might be config files, or generated code you can scan briefly looking for irregularities. But your job here is to be very thorough and carefully scrutinise the code. </p>
<p>Make sure you think about bugs, race conditions, alternate approaches, conciseness, readability, and so on.</p>
<p>If you can't understand the code, it's highly likely other developers won't be able to either, and should ask the developer to clarify it.</p>
<h3 id="heading-understand-the-context">Understand the Context</h3>
<p>Often times the version control software will only show the changed lines. But it's important to read the lines before and after, or the whole file, to ensure you understand exactly what the change is doing.  </p>
<p>You may only see someone adding 2 more <code>if</code> blocks in a change. But if you look at the context you might see that the <code>if</code> <code>else</code> block now has 15 different <code>if</code>'s inside it. Then you can reject the code change and properly improve the code quality in this area, rather than making it worse.</p>
<p>Remember code degradation happens slowly, with every change that goes in. Our main aim is to ensure the quality trends consistently up, and we never go backwards.</p>
<h2 id="heading-how-googlers-write-code-feedback"><strong>How Googlers Write Code Feedback</strong></h2>
<p>Google has some specific sections covering how to do <a target="_blank" href="https://chromium.googlesource.com/chromium/src/+/master/docs/cr_respect.md">code reviews courteously, and respectfully</a>. This isn't in opposition to being clear and as helpful as you can to the developer. The golden rule here is to make comments about the <em>code</em> and not the developer. </p>
<h2 id="heading-what-to-do">What to Do:</h2>
<p>#### </p>
<blockquote>
<p><strong>Ask for the why:</strong> If it is unclear why the author is doing things a certain way, feel free to ask why they made a particular change. Not knowing is OK, and asking “Why” leaves a written record that will help answer this question in the future. (And sometimes, “I'm curious, why did you decide to do it that way?” can help the author to rethink their decision.)  </p>
<p><strong>Find an end:</strong> If you like things neat, it’s tempting to go over a code review over and over until it’s perfect, dragging it out for longer than necessary. It’s soul-deadening for the recipient, though. Keep in mind that “LGTM” does not mean “I vouch my immortal soul this will never fail”, but “looks good to me”. If it looks good, move on. (That doesn’t mean you shouldn’t be thorough. It’s a judgment call.) And if there are bigger refactorings to be done, move them to a new CL. (<a target="_blank" href="https://chromium.googlesource.com/chromium/src/+/HEAD/docs/cr_respect.md">Source</a>)</p>
</blockquote>
<h2 id="heading-what-not-to-do">What Not to Do</h2>
<blockquote>
<p><strong>Don't use extreme or very negative language:</strong> Please don't say things like “no sane person would ever do this” or “this algorithm is terrible”, whether it’s about the change you're reviewing or about the surrounding code. While it might intimidate the reviewee into doing what you want, it’s not helpful in the long run - they will feel incapable, and there is not much info in there to help them improve. “This is a good start, but it could use some work” or “This needs some cleanup” are nicer ways of saying it. Discuss the code, not the person.  </p>
<p><strong>Don't bikeshed:</strong> Always ask yourself if this decision <em>really</em> matters in the long run, or if you're enforcing a subjective preference. It feels good to be right, but only one of the two participants can win that game. If it’s not important, agree to disagree, and move on. (<a target="_blank" href="https://chromium.googlesource.com/chromium/src/+/HEAD/docs/cr_respect.md">Source</a>)</p>
</blockquote>
<p>Remember code reviews can sometimes trend towards finding issues or discussions with code and not praise.</p>
<p>If your reviewer has addressed your comments, or they have done some optimisation or smart code you like, thank them. Say you like the approach / how they have solved an issue. </p>
<p>Conversely, thank the reviewer if they thoroughly explain what they want and promptly answer your questions.</p>
<p>I have had some reviews where reviewers have put huge comments explaining something I misunderstood and I can still remember who it was and what they said.</p>
<h2 id="heading-how-to-handle-pushback-in-code-reviews">How to Handle Pushback in Code Reviews</h2>
<p>Sometimes the developer who is receiving the review might disagree with the changes that you're proposing. Here's how to handle that.</p>
<h3 id="heading-consider-that-they-might-be-right">Consider That They Might Be Right</h3>
<p>Sometimes the developer is closer to the code and how it works, and they may be right. If they are, move on from that discussion point and leave that code as it is.</p>
<p>But if they're not, or they've misunderstood something, you should insist on the change. Respond to what the developer initially challenged you on, and explain your reasoning courteously. </p>
<p>Code quality improvements tend to happen in small incremental steps, and review is one way it happens. Insist on the code improvement, even if it means extra work for the developer.</p>
<h3 id="heading-try-to-avoid-ill-fix-this-later">Try to Avoid "I'll fix this later..."</h3>
<p>One of the most common issues in reviews is not that people disagree whether the code change is necessary, but rather that they want to do it under a different ticket or do it later. So if you pass this review, they assure you that they will follow up later and fix the issues.</p>
<p>Generally speaking, <em>following up later</em> rarely happens. This doesn't mean there's something wrong with the developer or their work ethic. But it's easy to forget, have priorities change, or even just get lost in their queue of work. </p>
<p>Insist that the work gets done now. There is no real fantastic gain to merging changes in the codebase you have to immediately fix. You are just adding technical debt that <em>might</em> be followed up on later, or might be forgotten<em>.</em> Fixing lots of tickets later is an easy way for quality to drop.</p>
<p>The only exception to this is <a target="_blank" href="https://google.github.io/eng-practices/review/emergencies.html">emergencies</a>, which involve the highest priority bugs Google deals with where there is something seriously wrong. This could be services going down, or errors crashing people's pages in production.</p>
<p>There is naturally an eagerness to merge changes ASAP, and the review might accept slightly lower quality, with a follow up fix immediately being written. The main point is that the first change removes the emergency, and the second change fixes it <em>properly.</em></p>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>I hope this has explained some helpful concepts Google makes use of in their code review process. I wrote this to better cement it into my own mind, and was curious about how other companies handle the QA process. </p>
<p>I found that there are quite a few points that I can take away and apply to the reviews I conduct.</p>
<p>The document I referred to throughout this article can be found <a target="_blank" href="https://google.github.io/eng-practices/review/reviewer/">here</a>.</p>
<p>I share my writing on <a target="_blank" href="https://twitter.com/kealanparr">Twitter</a> if you enjoyed this article and want to see more.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Test and Play with Web APIs the Easy Way with Postman ]]>
                </title>
                <description>
                    <![CDATA[ In a world where static websites and apps increasingly depend on separately maintained APIs, it can be hard to figure out how they work by just playing around in the browser.  So how can we use Postman to both test our existing APIs and understand ho... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-test-and-play-with-web-apis-the-easy-way-with-postman/</link>
                <guid isPermaLink="false">66b8e36e47e3b55b9fb6ee45</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ QA ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tools ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 30 Jun 2020 16:34:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/postman.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In a world where static websites and apps increasingly depend on separately maintained APIs, it can be hard to figure out how they work by just playing around in the browser. </p>
<p>So how can we use Postman to both test our existing APIs and understand how they work?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-postman">What is Postman?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build-learn">What are we going to build / learn?</a></li>
<li><a class="post-section-overview" href="#heading-part-0-getting-set-up-with-postman">Part 0: Getting set up with Postman</a></li>
<li><a class="post-section-overview" href="#heading-part-1-an-introduction-to-postman">Part 1: An introduction to Postman</a></li>
<li><a class="post-section-overview" href="#heading-part-2-creating-a-new-postman-request-to-get-info-about-squirtle">Part 2: Creating a new Postman request to GET info about Squirtle</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/p/a02335e1-4f9a-453d-8916-db6b8419cf99/part-3-creating-a-collection-of-requests-in-postman-for-the-pok-api">Part 3: Creating a collection of requests in Postman for the PokéAPI</a></li>
<li><a class="post-section-overview" href="#heading-part-4-making-post-requests-with-postman-to-translate-sentences-to-sound-like-yoda">Part 4: Making POST requests with Postman to translate sentences to sound like Yoda</a></li>
<li><a class="post-section-overview" href="#heading-part-5-authenticating-requests-to-the-lord-of-the-rings-api-with-an-api-key">Part 5: Authenticating requests to the Lord of the Rings API with an API Key</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/KFuaybrXCdw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-postman">What is Postman?</h2>
<p><a target="_blank" href="https://www.postman.com/">Postman</a> is a tool teams can use to reliably test APIs using easy to use configurations. It comes stocked with features you would expect when dealing with APIs, including authentication, setting headers, customizing the payload, and a bunch more that help reduce the friction of using an API.</p>
<p>And it’s not just for testing. The beauty is that this can be used for many aspects of working with APIs for many different members of the team. Maybe a Project Manager wants to verify that things work or might find it easier to make a change straight with the API, or a QA Engineer needs to make sure everything still works, or a developer wants to actively make changes while working on the API itself.</p>
<p>The best part about it – Postman provides collaboration features. The free tier includes exporting and importing collections of saved API requests as well as creating shared links. If you're part of a team, they have paid tiers that allow you to sync up your collections to make sure everyone has the most recent and up to date collection.</p>
<h2 id="heading-what-are-we-going-to-build-learn">What are we going to build / learn?</h2>
<p>We’re going to walk through two different example APIs to cover the concepts of Postman.</p>
<p>First, we’ll walk through some simple HTTP requests with a <a target="_blank" href="https://pokeapi.co/">public API for Pokémon</a>.</p>
<p>We’ll then use the Yoda Translator API for one part to demonstrate how to make specific HTTP requests.</p>
<p>Once we understand how the basics work, we’ll use the <a target="_blank" href="https://the-one-api.herokuapp.com/">Lord of the Rings API</a> to learn how authentication works with APIs. For this, you’ll need to register for a free account for an API key.</p>
<h2 id="heading-part-0-getting-set-up-with-postman">Part 0: Getting set up with Postman</h2>
<p>Before we get started, you’ll need <a target="_blank" href="https://www.postman.com/downloads/">Postman</a> in order to follow along with this walkthrough. The good news, is Postman is available for free on Mac, Windows, and Linux, so you should be able to find a version that works for you.</p>
<p>Get Postman: <a target="_blank" href="https://www.postman.com/downloads/">https://www.postman.com/downloads/</a></p>
<p>Once downloaded, go through the standard installation instructions, open it up, and we should be ready to go!</p>
<h2 id="heading-part-1-an-introduction-to-postman">Part 1: An introduction to Postman</h2>
<p>The first time you open up Postman you’ll immediately be shown a launchpad with a bunch of options to get started.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-launchpad.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>It might seem a bit overwhelming, but let’s break down some of the key concepts that we’ll need to know.</p>
<h3 id="heading-requests">Requests</h3>
<p>A request is kind of what it sounds like, it’s a specific API request. This will be a single type of request, whether it’s a GET or POST to a specific endpoint. You’ll want to create new requests for each type of endpoint which will allow you to move between them when testing.</p>
<h3 id="heading-collections">Collections</h3>
<p>A collection is a group of requests. This is handy for organizing your requests into different groups. This could be as simple as two totally different APIs (ie. Twitter vs Slack) or it could be two different groups of APIs for a single API (ie. Twitter Tweets API vs Twitter Accounts API).</p>
<h3 id="heading-authorization">Authorization</h3>
<p>Authorization is how requests are authenticated with an API, whether by a person making a request or by a computer making that request on your behalf. This commonly comes in the form of an API key which can be a static value assigned to your account or dynamically generated with tools like <a target="_blank" href="https://oauth.net/">OAuth</a>.</p>
<h3 id="heading-environments">Environments</h3>
<p>Environments will allow you to configure your endpoints to use specific variables that make it easier to use the same endpoints between different environments. For instance, you might have the same <code>/profile</code> endpoint on both your production and development environments, but they have different domains. Environments lets you manage a single request with a variable domain.</p>
<h3 id="heading-workspaces">Workspaces</h3>
<p>We won’t go too far into workspaces in this post, but it allows you to manage and organize different sets of collections. Imagine if you want to use Postman for both work and a personal project, you might have a Work workspace as well as a Personal workspace.</p>
<p>For the purposes of this article, we’ll be covering Requests, Collections, and Authorization.</p>
<h2 id="heading-part-2-creating-a-new-postman-request-to-get-info-about-squirtle">Part 2: Creating a new Postman request to GET info about Squirtle</h2>
<p>Now that we have a better understanding of the different terminology, let’s actually create a request.</p>
<p>At the top left of the UI you should see a but orange button that says <strong>New</strong>. Go ahead and click that and then select <strong>Request</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-create-new-request.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Before we get into the request itself, it requests a few things.</p>
<p>This first thing requires is a name. We’re going to start off by requesting information about the Pokémon Squirtle, so let’s name this “Pokémon - Squirtle”.</p>
<p>It also requires a collection, so click <strong>Create Collection</strong> and let’s name the collection “My Favorite Pokémon”.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-configure-new-request.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click the orange checkmark button next to the collection name then hit <strong>Save</strong>.</p>
<p>At this point we’ll have a new request, so let’s build that request.</p>
<p>There are two things we’ll first need to fill out for our first request:</p>
<ul>
<li><strong>Request type:</strong> GET, POST, PUT, etc - we’ll use GET</li>
<li><strong>Request URL:</strong> The endpoint for your API request - for our request we’ll use <a target="_blank" href="https://pokeapi.co/api/v2/pokemon/squirtle/">https://pokeapi.co/api/v2/pokemon/squirtle/</a></li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-squirtle-pokemon-get.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And once you make sure those are correct, you can simply hit the blue <strong>Send</strong> button on the right and we’ve successfully made our first request!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-squirtle-pokemon-get-success.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We immediately get a few things we can see:</p>
<ul>
<li><strong>Body:</strong> at the bottom we should now see the response body of the API request. For our Squirtle API, we should have a JSON object with data like <code>abilities</code>, <code>base_experience</code>, and <code>forms</code>.</li>
<li><strong>Status:</strong> on the right, we should see the HTTP status code. “200 Ok” is a good sign and it means it was successful!</li>
<li><strong>Time:</strong> simply how long the request took to finish</li>
<li><strong>Size:</strong> the size in KB (in our example) of the response data</li>
</ul>
<p>You can also hover over Status, Time, and Size and get a more in depth look at each option.</p>
<p>So we made our first request!</p>
<p>Once thing to notice before we move on is that our request looks like it’s in a browser tab. If we’re done with that particular request, we can close the tab and click <strong>Save</strong> to make sure all of our changes are there for next time!</p>
<h2 id="heading-part-3-creating-a-collection-of-requests-in-postman-for-the-pokeapi">Part 3: Creating a collection of requests in Postman for the PokéAPI</h2>
<p>Now that we’ve created a request, let’s create a collection of them. Technically we already had to create a new collection for Part 2, but we’ll create a new one to learn how collections themselves work.</p>
<p>At the top left of the UI, click the orange <strong>New</strong> button again and select <strong>Collection</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-create-new-collection.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Similar to a request, it asks for a name so let’s call this “PokéAPI”. Optionally you can add a description, then click <strong>Create</strong> at the bottom.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-configure-new-collection.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>On the left, you’ll now see your collection. You can select and expand the folder since we’ll be working with it.</p>
<p>Before we add a request, the PokéAPI has different types of requests, so it makes sense to organize it a little more thoroughly. So let’s click the three dots next to the PokéAPI collection and select <strong>Add Folder</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-add-folder-to-collection.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Similar to the others, this asks for a name. Folders are kind of like collections inside of a collection, so you get similar options. Let’s name this one “Pokémon” and click the orange <strong>Save</strong> button like before.</p>
<p>Now let’s add our requests! First, click the three dots next to the Pokémon folder, similar to how we added a folder to the collection, but this time select <strong>Add Request</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-add-request-to-collection.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let’s name this request “Pokemon”. While it might be confusing that we have a Pokemon request inside of the Pokémon folder, Pokemon is just one of the endpoints of the Pokémon group.</p>
<p>Now, let’s use the same exact API that we used with our Squirtle request before:</p>
<ul>
<li><strong>Request Type:</strong> GET</li>
<li><strong>Request URL:</strong> <a target="_blank" href="https://pokeapi.co/api/v2/pokemon/squirtle/">https://pokeapi.co/api/v2/pokemon/squirtle/</a></li>
</ul>
<p>And similar to before, when we hit the blue <strong>Send</strong> button, we should see a successful request!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-successful-get-request-squirtle.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now let’s add another request. Follow the same process as before to create a new request under the PokéAPI Pokémon folder and let’s name this request “Abilities”.</p>
<p>If you scroll through the response from the first Squirtle endpoint, you see a lot of other API urls. At the top, we have <code>abilities</code> and we have two different ones — “torrent” and “rain-dish”.</p>
<p>Choose your favorite Squirtle ability and copy the <code>url</code> value into the new Abilities request we just created, I’m going to use <code>rain-dish</code>.</p>
<p>We can leave the Request Type as GET, hit the blue <strong>Send</strong> button, and we can again see a successful response!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-successful-request-squirtle-abilities.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here we get a lot of information about our Squirtle ability Rain Dish and some of the details come in different languages which is cool!</p>
<p>So now we have a new PokéAPI collection with a Pokémon folder representing the group of Pokémon API endpoints including Pokemon and abilities.</p>
<p>We’re going to stop Part 3 with those 2 requests, but feel free to continue on and add as many of the PokéAPI requests as you’d like!</p>
<h2 id="heading-part-4-making-post-requests-with-postman-to-translate-sentences-to-sound-like-yoda">Part 4: Making POST requests with Postman to translate sentences to sound like Yoda</h2>
<p>So far we’ve only made GET requests, but what if we wanted to make a POST request where we need to actually send some data?</p>
<p>For making a POST request, we’re going to use the Yoda Translator API from funtranslations.com. While this API only takes a single parameter, it’s still a good public endpoint we can use to understand the concept.</p>
<p>First, let’s create a new collection with a new request:</p>
<ul>
<li><strong>Collection:</strong> Fun Translations</li>
<li><strong>Request:</strong> Yoda</li>
</ul>
<p>This time, instead of a GET request, our request configuration will be:</p>
<ul>
<li><strong>Request Type:</strong> POST</li>
<li><strong>Request URL:</strong> <a target="_blank" href="https://api.funtranslations.com/translate/yoda">https://api.funtranslations.com/translate/yoda</a></li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-new-request-yoda-api.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now this time, if we hit the blue <strong>Send</strong> button, we’ll notice we don’t get a successful 200 response, we get a 400!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-yoda-api-bad-request.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We never actually set up any data to be posted to the API and it requires that data, so let’s add it.</p>
<p>Right below the <strong>Request URL</strong>, click <strong>Body</strong>. Then instead of none, select <strong>raw</strong> as the body type. Finally, on the far right of the types, change <strong>Text</strong> to <strong>JSON</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-yoda-request-body-type.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then, in the space below it, you can add the following:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"text"</span>: <span class="hljs-string">"Hello, I am learning how to test APIs with Postman!"</span>
}
</code></pre>
<p>And now click the blue <strong>Send</strong> button again and we get a successful response!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-successful-post-body-yoda-api.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can apply this concept to pretty much any API. Postman doesn’t only permit you to post JSON, it allows you to use the other formats that we see listed in the Body Type section, meaning you have a lot of options depending on what the API you’re using requires.</p>
<h2 id="heading-part-5-authenticating-requests-to-the-lord-of-the-rings-api-with-an-api-key">Part 5: Authenticating requests to the Lord of the Rings API with an API Key</h2>
<p>For the rest of the walkthrough, we’re going to use the Lord of the Rings API.</p>
<p>First up, the Lord of the Rings API requires authentication in order to make requests using an API key. So to start, you’ll before we dive in, you’ll need to go <a target="_blank" href="https://the-one-api.herokuapp.com/sign-up">create a free account</a>.</p>
<p><a target="_blank" href="https://the-one-api.herokuapp.com/sign-up">https://the-one-api.herokuapp.com/sign-up</a></p>
<p>Once you sign up and log in, the first thing you’ll see is your API key! Either copy this key down or remember where you can find it for later. If you leave the page, you can always grab it by navigating to <strong>Welcome</strong> and then <strong>Account</strong> in the navigation of the API website.</p>
<p>To get started, let’s first create a new collection and request:</p>
<ul>
<li><strong>Collection:</strong> Lord of the Rings</li>
<li><strong>Folder:</strong> Movie</li>
<li><strong>Request:</strong> All Movies</li>
<li><strong>Request Type:</strong> GET</li>
<li><strong>Request URL:</strong> <a target="_blank" href="https://the-one-api.herokuapp.com/v1/movie">https://the-one-api.herokuapp.com/v1/movie</a></li>
</ul>
<p>Once you’re set with the above, click <strong>Send</strong>, and you’ll notice immediately it gives a response that says 401 and that it’s unauthenticated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-unauthorized-request-lord-of-the-rings-api.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Because this API requires the API key, this is exactly what we expected. So let’s click on the <strong>Authorization</strong> tab. We can then select a <strong>Type</strong> of <strong>Bearer Token</strong>, and on the right, we can paste in our key that we just set up with the Lord of the Rings API.</p>
<p>And as soon as we hit <strong>Send</strong>, we now see a successful response!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-authorized-successful-lord-of-the-rings-api-request.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This worked really great, but what if we have a bunch of requests that use a single key. Do we have to manage that on each request?</p>
<p>Instead of managing it on each individual request, we can manage it on the collection. Let’s first build another request.</p>
<p>Under our Lord of the Rings collection and in the Movie folder, create a new request:</p>
<ul>
<li><strong>Request:</strong> Quote by Movie ID</li>
<li><strong>Request Type:</strong> GET</li>
<li><strong>Request URL:</strong> <a target="_blank" href="https://the-one-api.herokuapp.com/v1/movie/%7Bid%7D">https://the-one-api.herokuapp.com/v1/movie/{id}</a></li>
</ul>
<p>In this request, let’s use an ID from the response of the first request, I’m going to use <code>5cd95395de30eff6ebccde5b</code> which is the ID of The Two Towers, so the request URL will look like:</p>
<pre><code>https:<span class="hljs-comment">//the-one-api.herokuapp.com/v1/movie/5cd95395de30eff6ebccde5b</span>
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-inherit-authorization-from-parent.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now, instead of setting our token in the request Authorization, we’re going to leave the type as <strong>Inherit auth from parent</strong>. Click on the three dots next to the collection and select <strong>Edit</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-edit-collection.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here, we’re going to do the same exact thing we did with the first request but on the Collection configuration. Select the <strong>Authorization</strong> tab, under type select <strong>Bearer Token</strong>, and in the <strong>Token</strong> field again paste your token.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-add-authorization-api-key-token-to-collection.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Finally, click <strong>Update</strong> and hit the blue <strong>Send</strong> button again and we can see a successful request!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-authorized-request-inherit-token-from-parent.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can now go back to our All Movies request and update the Authorization to use a Type of Inherit auth from parent and it should still continue to work!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/postman-successful-request-lord-of-the-rings-api.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-what-else-can-we-do-with-postman">What else can we do with Postman?</h2>
<p>While I covered a lot of the basics, there’s quite a lot more you can do with Postman. Here are a few of my favorites.</p>
<h3 id="heading-environment-variables">Environment Variables</h3>
<p>If you’re working as a developer on a project, it’s likely that your team uses multiple environments, such as a development and production environment. Instead of creating and maintaining completely separate requests, you can add an environment variable and instead change that variable when switching between environments!</p>
<p>Variables apply to many scenarios, but that’s a common use. Check out Postman’s docs to learn how.</p>
<p><a target="_blank" href="https://learning.postman.com/docs/postman/variables-and-environments/variables/">https://learning.postman.com/docs/postman/variables-and-environments/variables/</a></p>
<h3 id="heading-import-and-export-collections-and-data">Import and Export Collections and Data</h3>
<p>A great thing about Postman is once you have your requests all organized, you can export them for others to use. This also means that you can import collections from other team members. This makes it much easier to make sure everyone’s using the same collection.</p>
<p>Bonus: you can even store these files in a Git repository, as they’re just JSON.</p>
<p>But keep in mind - if you’re using Authorization on the collection like we went over in this guide, you’ll want to make sure you don’t include that when exporting your collection.</p>
<p><a target="_blank" href="https://learning.postman.com/docs/postman/collections/importing-and-exporting-data/">https://learning.postman.com/docs/postman/collections/importing-and-exporting-data/</a></p>
<h3 id="heading-automated-testing">Automated testing</h3>
<p>Once you have a set of requests in a collection and even better, if you’re storing them in Github, you can begin to use those requests as part of a way to manage automated testing of your API.</p>
<p>While there are a few solutions for doing this, Postman includes a Collection runner built right into the app and <a target="_blank" href="https://learning.postman.com/docs/postman/collection-runs/command-line-integration-with-newman/">Newman</a> is a command line tool that lets you run tests right from the terminal.</p>
<p><a target="_blank" href="https://www.postman.com/use-cases/api-testing-automation/">https://www.postman.com/use-cases/api-testing-automation/</a></p>
<h2 id="heading-whats-your-favorite-way-to-test-and-play-with-apis">What’s your favorite way to test and play with APIs?</h2>
<p><a target="_blank" href="https://twitter.com/colbyfayock">Share with me on Twitter!</a></p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Don’t Write All Your Software Tests First – Just Write One ]]>
                </title>
                <description>
                    <![CDATA[ By Alex Bunardzic Test Driven Development (TDD) is sometimes described as “writing tests first”. The TDD mantra states that we should not write code before we have written automated tests that exercise that code. Writing code first is considered subo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/dont-write-all-your-software-tests-first-just-write-one/</link>
                <guid isPermaLink="false">66d45d59b3016bf139028cf7</guid>
                
                    <category>
                        <![CDATA[ automation testing  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 11 Jun 2020 05:31:23 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9a5c740569d1a4ca252b.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Alex Bunardzic</p>
<p>Test Driven Development (TDD) is sometimes described as “writing tests first”. The TDD mantra states that we should not write code before we have written automated tests that exercise that code. Writing code first is considered suboptimal.</p>
<p>And of course, writing code first is how we develop software following the so-called waterfall model. In that model, we divide software development activities into stages. For example, we have a ‘requirements gathering’ stage, we have an ‘application building’ stage, we have an ‘application testing’ stage, we have an ‘application deployment’ stage and so on.</p>
<p>But how is that different from the agile methodology? Don’t we have the exact same stages in agile? </p>
<h3 id="heading-agile-methodology-vs-waterfall-methodology">Agile Methodology vs Waterfall Methodology</h3>
<p>Of course we do. The crucial difference is that in agile, those stages are not gated. </p>
<p>In waterfall, we gate the stages and execute them in strict sequence. This means we won’t begin building the shipping application until such time as the requirements have been gathered, completed, signed off on and frozen. Once requirements are frozen (and controlled by our change management policies), we move into the next stage (or phase) – application building. </p>
<p>And similarly, we won’t move into the testing stage until the entire application has been built and we have reached the code complete milestone, at which point code changes have been frozen. </p>
<p>Once code gets frozen (and code freeze is then controlled by our change management policies), we hand it off to the testers. The testing phase begins, and only once all testing has completed (and provided that no significant defects have been detected), do we move into the deployment phase.</p>
<p>In agile, we do all the above activities in parallel. At the same time. We keep working on user stories (specs) while simultaneously building the shipping application. As we’re building the application we are also testing it. And as we are building and testing the application, we are also deploying it. </p>
<p>We learn from the shipping application deployed to production and use that validated learning as the feedback that will inform new user stories. That way, the loop gets closed, and we’re iterating, improving the value incrementally.</p>
<p>The only way to enable such iterative value stream delivery is by relying on automated tests. And as we’ve described, those tests are being written very early in the game. Actually, tests must be written before we write shipping code.</p>
<p>Why then is the title of this article “Don’t Write All Your Tests First, Just Write One”? It sounds a bit confusing. Let’s unpack the meaning of this title. But first, here's an overview of what tech we'll be using:</p>
<h3 id="heading-the-technology-stack-used-for-this-exercise">The technology stack used for this exercise</h3>
<p>In the attempt to keep the exercise simple and easy to follow, I have chosen <strong><a target="_blank" href="https://dotnet.microsoft.com/">.NET Core</a></strong> platform, together with <strong><a target="_blank" href="https://xunit.net/">xUnit.net</a></strong> testing platform. To follow the coding examples, please install <code>.NET Core</code> and <code>xUnit.net</code>.</p>
<p>In order to be able to run the sample code, please open <code>./tests/tests.csproj</code> file and add this line to the <code>ItemGroup</code>:</p>
<pre><code class="lang-c#">&lt;ProjectReference Include=<span class="hljs-string">"../app/app.csproj"</span> /&gt;
</code></pre>
<p>You’re now all set for following the coding exercises.</p>
<h2 id="heading-a-simple-example">A simple example</h2>
<p>To understand the difference between writing all tests first and writing one test first, it may be better to show rather than just tell. </p>
<p>So let’s try to build a simple example – for this exercise I’ve chosen a trivial case of calculating a tip at a restaurant. Often times we find ourselves in a position where we want to tip the restaurant for the service, but it’s tough to calculate percentages in our head. So a nifty little <code>Tip Calculator</code> could come in handy.</p>
<p>Here are the expectations:</p>
<p><strong>As a patron<br>I want to calculate the total bill (total plus the tip)<br>Because I want to compliment the restaurant for the service</strong></p>
<h3 id="heading-scenario-1-patron-calculates-the-total-for-terrible-service">Scenario #1: Patron calculates the total for terrible service</h3>
<p>Given that the restaurant total is $100.00<br>And the service was terrible<br>When the tip calculator calculates the total charge<br>Then tip calculator shows $100.00 total charge</p>
<h3 id="heading-scenario-2-patron-calculates-the-total-for-poor-service">Scenario #2: Patron calculates the total for poor service</h3>
<p>Given that the restaurant total is $100.00<br>And the service was poor<br>When the tip calculator calculates the total charge<br>Then tip calculator shows $105.00 total charge</p>
<h3 id="heading-scenario-3-patron-calculates-the-total-for-good-service">Scenario #3: Patron calculates the total for good service</h3>
<p>Given that the restaurant total is $100.00<br>And the service was good<br>When the tip calculator calculates the total charge<br>Then tip calculator shows $110.00 total charge</p>
<h3 id="heading-scenario-4-patron-calculates-the-total-for-great-service">Scenario #4: Patron calculates the total for great service</h3>
<p>Given that the restaurant total is $100.00<br>And the service was great<br>When the tip calculator calculates the total charge<br>Then tip calculator shows $115.00 total charge</p>
<h3 id="heading-scenario-5-patron-calculates-the-total-for-excellent-service">Scenario #5: Patron calculates the total for excellent service</h3>
<p>Given that the restaurant total is $100.00<br>And the service was excellent<br>When the tip calculator calculates the total charge<br>Then tip calculator shows $120.00 total charge</p>
<p>Let’s now implement the above user story.</p>
<p>We see that the story has 5 acceptance criteria (a.k.a. scenarios). Now we move into the analysis phase – think about what should be the first functionality that our <code>Tip Calculator</code> application should implement. But first, let’s open the command line terminal and create the new directory:</p>
<pre><code>md TipCalculator
cd TipCalculator
</code></pre><p>and create <code>app</code> and <code>tests</code> directories inside the <code>TipCalculator</code> directory.</p>
<p>Now <code>cd tests</code> and run: </p>
<pre><code class="lang-net">dotnet new xunit
</code></pre>
<p>Then <code>cd ..</code> and <code>cd app</code>, then run: </p>
<pre><code>dotnet <span class="hljs-keyword">new</span> classlib
</code></pre><p>We’re now ready to boogie!</p>
<p>Open your favourite text editor (mine is <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a>) and set your mind on the expectations. What behaviour are we expecting from the <code>Tip Calculator</code>?</p>
<p>To narrow the scope of our expectations, it usually helps to take one acceptance criteria (i.e. one scenario) and focus on it first. Let’s take scenario #1:</p>
<h3 id="heading-scenario-1-patron-calculates-the-total-for-terrible-service-1">Scenario #1: Patron calculates the total for terrible service</h3>
<p>Given that the restaurant total is $100.00<br>And the service was terrible<br>When the tip calculator calculates the total charge<br>Then tip calculator shows $100.00 total charge</p>
<p>In case the service was terrible, we are not adding any tips, and <code>Tip Calculator</code> is calculating a $0.00 tip. So how do we automate that scenario?</p>
<p>My first expectation would be that we need to somehow inform the <code>Tip Calculator</code> that the service was terrible. We either type the word ‘Terrible’ into the input field, or we select ‘Terrible’ from the list of available service ratings. </p>
<p>So the first thing to do here is to articulate some expectations regarding <code>Tip Calculator</code>’s ability to get notified that the service was terrible.</p>
<p>I like to always start with the expectation that what the user inputs is valid. So I’d first write a test that checks if the rating ‘Terrible’ is recognized by the <code>Tip Calculator</code> as a valid rating. </p>
<p>Go to the <code>tests</code> directory, rename the autogenerated <code>UnitTest1.cs</code> file to <code>TipCalculatorTests.cs</code> and add the following test:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingTerribleIsValid</span>(<span class="hljs-params"></span>)</span>{    
  <span class="hljs-keyword">var</span> expectedResponseForValidRating = <span class="hljs-literal">true</span>;    
  <span class="hljs-keyword">var</span> actualResponseForValidRating = <span class="hljs-literal">false</span>;    
  Assert.Equal(expectedResponseForValidRating, 
  actualResponseForValidRating);
}
</code></pre>
<p>Now go to the command line, <code>cd tests</code>, and run: </p>
<pre><code>dotnet test
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-21.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Of course, the above trivial test will fail, because we have hardcoded the values. But it’s always a good practice to make sure we see our tests fail before we proceed. Not observing a test fail may give us false sense of safety later on, if no tests fail and we end up thinking that everything works as expected.</p>
<p>A few more observations about the above test:</p>
<ul>
<li>It helps if the test name is descriptive. I chose <code>CheckIfRatingTerribleIsValid</code> to communicate the fact that we must make sure our application is capable of recognizing our commands.</li>
<li>It also helps if the expected and actual variable names are descriptive. I chose <code>expectedResponseForValidRating</code> and <code>actualResponseForValidRating</code> as fairly indicative of what our expectation in this test is, and also what actual value will the <code>Tip Calculator</code> produce.</li>
<li>Test is a first-class source code and must be approached with equal care lavished upon the production code.</li>
</ul>
<h2 id="heading-first-design-decision">First design decision</h2>
<p>At this point, we are forced to make a decision – how will our nascent <code>Tip Calculator</code> know if the service rating provided by the user is valid or not? </p>
<p>The design decision that comes to mind is that <code>Tip Calculator</code> must be able to store and retrieve some data. In this case, the data we’re interested in is the service rating.</p>
<p>If we go back to the user story and review the five acceptance criteria, we will see that the expectations are that <code>Tip Calculator</code> must be able to recognize five different service ratings:</p>
<ol>
<li>Terrible</li>
<li>Poor</li>
<li>Good</li>
<li>Great</li>
<li>Excellent</li>
</ol>
<p>So the simplest way to get <code>Tip Calculator</code> to store that information would be to endow it with an array, or a list. </p>
<p>But rather than rushing in to implement that list, we should examine the expectations again, to see if there’s anything else we may have missed. And there is – not only must <code>Tip Calculator</code> be able to recognize valid service ratings, it also must be able to associate each rating with a percentage value. </p>
<p>Our analysis shows the following associations:</p>
<ol>
<li>Terrible =&gt; 0%</li>
<li>Poor =&gt; 5%</li>
<li>Good =&gt; 10%</li>
<li>Great =&gt; 15%</li>
<li>Excellent =&gt; 20%</li>
</ol>
<p>In this case, a simple array or a simple list won’t be sufficient for holding the above associations. What’s the next simplest data structure that will allow us to implement these associations? After doing a little bit of research, we figure out that <code>Hashtable</code> is probably the most fitting data structure that can cover our needs with the least amount of ceremony.</p>
<p>We now navigate to the <code>app</code> directory and rename autogenerated <code>Class1.cs</code> file to <code>TipCalculator.cs</code>. We now want to add a <code>Hashtable</code> that will hold service ratings and the associated percentage values:</p>
<pre><code class="lang-c#">System.Collections.Hashtable ratingPercentages = <span class="hljs-keyword">new</span> System.Collections.Hashtable();
</code></pre>
<p>Now is a good time to recall that TDD is focused on coupling the expectations to the application’s behaviour, not to the application’s structure. Knowing that, we need to modify our test to make <code>Tip Calculator</code> exhibit some behaviour. The test codifies some expectations with regards to how the application must behave, and the running application provides the evidence of the expected behaviour.</p>
<p>But what is the evidence of the application’s behaviour? There is no other way for us to assess and evaluate application’s behaviour other than through examining the values that the running application produces. </p>
<p>In this case, we are expecting the running application to produce values <code>true</code> or <code>false</code> (Boolean values) after we ask the application if certain value (i.e. service rating) is valid.</p>
<p>To teach the application how to behave in the expected fashion, we need to endow it with an API. In this case, we design the API as follows:</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">CheckIfRatingIsValid</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span>
</code></pre>
<p>In our test, we will modify the actual expected value to exercise the running application and collect the output value:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image001--1-.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see from the screenshot above, we have instantiated <code>TipCalculator</code> but when attempting to ask the instance to check if the supplied rating (“Terrible”) is valid, the editor is complaining that it cannot find that method.</p>
<p>Well of course, the method hasn’t been implemented yet. Now’s the time to go ahead and do it:</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">CheckIfRatingIsValid</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span> {    
  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>Now that the method is implemented, the test works; here is the complete listing:</p>
<pre><code class="lang-c#"><span class="hljs-keyword">using</span> Xunit;
<span class="hljs-keyword">using</span> app;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">tests</span> {    
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TipCalculatorTests</span> {        
    TipCalculator tipCalculator = <span class="hljs-keyword">new</span> TipCalculator();        

    [<span class="hljs-meta">Fact</span>]        
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingTerribleIsValid</span>(<span class="hljs-params"></span>)</span>{            
      <span class="hljs-keyword">var</span> expectedResponseForValidRating = <span class="hljs-literal">true</span>;            
      <span class="hljs-keyword">var</span> actualResponseForValidRating = 
      tipCalculator.CheckIfRatingIsValid(<span class="hljs-string">"Terrible"</span>);                  
      Assert.Equal(expectedResponseForValidRating, 
      actualResponseForValidRating);        
    }    
  }
}
</code></pre>
<p>We see from the above example that we’re cheating again (we have hardcoded return false; in our newly minted method). What’s the point of beating around the bush and merely creating skeletons and scaffoldings instead of rolling up our sleeves and doing actual coding? Let’s discuss this important topic.</p>
<h3 id="heading-discussion-about-our-first-design-decision">Discussion about our first design decision</h3>
<p>We’re illustrating here how to do TDD step-by-step. The funny part is that this step-by-step illustration is actually the exact way how we do TDD: step-by-step. There is no other way to do TDD than by doing it step-by-step. One step at a time.</p>
<p>How’s that different from any other way of doing software development? Don’t we also do everything step-by-step even when not following TDD methodology? Well, not really. Let me explain:</p>
<p>TDD to me feels like riding a galloping horse. We’re moving swiftly toward our goal, but we’re frequently touching the ground (the galloping horse is every now and then hitting the ground in order to bounce off and run fast). </p>
<p>In comparison, when I’m doing software development without TDD, it feels to me like I’m flying a kite. I’m making swift moves with the kite, but I never touch the ground, not even once. By the time I land the kite, the landing place may not be where I intended the kite to go (it’s very hard to control the direction of a kite if it’s flying in a strong wind).</p>
<p>With TDD, any time we make a change to the code (both the test code and the shipping application code), we run the tests and so we touch the ground. We are galloping, but at the same time we need this frequent grounding. We need to see whether we’re going in the right direction and also whether we’ve broken anything during our galloping. Our tests are the Oracle who keeps telling us if everything works as expected or if something started misbehaving.</p>
<p>Making changes to the code is a risky business. TDD provides a nice harness that is both guiding our design decisions and ensuring we don’t mess up something that we’ve already confirmed works to our expectations.</p>
<h2 id="heading-replace-hardcoded-value-with-actual-processing-logic">Replace hardcoded value with actual processing logic</h2>
<p>Let’s now replace the hardcoded value with actual running code. We first teach our <code>Tip Calculator</code> that there is a service rating called “Terrible” and that tip percentage associated with this rating is 0:</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">CheckIfRatingIsValid</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span> {      
  ratingPercentages.Add(<span class="hljs-string">"Terrible"</span>, <span class="hljs-number">0</span>);    
  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>Our <code>Tip Calculator</code> is now knowledgeable about the fact that there is a service rating labeled “Terrible” and the tip percentage associated with terrible service is 0%. Great, but we’re still returning hardcoded value <code>false</code>. Time to replace it with actual calculation:</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">CheckIfRatingIsValid</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span> {    
  ratingPercentages.Add(<span class="hljs-string">"Terrible"</span>, <span class="hljs-number">0</span>);    
  <span class="hljs-keyword">return</span> ratingPercentages.ContainsKey(rating);
}
</code></pre>
<p>Run the test again:  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-22.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Great, but the code still looks contrived. We are loading the “Terrible” value into the instance of <code>Hashtable ratingPercentages</code> and then immediately checking to see if that value exists in the <code>Hashtable</code>. Now that we have moved from the failing test (Red) to the passing test (Green), it’s time to perform the third step in the TDD loop – Refactor.</p>
<p>Refactoring is basically the activity of modifying the code structure without affecting the code behaviour. Our task here is simple: extract the code responsible for populating of the <code>Hashtable ratingPercentages</code> into a separate block of code. </p>
<p>The most natural place for this loading is in the block of code that is doing the initialization of the <code>Tip Calculator</code> – the <code>constructor</code> method. After refactoring, our shipping application source code looks like this:</p>
<pre><code class="lang-c#"><span class="hljs-keyword">using</span> System.Collections;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span> {    
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TipCalculator</span> {        
    <span class="hljs-keyword">private</span> Hashtable ratingPercentages = <span class="hljs-keyword">new</span> Hashtable();        
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">TipCalculator</span>(<span class="hljs-params"></span>)</span> {            
      ratingPercentages.Add(<span class="hljs-string">"Terrible"</span>, <span class="hljs-number">0</span>);        
    }        

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">CheckIfRatingIsValid</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span> {            
      <span class="hljs-keyword">return</span> ratingPercentages.ContainsKey(rating);        
    }    
  }
}
</code></pre>
<p>Run the test again, and it passes (we’re in green). We have modified the structure of the code without modifying its behaviour! Good job.</p>
<h2 id="heading-flip-the-coin">Flip the coin</h2>
<p>Any time we satisfy a positive expectation, it is a prudent practice to turn things on their head and describe the negative expectation. </p>
<p>At this point, since we’ve satisfied that a legitimate service rating value is found in the <code>Tip Calculator</code>, we want to ensure that non-legitimate values are not found in the <code>Tip Calculator</code>. </p>
<p>What do we mean by non-legitimate values? Any value other than “Terrible”, “Poor”, “Good”, “Great” and “Excellent”. Time to write the new expectation (i.e. test):</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingWhateverIsValid</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> expectedResponseForValidRating = <span class="hljs-literal">true</span>;    
  <span class="hljs-keyword">var</span> actualResponseForValidRating =                        
  tipCalculator.CheckIfRatingIsValid(<span class="hljs-string">"Whatever"</span>);
  Assert.Equal(expectedResponseForValidRating, 
  actualResponseForValidRating);
}
</code></pre>
<p>Run the tests:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-23.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Fails. As expected. (We specified that our expectation when supplying the service rating as “Whatever” should be <code>true</code>. In reality, it is <code>false</code>, because our <code>Tip Calculator</code> does not contain value “Whatever”.)</p>
<p>Fix the test (change the <code>expectedResponseForValidRating</code> from <code>true</code> to <code>false</code>) and run it again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-24.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>A moment of reflection: why did we fake the first test run and made it fail? Because we always want to make sure we observe our new test failing. That way, we’ll know that in the future any successful passing of the test is not merely a false positive.</p>
<h2 id="heading-in-praise-of-steady-state">In praise of steady state</h2>
<p>Software engineering is a balancing act between steady state and periods of unstable state. What do we mean by steady state? </p>
<p>If we have a system (a running application) that behaves the way we expect it to behave (i.e. it produces values we have specified as expected values), we declare that the system is in a steady state. It is running, and delivering some value. </p>
<p>That value delivery is still partial. In our case, the only value to the users this <code>Tip Calculator</code> delivers is its ability to recognize service rating “Terrible” as a legitimate rating. In addition, it is capable of informing us that service rating “Whatever” is not a legitimate rating.</p>
<p>That’s not much, but still is better than nothing. And good news – our running application is currently in a steady state. Now we want to look into how to add more valuable behaviour to our <code>Tip Calculator</code>. And the only way to add more value is by making some changes.</p>
<p>Any time we make a change to our application, we disturb its steady state. This disturbance is risky. It may mean our changes could break something that is already working. Because of that concern, we strive to make the duration of this unstable state as short as possible. </p>
<p>Remember how we compared TDD to riding a galloping horse? When the horse is in flight (i.e. not touching the ground) it is advancing toward our goal, but it’s not in the steady state. Only when the horse touches the ground does its state stabilize.</p>
<p>TDD encourages making small changes (in flight) and immediately grounding the system by verifying that it is back in the steady state. We value steady state despite the fact that we eagerly embrace changes. Without changes, we won’t be able to deliver value, but we must do it in a very deliberate, careful fashion. </p>
<p>When doing TDD, we treat changes to steady state like walking on eggshells. No matter how sure we may be in knowing what and how we’re doing software engineering, it is prudent to still let failing tests guide our decisions.</p>
<h2 id="heading-check-if-correct-tip-percentage-is-associated-with-service-rating">Check if correct tip percentage is associated with service rating</h2>
<p>Let’s now introduce another change into our application – a test to verify if correct tip percentage is associated with service rating “Terrible”. Remember that we populated the instance of <code>Hashtable ratingPercentages</code> with the following values:</p>
<pre><code class="lang-c#">ratingPercentages.Add(<span class="hljs-string">"Terrible"</span>, <span class="hljs-number">0</span>);
</code></pre>
<p>We have written a test that verifies that our <code>Hashtable ratingPercentages</code> does contain legitimate service rating “Terrible”. Now we need a test that verifies that service rating “Terrible” means that the tip percentage for that rating is 0.</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingTerribleHasZeroPercentTip</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> expectedZeroPercentForTerribleRating = <span class="hljs-number">0</span>;    
  <span class="hljs-keyword">var</span> actualZeroPercentForTerribleRating = <span class="hljs-number">10</span>;    
  Assert.Equal(expectedZeroPercentForTerribleRating, 
  actualZeroPercentForTerribleRating);
}
</code></pre>
<p>The new test <code>CheckIfRatingTerribleHasZeroPercentTip</code> should fail:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-25.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Again, we’re purposefully hard coding wrong actual values just so that we could observe our brand new test fail. Now we must replace hard coded value with the actual call to the <code>Tip Calculator</code>’s method that returns tip percentage for the service rating:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingTerribleHasZeroPercentTip</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> expectedZeroPercentForTerribleRating = <span class="hljs-number">0</span>;    
  <span class="hljs-keyword">var</span> actualZeroPercentForTerribleRating =                 
  tipCalculator.GetPercentageTipForRating(<span class="hljs-string">"Terrible"</span>);
  Assert.Equal(expectedZeroPercentForTerribleRating, 
  actualZeroPercentForTerribleRating);
}
</code></pre>
<p>As in the previous case, we have invented a new API for <code>Tip Calculator</code>. We call this new capability <code>GetPercentageTipForRating("Terrible")</code>. It takes the value of the service rating and returns the tip percentage for that rating.</p>
<p>Flip over to the <code>app/TipCalculator.cs</code> and add the hard coded skeleton of the new method:</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">GetPercentageTipForRating</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span> {    
  <span class="hljs-keyword">return</span> <span class="hljs-number">10</span>;
}
</code></pre>
<p>Running the test fails again, because we have hard coded the return value. Let’s replace it with actual processing:</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">GetPercentageTipForRating</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span> {    
  <span class="hljs-keyword">int</span> tipPercentage = Int32.Parse(ratingPercentages[rating].ToString());
  <span class="hljs-keyword">return</span> tipPercentage;
}
</code></pre>
<p>Run the test again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-26.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>All three tests pass – we’re in green, we’re back to steady state!</p>
<h2 id="heading-what-tip-percentage-do-we-expect-for-non-legitimate-service-ratings">What tip percentage do we expect for non-legitimate service ratings?</h2>
<p>Many years of experience in the field taught me to be a bit pessimistic. Now that we have our application back in the steady state and delivering value (answering questions about legitimate service ratings and also giving us correct tip percentage for the “Terrible” rating), we need to see what happens when we run our application by giving it non-legitimate service rating value (for example, by giving it service rating “Whatever”).</p>
<p>Time for leaving the steady state yet again. We will write another test:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingWhateverHasNegativeOnePercentTip</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> expectedZeroPercentForWhateverRating = <span class="hljs-number">-1</span>;    
  <span class="hljs-keyword">var</span> actualZeroPercentForWhateverRating =       
  tipCalculator.GetPercentageTipForRating(<span class="hljs-string">"Whatever"</span>);
  Assert.Equal(expectedZeroPercentForWhateverRating, 
  actualZeroPercentForWhateverRating);
}
</code></pre>
<p>We are describing our expectation when <code>Tip Calculator</code> is asked to return tip percentage for service rating “Whatever”. Because service rating “Whatever” is a non-legitimate rating, we are expecting <code>Tip Calculator</code> to return tip percentage of value -1.</p>
<p>This test now precipitates one improvement to our shipping code. We need to add some logic to first check whether the supplied service rating is legitimate or not. Only if it is legitimate do we ask <code>Hashtable ratingPercentages</code> to tell us what the associated value of the tip percentage is. If the supplied service rating is non-legitimate (for example, if it is “Whatever”) we bypass talking to <code>Hashtable ratingPercentages</code> and simply return -1.</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">GetPercentageTipForRating</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> rating</span>)</span> {    
  <span class="hljs-keyword">int</span> tipPercentage = <span class="hljs-number">-1</span>;    
  <span class="hljs-keyword">if</span>(CheckIfRatingIsValid(rating)) {        
    tipPercentage = Int32.Parse(ratingPercentages[rating].ToString());    
  }    
  <span class="hljs-keyword">return</span> tipPercentage;
}
</code></pre>
<p>Run the tests, and all 4 tests pass:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-27.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We are back to the steady state. Another short excursion into the volatile area, and another swift victory and a safe return to steady, imperturbable state.</p>
<h2 id="heading-populate-other-service-rating-tip-percentages">Populate other service rating tip percentages</h2>
<p>Now is a good time to take a breather and make less risky changes, following the already established pattern. Leave the safety of the steady state and make short trips into the volatile territory by adding a new test to verify if service rating “Poor” is a valid, legitimate rating:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingPoorIsValid</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> expectedResponseForValidRating = <span class="hljs-literal">true</span>;    
  <span class="hljs-keyword">var</span> actualResponseForValidRating =       
  tipCalculator.CheckIfRatingIsValid(<span class="hljs-string">"Poor"</span>);
  Assert.Equal(expectedResponseForValidRating, 
  actualResponseForValidRating);
}
</code></pre>
<p>Running this test will fail:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Service rating “Poor” hasn’t been implemented yet. To make the test pass, implement service rating “Poor” by adding this line to the <code>TipCalculator</code> constructor:</p>
<pre><code class="lang-c#">ratingPercentages.Add(<span class="hljs-string">"Poor"</span>, <span class="hljs-number">5</span>);
</code></pre>
<p>Run the tests, and we’re back to safety:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We’re enjoying steady state with 6 tests successfully passing.</p>
<p>Now that we have added service rating “Poor” associated with the 5% tip, let’s write a test that will describe that expectation:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckIfRatingPoorHasFivePercentTip</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> expectedZeroPercentForPoorRating = <span class="hljs-number">5</span>;    
  <span class="hljs-keyword">var</span> actualZeroPercentForPoorRating =       
  tipCalculator.GetPercentageTipForRating(<span class="hljs-string">"Poor"</span>);
  Assert.Equal(expectedZeroPercentForPoorRating, 
  actualZeroPercentForPoorRating);
}
</code></pre>
<p>The tests run successfully, and we’re back to being safe in the steady state.<br>I will leave it to the reader to make the changes that will drive the implementation of the service ratings “Good”, “Great” and “Excellent”. At the end of the exercise you should have your system back in the steady state with 12 tests successfully passing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-35.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-calculate-grand-total-given-the-total-and-the-service-rating">Calculate grand total given the total and the service rating</h2>
<p>We are now ready for the final step – given the total bill and the service rating, we expect <code>Tip Calculator</code> to calculate tip percentage and add it to the total, producing the grand total to be paid to the restaurant.</p>
<p>As we always do, first we describe the expectation:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CalculateTotalWithTip</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> expectedTotalWithTip = <span class="hljs-number">135.7</span>;    
  <span class="hljs-keyword">var</span> actualTotalWithTip = <span class="hljs-number">200.0</span>;    
  Assert.Equal(expectedTotalWithTip, actualTotalWithTip);
}
</code></pre>
<p>As usual, we first hard code some expectations that we know are going to fail. This is so that we observe our new test failing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-36.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Time to implement processing logic that will calculate correct total with tip. Given the total of $118.0, and the service rating “Great” (15% tip), we’re expecting the total to be $135.7:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CalculateTotalWithTip</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> rating = <span class="hljs-string">"Great"</span>;    
  <span class="hljs-keyword">var</span> total = <span class="hljs-number">118</span>;    
  <span class="hljs-keyword">var</span> expectedTotalWithTip = <span class="hljs-number">135.7</span>;    
  <span class="hljs-keyword">var</span> actualTotalWithTip = tipCalculator.CalculateTotalWithTip(total, 
  rating);    
  Assert.Equal(expectedTotalWithTip, actualTotalWithTip);
}
</code></pre>
<p>We have designed a new API the <code>Tip Calculator</code> – a method called <code>CalculateTotalWithTip(total, rating)</code>. It takes the total value and the service rating and returns the total with tip. The implementation of the method looks like this:</p>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">CalculateTotalWithTip</span>(<span class="hljs-params"><span class="hljs-keyword">double</span> total, <span class="hljs-keyword">string</span> rating</span>)</span> {    
  <span class="hljs-keyword">double</span> totalWithTip = <span class="hljs-number">-1</span>;    
  <span class="hljs-keyword">if</span>(CheckIfRatingIsValid(rating)) {        
    <span class="hljs-keyword">int</span> percentage = GetPercentageTipForRating(rating);        
    totalWithTip = total + ((total/<span class="hljs-number">100</span>) * percentage);    
  }    
  <span class="hljs-keyword">return</span> totalWithTip;
}
</code></pre>
<p>Run the tests, and we’re back to steady state:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-37.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-are-we-done-here">Are we done here?</h2>
<p>No, not yet. Even when all tests are in green and we’re back to the steady state, there are still a couple of things we need to do. </p>
<p>To begin with, we need to add a pessimistic expectation for our <code>Tip Calculator</code> calculation of total with the tip based on the service rating:</p>
<pre><code class="lang-c#">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CalculateTotalWithTipForNonlegitimateRating</span>(<span class="hljs-params"></span>)</span> {    
  <span class="hljs-keyword">var</span> rating = <span class="hljs-string">"Meh"</span>;    
  <span class="hljs-keyword">var</span> total = <span class="hljs-number">118</span>;    
  <span class="hljs-keyword">var</span> expectedTotalWithTip = <span class="hljs-number">135.7</span>;    
  <span class="hljs-keyword">var</span> actualTotalWithTip = tipCalculator.CalculateTotalWithTip(total, 
  rating);    
  Assert.Equal(expectedTotalWithTip, actualTotalWithTip);
}
</code></pre>
<p>Running the tests produces one failing test:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-38.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Our expectation for non-legitimate service rating (“Meh”) was incorrect. The actual total is -1, so we need to adjust our expectation by replacing 135.7 with -1. Run the tests again, and we’re back to the steady state!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-39.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We now have 14 tests, they all successfully pass, and our <em>Tip Calculator</em> works according to our expectations and satisfies the acceptance criteria.</p>
<p>We’re almost done. One more sanity check before we can confidently ship our shiny new <code>Tip Calculator</code> – we must run <em><a target="_blank" href="https://opensource.com/article/19/9/mutation-testing-example-definition">mutation testing</a></em>. </p>
<p>Our mutation testing framework will mutate the shipping code, one line at a time, and will run all tests for each individual mutation. </p>
<p>If the tests complain about the mutated code, all is good, we have killed the mutant. If the tests don’t complain, we’re in trouble. We have a surviving mutant in our codebase, which means there are lines of code in our repo that are doing something for which we haven’t provided any expectations.</p>
<p>Let’s run mutation testing to see how solid our solution is. Good news – our solution has killed 100% of mutants!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-40.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Mutation testing has given our shipping application a clean bill of health. Our <code>Tip Calculator</code> seems to be in good shape.</p>
<h2 id="heading-red-green-refactor-reflect">Red-Green-Refactor-Reflect</h2>
<p>Let’s review our <code>Tip Calculator</code> building exercise. We started the process by describing our expectations using the classical user story format. User story (as the name implies) is focused on describing scenarios that fulfill end user’s goals. </p>
<p>In this case, the simple goal is to calculate the tip amount from the supplied service rating and the restaurant bill total. The calculated tip amount is then automatically added to the total.</p>
<p>From there we proceeded to build our shipping application by following the TDD methodology. As we’ve demonstrated, the methodology consists of writing a failing test, observing it fail (the Red phase of TDD), then immediately making code changes that ensure the test passes (the Green phase of TDD). Once the test passes, we move into the Refactor phase (we restructure the code without affecting its behaviour). That way, we make sure our code is not expensive to change.</p>
<p>A proper TDD practice also mandates frequent retrospective – we call it reflection. We stop and think about the things we’ve accomplished thus far, to see if we could learn from our recent experiences. This reflection fortifies the process, as it relies on frequent and tight feedback provided by the failing, then succeeding tests.</p>
<p>I have already compared Test Driven Development to the experience of riding a galloping horse. While riding a horse, we’re alternating between flying through the air (i.e. speed achieved when the horse leaps from the ground) and steering the horse. It is impossible to steer the horse while we’re off the ground, up in the air. At that point, we gain speed, but we cannot make any changes of the direction. It is only once the horse touches the ground that we can make a change in direction.</p>
<p>In TDD, we strive to touch the ground as frequently as possible. The longer the leaps we make without touching the ground, the less chance we have for correcting the course.</p>
<p>I also compared software development practices that don’t follow TDD principles to the experience of flying a kite. When flying a kite, we never touch the ground. It is an exhilarating feeling of letting the wind pick the kite up and bounce it up in the air. We can achieve considerable speed that way. But we struggle in such situations to maintain desired course. And after we eventually land the kite, it usually does not land in the spot we originally wanted it to land.</p>
<p>Why is the emphasis of this article on “don’t write tests first”? Many software engineers who are not familiar with agile practices as implemented in TDD usually either claim that writing automated tests isn’t necessary, or claim that automated tests should be written after the code is complete. </p>
<p>Once they start learning about agile and TDD, they may reconsider their practices and decide that writing tests before writing implementation code may make more sense. Still, because of the ingrained waterfall mentality, some of those engineers make the mistake of writing all tests first, and only then move into writing the code.</p>
<p>That approach is completely wrong. It is equivalent to the traditional waterfall approach where we go through the development process by respecting gated phases. </p>
<p>First we write the requirements (in this case, requirements would be expectations written in the form of automated tests). Only once all the requirements (i.e. automated tests) have been written, signed off and frozen, do we move into the next gated phase – write the code for the shipping application.</p>
<p>TDD is the exact opposite of the “write tests first” approach. In TDD, we always write only one test. That test describes a desired behaviour. The desired behaviour does not exist yet (that’s why it is desired), and the test fails. </p>
<p>We then immediately move into making changes to the code in the attempt to create the desired behaviour. Once desired behaviour is created, it gets validated by the test, and if the expectations of the test are satisfied, we move into refactoring the code (to satisfy nonfunctional requirements, such as cost of change).</p>
<p>We practice a rigorous discipline to never succumb to the temptation to write more than one test at a time. That way, we ensure that we keep touching the ground as frequently as possible. </p>
<p>We prefer to remain ‘in flight’ for the shortest possible time. We are ‘in flight’ during that period when the desired behaviour described in the test has not materialized yet. The smaller the expected and desired behaviour is, the shorter will be our ‘in flight’ trajectory. That way, we keep touching the ground often, which gives us a chance to adjust the steering.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building a simple <code>Tip Calculator</code> is a toy sized problem, and using that exercise to illustrate TDD methodology is not necessarily providing a convincing argument in favour of TDD. Still, within the constraints of a technical article, going over this hands-on exercise may provide valuable insights into the benefits of adopting TDD.</p>
<p>We would still argue that the real benefits of TDD only become apparent when dealing with much larger, more complex software engineering efforts. The ability to remain grounded while making potentially risky changes to a large, complex system is often a life saver. </p>
<p>In addition to that, building software using TDD methodology results in much less rework. TDD drives high degree of modularization, which results in high cohesiveness of the modules and low coupling between the modules. </p>
<p>All these characteristics produce a shipping application whose codebase is easy and inexpensive to change. And lowering the cost of change has proven to be the best way on the path to embracing changes and abandoning the concept known as ‘scope creep’. </p>
<p>Bottom line, TDD enables software engineering teams to deliver high degree of flexibility to the business.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Software Quality Assurance Guide ]]>
                </title>
                <description>
                    <![CDATA[ Quality Assurance Quality Assurance (commonly known as QA) is the means by which a product in development is checked to make sure it works as it’s supposed to. The actual methods used in QA processes vary hugely depending on the size and nature of th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/software-quality-assurance-guide/</link>
                <guid isPermaLink="false">66c35f21c337fbd10a4b5968</guid>
                
                    <category>
                        <![CDATA[ QA ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ toothbrush ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 01 Mar 2020 19:48:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9c58740569d1a4ca3194.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-quality-assurance"><strong>Quality Assurance</strong></h2>
<p>Quality Assurance (commonly known as QA) is the means by which a product in development is checked to make sure it works as it’s supposed to. The actual methods used in QA processes vary hugely depending on the size and nature of the product.</p>
<p>For a personal project you will probably just test as you go, asking others to provide feedback at appropriate stages. By contrast, a banking application must have every aspect of every feature exhaustively checked and documented to ensure it is both functional and safe.</p>
<p>Regardless of how formal or detailed a QA process is, its aim is to identify bugs so they can be resolved before the product is released.</p>
<h2 id="heading-methodologies">Methodologies</h2>
<h3 id="heading-agile">Agile</h3>
<p>In an Agile approach to development, the aim is that each cycle of work (‘sprint’) produces working software that can be added to and improved upon iteratively. This makes the QA processes an intrinsic part of the development cycle. </p>
<p>By testing software components at each stage of their production you reduce the risk of bugs being present at release.</p>
<h2 id="heading-terminology">Terminology</h2>
<h3 id="heading-automation-testing">Automation Testing</h3>
<p>Testing done with pre-written scripts designed to control the execution of tests.</p>
<h3 id="heading-black-box">Black Box</h3>
<p>These test do not look inside the system under test, but treat it as ‘closed’ in the same way that the end user will experience it.</p>
<h3 id="heading-defect">Defect</h3>
<p>Any deviation from an application’s specifications; often referred to as a “bug”.</p>
<h3 id="heading-exploratory-testing">Exploratory Testing</h3>
<p>An unscripted approach to testing, which relies on the tester’s unique creativity in an effort to find unknown bugs and identify regressions.</p>
<h3 id="heading-integration-testing">Integration Testing</h3>
<p>Testing individual components/modules together to ensure they connect and interact well with one another.</p>
<h3 id="heading-negative-path-testing">Negative Path Testing</h3>
<p>A testing scenario designed to produce an error state in a feature/application and verify that the error is handled gracefully. An example of this is inputing a series of numbers in the email field in a user registration form and checking to make sure the registration is not accepted until an actual email address is provided.</p>
<h3 id="heading-regression-testing">Regression Testing</h3>
<p>Testing done on a new build to ensure that new functionality has not unintentionally broken previously tested functionality.</p>
<h3 id="heading-smoke-tests">Smoke Tests</h3>
<p>A minimalistic approach to testing intended to ensure basic functionality is working before more in-depth testing takes place. Typically occurs at the beginning of the testing process.</p>
<h3 id="heading-test-case">Test Case</h3>
<p>Specified preconditions, steps, and expected results referred to by a QA tester/engineer to determine whether or not a feature performs its task as expected.</p>
<h3 id="heading-white-box">White Box</h3>
<p>Refers to tests performed at a structural level, within the codebase. Programmers checking that the inputs to and outputs from specific functions or components would be white box testing.</p>
<p>Also known as ‘Glass Box’, ‘Clear Box’, ‘Transparent Box’ because the tester can ‘see inside’ the system under test.</p>
<p>Main categories are</p>
<ul>
<li><strong>Unit tests</strong> (individual units of code do what they should)</li>
<li><strong>Integration tests</strong> (units/components interact with each other properly)</li>
<li><strong>Regression tests</strong> (re-applying tests at later stages of development to ensure they still work)</li>
</ul>
<p>There are three main techniques:</p>
<ul>
<li><strong>Equivalence partitioning</strong> (the tested input values are representative of larger input datasets)</li>
<li><strong>Boundary Value Analysis</strong> (the system is tested with chosen inputs where behaviour and therefore output should change)</li>
<li><strong>Cause-Effect Graphing</strong> (tests are designed from a visualization of the input-output relations)</li>
</ul>
<h3 id="heading-other-resources"><strong>Other Resources</strong></h3>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-write-qa-documentation-that-will-work/">How to write QA documentation that actually works</a></li>
<li><a target="_blank" href="https://guide.freecodecamp.org/agile/test-driven-development">Test Driven Development</a></li>
<li><a target="_blank" href="https://guide.freecodecamp.org/software-engineering/unit-tests/">Unit tests</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Test-driven development might seem like twice the work — but you should do it anyway ]]>
                </title>
                <description>
                    <![CDATA[ By Navdeep Singh Isn’t Test Driven Development (TDD) twice the work? Should you do it anyway? The short answer to the first question is NO. On the surface, it may seem like without TDD, time is only required to create the feature. With TDD, you need ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/isnt-tdd-test-driven-development-twice-the-work-why-should-you-care-4ddcabeb3df9/</link>
                <guid isPermaLink="false">66c3589271e87702d4e5b6ea</guid>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 17 Aug 2017 11:25:44 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*C1mf126YNJHmaaMUbaYYyQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Navdeep Singh</p>
<p>Isn’t Test Driven Development (TDD) twice the work? Should you do it anyway?</p>
<p>The short answer to the first question is <strong>NO</strong>. On the surface, it may seem like without TDD, time is only required to create the feature. With TDD, you need time to create the test AND create the feature, thus doubling the development time required.</p>
<p>What you’re not considering is the amount of time required for QA testing and debugging when the feature isn’t performing properly.</p>
<blockquote>
<p>Case studies were conducted with three development teams at Microsoft and one at IBM that adopted TDD. The results of the case studies indicated that the pre-release defect density of the four products decreased between 40% and 90% relative to similar projects that did not use the TDD practice.</p>
<p>Subjectively, the teams experienced a 15–35% increase in initial development time after adopting TDD. (<a target="_blank" href="https://www.microsoft.com/en-us/research/wp-content/uploads/2009/10/Realizing-Quality-Improvement-Through-Test-Driven-Development-Results-and-Experiences-of-Four-Industrial-Teams-nagappan_tdd.pdf">source</a>)</p>
</blockquote>
<p>That 40–90% decrease in pre-release defects means that QA teams and customers weren’t finding and reporting those issues. Engineering wasn’t trying to recreate bugs and develop patches, all of which have associated costs.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/rsCNd3MzBvEUjx9bQ-QYiXjG1vaZ4V35yZCr" alt="Image" width="522" height="269" loading="lazy">
<em>Number of Iterations per task</em></p>
<p>When discussing TDD, we consider a task to be a subset of a requirement that can be implemented in a few days or less. TDD software engineers develop production code through rapid iterations, as shown in the figure above.</p>
<h3 id="heading-what-is-tdd">What Is TDD?</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JWJWnEz2BCL7beWEwIlBRSKv4Qretm6OXGtn" alt="Image" width="489" height="511" loading="lazy"></p>
<p>Test-Driven Development is an approach to writing software in which the developer uses specifications to shape the way they implement a feature. For short, we describe it as the “red-green-refactor cycle”.</p>
<p>Before writing any code that adds new functionality to an application, the developer first writes an automated test describing how the new code should behave, and watches it turn red (fail to pass). They then write the code to the specification, and the test turns green (it passes). Finally, the developer takes a little time to make sure that the code just written is as clean as possible (refactoring).</p>
<h3 id="heading-why-you-should-care-about-tdd">Why you should care about TDD</h3>
<p>Automated testing gives your software developers the confidence to make changes to the software and to know that no bugs were created as a byproduct.</p>
<p>Additionally, it allows more agility for developers who aren’t familiar with the details of the software to confidently modify the source code without introducing errors.</p>
<p>Let’s discuss some really cool advantages of TDD.</p>
<h4 id="heading-1-tdd-helps-you-prevent-bugs">1. TDD Helps You Prevent Bugs</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FOKSPU5-luiwfkdcFbOqWqRWYBhJyD3TwncA" alt="Image" width="638" height="479" loading="lazy"></p>
<p>First, test suites ensure comprehensive test coverage of the codebase, so bugs are less likely to pop up unnoticed. Second, test suites allow developers to work out potential issues before the application is ready to go into production. Finally, because test suites are constantly maintained, they guarantee software quality.</p>
<h4 id="heading-2-self-explanatory-code-well-documented">2. Self Explanatory code (well-documented)</h4>
<p>Because refactoring code is a built-in step in TDD, you end up with a much cleaner codebase as you go. Apps built with TDD tend to have less duplication, fewer edge cases that aren’t thought through, and a better overall architecture.</p>
<p>The test serves as a specification for what the code that will be written should <strong>do</strong>. As long as you’re writing good stories, your development team should be able to build exactly what you asked for. If your team agrees to use <a target="_blank" href="https://en.wikipedia.org/wiki/Test-driven_development#TDD_and_ATDD">Acceptance Test-Driven Development</a>, you can even write tests that describe how you want it to work in plain English!</p>
<h4 id="heading-3-avoid-the-bugger-debugger-problem">3. Avoid the bugger debugger problem</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/VFYfcFvkkNINz-pUynhdPkrrXDXYwt6SKECJ" alt="Image" width="800" height="470" loading="lazy"></p>
<p>Typically, when talking tech about software development, there are two main types of testing that can be integrated: functional and non-functional. These two types of testing practices are further divided into numerous types of testing techniques as you can see here:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/U4QtKTWFv4bTw1VsmXZTSIfgG2xPwz7gBLTx" alt="Image" width="580" height="341" loading="lazy">
<em>And the list goes on</em></p>
<p>It becomes really important to strategize the testing plan before project commencement, since that helps in clearly defining the roles and responsibilities of developers with respect to testers when it comes to testing.</p>
<p>For example:</p>
<ul>
<li>Unit and Integration tests to be performed by developers before handing out builds to testers</li>
<li>User acceptance testing to be performed by the testers</li>
<li>Performance testing and UI testing should be done by both</li>
</ul>
<p>A brief description of a few very important testing methodologies from the diagram above, that should be included in almost every test plan, are covered below.</p>
<p><strong>Unit Testing</strong> involves testing individual units of source code to determine if they are fit for use. Intuitively, one can view a unit as the smallest testable part of an application. <a target="_blank" href="https://www.martinfowler.com/articles/mocksArentStubs.html"><strong>Faking, Mocking, and Stubbing</strong></a> <strong>are indispensable while writing unit tests for code which has API interactions<em>.</em></strong></p>
<p><strong>Integration testing</strong> involves a combination of two or more “units” being tested. Integration tests verify that the components of the software all work together or “integrate” appropriately.</p>
<p><strong>Performance testing</strong> is used to ensure that software applications will perform well under their expected workload. The features and functionality supported by a software system are not the only concerns. A software application’s performance, like its <strong>response time, reliability, resource usage,</strong> and <strong>scalability</strong>, matters<strong>.</strong> The goal of performance testing is not to find bugs, but to eliminate performance bottlenecks.</p>
<h4 id="heading-4-you-can-forecast-troubles">4. You can forecast troubles</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/KGS6NPx9YOIVplTrknkvNnydeZpmVo9pdtPZ" alt="Image" width="300" height="294" loading="lazy">
<em>A solid TDD approach alarms you about troubles upfront</em></p>
<p>The benefit of a comprehensive test suite is that it alerts you to changes early. For example, if your checkout flow stops charging users’ credit cards, you’ll know it right away, because the tests will fail. It also means that if someone makes a mistake and something doesn’t work the way it was supposed to, it will be obvious.</p>
<p>This is good, because it will give you a chance to fix it before it goes to production. If it becomes necessary down the road, you can even start a campaign of deep refactoring without fear, because you’ll have an ironclad test suite that will remain green.</p>
<h4 id="heading-5-save-money">5. Save Money</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dCY0sc49bVWFBMBR5Fk-dKyUTTjEEnwDBvMw" alt="Image" width="800" height="533" loading="lazy"></p>
<p>When code is complicated, it gets much harder to get anything done — one little change over here can result in a big problem over there. When following TDD, developers can make changes with confidence and your QA team will catch fewer regressions. In development speak, <strong>“time saved is equal to money earned.”</strong></p>
<h4 id="heading-6-invest-the-saved-time-in-innovations-and-research">6. Invest the saved time in innovations and research</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/u7Z0aFmVNsdtWOYuf2Z80vDXQKgG1DfuL83g" alt="Image" width="480" height="225" loading="lazy">
<em>Spend the saved time in innovation</em></p>
<p>If we just adopted a TDD approach, much of this money (time saved as expressed in point 5) could be spent on new innovations instead.</p>
<h4 id="heading-7-tdd-helps-you-avoid-scope-creep"><strong>7. TDD Helps You Avoid Scope Creep</strong></h4>
<p>The nightmare of any project manager is scope creep — any unexpected growth in the scope of work which leads to delays in project delivery.</p>
<p>Scope creep can happen for various reasons: poorly defined tasks, misinterpretation of project requirements, lack of documentation, and so on. There are many methods aimed at mitigating scope creep, and TDD is one of them.</p>
<p>Thanks for reading! Please share it if you found it useful :)</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
