<?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[ unit testing - 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[ unit testing - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 14 May 2026 22:43:57 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/unit-testing/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Test React Applications with Vitest ]]>
                </title>
                <description>
                    <![CDATA[ Testing is one of those things that every developer knows they should do, but many put off until problems start appearing in production. If you’re building React applications with Vite, there's a testing framework that fits so naturally into your wor... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-test-react-applications-with-vitest/</link>
                <guid isPermaLink="false">698bb499f3de8b702a26aec1</guid>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vitest ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Aiyedogbon Abraham ]]>
                </dc:creator>
                <pubDate>Tue, 10 Feb 2026 22:43:37 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770763375195/82544dec-aec2-4de9-b7f8-f90349394e81.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Testing is one of those things that every developer knows they should do, but many put off until problems start appearing in production. If you’re building React applications with Vite, there's a testing framework that fits so naturally into your workflow that you might actually enjoy writing tests. That framework is Vitest.</p>
<p>In this tutorial, you’ll learn how to set up Vitest in a React project, write effective tests for your components and hooks, and understand the testing patterns that will help you build more reliable applications.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-vitest-and-why-should-you-use-it">What is Vitest and Why Should You Use It?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-vitest-in-your-react-project">How to Set Up Vitest in Your React Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-write-your-first-test">How to Write Your First Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-react-components">How to Test React Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-user-interactions">How to Test User Interactions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-custom-hooks">How to Test Custom Hooks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-mock-api-calls">How to Mock API Calls</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-for-testing-react-components">Best Practices for Testing React Components</a></p>
</li>
</ul>
<h2 id="heading-what-is-vitest-and-why-should-you-use-it">What is Vitest and Why Should You Use It?</h2>
<p>Vitest is a testing framework built on top of Vite. It uses Vite’s development server and plugin pipeline to transform and load files during testing. This means your tests use the same configuration and plugins as your app (for example, the React plugin, TypeScript support,and so on), so you don’t need a separate build or compile step.</p>
<p>Vitest runs tests in parallel across worker threads for maximum speed, and it automatically enables an instant “watch” mode (similar to Vite’s HMR) that reruns only the tests related to changed files. Vitest also has first-class support for modern JavaScript out of the box: it handles ESM, TypeScript, and JSX natively via Vite’s transformer (powered by Oxc).</p>
<p>Because Vitest provides a Jest-compatible API, you can continue to use familiar testing libraries (for example, React Testing Library, jest-dom matchers, user-event, and so on) without extra setup.</p>
<p>In short, Vitest tightly integrates with your Vite-powered stack (or can even run standalone) and lets you plug in existing testing tools seamlessly.</p>
<p>Here is why Vitest has become popular in the React ecosystem:</p>
<ul>
<li><p><strong>Speed</strong>: Vitest can run tests more than four times faster than Jest in many scenarios. This speed comes from Vite's fast Hot Module Replacement and efficient caching capabilities.</p>
</li>
<li><p><strong>Zero configuration</strong>: Unlike Jest, which required Babel integration, TSJest setup, and multiple dependencies, Vitest works out of the box. It reuses your existing Vite configuration, eliminating the need to configure a separate test pipeline.</p>
</li>
<li><p><strong>Native TypeScript support</strong>: Vitest handles TypeScript and JSX natively through ESBuild, with no additional configuration needed.</p>
</li>
<li><p><strong>Modern JavaScript</strong>: Vitest offers native support for ES modules out of the box, making it ideal for modern JavaScript stacks.</p>
</li>
<li><p><strong>Familiar API</strong>: If you know Jest, you already know most of Vitest. The API is intentionally compatible, making migration straightforward.</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this tutorial, you should have:</p>
<ul>
<li><p>Basic knowledge of React and JavaScript</p>
</li>
<li><p>Understanding of React Hooks</p>
</li>
<li><p>Node.js installed (version 14 or higher)</p>
</li>
<li><p>A React project created with Vite (or you can create one as we go)</p>
</li>
</ul>
<h2 id="heading-how-to-set-up-vitest-in-your-react-project">How to Set Up Vitest in Your React Project</h2>
<p>Let's start by creating a new React project with Vite and setting up Vitest.</p>
<h3 id="heading-step-1-create-a-react-project-with-vite">Step 1: Create a React Project with Vite</h3>
<p>If you don't have an existing project, create one with the following command:</p>
<pre><code class="lang-bash">npm create vite@latest my-react-app -- --template react
<span class="hljs-built_in">cd</span> my-react-app
npm install
</code></pre>
<p>This creates a React project with Vite as the build tool.</p>
<h3 id="heading-step-2-install-vitest-and-testing-dependencies">Step 2: Install Vitest and Testing Dependencies</h3>
<p>Install Vitest along with the React Testing Library and other necessary dependencies:</p>
<pre><code class="lang-bash">npm install --save-dev vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom
</code></pre>
<p>Here's what each package does:</p>
<ul>
<li><p><strong>vitest</strong>: The testing framework itself</p>
</li>
<li><p><strong>@testing-library/react</strong>: Provides utilities for testing React components</p>
</li>
<li><p><strong>@testing-library/jest-dom</strong>: Adds custom matchers for DOM assertions</p>
</li>
<li><p><strong>@testing-library/user-event</strong>: Simulates user interactions</p>
</li>
<li><p><strong>jsdom</strong>: Provides a DOM environment for testing</p>
</li>
</ul>
<h3 id="heading-step-3-configure-vitest">Step 3: Configure Vitest</h3>
<p>Create a <code>vitest.config.js</code> file in your project root:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest/config'</span>;
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">plugins</span>: [react()],
  <span class="hljs-attr">test</span>: {
    <span class="hljs-attr">globals</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">environment</span>: <span class="hljs-string">'jsdom'</span>,
    <span class="hljs-attr">setupFiles</span>: <span class="hljs-string">'./src/test/setup.js'</span>,
  },
});
</code></pre>
<p>Setting <code>globals: true</code> exposes the <code>describe</code> and <code>it</code> functions on the global object, so you don't need to import them in every test file. The <code>environment: 'jsdom'</code> setting tells Vitest to use jsdom for simulating a browser environment.</p>
<h3 id="heading-step-4-create-the-test-setup-file">Step 4: Create the Test Setup File</h3>
<p>Create a file at <code>src/test/setup.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { expect, afterEach } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest'</span>;
<span class="hljs-keyword">import</span> { cleanup } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@testing-library/jest-dom'</span>;

afterEach(<span class="hljs-function">() =&gt;</span> {
  cleanup();
});
</code></pre>
<p>The <code>cleanup()</code> function runs after each test to clean up the DOM, ensuring tests don't interfere with each other.</p>
<h3 id="heading-step-5-add-test-scripts">Step 5: Add Test Scripts</h3>
<p>Add the following script to your <code>package.json</code>:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"vite"</span>,
    <span class="hljs-attr">"build"</span>: <span class="hljs-string">"vite build"</span>,
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"vitest"</span>,
    <span class="hljs-attr">"test:ui"</span>: <span class="hljs-string">"vitest --ui"</span>,
    <span class="hljs-attr">"coverage"</span>: <span class="hljs-string">"vitest --coverage"</span>
  }
}
</code></pre>
<p>Now you can run tests with <code>npm test</code>.</p>
<h2 id="heading-how-to-write-your-first-test">How to Write Your First Test</h2>
<p>Let's write a simple test to make sure everything is working. Create a file called <code>sum.test.js</code> in your <code>src</code> directory:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { expect, test } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest'</span>;

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

test(<span class="hljs-string">'adds 1 + 2 to equal 3'</span>, <span class="hljs-function">() =&gt;</span> {
  expect(sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)).toBe(<span class="hljs-number">3</span>);
});
</code></pre>
<p>Run <code>npm test</code> and you should see your test pass. A test in Vitest passes if it doesn't throw an error.</p>
<h2 id="heading-how-to-test-react-components">How to Test React Components</h2>
<p>Now let's test an actual React component. We'll start with a simple component and gradually build up to more complex scenarios.</p>
<h3 id="heading-testing-a-simple-component">Testing a Simple Component</h3>
<p>Create a component called <code>Greeting.jsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Greeting</span>(<span class="hljs-params">{ name }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, {name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Welcome to our application<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now create a test file <code>Greeting.test.jsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> { Greeting } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Greeting'</span>;

describe(<span class="hljs-string">'Greeting Component'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'should render the greeting with the provided name'</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Greeting</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Alice"</span> /&gt;</span></span>);

    <span class="hljs-keyword">const</span> heading = screen.getByRole(<span class="hljs-string">'heading'</span>, { <span class="hljs-attr">level</span>: <span class="hljs-number">1</span> });
    expect(heading).toHaveTextContent(<span class="hljs-string">'Hello, Alice!'</span>);
  });

  it(<span class="hljs-string">'should render the welcome message'</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Greeting</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Bob"</span> /&gt;</span></span>);

    <span class="hljs-keyword">const</span> paragraph = screen.getByText(<span class="hljs-string">'Welcome to our application'</span>);
    expect(paragraph).toBeInTheDocument();
  });
});
</code></pre>
<p>The <code>describe</code> function groups related tests into a single describe block. Each <code>it</code> function contains one test case.</p>
<p>The <code>render</code> function from React Testing Library renders your component in a test environment. The <code>screen</code> object provides query methods to find elements in the rendered output.</p>
<h3 id="heading-understanding-query-functions">Understanding Query Functions</h3>
<p>React Testing Library provides three types of query functions: <code>get</code>, <code>query</code>, and <code>find</code>.</p>
<p><strong>getBy queries</strong>: Throw an error if the element isn't found. Use these when you expect the element to be present.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> button = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/click me/i</span> });
</code></pre>
<p><strong>queryBy queries</strong>: Return <code>null</code> if the element isn't found. Use these when you want to assert that an element doesn't exist.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> errorMessage = screen.queryByText(<span class="hljs-string">'Error'</span>);
expect(errorMessage).not.toBeInTheDocument();
</code></pre>
<p><strong>findBy queries</strong>: Return a promise and wait for the element to appear. Use these for asynchronous operations.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> loadedData = <span class="hljs-keyword">await</span> screen.findByText(<span class="hljs-string">'Data loaded'</span>);
</code></pre>
<h3 id="heading-testing-a-counter-component">Testing a Counter Component</h3>
<p>Let's test a more interactive component. Create <code>Counter.jsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params">{ initialCount = <span class="hljs-number">0</span> }</span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(initialCount);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count - 1)}&gt;Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(0)}&gt;Reset<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Create the test file <code>Counter.test.jsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> userEvent <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/user-event'</span>;
<span class="hljs-keyword">import</span> { Counter } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Counter'</span>;

describe(<span class="hljs-string">'Counter Component'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'should render with initial count of 0'</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> /&gt;</span></span>);

    expect(screen.getByText(<span class="hljs-string">'Count: 0'</span>)).toBeInTheDocument();
  });

  it(<span class="hljs-string">'should render with custom initial count'</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> <span class="hljs-attr">initialCount</span>=<span class="hljs-string">{5}</span> /&gt;</span></span>);

    expect(screen.getByText(<span class="hljs-string">'Count: 5'</span>)).toBeInTheDocument();
  });

  it(<span class="hljs-string">'should increment count when increment button is clicked'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> user = userEvent.setup();
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> /&gt;</span></span>);

    <span class="hljs-keyword">const</span> incrementButton = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/increment/i</span> });
    <span class="hljs-keyword">await</span> user.click(incrementButton);

    expect(screen.getByText(<span class="hljs-string">'Count: 1'</span>)).toBeInTheDocument();
  });

  it(<span class="hljs-string">'should decrement count when decrement button is clicked'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> user = userEvent.setup();
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> <span class="hljs-attr">initialCount</span>=<span class="hljs-string">{5}</span> /&gt;</span></span>);

    <span class="hljs-keyword">const</span> decrementButton = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/decrement/i</span> });
    <span class="hljs-keyword">await</span> user.click(decrementButton);

    expect(screen.getByText(<span class="hljs-string">'Count: 4'</span>)).toBeInTheDocument();
  });

  it(<span class="hljs-string">'should reset count to 0 when reset button is clicked'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> user = userEvent.setup();
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> <span class="hljs-attr">initialCount</span>=<span class="hljs-string">{10}</span> /&gt;</span></span>);

    <span class="hljs-keyword">const</span> resetButton = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/reset/i</span> });
    <span class="hljs-keyword">await</span> user.click(resetButton);

    expect(screen.getByText(<span class="hljs-string">'Count: 0'</span>)).toBeInTheDocument();
  });
});
</code></pre>
<p>In these Counter tests, we first use <code>render(&lt;Counter /&gt;)</code> to mount the component in a virtual DOM. We then query the output using Testing Library’s <code>screen</code> object. For example, <code>screen.getByText('Count: 0')</code> finds the element displaying the initial count of 0, and <code>expect(...).toBeInTheDocument()</code> asserts that it is present. The <code>getByText</code> query will throw an error if the text isn’t found, immediately failing the test.</p>
<p>For interactive tests, we create a <code>user</code> with <code>const user = userEvent.setup()</code> and then call <code>await user.click(...)</code> on the increment/decrement/reset buttons. The <code>userEvent.click</code> method simulates a real user click (dispatching the sequence of events a browser would fire). We locate buttons by their accessible role and name (for example, <code>getByRole('button', { name: /increment/i })</code>), following best practices for accessible queries.</p>
<p>After each click, we assert that the DOM updates accordingly (for example, the count text changes to “Count: 1”). Using <code>async/await</code> with <code>user.click</code> ensures the test waits for any state changes. In this way, each test checks the user-visible behavior: that clicking the Increment button increases the count, the Decrement button decreases it, and the Reset button sets it back to zero, without depending on the component’s internal implementation.</p>
<h2 id="heading-how-to-test-user-interactions">How to Test User Interactions</h2>
<p>User interactions are a critical part of testing React applications. The <code>@testing-library/user-event</code> library provides a more realistic simulation of user behaviour than simple event dispatching.</p>
<h3 id="heading-testing-form-inputs">Testing Form Inputs</h3>
<p>Create a <code>LoginForm.jsx</code> component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">LoginForm</span>(<span class="hljs-params">{ onSubmit }</span>) </span>{
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault();

    <span class="hljs-keyword">if</span> (!email || !password) {
      setError(<span class="hljs-string">'Both fields are required'</span>);
      <span class="hljs-keyword">return</span>;
    }

    setError(<span class="hljs-string">''</span>);
    onSubmit({ email, password });
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"password"</span>&gt;</span>Password<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setPassword(e.target.value)}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>{error}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Log In<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<p>Create the test file <code>LoginForm.test.jsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> userEvent <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/user-event'</span>;
<span class="hljs-keyword">import</span> { LoginForm } <span class="hljs-keyword">from</span> <span class="hljs-string">'./LoginForm'</span>;

describe(<span class="hljs-string">'LoginForm Component'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'should render email and password inputs'</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LoginForm</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{()</span> =&gt;</span> {}} /&gt;</span>);

    expect(screen.getByLabelText(<span class="hljs-regexp">/email/i</span>)).toBeInTheDocument();
    expect(screen.getByLabelText(<span class="hljs-regexp">/password/i</span>)).toBeInTheDocument();
  });

  it(<span class="hljs-string">'should update input values when user types'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> user = userEvent.setup();
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LoginForm</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{()</span> =&gt;</span> {}} /&gt;</span>);

    <span class="hljs-keyword">const</span> emailInput = screen.getByLabelText(<span class="hljs-regexp">/email/i</span>);
    <span class="hljs-keyword">const</span> passwordInput = screen.getByLabelText(<span class="hljs-regexp">/password/i</span>);

    <span class="hljs-keyword">await</span> user.type(emailInput, <span class="hljs-string">'test@example.com'</span>);
    <span class="hljs-keyword">await</span> user.type(passwordInput, <span class="hljs-string">'password123'</span>);

    expect(emailInput).toHaveValue(<span class="hljs-string">'test@example.com'</span>);
    expect(passwordInput).toHaveValue(<span class="hljs-string">'password123'</span>);
  });

  it(<span class="hljs-string">'should show error when form is submitted empty'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> user = userEvent.setup();
    <span class="hljs-keyword">const</span> mockSubmit = vi.fn();
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LoginForm</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{mockSubmit}</span> /&gt;</span></span>);

    <span class="hljs-keyword">const</span> submitButton = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/log in/i</span> });
    <span class="hljs-keyword">await</span> user.click(submitButton);

    expect(screen.getByRole(<span class="hljs-string">'alert'</span>)).toHaveTextContent(<span class="hljs-string">'Both fields are required'</span>);
    expect(mockSubmit).not.toHaveBeenCalled();
  });

  it(<span class="hljs-string">'should call onSubmit with form data when valid'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> user = userEvent.setup();
    <span class="hljs-keyword">const</span> mockSubmit = vi.fn();
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LoginForm</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{mockSubmit}</span> /&gt;</span></span>);

    <span class="hljs-keyword">await</span> user.type(screen.getByLabelText(<span class="hljs-regexp">/email/i</span>), <span class="hljs-string">'test@example.com'</span>);
    <span class="hljs-keyword">await</span> user.type(screen.getByLabelText(<span class="hljs-regexp">/password/i</span>), <span class="hljs-string">'password123'</span>);
    <span class="hljs-keyword">await</span> user.click(screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/log in/i</span> }));

    expect(mockSubmit).toHaveBeenCalledWith({
      <span class="hljs-attr">email</span>: <span class="hljs-string">'test@example.com'</span>,
      <span class="hljs-attr">password</span>: <span class="hljs-string">'password123'</span>,
    });
  });
});
</code></pre>
<p>The LoginForm tests similarly use <code>render</code> and <code>screen</code> to interact with the component. We use <code>screen.getByLabelText(/email/i)</code> and <code>screen.getByLabelText(/password/i)</code> to find the input fields by their associated labels, mimicking how users identify form fields.</p>
<p>To simulate typing, we use <code>await user.type(input, text)</code>, which sends real keyboard events to the input (via user-event). After typing, we assert the input’s value with <code>expect(input).toHaveValue(...)</code> (a custom matcher from jest-dom).</p>
<p>When submitting the form empty, clicking the <strong>Log In</strong> button triggers the form’s validation and displays an error message. We find this error by querying <code>getByRole('alert')</code> and check its text content. We also assert that the mock <code>onSubmit</code> handler was <em>not</em> called.</p>
<p>In the valid submission test, we fill both fields and click <strong>Log In</strong>; then <code>expect(mockSubmit).toHaveBeenCalledWith({...})</code> verifies the submit handler received the correct <code>{ email, password }</code> object.</p>
<p>These tests focus on user actions and outcomes: typing and clicking drive the form logic, and our assertions confirm the expected outputs (visible error text or the callback arguments).</p>
<h2 id="heading-how-to-test-custom-hooks">How to Test Custom Hooks</h2>
<p>Custom hooks encapsulate reusable logic, and they need testing just like components. React Testing Library provides a <code>renderHook</code> function specifically for this purpose.</p>
<h3 id="heading-creating-and-testing-a-custom-hook">Creating and Testing a Custom Hook</h3>
<p>Create a custom hook <code>useFetch.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useFetch</span>(<span class="hljs-params">url</span>) </span>{
  <span class="hljs-keyword">const</span> [data, setData] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fetchData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        setLoading(<span class="hljs-literal">true</span>);
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url);

        <span class="hljs-keyword">if</span> (!response.ok) {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Network response was not ok'</span>);
        }

        <span class="hljs-keyword">const</span> json = <span class="hljs-keyword">await</span> response.json();
        setData(json);
        setError(<span class="hljs-literal">null</span>);
      } <span class="hljs-keyword">catch</span> (err) {
        setError(err.message);
        setData(<span class="hljs-literal">null</span>);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    };

    fetchData();
  }, [url]);

  <span class="hljs-keyword">return</span> { data, loading, error };
}
</code></pre>
<p>Create the test file <code>useFetch.test.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { renderHook, waitFor } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> { useFetch } <span class="hljs-keyword">from</span> <span class="hljs-string">'./useFetch'</span>;

describe(<span class="hljs-string">'useFetch Hook'</span>, <span class="hljs-function">() =&gt;</span> {
  beforeEach(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">global</span>.fetch = vi.fn();
  });

  afterEach(<span class="hljs-function">() =&gt;</span> {
    vi.restoreAllMocks();
  });

  it(<span class="hljs-string">'should return loading state initially'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">global</span>.fetch.mockImplementation(<span class="hljs-function">() =&gt;</span> 
      <span class="hljs-built_in">Promise</span>.resolve({
        <span class="hljs-attr">ok</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">json</span>: <span class="hljs-keyword">async</span> () =&gt; ({ <span class="hljs-attr">data</span>: <span class="hljs-string">'test'</span> }),
      })
    );

    <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useFetch(<span class="hljs-string">'https://api.example.com/data'</span>));

    expect(result.current.loading).toBe(<span class="hljs-literal">true</span>);
    expect(result.current.data).toBe(<span class="hljs-literal">null</span>);
    expect(result.current.error).toBe(<span class="hljs-literal">null</span>);
  });

  it(<span class="hljs-string">'should return data when fetch succeeds'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> mockData = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Test Post'</span> };

    <span class="hljs-built_in">global</span>.fetch.mockImplementation(<span class="hljs-function">() =&gt;</span>
      <span class="hljs-built_in">Promise</span>.resolve({
        <span class="hljs-attr">ok</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">json</span>: <span class="hljs-keyword">async</span> () =&gt; mockData,
      })
    );

    <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useFetch(<span class="hljs-string">'https://api.example.com/posts/1'</span>));

    <span class="hljs-keyword">await</span> waitFor(<span class="hljs-function">() =&gt;</span> expect(result.current.loading).toBe(<span class="hljs-literal">false</span>));

    expect(result.current.data).toEqual(mockData);
    expect(result.current.error).toBe(<span class="hljs-literal">null</span>);
  });

  it(<span class="hljs-string">'should return error when fetch fails'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-built_in">global</span>.fetch.mockImplementation(<span class="hljs-function">() =&gt;</span>
      <span class="hljs-built_in">Promise</span>.resolve({
        <span class="hljs-attr">ok</span>: <span class="hljs-literal">false</span>,
      })
    );

    <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useFetch(<span class="hljs-string">'https://api.example.com/posts/1'</span>));

    <span class="hljs-keyword">await</span> waitFor(<span class="hljs-function">() =&gt;</span> expect(result.current.loading).toBe(<span class="hljs-literal">false</span>));

    expect(result.current.data).toBe(<span class="hljs-literal">null</span>);
    expect(result.current.error).toBe(<span class="hljs-string">'Network response was not ok'</span>);
  });
});
</code></pre>
<p>The <code>renderHook</code> function from React Testing Library renders custom hooks, and <code>waitFor</code> is used to wait for asynchronous state updates in the hook.</p>
<h2 id="heading-how-to-mock-api-calls">How to Mock API Calls</h2>
<p>When testing components that make API calls, you don't want to hit real endpoints. Mocking ensures your tests are fast, reliable, and don't depend on network conditions.</p>
<h3 id="heading-mocking-with-vitest">Mocking with Vitest</h3>
<p>Vitest doesn’t auto-mock modules like Jest does, so you need to manually mock them. Let's see how to mock an Axios call.</p>
<p>Create a <code>PostsList.jsx</code> component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PostsList</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [posts, setPosts] = useState([]);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fetchPosts = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://api.example.com/posts'</span>);
        setPosts(response.data);
      } <span class="hljs-keyword">catch</span> (err) {
        setError(err.message);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    };

    fetchPosts();
  }, []);

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Error: {error}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      {posts.map((post) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span>&gt;</span>{post.title}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
  );
}
</code></pre>
<p>Create the test file <code>PostsList.test.jsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen, waitFor } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { PostsList } <span class="hljs-keyword">from</span> <span class="hljs-string">'./PostsList'</span>;

vi.mock(<span class="hljs-string">'axios'</span>);

describe(<span class="hljs-string">'PostsList Component'</span>, <span class="hljs-function">() =&gt;</span> {
  beforeEach(<span class="hljs-function">() =&gt;</span> {
    vi.clearAllMocks();
  });

  it(<span class="hljs-string">'should display loading state initially'</span>, <span class="hljs-function">() =&gt;</span> {
    axios.get.mockImplementation(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">() =&gt;</span> {}));
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">PostsList</span> /&gt;</span></span>);

    expect(screen.getByText(<span class="hljs-string">'Loading...'</span>)).toBeInTheDocument();
  });

  it(<span class="hljs-string">'should display posts when API call succeeds'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> mockPosts = [
      { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'First Post'</span> },
      { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Second Post'</span> },
    ];

    axios.get.mockResolvedValue({ <span class="hljs-attr">data</span>: mockPosts });
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">PostsList</span> /&gt;</span></span>);

    <span class="hljs-keyword">await</span> waitFor(<span class="hljs-function">() =&gt;</span> {
      expect(screen.queryByText(<span class="hljs-string">'Loading...'</span>)).not.toBeInTheDocument();
    });

    expect(screen.getByText(<span class="hljs-string">'First Post'</span>)).toBeInTheDocument();
    expect(screen.getByText(<span class="hljs-string">'Second Post'</span>)).toBeInTheDocument();
  });

  it(<span class="hljs-string">'should display error when API call fails'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    axios.get.mockRejectedValue(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Network error'</span>));
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">PostsList</span> /&gt;</span></span>);

    <span class="hljs-keyword">await</span> waitFor(<span class="hljs-function">() =&gt;</span> {
      expect(screen.queryByText(<span class="hljs-string">'Loading...'</span>)).not.toBeInTheDocument();
    });

    expect(screen.getByText(<span class="hljs-regexp">/error/i</span>)).toBeInTheDocument();
  });
});
</code></pre>
<p>In these tests, we verify specific UI states: the “loading” test checks that a loading indicator shows while data is being fetched, the “success” test confirms that post items render when the API returns data, and the “error” test makes sure an error message appears if the call fails.</p>
<p>We mock Axios by calling <code>vi.mock('axios')</code> and then using methods like <code>mockResolvedValue(...)</code> on <code>axios.get</code> to simulate a successful response (and <code>mockRejectedValue(...)</code> to simulate a failure). This kind of mocking isolates our tests from real network calls (making them fast and reliable) and lets us control exactly what data or error the hook receives.</p>
<p>We use <code>await waitFor(...)</code> to pause the test until those asynchronous updates complete before making assertions. Finally, we use <code>screen.getByText(...)</code> to find elements that should be present (it will throw an error if they’re missing) and <code>screen.queryByText(...)</code> to check that elements aren’t present (it returns null if the element is not in the DOM).</p>
<h3 id="heading-mocking-specific-module-functions">Mocking Specific Module Functions</h3>
<p>Sometimes you only want to mock specific functions while keeping the rest of a module's behaviour intact. Here's how to do that:</p>
<pre><code class="lang-javascript">vi.mock(<span class="hljs-string">'date-fns'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> original = <span class="hljs-keyword">await</span> vi.importActual(<span class="hljs-string">'date-fns'</span>);
  <span class="hljs-keyword">return</span> {
    ...original,
    <span class="hljs-attr">format</span>: vi.fn(<span class="hljs-function">() =&gt;</span> <span class="hljs-string">'2025-01-01'</span>),
  };
});
</code></pre>
<p>In Vitest, you use <code>vi.importActual</code> to retain all original methods while mocking only the <code>format</code> method.</p>
<h2 id="heading-best-practices-for-testing-react-components">Best Practices for Testing React Components</h2>
<p>Now that you know how to write tests, let's talk about how to write good tests.</p>
<h3 id="heading-test-user-behaviour-not-implementation">Test User Behaviour, Not Implementation</h3>
<p>Focus on testing what users see and do, not internal component details. If you refactor your component's implementation without changing its behaviour, your tests shouldn't break.</p>
<p><strong>Bad test (testing implementation):</strong></p>
<pre><code class="lang-javascript">it(<span class="hljs-string">'should set isOpen state to true'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useState(<span class="hljs-literal">false</span>));
  <span class="hljs-comment">// Testing internal state directly</span>
});
</code></pre>
<p><strong>Good test (testing behaviour):</strong></p>
<pre><code class="lang-javascript">it(<span class="hljs-string">'should show menu when button is clicked'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> user = userEvent.setup();
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Menu</span> /&gt;</span></span>);

  <span class="hljs-keyword">await</span> user.click(screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/menu/i</span> }));
  expect(screen.getByRole(<span class="hljs-string">'navigation'</span>)).toBeVisible();
});
</code></pre>
<h3 id="heading-use-accessible-queries">Use Accessible Queries</h3>
<p>React Testing Library encourages you to query elements the way users do. Prefer queries that mirror user interaction:</p>
<ol>
<li><p><code>getByRole</code> (best for interactive elements)</p>
</li>
<li><p><code>getByLabelText</code> (for form fields)</p>
</li>
<li><p><code>getByPlaceholderText</code></p>
</li>
<li><p><code>getByText</code></p>
</li>
<li><p><code>getByTestId</code> (last resort)</p>
</li>
</ol>
<h3 id="heading-keep-tests-simple-and-focused">Keep Tests Simple and Focused</h3>
<p>Each test should verify one thing. If your test needs a lot of setup or has many assertions, consider splitting it into multiple tests.</p>
<h3 id="heading-clean-up-between-tests">Clean Up Between Tests</h3>
<p>Use <code>afterEach</code> to clean up the DOM after each test run, ensuring tests don't interfere with each other. This is already handled if you followed the setup steps earlier.</p>
<h3 id="heading-use-descriptive-test-names">Use Descriptive Test Names</h3>
<p>Test names should clearly describe what they're testing and what the expected outcome is.</p>
<p>Good test names:</p>
<pre><code class="lang-javascript">it(<span class="hljs-string">'should display error message when form is submitted empty'</span>);
it(<span class="hljs-string">'should call onSubmit with email and password when form is valid'</span>);
it(<span class="hljs-string">'should disable submit button while request is pending'</span>);
</code></pre>
<h3 id="heading-mock-external-dependencies">Mock External Dependencies</h3>
<p>Always mock API calls, timers, and other external dependencies. Your tests should be isolated and not depend on network conditions or external services.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now, you have learned how to set up Vitest in a React project and write effective tests for components, user interactions, custom hooks, and API calls. Vitest provides a powerful and efficient way to test React applications, especially when combined with modern tools like Vite.</p>
<p>Testing is about building confidence in your code, documenting expected behaviour, and enabling safe refactoring. Vitest's speed makes testing feel less like a chore and more like a natural part of development.</p>
<p>Start small. Add tests for critical user flows. Test the components that change frequently. As you build the habit, you will find that tests actually make development faster, not slower. The code will still be there tomorrow. But the bugs you catch today won't be.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Unit Testing in Go - A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ If you're learning Go and you’re already familiar with the idea of unit testing, the main challenge is usually not why to test, but how to test in Go. Go takes a deliberately minimal approach to testing. There are no built-in assertions, no annotatio... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/unit-testing-in-go-a-beginners-guide/</link>
                <guid isPermaLink="false">696535ad7a48c374647910f2</guid>
                
                    <category>
                        <![CDATA[ Go Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ golang ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gabor Koos ]]>
                </dc:creator>
                <pubDate>Mon, 12 Jan 2026 17:55:57 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768240528981/73c9c9f6-4942-4c39-9e62-87f540fd2233.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're learning Go and you’re already familiar with the idea of <strong>unit testing</strong>, the main challenge is usually not <em>why</em> to test, but <em>how</em> to test in Go.</p>
<p>Go takes a deliberately minimal approach to testing. There are no built-in assertions, no annotations, and no special syntax. Instead, tests are written as regular Go code using a small standard library package, and run with a single command. This can feel unusual at first if you're coming from ecosystems with richer testing frameworks, but it quickly becomes predictable and easy to reason about.</p>
<p>In this article, we'll look at how unit testing works in Go in practice. We'll write a few small tests, run them from the command line, and cover the most common patterns you'll see in real Go codebases, such as table-driven tests and testing functions that return errors. We'll focus on the essentials and won't cover more advanced topics like mocks or external frameworks.</p>
<p>The goal is to show how familiar testing concepts translate into idiomatic Go. By the end, you should feel comfortable reading and writing basic unit tests and integrating them into your regular Go workflow.</p>
<h2 id="heading-what-well-cover">What We'll Cover:</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-writing-your-first-test">Writing Your First Test</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-running-your-test">Running Your Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-divide-by-zero">Divide by Zero</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-terrorf-vs-tfatalf">t.Errorf vs t.Fatalf</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-table-driven-tests">Table-Driven Tests</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-table-driven-add-test">Table-Driven Add Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-table-driven-divide-test">Table-Driven Divide Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-exercise">Exercise</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-functions-that-return-errors">Testing Functions That Return Errors</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-safe-divide-function">Safe Divide Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-writing-tests-for-safedivide">Writing Tests for SafeDivide()</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-exercise-1">Exercise</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-and-tips">Best Practices and Tips</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-name-tests-clearly">Name Tests Clearly</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-keep-tests-small-and-focused">Keep Tests Small and Focused</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-table-driven-tests-for-repetitive-cases">Use Table-Driven Tests for Repetitive Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-check-errors-explicitly">Check Errors Explicitly</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-avoid-panics-when-possible">Avoid Panics When Possible</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-run-tests-frequently">Run Tests Frequently</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-keep-tests-in-the-same-package">Keep Tests in the Same Package</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-tfatalf-vs-terrorf-appropriately">Use t.Fatalf vs t.Errorf Appropriately</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solutions-to-exercises">Solutions to Exercises</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-subtract-function-and-tests">Subtract Function and Tests</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-safesubtract-function-and-tests">SafeSubtract Function and Tests</a></p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start, you should be comfortable with:</p>
<ul>
<li><p>Writing and running basic Go programs</p>
</li>
<li><p>Defining and calling functions in Go</p>
</li>
<li><p>Understanding basic Go types (int, string, bool, and so on)</p>
</li>
<li><p>Using the Go command-line tool (go run, go build)</p>
</li>
<li><p>Basic understanding of unit tests: what a test is and why it's useful</p>
</li>
<li><p>Familiarity with Test-Driven Development concepts like testing before or alongside writing code</p>
</li>
<li><p>Awareness of common testing ideas such as assertions, test coverage, and checking error conditions</p>
</li>
</ul>
<p>You don't need prior experience with Go's <code>testing</code> package or Go-specific test patterns, as this guide will cover all of that.</p>
<h2 id="heading-writing-your-first-test">Writing Your First Test</h2>
<p>Let's start with a simple function to test. Imagine you have a small <code>calc</code> package with an <code>Add</code> function:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-comment">// Add returns the sum of two integers</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Add</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">return</span> a + b
}
</code></pre>
<p>To test this function, create a new file named <code>calc_test.go</code> in the same package. In Go, test files must end with <code>_test.go</code> to be recognized by the testing tool.</p>
<p>Inside <code>calc_test.go</code>, you write a test function:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc_test.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-keyword">import</span> <span class="hljs-string">"testing"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestAdd</span><span class="hljs-params">(t *testing.T)</span></span> {
    got := Add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>)
    want := <span class="hljs-number">5</span>
    <span class="hljs-keyword">if</span> got != want {
        t.Errorf(<span class="hljs-string">"Add(2, 3) = %d; want %d"</span>, got, want)
    }
}
</code></pre>
<p>Here's what's happening:</p>
<ul>
<li><p>The function name starts with <code>Test</code> and takes a single <code>*testing.T</code> parameter. Go automatically discovers and runs any function that follows this convention.</p>
</li>
<li><p>The <code>t.Errorf</code> call reports a test failure. Unlike some frameworks, Go doesn't provide special assertions – you simply check a condition and call <code>t.Errorf</code> or <code>t.Fatalf</code> if it fails.</p>
</li>
<li><p>Each test is a standalone function. You can write as many as you like, and Go will run them all.</p>
</li>
</ul>
<h3 id="heading-running-your-test">Running Your Test</h3>
<p>Once the file is saved, you can run your test with:</p>
<pre><code class="lang-bash">go <span class="hljs-built_in">test</span>
</code></pre>
<p>This runs tests for the current package (files ending with <code>_test.go</code>). If you want to run tests recursively in all subdirectories of your project, use:</p>
<pre><code class="lang-bash">go <span class="hljs-built_in">test</span> ./...
</code></pre>
<p>The <code>./...</code> pattern is shorthand for "run tests in this directory and all subdirectories". This is especially useful in larger projects where your code is spread across multiple packages.</p>
<p>If everything is working, you should see output indicating that the test passed:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span>
PASS
ok      _/C_/projects/Articles/Go_Testing       0.334s
</code></pre>
<p>You can add the <code>-v</code> flag for verbose output:</p>
<pre><code class="lang-bash">go <span class="hljs-built_in">test</span> -v
</code></pre>
<p>This will show you the names of the tests as they run:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span> -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok      _/C_/projects/Articles/Go_Testing       0.356s
</code></pre>
<p>Not much difference for a single test, but it becomes useful as you add more tests.</p>
<p>Now let's see what happens if the test fails. Change the expected value in <code>calc_test.go</code> to an incorrect one:</p>
<pre><code class="lang-go">  ...
    want := <span class="hljs-number">6</span> <span class="hljs-comment">// Incorrect expected value</span>
  ...
</code></pre>
<p>Run the tests again:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span>
--- FAIL: TestAdd (0.00s)
    calc_test.go:9: Add(2, 3) = 5; want 6
FAIL
<span class="hljs-built_in">exit</span> status 1
FAIL    _/C_/projects/Articles/Go_Testing       0.340s
</code></pre>
<p>or with verbose output:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span> -v
=== RUN   TestAdd
    calc_test.go:9: Add(2, 3) = 5; want 6
--- FAIL: TestAdd (0.00s)
FAIL
<span class="hljs-built_in">exit</span> status 1
FAIL    _/C_/projects/Articles/Go_Testing       0.337s
</code></pre>
<p>Of course, your tests should always check for the correct expected values! A failing (but correct) test is a sign that your code needs to be fixed.</p>
<p>We only created one test file and one test function with one assertion here, but Go's testing tool can handle many files and functions at once. Behind the scenes, Go will automatically:</p>
<ul>
<li><p>Find <strong>all</strong> <code>_test.go</code> files in the specified packages (for example, current directory for <code>go test</code>, or recursively in all subdirectories with <code>go test ./...</code>).</p>
</li>
<li><p>Identify functions that start with <code>Test</code> and have the correct signature.</p>
</li>
<li><p>Compile them together with your package into a temporary test binary.</p>
</li>
<li><p>Execute each test function and report the results.</p>
</li>
</ul>
<p>To prove this, let's quickly add a <code>Divide</code> function to our package:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc.go</span>
...
<span class="hljs-comment">// Divide returns the result of dividing a by b</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Divide</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">return</span> a / b
}
</code></pre>
<p>(Note that this is an <strong>integer division</strong>, so fractional parts are discarded. <code>Divide(5, 2)</code> would return <code>2</code>.)</p>
<p>And another test file with a corresponding test:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc_2_test.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-keyword">import</span> <span class="hljs-string">"testing"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestDivide</span><span class="hljs-params">(t *testing.T)</span></span> {
    got := Divide(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)
    want := <span class="hljs-number">5</span>    
    <span class="hljs-keyword">if</span> got != want {
        t.Errorf(<span class="hljs-string">"Divide(10, 2) = %d; want %d"</span>, got, want)
    }    
}
</code></pre>
<p>Now when you run <code>go test</code>, both <code>TestAdd</code> and <code>TestDivide</code> will be executed:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span>
PASS
ok      _/C_/projects/Articles/Go_Testing       0.325s
</code></pre>
<p>Or:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span> -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
=== RUN   TestDivide
--- PASS: TestDivide (0.00s)
PASS
ok      _/C_/projects/Articles/Go_Testing       0.323s
</code></pre>
<h3 id="heading-divide-by-zero">Divide by Zero</h3>
<p>What happens if we try to <code>Divide</code> by zero? Let's add another test case for that:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc_test.go</span>
...
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestDivideByZero</span><span class="hljs-params">(t *testing.T)</span></span> {
    <span class="hljs-keyword">defer</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">if</span> r := <span class="hljs-built_in">recover</span>(); r == <span class="hljs-literal">nil</span> { <span class="hljs-comment">// Check if a panic occurred</span>
            t.Errorf(<span class="hljs-string">"Divide did not panic on division by zero"</span>)
        }
    }()
    Divide(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>) <span class="hljs-comment">// This should cause a panic</span>
}
</code></pre>
<p>This test checks that the <code>Divide</code> function panics when dividing by zero. When you run the tests again, you'll see that this new test also passes:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span> -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
=== RUN   TestDivide
--- PASS: TestDivide (0.00s)
=== RUN   TestDivideByZero
--- PASS: TestDivideByZero (0.00s)
PASS
ok      _/C_/projects/Articles/Go_Testing       0.312s
</code></pre>
<p>(Note that in real-world Go code, it's better to return <code>(int, error)</code> for unsafe operations instead of panicking.)</p>
<p>Feel free to experiment by adding more test cases, changing expected values, and exploring how Go's testing framework handles different scenarios.</p>
<h3 id="heading-terrorf-vs-tfatalf"><code>t.Errorf</code> vs <code>t.Fatalf</code></h3>
<p>In the examples above, we used <code>t.Errorf</code> to report test failures. This function logs the error but allows the test to continue running. This is useful when you want to check multiple conditions in a single test function.</p>
<p>In contrast, <code>t.Fatalf</code> logs the error and immediately stops the execution of the current test. Use <code>t.Fatalf</code> when continuing the test after a failure doesn't make sense or could cause misleading results.</p>
<p>For example, in the <code>TestDivideByZero</code> test, if the <code>Divide</code> function does not panic, we use <code>t.Errorf</code> to report the failure but continue to the end of the test. But if we had additional checks after the division, we might want to use <code>t.Fatalf</code> to stop execution immediately upon failure.</p>
<p>While <code>t.Errorf</code> and <code>t.Fatalf</code> use <code>fmt</code>-style formatting, for simple messages without formatting, you can also use <code>t.Error</code> and <code>t.Fatal</code>, respectively.</p>
<p>In the next section, we'll look at <em>table-driven tests</em>, a common Go pattern for testing multiple cases efficiently.</p>
<h2 id="heading-table-driven-tests">Table-Driven Tests</h2>
<p>In Go, it's common to want to run the same test logic for multiple inputs and expected outputs. Rather than writing a separate test function for each case, Go developers often use <strong>table-driven tests</strong>. This pattern keeps your tests concise, readable, and easy to extend.</p>
<h3 id="heading-table-driven-add-test">Table-Driven <code>Add</code> Test</h3>
<p>Let's rewrite our Add test using a table-driven approach (and delete <code>calc_2_test.go</code> for clarity):</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc_test.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-keyword">import</span> <span class="hljs-string">"testing"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestAddTableDriven</span><span class="hljs-params">(t *testing.T)</span></span> {
    tests := []<span class="hljs-keyword">struct</span> {<span class="hljs-comment">// Define a struct for each test case and create a slice of them</span>
        name <span class="hljs-keyword">string</span>
        a, b <span class="hljs-keyword">int</span>
        want <span class="hljs-keyword">int</span>
    }{
        {<span class="hljs-string">"both positive"</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>},
        {<span class="hljs-string">"positive + zero"</span>, <span class="hljs-number">5</span>, <span class="hljs-number">0</span>, <span class="hljs-number">5</span>},
        {<span class="hljs-string">"negative + positive"</span>, <span class="hljs-number">-1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>},
        {<span class="hljs-string">"both negative"</span>, <span class="hljs-number">-2</span>, <span class="hljs-number">-3</span>, <span class="hljs-number">-5</span>},
    }

    <span class="hljs-keyword">for</span> _, tt := <span class="hljs-keyword">range</span> tests {<span class="hljs-comment">// Loop over each test case</span>
        t.Run(tt.name, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> {<span class="hljs-comment">// Run each case as a subtest</span>
            got := Add(tt.a, tt.b)
            <span class="hljs-keyword">if</span> got != tt.want {<span class="hljs-comment">// Check the result</span>
                t.Errorf(<span class="hljs-string">"Add(%d, %d) = %d; want %d"</span>, tt.a, tt.b, got, tt.want) <span class="hljs-comment">// Report failure if it doesn't match</span>
            }
        })
    }
}
</code></pre>
<p>Here's how it works:</p>
<ul>
<li><p>We define a <strong>slice of structs</strong>, each representing a test case.</p>
</li>
<li><p>Each struct contains the test name, input values, and the expected result.</p>
</li>
<li><p>We loop over the slice and call <code>t.Run(tt.name, func(t *testing.T) { ... })</code> to run each test as a <strong>subtest</strong>.</p>
</li>
<li><p>If a subtest fails, you can see which one by its name in the output.</p>
</li>
</ul>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span>
PASS
ok      _/C_/projects/Articles/Go_Testing       0.452s
</code></pre>
<p>Or to see detailed output:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span> -v
=== RUN   TestAddTableDriven
=== RUN   TestAddTableDriven/both_positive
=== RUN   TestAddTableDriven/positive_+_zero
=== RUN   TestAddTableDriven/negative_+_positive
=== RUN   TestAddTableDriven/both_negative
--- PASS: TestAddTableDriven (0.00s)
    --- PASS: TestAddTableDriven/both_positive (0.00s)
    --- PASS: TestAddTableDriven/positive_+_zero (0.00s)
    --- PASS: TestAddTableDriven/negative_+_positive (0.00s)
    --- PASS: TestAddTableDriven/both_negative (0.00s)
PASS
ok      _/C_/projects/Articles/Go_Testing       0.385s
</code></pre>
<h3 id="heading-table-driven-divide-test">Table-Driven Divide Test</h3>
<p>We can apply the same pattern to <code>Divide</code>, including checking for divide-by-zero:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc_test.go</span>
...
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestDivideTableDriven</span><span class="hljs-params">(t *testing.T)</span></span> {
    tests := []<span class="hljs-keyword">struct</span> { <span class="hljs-comment">// Define test cases</span>
        name     <span class="hljs-keyword">string</span>
        a, b     <span class="hljs-keyword">int</span>
        want     <span class="hljs-keyword">int</span>
        wantPanic <span class="hljs-keyword">bool</span>
    }{
        {<span class="hljs-string">"normal division"</span>, <span class="hljs-number">10</span>, <span class="hljs-number">2</span>, <span class="hljs-number">5</span>, <span class="hljs-literal">false</span>},
        {<span class="hljs-string">"division by zero"</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-literal">true</span>},
    }

    <span class="hljs-keyword">for</span> _, tt := <span class="hljs-keyword">range</span> tests { <span class="hljs-comment">// Loop over</span>
        t.Run(tt.name, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> { <span class="hljs-comment">// Run subtest</span>
            <span class="hljs-keyword">if</span> tt.wantPanic { <span class="hljs-comment">// Check for expected panic</span>
                <span class="hljs-keyword">defer</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> { <span class="hljs-comment">// Recover from panic</span>
                    <span class="hljs-keyword">if</span> r := <span class="hljs-built_in">recover</span>(); r == <span class="hljs-literal">nil</span> {
                        t.Errorf(<span class="hljs-string">"Divide(%d, %d) did not panic"</span>, tt.a, tt.b)
                    }
                }()
            }
            got := Divide(tt.a, tt.b) <span class="hljs-comment">// Tests that do not panic</span>
            <span class="hljs-keyword">if</span> !tt.wantPanic &amp;&amp; got != tt.want {
                t.Errorf(<span class="hljs-string">"Divide(%d, %d) = %d; want %d"</span>, tt.a, tt.b, got, tt.want)
            }
        })
    }
}
</code></pre>
<p>This example shows how to handle both normal and panic cases in a single table-driven test:</p>
<ul>
<li><p>The <code>wantPanic</code> field tells the test whether we expect a panic.</p>
</li>
<li><p>We use <code>defer</code> and <code>recover</code> to check for a panic when needed.</p>
</li>
<li><p>Normal test cases still check the result as usual.</p>
</li>
</ul>
<p>Run all tests as before:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span> -v
=== RUN   TestAddTableDriven
=== RUN   TestAddTableDriven/both_positive
=== RUN   TestAddTableDriven/positive_+_zero
=== RUN   TestAddTableDriven/negative_+_positive
=== RUN   TestAddTableDriven/both_negative
--- PASS: TestAddTableDriven (0.00s)
    --- PASS: TestAddTableDriven/both_positive (0.00s)
    --- PASS: TestAddTableDriven/positive_+_zero (0.00s)
    --- PASS: TestAddTableDriven/negative_+_positive (0.00s)
    --- PASS: TestAddTableDriven/both_negative (0.00s)
=== RUN   TestDivideTableDriven
=== RUN   TestDivideTableDriven/normal_division
=== RUN   TestDivideTableDriven/division_by_zero
--- PASS: TestDivideTableDriven (0.00s)
    --- PASS: TestDivideTableDriven/normal_division (0.00s)
    --- PASS: TestDivideTableDriven/division_by_zero (0.00s)
PASS
ok      _/C_/projects/Articles/Go_Testing       0.321s
</code></pre>
<p>Subtest names make it easy to see which case passed or failed.</p>
<h3 id="heading-exercise">Exercise</h3>
<p>Try creating your own table-driven test for a new function, <code>Subtract(a, b int) int</code>. Include at least four test cases:</p>
<ul>
<li><p>Both positive numbers</p>
</li>
<li><p>Positive minus zero</p>
</li>
<li><p>Negative minus positive</p>
</li>
<li><p>Both negative</p>
</li>
</ul>
<p>Then run your tests and verify the output.</p>
<h2 id="heading-testing-functions-that-return-errors">Testing Functions That Return Errors</h2>
<p>Many Go functions return an error as the last return value. Writing tests for these functions is slightly different from testing pure functions like our <code>Add</code> or <code>Divide</code>, because you need to check both the result and whether an error occurred.</p>
<h3 id="heading-safe-divide-function">Safe Divide Function</h3>
<p>Let's add a <code>SafeDivide</code> function to return an error instead of panicking:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc.go</span>
...
<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>
...
<span class="hljs-comment">// SafeDivide returns the result of dividing a by b.</span>
<span class="hljs-comment">// It returns an error if b is zero.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">SafeDivide</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>, error)</span></span> {
    <span class="hljs-keyword">if</span> b == <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, fmt.Errorf(<span class="hljs-string">"cannot divide by zero"</span>)
    }
    <span class="hljs-keyword">return</span> a / b, <span class="hljs-literal">nil</span>
}
</code></pre>
<h3 id="heading-writing-tests-for-safedivide">Writing Tests for <code>SafeDivide()</code></h3>
<p>We can use a table-driven test again:</p>
<pre><code class="lang-go"><span class="hljs-comment">// calc_test.go</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestSafeDivide</span><span class="hljs-params">(t *testing.T)</span></span> {
    tests := []<span class="hljs-keyword">struct</span> {
        name      <span class="hljs-keyword">string</span>
        a, b      <span class="hljs-keyword">int</span>
        want      <span class="hljs-keyword">int</span>
        wantError <span class="hljs-keyword">bool</span>
    }{
        {<span class="hljs-string">"normal division"</span>, <span class="hljs-number">10</span>, <span class="hljs-number">2</span>, <span class="hljs-number">5</span>, <span class="hljs-literal">false</span>},
        {<span class="hljs-string">"division by zero"</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-literal">true</span>},
    }

    <span class="hljs-keyword">for</span> _, tt := <span class="hljs-keyword">range</span> tests {
        t.Run(tt.name, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> {
            got, err := SafeDivide(tt.a, tt.b)
            <span class="hljs-keyword">if</span> tt.wantError {
                <span class="hljs-keyword">if</span> err == <span class="hljs-literal">nil</span> {
                    t.Errorf(<span class="hljs-string">"SafeDivide(%d, %d) expected error, got nil"</span>, tt.a, tt.b)
                }
                <span class="hljs-keyword">return</span> <span class="hljs-comment">// stop here, no need to check `got`</span>
            }
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                t.Errorf(<span class="hljs-string">"SafeDivide(%d, %d) unexpected error: %v"</span>, tt.a, tt.b, err)
            }
            <span class="hljs-keyword">if</span> got != tt.want {
                t.Errorf(<span class="hljs-string">"SafeDivide(%d, %d) = %d; want %d"</span>, tt.a, tt.b, got, tt.want)
            }
        })
    }
}
</code></pre>
<p>What's happening here:</p>
<ul>
<li><p>We added a <code>wantError</code> field to indicate whether the test expects an error.</p>
</li>
<li><p>If an error is expected, we check that <code>err != nil</code>. If not (that is, <code>err == nil</code>), we fail the test.</p>
</li>
<li><p>If no error is expected, we check both the returned value (<code>got</code>) and that <code>err == nil</code>.</p>
</li>
<li><p>Using <code>t.Run</code> subtests keeps everything organized and readable.</p>
</li>
</ul>
<p>Running the tests again:</p>
<pre><code class="lang-bash">$ go <span class="hljs-built_in">test</span> -v
...
=== RUN   TestSafeDivide
=== RUN   TestSafeDivide/normal_division
=== RUN   TestSafeDivide/division_by_zero
--- PASS: TestSafeDivide (0.00s)
    --- PASS: TestSafeDivide/normal_division (0.00s)
    --- PASS: TestSafeDivide/division_by_zero (0.00s)
PASS
ok      _/C_/projects/Articles/Go_Testing       0.323s
</code></pre>
<p>Showing that both normal and error cases are handled correctly.</p>
<h3 id="heading-exercise-1">Exercise</h3>
<p>Update your <code>Subtract(a, b int) int</code> function to a <code>SafeSubtract(a, b int) (int, error)</code> variant that returns an error if the result would be negative. Then write a table-driven test that covers:</p>
<ul>
<li><p>A positive result</p>
</li>
<li><p>Zero result</p>
</li>
<li><p>A negative result (should return an error)</p>
</li>
</ul>
<h2 id="heading-best-practices-and-tips">Best Practices and Tips</h2>
<p>Writing tests in Go is straightforward, but there are a few conventions and tips that make your tests more readable, maintainable, and idiomatic:</p>
<h3 id="heading-name-tests-clearly">Name Tests Clearly</h3>
<p>First, make sure you use descriptive names for test functions and subtests. A good name explains what you're testing and under what conditions.</p>
<p>Here’s an example:</p>
<pre><code class="lang-go">t.Run(<span class="hljs-string">"Divide positive numbers"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> { ... })
t.Run(<span class="hljs-string">"Divide by zero returns error"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> { ... })
</code></pre>
<h3 id="heading-keep-tests-small-and-focused">Keep Tests Small and Focused</h3>
<p>Each subtest should verify one thing, and each test function should cover a single function or method.</p>
<p>Try to avoid combining multiple unrelated checks in the same test function, and use table-driven tests help keep multiple similar checks concise without losing clarity.</p>
<h3 id="heading-use-table-driven-tests-for-repetitive-cases">Use Table-Driven Tests for Repetitive Cases</h3>
<p>If you find yourself writing multiple similar test functions, switch to a table-driven pattern. It makes it easier to add new cases, reduces duplicated code, and keeps output organized with <code>t.Run</code>.</p>
<h3 id="heading-check-errors-explicitly">Check Errors Explicitly</h3>
<p>In Go, functions often return <code>error</code>. So make sure you always check for errors in tests, even if you expect <code>nil</code>.</p>
<p>You can use the <code>wantError</code> pattern in table-driven tests for clarity.</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> tt.wantError {
    <span class="hljs-keyword">if</span> err == <span class="hljs-literal">nil</span> {
        t.Errorf(<span class="hljs-string">"expected error, got nil"</span>)
    }
}
</code></pre>
<h3 id="heading-avoid-panics-when-possible">Avoid Panics When Possible</h3>
<p>Panics are fine for some internal checks, but in production code, prefer returning an error.</p>
<p>Your tests can check for panics using <code>defer</code> and <code>recover</code>, but this should be the exception rather than the norm.</p>
<h3 id="heading-run-tests-frequently">Run Tests Frequently</h3>
<p>Try to make running tests a habit: <code>go test -v ./...</code>. Frequent testing helps catch mistakes early and reinforces TDD practices.</p>
<h3 id="heading-keep-tests-in-the-same-package">Keep Tests in the Same Package</h3>
<p>By convention, tests live in the same package as the code they test. You can create <code>_test.go</code> files for testing, and Go automatically recognizes them.</p>
<p>Only use a separate <code>package calc_test</code> if you want to test your code from the outside, like a consumer. External test packages (just like every other external package) cannot access unexported identifiers.</p>
<h3 id="heading-use-tfatalf-vs-terrorf-appropriately">Use t.Fatalf vs t.Errorf Appropriately</h3>
<ul>
<li><p><code>t.Errorf</code> reports a failure but continues running the test.</p>
</li>
<li><p><code>t.Fatalf</code> stops the test immediately, which is useful if subsequent code depends on successful setup.</p>
</li>
</ul>
<p>These tips will help you write clean, maintainable, and idiomatic Go tests that are easy to read and extend. Following these practices early in your Go journey will make testing less intimidating and more effective.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Unit testing in Go may feel different at first, especially if you're coming from ecosystems with heavy frameworks and assertions. But the simplicity of Go's testing tools is one of its strengths: once you understand the conventions, writing, running, and organizing tests becomes predictable and intuitive.</p>
<p>In this guide, you've seen how to:</p>
<ul>
<li><p>Write basic test functions with the testing package</p>
</li>
<li><p>Run tests from the command line and interpret the results</p>
</li>
<li><p>Use table-driven tests to cover multiple cases efficiently</p>
</li>
<li><p>Handle functions that return errors and check for expected failures</p>
</li>
</ul>
<p>Beyond these fundamentals, testing is not just about verifying correctness, it's also about confidence. Well-tested code allows you to refactor, experiment, and add new features with less fear of breaking existing functionality.</p>
<p>As you continue writing Go code, try to integrate testing early, follow the idiomatic patterns you've learned, and explore more advanced topics such as:</p>
<ul>
<li><p>Using <em>mocks</em> or <em>interfaces</em> to isolate dependencies</p>
</li>
<li><p>Benchmark tests with <code>testing.B</code></p>
</li>
<li><p>Coverage analysis with <code>go test -cover</code></p>
</li>
</ul>
<p>The key takeaway is that testing in Go is accessible, flexible, and powerful, even without fancy frameworks. By building these habits now, you'll write code that's more reliable, maintainable, and enjoyable to work with.</p>
<h2 id="heading-solutions-to-exercises">Solutions to Exercises</h2>
<h3 id="heading-subtract-function-and-tests">Subtract Function and Tests</h3>
<pre><code class="lang-go"><span class="hljs-comment">// calc.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Subtract</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">return</span> a - b
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-comment">// calc_test.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-keyword">import</span> <span class="hljs-string">"testing"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestSubtractTableDriven</span><span class="hljs-params">(t *testing.T)</span></span> {
    tests := []<span class="hljs-keyword">struct</span> {
        name <span class="hljs-keyword">string</span>
        a, b <span class="hljs-keyword">int</span>
        want <span class="hljs-keyword">int</span>
    }{
        {<span class="hljs-string">"both positive"</span>, <span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>},
        {<span class="hljs-string">"positive minus zero"</span>, <span class="hljs-number">5</span>, <span class="hljs-number">0</span>, <span class="hljs-number">5</span>},
        {<span class="hljs-string">"negative minus positive"</span>, <span class="hljs-number">-1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">-5</span>},
        {<span class="hljs-string">"both negative"</span>, <span class="hljs-number">-3</span>, <span class="hljs-number">-2</span>, <span class="hljs-number">-1</span>},
    }

    <span class="hljs-keyword">for</span> _, tt := <span class="hljs-keyword">range</span> tests {
        t.Run(tt.name, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> {
            got := Subtract(tt.a, tt.b)
            <span class="hljs-keyword">if</span> got != tt.want {
                t.Errorf(<span class="hljs-string">"Subtract(%d, %d) = %d; want %d"</span>, tt.a, tt.b, got, tt.want)
            }
        })
    }
}
</code></pre>
<h3 id="heading-safesubtract-function-and-tests">SafeSubtract Function and Tests</h3>
<pre><code class="lang-go"><span class="hljs-comment">// calc.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">SafeSubtract</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>, error)</span></span> {
    result := a - b
    <span class="hljs-keyword">if</span> result &lt; <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, fmt.Errorf(<span class="hljs-string">"result would be negative"</span>)
    }
    <span class="hljs-keyword">return</span> result, <span class="hljs-literal">nil</span>
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-comment">// calc_test.go</span>
<span class="hljs-keyword">package</span> calc

<span class="hljs-keyword">import</span> <span class="hljs-string">"testing"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestSafeSubtract</span><span class="hljs-params">(t *testing.T)</span></span> {
    tests := []<span class="hljs-keyword">struct</span> {
        name      <span class="hljs-keyword">string</span>
        a, b      <span class="hljs-keyword">int</span>
        want      <span class="hljs-keyword">int</span>
        wantError <span class="hljs-keyword">bool</span>
    }{
        {<span class="hljs-string">"positive result"</span>, <span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-literal">false</span>},
        {<span class="hljs-string">"zero result"</span>, <span class="hljs-number">3</span>, <span class="hljs-number">3</span>, <span class="hljs-number">0</span>, <span class="hljs-literal">false</span>},
        {<span class="hljs-string">"negative result"</span>, <span class="hljs-number">2</span>, <span class="hljs-number">5</span>, <span class="hljs-number">0</span>, <span class="hljs-literal">true</span>},
    }

    <span class="hljs-keyword">for</span> _, tt := <span class="hljs-keyword">range</span> tests {
        t.Run(tt.name, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> {
            got, err := SafeSubtract(tt.a, tt.b)
            <span class="hljs-keyword">if</span> tt.wantError {
                <span class="hljs-keyword">if</span> err == <span class="hljs-literal">nil</span> {
                    t.Errorf(<span class="hljs-string">"SafeSubtract(%d, %d) expected error, got nil"</span>, tt.a, tt.b)
                }
                <span class="hljs-keyword">return</span>
            }
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                t.Errorf(<span class="hljs-string">"SafeSubtract(%d, %d) unexpected error: %v"</span>, tt.a, tt.b, err)
            }
            <span class="hljs-keyword">if</span> got != tt.want {
                t.Errorf(<span class="hljs-string">"SafeSubtract(%d, %d) = %d; want %d"</span>, tt.a, tt.b, got, tt.want)
            }
        })
    }
}
</code></pre>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use pytest: A Simple Guide to Testing in Python ]]>
                </title>
                <description>
                    <![CDATA[ With the recent advancements in AI, tools like ChatGPT have made the development process faster and more accessible. Developers can now write code and build web apps with some well-articulated prompts and careful code reviews. While this brings an in... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-pytest-a-guide-to-testing-in-python/</link>
                <guid isPermaLink="false">686d82b56332ba136ecc139e</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ pytest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TDD (Test-driven development) ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ guide ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Olowo Jude ]]>
                </dc:creator>
                <pubDate>Tue, 08 Jul 2025 20:42:29 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752007334998/e196493e-f3e0-4e63-b6eb-ce66c5481d9c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>With the recent advancements in AI, tools like ChatGPT have made the development process faster and more accessible. Developers can now write code and build web apps with some well-articulated prompts and careful code reviews.</p>
<p>While this brings an increase in productivity, there's a growing downside. AI-generated code is prone to errors, unexpected bugs, or poor integration with the rest of your code.</p>
<p>Because of these risks, it’s more important than ever to establish robust testing practices to make sure your code is high quality and properly functioning. Various testing tools are available to help solve these challenges, and pytest stands out in the Python ecosystem for its simplicity, flexibility, and powerful features.</p>
<p>In this article, we'll explore the following topics:</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-use-pytest">Why Use pytest?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-write-your-first-tests-with-pytest">How to Write Your First Tests with pytest</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-run-pytest-tests">How to Run pytest Tests</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-interpret-pytest-results">How to Interpret pytest Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-handle-exceptions-in-pytest">How to Handle Exceptions in pytest</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-advanced-pytest-features">Advanced pytest Features</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-pytest-markers">1. pytest Markers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-pytest-fixtures">2. pytest Fixtures</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-parametrization">3. Parametrization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-pytest-plugins">4. pytest Plugins</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<p>By the end of this article, you will have a comprehensive knowledge of pytest and be able to use it in your Python development process.</p>
<h2 id="heading-pre-requisites"><strong>Pre-requisites</strong></h2>
<ul>
<li><p>Must have Python installed</p>
</li>
<li><p>An understanding of the Python programming language</p>
</li>
</ul>
<h2 id="heading-why-use-pytest">Why Use pytest?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751221734601/f5d6093a-37d2-4d49-85f2-c1a41a98ab67.png" alt="An image of pytest logo." class="image--center mx-auto" width="742" height="677" loading="lazy"></p>
<p>pytest is a popular testing framework for Python that makes it easy to write and run tests. Unlike unittest and other Python testing frameworks, pytest’s simple syntax allows developers to write tests directly as functions or within classes. This lets you write clean, readable code without complexities.</p>
<p>pytest also supports popular Python frameworks like Flask, Django, and more. Combined with other rich features, pytest equips you with the tools you need to ship reliable software in today’s AI-driven era.</p>
<p>Key features of pytest that make it a preferred testing tool include:</p>
<ul>
<li><p><strong>Flexibility:</strong> it provides flexibility in test structure by supporting tests for functions, classes, and modules.</p>
</li>
<li><p><strong>Detailed test output:</strong> it provides a detailed and readable test output, making it easy to understand test failures and errors.</p>
</li>
<li><p><strong>Automatic test discovery:</strong> it automatically discovers tests by looking for files that start with "<code>test_</code>" or end with "<code>_test.py</code>". This eliminates the need for manually specifying test files**.**</p>
</li>
<li><p><strong>Parameterization:</strong> it supports parameterized tests, which allow you to run a single test function with multiple sets of inputs.</p>
</li>
<li><p><strong>Fixtures:</strong> it fixtures provide <code>setup</code> and <code>tearDown</code> methods that help prevent code repetition. This enables you to set up baseline conditions for your tests and also delete them after each test.</p>
</li>
<li><p><strong>Plugins and extensions:</strong> it has a rich ecosystem of plugins and extensions that add extra functionalities, such as detailed tests reporting, and integration with other tools and Python frameworks like Django and Flask.</p>
</li>
<li><p><strong>Compatibility:</strong> it is compatible with other testing frameworks like <code>unittest</code> , allowing you to migrate tests from different testing frameworks and run them seamlessly on it.</p>
</li>
</ul>
<h2 id="heading-how-to-write-your-first-tests-with-pytest">How to Write Your First Tests with pytest</h2>
<p>This section will guide you through writing your first set of tests using the pytest framework.</p>
<p>pytest is a Python package, and you’ll need to install it before using it. You can do that with the following command:</p>
<pre><code class="lang-python">pip install pytest
</code></pre>
<p><strong>NOTE:</strong> Following Python's best practices, it’s recommended you install pytest within a virtual environment. <a target="_blank" href="https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/">Here's a guide</a> to help you set it up.</p>
<p>Next, create a Python file where you will write your tests and import pytest into it using:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest
</code></pre>
<p>pytest has 2 basic methods of writing tests, which include:</p>
<ul>
<li><p><strong>The function-based method:</strong> This method is straightforward for writing tests because you write the tests in individual functions.</p>
<p>  <strong>Note:</strong> Each function name must be prefixed with the word <code>test_</code> for pytest to discover and run these tests automatically.</p>
<p>  Here’s an example of a function-based test:</p>
<pre><code class="lang-python">  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_addition</span>():</span>
      <span class="hljs-keyword">assert</span> <span class="hljs-number">1</span> + <span class="hljs-number">1</span> == <span class="hljs-number">2</span>
</code></pre>
<p>  <strong>Note:</strong> In the code above, the <code>assert</code> statement used here in pytest is Python’s built-in “<code>assert</code>”. It’s more convenient and doesn’t require the specific methods like <code>assertEqual</code> and <code>assertTrue</code> which are common with unittest. Another advantage of using the <code>assert</code> statement is that it provides more detailed error messages when an assertion fails.</p>
</li>
<li><p><strong>Class-based method:</strong> This method is similar to the way of writing tests in <code>unittest</code>, except that your test class does not inherit any methods. An example is shown below:</p>
<pre><code class="lang-python">  <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestMathOperations</span>:</span>
      <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_addition</span>(<span class="hljs-params">self</span>):</span>
          <span class="hljs-keyword">assert</span> <span class="hljs-number">1</span> + <span class="hljs-number">1</span> == <span class="hljs-number">2</span>
</code></pre>
<p>  This method of writing tests in pytest is useful when you want to group related tests together.</p>
</li>
</ul>
<h2 id="heading-how-to-run-pytest-tests">How to Run pytest Tests</h2>
<p>Running pytest differs slightly from the normal convention of running regular Python scripts.</p>
<p>The general method of running pytest tests is by running the <code>pytest</code> command in your terminal. pytest will automatically look for and run all files of the form <code>test_*.py</code> or <code>*_test.py</code> in the current directory and subdirectories. But while this may be a great way to run tests, pytest offers more flexibility beyond this general method of running tests.</p>
<p>Depending on preferences, you may want to run your test files based on the following:</p>
<ol>
<li><p><strong>To run a specific test file</strong>: To run tests in a specific file, use the <code>pytest</code> command followed by the file name. For example: <code>pytest test_example.py</code>.</p>
</li>
<li><p><strong>To run tests in a directory:</strong> Let’s say you have a directory named Tests that contains some test files. To run all the tests in that directory, use the <code>pytest</code> command followed by the directory and a forward slash. For example: <code>pytest Tests/</code>.</p>
</li>
<li><p><strong>To run tests using specific keywords:</strong> To run tests based on a certain keyword, use the command <code>pytest -k "keyword"</code>. Pytest will automatically look for and run function names, class names, or file names matching that keyword in the current directory and subdirectories. But to run tests matching a certain keyword in a specific file, you’d have to specify the file name after the <code>pytest</code> command. For example: <code>pytest test_example.py -k "keyword"</code>.</p>
</li>
<li><p><strong>Run a specific test within a test file:</strong> To run only a specific test inside a test file, use the command <code>pytest test_example.py::test_addition</code>. This will run only the <code>test_addition</code> test function within the <code>test_example.py</code> module.</p>
</li>
<li><p><strong>To run all test methods in a specific class</strong>: To run all the tests within a specific class, use <code>pytest test_example.py::TestClass</code>. This command would run all the test methods inside the <code>TestClass</code> class in the <code>test_example.py</code> module.</p>
</li>
<li><p><strong>To run a specific test method inside a specific class:</strong> To run a specific test inside a specific class, use <code>pytest test_example.py::TestClass::test_addition</code>. This command would run the specific <code>test_addition</code> method within the <code>TestClass</code> class in the <code>test_example.py</code> module.</p>
</li>
</ol>
<h2 id="heading-how-to-interpret-pytest-results">How to Interpret pytest Results</h2>
<p>One major advantage pytest has over other Python testing frameworks is the rich output it provides, which gives very detailed information about the status of your tests.</p>
<p>Let’s use a basic test to understand how to interpret pytest’s output:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_addition</span>():</span>
    <span class="hljs-keyword">assert</span> <span class="hljs-number">1</span> + <span class="hljs-number">1</span> == <span class="hljs-number">3</span>
</code></pre>
<p>Run this test, and we get an output similar to the one below:</p>
<pre><code class="lang-python">============================== test session starts ====================================
platform win32 -- Python <span class="hljs-number">3.10</span><span class="hljs-number">.5</span>, pytest<span class="hljs-number">-8.4</span><span class="hljs-number">.1</span>, pluggy<span class="hljs-number">-1.6</span><span class="hljs-number">.0</span>
rootdir: C:\\Users\\hp\\Desktop\\Pytest
collected <span class="hljs-number">1</span> items

                                                                                  [ <span class="hljs-number">50</span>%]
test_example.py F                                                                 [<span class="hljs-number">100</span>%]

===================================== FAILURES =========================================
____________________________________test_addition ______________________________________

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_addition</span>():</span>
&gt;       <span class="hljs-keyword">assert</span> <span class="hljs-number">1</span> + <span class="hljs-number">1</span> == <span class="hljs-number">3</span>
E       <span class="hljs-keyword">assert</span> (<span class="hljs-number">1</span> + <span class="hljs-number">1</span>) == <span class="hljs-number">3</span>

test_example.py:<span class="hljs-number">4</span>: AssertionError
============================== short test summary info =================================
FAILED test_example.py::test_addition - <span class="hljs-keyword">assert</span> (<span class="hljs-number">1</span> + <span class="hljs-number">1</span>) == <span class="hljs-number">3</span>
========================= <span class="hljs-number">1</span> failed, <span class="hljs-number">1</span> passed <span class="hljs-keyword">in</span> <span class="hljs-number">0.13</span>s ==================================
</code></pre>
<p>The above output is divided into several sections. Here’s a breakdown of what each section means:</p>
<ol>
<li><p>Test session information:</p>
<pre><code class="lang-python"> =============================== test session starts ===============================
 platform win32 -- Python <span class="hljs-number">3.10</span><span class="hljs-number">.5</span>, pytest<span class="hljs-number">-8.4</span><span class="hljs-number">.1</span>, pluggy<span class="hljs-number">-1.6</span><span class="hljs-number">.0</span>
 rootdir: C:\\Users\\hp\\Desktop\\TDD pytest
 collected <span class="hljs-number">1</span> item
</code></pre>
<ul>
<li><p>This section displays a summary of the test environment. It begins with a line marker that indicates the beginning of the test session.</p>
</li>
<li><p>Below the marker, pytest displays information about the operating system, along with the installed versions of Python, pytest and pluggy. (Pluggy is a pytest dependency used to manage plugins.)</p>
</li>
<li><p>The next line indicates the root directory where the test is being run.</p>
</li>
<li><p>The last line in this section displays the number of tests found in this directory.</p>
</li>
</ul>
</li>
<li><p>Test status:</p>
<pre><code class="lang-python"> test_example.py F                                                              [<span class="hljs-number">100</span>%]

 ================================== FAILURES =========================================
 ________________________________ test_addition ______________________________________

     <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_addition</span>():</span>
 &gt;       <span class="hljs-keyword">assert</span> <span class="hljs-number">1</span> + <span class="hljs-number">1</span> == <span class="hljs-number">3</span>
 E       <span class="hljs-keyword">assert</span> (<span class="hljs-number">1</span> + <span class="hljs-number">1</span>) == <span class="hljs-number">3</span>

 test_example.py:<span class="hljs-number">4</span>: AssertionError
</code></pre>
<ul>
<li><p>This section displays information about the status of our tests</p>
</li>
<li><p>The first line in this section specifies the test file which is being run, followed by the status (F in this case, which indicates a test failure).</p>
</li>
<li><p>The next set of lines gives specific information about the failed tests. This includes the function where the failure occurred (<code>test_addition</code>), and the exact line of code responsible for the error.</p>
</li>
<li><p>The last line gives a concise summary of this section. It indicates that the error occurred in <code>test_example.py</code> on line <code>4</code> and it was an <code>AssertionError</code>.</p>
</li>
</ul>
</li>
<li><p>Test summary:</p>
<pre><code class="lang-python"> ============================= short test summary info =============================
 FAILED test_example.py::test_addition - <span class="hljs-keyword">assert</span> (<span class="hljs-number">1</span> + <span class="hljs-number">1</span>) == <span class="hljs-number">3</span>
 ================================ <span class="hljs-number">1</span> failed <span class="hljs-keyword">in</span> <span class="hljs-number">0.13</span>s ================================
</code></pre>
<ul>
<li><p>This section provides an overall summary of the test.</p>
</li>
<li><p>It indicates that the failed test occurred in <code>test_example.py</code> file in the <code>test_addition</code> function because of an incorrect assertion <code>(1 + 1) == 3</code> which isn’t true.</p>
</li>
</ul>
</li>
</ol>
<p>Edit the code with the correct assertion <code>assert(1 + 1) == 2</code> and rerun the code. This time, the code passes with a different output.</p>
<pre><code class="lang-python">=============================== test session starts ==================================
platform win32 -- Python <span class="hljs-number">3.10</span><span class="hljs-number">.5</span>, pytest<span class="hljs-number">-8.3</span><span class="hljs-number">.2</span>, pluggy<span class="hljs-number">-1.5</span><span class="hljs-number">.0</span>
rootdir: C:\\Users\\hp\\Desktop\\TDD pytest
collected <span class="hljs-number">1</span> items

test_example.py .                                                               [<span class="hljs-number">100</span>%]

=============================== <span class="hljs-number">1</span> passed <span class="hljs-keyword">in</span> <span class="hljs-number">0.01</span>s =================================
</code></pre>
<h3 id="heading-how-to-handle-exceptions-in-pytest">How to Handle Exceptions in pytest</h3>
<p>Exceptions are unexpected errors that occur while running our tests, and they prevent our code from performing as expected. As a result, pytest offers several built-in mechanisms for handling these exceptions (but we’ll just cover one of them in this article).</p>
<p><code>pytest.raises</code> <strong>Context Manager</strong> is a tool that checks if your code raises specific exceptions. If the specified exception is raised, that test passes, confirming that the expected error occurred. But if the specified exception is not raised, that test fails.</p>
<p><strong>Usage Examples of</strong> <code>pytest.raises</code></p>
<ol>
<li><p><strong>Checking for</strong> <code>ValueError</code>: In Python, a <code>ValueError</code> is raised when a function receives an argument with an incorrect value. In the example below, we can verify that a <code>ValueError</code> is raised when attempting to calculate the square root of a negative number.</p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> pytest
 <span class="hljs-keyword">import</span> math

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_square_root</span>(<span class="hljs-params">value</span>):</span>
     <span class="hljs-keyword">if</span> value &lt; <span class="hljs-number">0</span>:
         <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Cannot calculate the square root of a negative number"</span>)
     <span class="hljs-keyword">return</span> math.sqrt(value)

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_calculate_square_root</span>():</span>
     <span class="hljs-keyword">with</span> pytest.raises(ValueError):
         calculate_square_root(<span class="hljs-number">-1</span>)
</code></pre>
</li>
<li><p><strong>Checking for</strong> <code>ZeroDivisionError</code>: Dividing a number by zero raises a <code>ZeroDivisionError</code>. In this example, we check that this error is raised when dividing a number by zero.</p>
<pre><code class="lang-jsx"> <span class="hljs-keyword">import</span> pytest

 def divide_numbers(numerator, denominator):
     <span class="hljs-keyword">return</span> numerator / denominator

 def test_divide_numbers():
     <span class="hljs-keyword">with</span> pytest.raises(ZeroDivisionError):
         divide_numbers(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>)
</code></pre>
</li>
<li><p><strong>Checking for</strong> <code>TypeError</code>: A <code>TypeError</code> is raised when an operation is applied to an object of an inappropriate type. Here, we check that this error is raised when adding incompatible data types, such as a string and an integer given in the example.</p>
<pre><code class="lang-jsx"> <span class="hljs-keyword">import</span> pytest

 def add_numbers(a, b):
     <span class="hljs-keyword">return</span> a + b

 def test_add_numbers():
     <span class="hljs-keyword">with</span> pytest.raises(<span class="hljs-built_in">TypeError</span>):
         add_numbers(<span class="hljs-string">"10"</span>, <span class="hljs-number">5</span>)
</code></pre>
</li>
<li><p><strong>Checking for</strong> <code>KeyError</code>: A <code>KeyError</code> is raised when we try to access a dictionary key that doesn’t exist. We can verify and handle this error using the following code:</p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> pytest

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_value</span>(<span class="hljs-params">dictionary, key</span>):</span>
     <span class="hljs-keyword">return</span> dictionary[key]

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_get_value</span>():</span>
     <span class="hljs-keyword">with</span> pytest.raises(KeyError):
         get_value({<span class="hljs-string">"name"</span>: <span class="hljs-string">"Alice"</span>}, <span class="hljs-string">"age"</span>)
</code></pre>
</li>
</ol>
<h2 id="heading-advanced-pytest-features">Advanced pytest Features</h2>
<p>As a robust testing framework, pytest offers some advanced features that help you manage complex test scenarios. In this section, we will explore some of these advanced features at a beginner-friendly level and demonstrate how you can start applying them in your tests.</p>
<h3 id="heading-1-pytest-markers">1. pytest Markers</h3>
<p>When working with a large codebase, sometimes running every single test can be time-consuming. This is where pytest markers come in handy.</p>
<p>A marker is just like a label that you can attach to a test function to categorise it. Once a test is labelled, you can instruct pytest to run only tests with certain markers. For example, you may label some tests as "slow" if they take longer to execute and run them separately from the faster ones.</p>
<p>One advantage to using Markers is that it allows you to run specific tests based on categories or specific parameters, and also skip tests if certain conditions aren’t met.</p>
<p>pytest comes along with some built-in markers that can be quite useful:</p>
<ol>
<li><p><code>@pytest.mark.skip</code>: This marker allows you to skip a test unconditionally, and can be useful when you know a test will fail due to an external issue or incomplete code.</p>
<p> <strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-meta"> @pytest.mark.skip(reason="Feature not yet implemented")</span>
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_feature</span>():</span>
     <span class="hljs-keyword">pass</span>
</code></pre>
</li>
<li><p><code>@pytest.mark.skipif</code>: This marker allows you to skip a test conditionally if certain conditions are met.</p>
<p> <strong>Example:</strong></p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> sys

<span class="hljs-meta"> @pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")</span>
 <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestClass</span>:</span>
     <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_function</span>(<span class="hljs-params">self</span>):</span>
         <span class="hljs-string">"This test will not run under 'win32' platform"</span>
</code></pre>
</li>
<li><p><code>@pytest.mark.xfail</code>: This marker is attached to tests that are expected to fail, probably due to a bug or incomplete feature. So when pytest runs such tests, it won’t count it as a failure.</p>
<p> <strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-meta"> @pytest.mark.xfail(reason="division by zero not handled yet")</span>
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_divide_by_zero</span>():</span>
     <span class="hljs-keyword">assert</span> divide(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>) == <span class="hljs-number">0</span>
</code></pre>
<p> <strong>Note:</strong> Detailed information about skipped/failed tests is not shown by default to avoid cluttering the output.</p>
</li>
</ol>
<p>While pytest comes along with some built-in markers, you can also create your own custom marker (but we won’t cover that in this tutorial). Kindly refer to the documentation for more information on <a target="_blank" href="https://docs.pytest.org/en/stable/example/markers.html">working with custom markers</a></p>
<h3 id="heading-2-pytest-fixtures">2. pytest Fixtures</h3>
<p>In pytest, fixtures allow you to create reusable default data that can be shared across multiple tests. By using fixtures, you can reduce code repetition, making your tests cleaner and more maintainable.</p>
<p>In pytest, fixtures are defined with the <code>@pytest.fixture</code> decorator as shown in the example below:</p>
<p>Let’s say we have several tests that rely on a list of user data. Instead of repeating the same data in each test, we can create a fixture to hold this data, and the fixture is passed across the tests that need it.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest

<span class="hljs-meta">@pytest.fixture</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_data</span>():</span>
    <span class="hljs-keyword">return</span> [
        {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">30</span>},
        {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Bob"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">25</span>},
        {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Charlie"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">35</span>}
    ]

<span class="hljs-comment"># Test function to check for a specific user by name and age</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_user_exists</span>(<span class="hljs-params">user_data</span>):</span>
    user = {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">30</span>}

    <span class="hljs-comment"># Check if the target user is in the list</span>
    <span class="hljs-keyword">assert</span> user <span class="hljs-keyword">in</span> user_data

<span class="hljs-comment"># Test average age of users</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_average_age</span>(<span class="hljs-params">user_data</span>):</span>
    ages = [user[<span class="hljs-string">"age"</span>] <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> user_data]
    avg_age = sum(ages) / len(ages)
    <span class="hljs-keyword">assert</span> avg_age == <span class="hljs-number">30</span>
</code></pre>
<p><strong>Note:</strong> The <code>@pytest.fixture</code> decorator in the code above marks the <code>user_data</code> function as a fixture in pytest. This fixture provides reusable data that can be shared across multiple test functions, allowing them to share the same setup without repeating code.</p>
<h3 id="heading-3-parametrization">3. Parametrization</h3>
<p>Parametrization is a pytest feature that allows you to run a test function with different sets of data at once.</p>
<p>For example: Let’s say you have a function that calculates the square of a number. To provide enough coverage while testing, you would want to test the function with zero, positive, and negative numbers.</p>
<p>Instead of writing separate test functions for each scenario, you can use parametrization to run a test function with different sets of data at once. This approach is more concise, and reduces code duplication.</p>
<p>To use parametrization in pytest, we use the <code>@pytest.mark.parametrize</code> decorator as shown in the example below:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest

<span class="hljs-comment"># Function to calculate the square of a number</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">square_numbers</span>(<span class="hljs-params">num</span>):</span>
    <span class="hljs-keyword">return</span> num * num

<span class="hljs-comment">#Parametrize decorator to test the square function with different inputs</span>
<span class="hljs-meta">@pytest.mark.parametrize("input_value, expected_output", [</span>
    (<span class="hljs-number">2</span>, <span class="hljs-number">4</span>),     
    (<span class="hljs-number">-3</span>, <span class="hljs-number">9</span>),    
    (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)    
])

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_square</span>(<span class="hljs-params">input_value, expected_output</span>):</span>
    <span class="hljs-keyword">assert</span> square_numbers(input_value) == expected_output
</code></pre>
<p>In the example above, the different input values and expected values are listed in the <code>@pytest.mark.parametrize</code> decorator. We’re testing the <code>square_numbers()</code> function with three different input values: <code>2</code>, <code>-3</code>, and <code>0</code>.</p>
<p>For each value, pytest calls the <code>test_square()</code> function and compares the result of <code>square_numbers(input_value)</code> to <code>expected_output</code>.</p>
<p>This approach is more efficient and ensures the function behaves as expected across a variety of cases.</p>
<h3 id="heading-4-pytest-plugins">4. pytest Plugins</h3>
<p>Plugins are an extension mechanism that allows you to add new functionality to pytest or modify its existing behaviour. These plugins work by providing additional features that extend pytest’s capabilities, which can be useful, especially in complex test scenarios.</p>
<p>pytest has a vast ecosystem of plugins, each designed to suit your different testing needs. You can find the full list of available plugins on <a target="_blank" href="https://pypi.org/">PyPI</a> in the <a target="_blank" href="https://docs.pytest.org/en/stable/reference/plugin_list.html#plugin-list">pytest Plugin List</a>.</p>
<p>To use a plugin, simply install it with <code>pip</code>.</p>
<p><strong>For example:</strong></p>
<pre><code class="lang-python">pip install pytest-NAME
pip uninstall pytest-NAME
</code></pre>
<p><strong>Note:</strong> <code>NAME</code> in the code above should be replaced with the name of the plugin you want to install.</p>
<p>After installing a plugin, pytest automatically finds and integrates it. There’s no need for any additional configuration.</p>
<p>In this section, we explored some of pytest's advanced features. By leveraging these features, you can now significantly improve the quality of your tests by ensuring they’re more efficient, scalable, and easier to maintain over time.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you’ve learned the basics of testing with pytest, from writing and interpreting tests to handling exceptions and using advanced features like fixtures and parametrization.</p>
<p>Whether your code is written manually or generated by AI, learning how to write tests empowers you to detect bugs early, and build more reliable software. Testing acts as a safety net that boosts you confidence during development and ensures your code works as expected.</p>
<p>If you're ready to go a step further, I’ve written an in-depth article on <a target="_blank" href="https://judeolowo.hashnode.dev/test-driven-development-in-python-a-complete-guide-to-unittest">Test Driven Development in Python</a>. It is a powerful approach where writing tests guides your entire coding process.</p>
<p>If you found this helpful, let me know, share it with your network, or give it a like to help others discover it too.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Unit Tests in Python – with Example Test Code ]]>
                </title>
                <description>
                    <![CDATA[ Unit testing is a software testing technique in which individual components or units of a software application are tested independently from the rest of the application. In software development, it's beneficial to break your application into small, i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/unit-testing-in-python/</link>
                <guid isPermaLink="false">66d45e0cf855545810e93423</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Damilola Oladele ]]>
                </dc:creator>
                <pubDate>Mon, 10 Jun 2024 16:33:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/WhatsApp-Image-2024-06-10-at-10.46.58-AM.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Unit testing is a software testing technique in which individual components or units of a software application are tested independently from the rest of the application.</p>
<p>In software development, it's beneficial to break your application into small, isolated units. This approach allows you to write independent tests to check all parts of your application, ensuring that they behave as expected. Also, if a test fails, you can easily isolate and troubleshoot the area of the code that has the bug without tampering with the rest of your application.</p>
<p>Python provides built-in support for unit testing through the <a target="_blank" href="https://docs.python.org/3/library/unittest.html">unittest</a> testing framework. There are also other third-party testing frameworks that you can use for your unit testing, such as <a target="_blank" href="https://docs.pytest.org/en/7.1.x/contents.html">pytest</a>.</p>
<p>This article focuses on how to use the <code>unittest</code> framework to write tests for your Python applications and why developers often prefer it.</p>
<p>To get the best out of this article, you should have a basic understanding of the Python programming language.</p>
<h2 id="heading-why-do-developers-prefer-to-use-unittest">Why Do Developers Prefer to Use unittest?</h2>
<p>While there are many frameworks for unit testing in the Python ecosystem, many developers still prefer the built-in <code>unittest</code> due to its compelling advantages.</p>
<p>First, the <code>unittest</code> module is part of Python's standard library. This ensures immediate availability and compatibility across various environments without extra dependencies. The seamless integration with various environments makes it convenient for developers to use <code>unittest</code> without installing additional packages.</p>
<p>Second, as a long-standing framework within the Python ecosystem, <code>unittest</code> benefits from familiarity and longevity. Many developers are already used to its API and structure, making it a reliable choice for testing.</p>
<p>Third, most integrated development environments (IDEs) such as PyCharm offer built-in support for <code>unittest</code>. This improves developer productivity and streamlines the testing process, allowing for easier test management and execution.</p>
<p>Fourth, the framework has comprehensive and well-maintained documentation. This provides detailed guidance and examples, aiding developers in effectively using <code>unittest</code> for their testing needs.</p>
<p>Finally, many existing Python projects use <code>unittest</code> for testing, ensuring compatibility with legacy codebases. This widespread adoption allows developers to maintain and extend older projects without needing to introduce and adapt to a new testing framework.</p>
<h2 id="heading-how-to-write-unit-tests-with-unittest">How to Write Unit Tests with unittest</h2>
<p>Unit testing with <code>unittest</code> involves creating test cases to verify the functionality of individual units of your code. Each test case is defined by subclassing <code>unittest.TestCase</code>. This allows you to inherit the several methods provided by the <a target="_blank" href="https://docs.python.org/3/library/unittest.html#test-cases">TestCase</a> class.</p>
<p>Some of the methods provided by the <code>TestCase</code> class are assert methods. These assert methods allow you to check whether the actual result of a function or operation matches the expected result, or whether certain conditions are met. If an assertion fails, the test is marked as failed, and you will receive an error message.</p>
<p>See <a target="_blank" href="https://docs.python.org/3/library/unittest.html#classes-and-functions">Classes and functions</a> for detailed information about the different methods provided by the <code>TestCase</code> class.</p>
<p>Now, let's use two of the assert methods to write tests for a simple calculator program. First, create a new folder (directory), named <code>unit-testing</code>. Then, create a file named <code>calculator.py</code> within your <code>unit-testing</code> folder. Now, copy the following code into your <code>calculator.py</code> file:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-string">"""add numbers"""</span>
    <span class="hljs-keyword">return</span> x + y

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">subtract</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-string">"""subtract numbers"""</span>
    <span class="hljs-keyword">return</span> x - y

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">divide</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-string">"""divide numbers"""</span>
    <span class="hljs-keyword">return</span> x / y

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-string">"""multiply numbers"""</span>
    <span class="hljs-keyword">return</span> x * y
</code></pre>
<p>Notice that instead of having your calculator program within a single function, we broke it into four independent functions (units). This is to ensure that each part of the program is independently tested. So if any of the units gives an error during testing, you can easily identify that unit and troubleshoot it without tampering with the other parts of your program.</p>
<p>As earlier mentioned, testing with <code>unittest</code> involves creating a subclass of the <code>unittest.TestCase</code> class and then defining methods within the subclass to test individual units of your program.</p>
<p>To show how this works, let's write a test for the <code>add</code> function in your calculator program. In your <code>unit-testing</code> folder, create a new file named <code>test_calculator.py</code> and then copy the following code into it:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest
<span class="hljs-keyword">import</span> calculator

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestCalculator</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_add</span>(<span class="hljs-params">self</span>):</span>
        self.assertEqual(calculator.add(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>), <span class="hljs-number">3</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">-1</span>, <span class="hljs-number">1</span>), <span class="hljs-number">0</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>), <span class="hljs-number">-2</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>), <span class="hljs-number">0</span>)
</code></pre>
<p>In lines one and two of your code, you imported the <code>unittest</code> and your <code>calculator</code> modules. You then created a <code>TestCalculator</code> class, which inherits from the <code>TestCase</code> class.</p>
<p>In line five of your code, you defined a <code>test_add</code> method within your class. The method just like every instance methods in Python takes <code>self</code> as its first argument. Since <code>self</code> is a reference of the <code>TestCalculator</code> class, it can access the <code>assertEqual</code> method provided by the <code>TestCase</code> class, which <code>TestCalculator</code> inherits from.</p>
<p>The <code>assertEqual</code> method checks if two values are equal. It has the following syntax:</p>
<pre><code class="lang-python">self.assertEqual(first, second, msg=<span class="hljs-literal">None</span>)
</code></pre>
<p>In the preceding syntax, <code>first</code> represents the value you want to test against the <code>second</code> value. <code>msg</code> is optional and it represents a custom message that you will receive if the assertion fails. If you don't provide a value for <code>msg</code>, you will receive a default message.</p>
<p>Now, let's use the explanation of the syntax to explain the use of <code>assertEqual</code> in your <code>test_add</code> method. In your first assertion, <code>self.assertEqual(add(1, 2), 3)</code> checks if the result of <code>add(1, 2)</code> is equal to 3. If the function returns 3, the test passes. Otherwise, it fails and outputs a message indicating the mismatch. This explanation is the same for the rest of your assertions.</p>
<p>Also, notice that you tested just representative values in your <code>test_add</code> method. This ensures that your test covers a wide range of possible inputs without redundant code. Here is a breakdown of the representative values in your <code>test_add</code> method:</p>
<ul>
<li><p>The addition of two positive numbers (<code>self.assertEqual(calculator.add(1, 2), 3)</code>).</p>
</li>
<li><p>The addition of a negative number and a positive number (<code>self.assertEqual(calculator.add(-1, 1), 0)</code>).</p>
</li>
<li><p>The addition of two negative numbers (<code>self.assertEqual(calculator.add(-1, -1), -2)</code>).</p>
</li>
<li><p>The addition of two zeros (<code>self.assertEqual(calculator.add(0, 0), 0)</code>).</p>
</li>
</ul>
<p>Now, to run your test, navigate to the <code>unit-testing</code> directory in your terminal and run the following command:</p>
<pre><code class="lang-bash">python -m unittest test_calculator.py
</code></pre>
<p>Running the preceding command will give you the following message in your terminal:</p>
<pre><code class="lang-bash">.
----------------------------------------------------------------------
Ran 1 <span class="hljs-built_in">test</span> <span class="hljs-keyword">in</span> 0.000s

OK
</code></pre>
<p>The output indicates that you ran a single test and it was successful.</p>
<p>To ensure that your test is working as expected, you go back to your <code>calculator.py</code> file and change the addition (<code>+</code>) operator in your <code>add</code> function to subtraction (<code>-</code>), like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-string">"""add numbers"""</span>
    <span class="hljs-keyword">return</span> x - y
</code></pre>
<p>Once you've made the changes, running your test again will raise an <code>AssertionError</code> showing that your test failed:</p>
<pre><code class="lang-bash">Traceback (most recent call last):
  File <span class="hljs-string">".../test_calculator.py"</span>, line 6, <span class="hljs-keyword">in</span> test_add
    self.assertEqual(calculator.add(1, 2), 3)
AssertionError: -1 != 3

----------------------------------------------------------------------
Ran 1 <span class="hljs-built_in">test</span> <span class="hljs-keyword">in</span> 0.000s
</code></pre>
<p>You may be wondering why you have to include the <code>unittest</code> module in your command instead of running <code>python test_calculator.py</code>. That's because you are yet to make your <code>test_calculator.py</code> file a standalone script. So running <code>python test_calculator.py</code> won't give you any output.</p>
<p>To make your <code>test_calculator.py</code> executable as a standalone script, you need to add the following to the bottom of your <code>test_calculator.py</code> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    unittest.main()
</code></pre>
<p>Also, the <code>unittest</code> module requires that you start the name of your test methods with the word <code>test</code>, otherwise, your test won't run as expected.</p>
<p>To try this, change the name of your <code>test_add</code> method to <code>add_test</code> like this:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestCalculator</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_test</span>(<span class="hljs-params">self</span>):</span>
        self.assertEqual(calculator.add(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>), <span class="hljs-number">3</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">-1</span>, <span class="hljs-number">1</span>), <span class="hljs-number">0</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>), <span class="hljs-number">-2</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>), <span class="hljs-number">0</span>)
</code></pre>
<p>Now, if you run the command <code>python test_calculator.py</code>, you will get a message similar to this:</p>
<pre><code class="lang-bash">----------------------------------------------------------------------
Ran 0 tests <span class="hljs-keyword">in</span> 0.000s

OK
</code></pre>
<p>Notice that the preceding output shows that zero tests ran. Now, change your method's name back to <code>test_add</code>. Also, change the operator in the <code>add</code> function of your <code>calculator.py</code> back to addition (<code>+</code>). Now, rerun the test with the command <code>python test_calculator.py</code> and compare your output to the preceding output.</p>
<p>It's a common practice for developers to handle invalid input by raising exceptions. So, it's important to write tests that check for these exceptions.</p>
<p>For example, Python will raise a <code>ZeroDivisionError</code> if you try to divide any number by zero. You can use the <code>unittest</code> module to test for such errors.</p>
<p>Now, modify your <code>test_calculator.py</code> file to include a test method for your <code>divide</code> function:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest
<span class="hljs-keyword">import</span> calculator

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestMathOperations</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_add</span>(<span class="hljs-params">self</span>):</span>
        self.assertEqual(calculator.add(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>), <span class="hljs-number">3</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">-1</span>, <span class="hljs-number">1</span>), <span class="hljs-number">0</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>), <span class="hljs-number">-2</span>)
        self.assertEqual(calculator.add(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>), <span class="hljs-number">0</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_divide</span>(<span class="hljs-params">self</span>):</span>
        self.assertEqual(calculator.divide(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>), <span class="hljs-number">5</span>)
        self.assertEqual(calculator.divide(<span class="hljs-number">9</span>, <span class="hljs-number">3</span>), <span class="hljs-number">3</span>)
        self.assertEqual(calculator.divide(<span class="hljs-number">-6</span>, <span class="hljs-number">2</span>), <span class="hljs-number">-3</span>)
        self.assertEqual(calculator.divide(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>), <span class="hljs-number">0</span>)
        <span class="hljs-keyword">with</span> self.assertRaises(ZeroDivisionError):
            calculator.divide(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    unittest.main()
</code></pre>
<p>In the preceding code, your new <code>test_divide</code> method tests representative values just like your <code>test_add</code> method. But there is new code at the end that uses <code>assertRaises</code>. <code>assertRaises</code> is another assert method provided by <code>unittest</code> to check if your code raises an exception. Here, you used the method to check for <code>ZeroDivisionError</code>.</p>
<p>So, if you run the tests now, you will get a message showing two dots (<code>..</code>) and indicating that you ran two successful tests:</p>
<pre><code class="lang-bash">..
----------------------------------------------------------------------
Ran 2 tests <span class="hljs-keyword">in</span> 0.000s

OK
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article has taught you the basics of unit testing in Python using the <code>unittest</code> testing framework.</p>
<p>You've learned the importance of independently testing individual units of your application and the reasons <code>unittest</code> is still a popular choice among Python developers. Also, you've learned how to write basic test cases for the <code>add</code> and <code>divide</code> functions in your simple calculator program.</p>
<p>With this knowledge, you can now confidently create tests that ensure your code behaves as expected, making it more robust and maintainable. I encourage you to apply these lessons by writing tests for the remaining <code>subtract</code> and <code>multiply</code> functions in your calculator program.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Mocking? Mocking in .NET Explained With Examples ]]>
                </title>
                <description>
                    <![CDATA[ Let's go on a journey to demystify the concept of mocking in .NET software development. Let's delve into how straightforward and accessible mocking truly is. Join me as we navigate through this subject, as I cover: Understanding mocking: Why it's ne... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/explore-mocking-in-net/</link>
                <guid isPermaLink="false">66bb888a6b3bd8d6bf25ae34</guid>
                
                    <category>
                        <![CDATA[ .NET ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Grant Riordan ]]>
                </dc:creator>
                <pubDate>Fri, 12 Apr 2024 19:37:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/Mocking-in-Dotnet.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let's go on a journey to demystify the concept of mocking in .NET software development. Let's delve into how straightforward and accessible mocking truly is. Join me as we navigate through this subject, as I cover:</p>
<ul>
<li>Understanding mocking: Why it's necessary for building a robust testing strategy.</li>
<li>Exploring some of the most common mocking libraries: Such as Moq, NSubstitute, FakeItEasy, and Rhino Mocks.</li>
<li>Mastering mocking techniques: Using each of these libraries, equipping you with the knowledge to choose the best mocking tool for your needs.</li>
</ul>
<p>The aim of this tutorial is to give you the knowledge to make up your own mind on which mocking library you prefer, so you can go forward and write some powerful tests in your application. </p>
<h2 id="heading-prerequisites-for-this-tutorial">Prerequisites for this tutorial</h2>
<ol>
<li>Understanding of C# programming</li>
<li>Understanding of C# Unit Testing</li>
<li>An IDE (Rider, Visual Studio, and so on), or Code Editor (VS Code, Sublime Text, Atom, and so on)</li>
</ol>
<h2 id="heading-getting-startedsetup">Getting Started/Setup</h2>
<p>To speed up the process, I've made a public GitHub repo available for this tutorial,. You can clone and use it on your local machine to follow along.</p>
<p>Simply navigate to <a target="_blank" href="https://github.com/grant-dot-dev/mocking-tutorial">this link</a> and clone the repo to your local machine.  </p>
<p>Quick refresher if you've forgotten to do that: go to the link above, and in the top right corner click "Code", and then copy the URL provided. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Find your local <strong>git</strong> folder, (if you don't have one, create one in your user root folder). Then in your preferred terminal navigate to your <strong>git</strong> older, and execute the following command.</p>
<pre><code class="lang-terminal">// (replacing &lt;url&gt; with the url)
git clone &lt;url&gt;
</code></pre>
<h2 id="heading-a-brief-overview-of-the-application">A Brief Overview of the Application</h2>
<p>The solution you've just cloned is a basic Web API project which references a class library with some Todo domain objects and services which will alter a list of todo items.   </p>
<p>For the purpose of this tutorial, these elements are stored in an in-memory list, rather than connecting to a database. But you can use a database or other forms of data persistence methods.</p>
<p>However, for the purpose of this tutorial, we're less concerned with persisting the data, and more so around mocking this service. </p>
<h2 id="heading-what-is-mocking">What Is Mocking?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/image-112.png" alt="Two arrows with text Real and Fake" width="600" height="400" loading="lazy">
<em>With mocking you won't tell the difference</em></p>
<p>Mocking in software development is the concept of simulating a behavior or returned object of a class, method or service that another part of the system under test depends on. </p>
<p>When testing a particular component or unit of code, it's often necessary to isolate it from its dependencies, such as databases, web services, or other classes, in order to ensure that the test focuses solely on the functionality of the unit being tested rather than concerning itself with external aspects of the code.</p>
<p>Mocking allow developers to create mock objects or dummy implementations of these dependencies that behave in a predetermined way, mimicking the behavior of the real objects.</p>
<p>By using mocked objects or methods, we can control the input and output of the dependencies. This makes it a lot easier to test different scenarios, where business logic is dependent on the outcome of a dependency. </p>
<h3 id="heading-example">Example</h3>
<p>Let's say we have a API endpoint that calls a repository which connects to a database. Our API response type depends on the returned value from the repository: we either return a 400 or a 200 response from our API.</p>
<p>We can simply mock the repository return value, and test that our API returns the correct response in both scenarios without having to actually touch our database at all. </p>
<p>In essence, mocking helps developers write more reliable and efficient tests by isolating the code under test and providing predictable behaviour for its dependencies, thereby improving the overall quality of the software.</p>
<h2 id="heading-what-are-the-benefits-of-mocking">What Are the Benefits of Mocking?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/image-113.png" alt="Image showing jigsaw pieces, with one highlighted saying Benefits" width="600" height="400" loading="lazy">
<em>Benefits</em></p>
<h3 id="heading-code-isolation">Code Isolation</h3>
<p>As I've already explained, mocking dependencies allows for isolation of code for testing. By mocking the dependencies, you can assert the points of failure in the code under test, and not the dependencies themselves (unless you mock them incorrectly – which hopefully this tutorial will help you avoid). </p>
<h3 id="heading-faster-testing">Faster Testing</h3>
<p>By replacing real dependencies with mocked implementations, testing can be performed faster. You're not battling with inconsistencies, unreliable or unpredictable outcomes from those dependencies. It eliminates the need for setting up and tearing down external sources, which can sometimes be complex and time consuming. </p>
<h3 id="heading-deterministic-testing">Deterministic Testing</h3>
<p>Mock objects offer a controlled environment, allowing developers to specify the exact behavior and responses of dependencies. This approach means that the tests are consistent, making it easier to find bugs and debug issues, especially those adopting a TDD (Test Driven Development) approach. </p>
<h3 id="heading-parallel-testing">Parallel Testing</h3>
<p>Mocking enables parallel testing (multiple tests being ran at the same time) by removing dependencies on external resources that may be limited or inaccessible during testing. </p>
<p>For example if you weren't mocking your database connection layer, trying to run tests in parallel may cause inconsistent pass/fail metrics, as another test could be affecting the database table you're utilizing in another test. Mocking this layer means your tests are now agnostic to this layer, and can be ran at the same time. </p>
<h3 id="heading-reduced-test-maintenance">Reduced Test Maintenance</h3>
<p>Since mock objects encapsulate the behavior of dependencies, changes to those dependencies do not necessarily require updates to the tests themselves. This reduces the maintenance overhead associated with evolving codebases and dependencies.</p>
<h3 id="heading-enhanced-test-coverage">Enhanced Test Coverage</h3>
<p>Mocking allows developers to simulate a wide range of scenarios and edge cases. By controlling the behavior of dependencies, developers can ensure that their tests exercise all relevant paths through the code, removing any real life or physical limitations.</p>
<h2 id="heading-things-to-be-aware-of-with-mocking">Things To Be Aware of With Mocking</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-20.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Complexity:</strong> Sometimes when mocking/testing complex areas of the application, mocking can also become complex. However, if the system is too difficult to mock, you may need to reassess your architecture. </p>
<p><strong>Learning Curve:</strong> It requires an understanding of the syntax and concepts of the mocking library, which can be challenging for developers who are new to unit testing or the specific framework.</p>
<p><strong>Over-specification</strong>: Mocking can lead to over-specifying the behavior of the code under test. This means that tests may become tightly coupled to the implementation details, making them brittle and prone to breaking when the implementation changes. It's essential to strike a balance between verifying behavior and focusing on the desired outcomes.</p>
<p><strong>Be mindful of false-positive tests:</strong> While mocking allows you to isolate units of code, it may also create a false sense of security. Mocks simulate dependencies, but they may not fully replicate the behaviour of the real dependencies. <a target="_blank" href="https://www.browserstack.com/guide/integration-testing">Integration</a> tests or <a target="_blank" href="https://www.browserstack.com/guide/end-to-end-testing">end-to-end tests</a> are still necessary to verify the system's behavior as a whole.  </p>
<h2 id="heading-popular-net-mocking-libraries">Popular .NET Mocking Libraries</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-25.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here are some popular .NET testing libraries:</p>
<ul>
<li>FakeItEasy</li>
<li>NSubstitute</li>
<li>Moq</li>
<li>Rhino Mocks</li>
</ul>
<p>These are just a list of the most commonly used .NET mocking libraries available online, but there are many more. I'd highly recommend using one of these as they have a larger community, more reputable code base, and good documentation (vital when starting out).   </p>
<p>Each of these mocking libraries have their own syntax for creating mocks of objects however they all follow the same principles. </p>
<ol>
<li>Declare the object/type/service you'd like to mock</li>
<li>How you want that object/type/service to run (the implementation)</li>
<li>What is the returned value (where necessary). </li>
</ol>
<h2 id="heading-looking-at-the-tests">Looking at the Tests</h2>
<p>If you open the solution, and navigate to the "Test" project, you can see that we have four files with each of the different mocking library tests in there. </p>
<ol>
<li>FakeItEasyApiTests.cs</li>
<li>MoqApiTests.cs</li>
<li>NSubstituteApiTests.cs</li>
<li>RhinoMocksApiTests.cs</li>
</ol>
<p>Within these files, you will see that we have four very basic XUnit tests. I've kept them brief and simple for the purpose of this tutorial. </p>
<h2 id="heading-deep-dive-into-the-test-structure">Deep Dive Into the Test Structure</h2>
<p>Each test file uses a constructor to initialize a private version of their respectable services, and you can see how these differ from one library to the next, yet still follow the same concepts. </p>
<pre><code class="lang-csharp"><span class="hljs-comment">// FakeItEasy</span>
 _fakeTodoService = A.Fake&lt;ITodoService&gt;();

<span class="hljs-comment">// NSubstitute</span>
  _substituteTodoService = Substitute.For&lt;ITodoService&gt;();

<span class="hljs-comment">// Moq</span>
 _mockTodoService = <span class="hljs-keyword">new</span> Mock&lt;ITodoService&gt;();

<span class="hljs-comment">// Rhino Mocks</span>
 _mockTodoService = MockRepository.GenerateMock&lt;ITodoService&gt;();
</code></pre>
<p>Choosing the "right" mocking library all comes down to personal preference, and what you feel is easier to write, work with and read/understand.  </p>
<p>Some may find the use of words like <code>Fake</code>, or <code>Substitute.For</code> easier to comprehend or read. Whereas others may find the <code>A.Fake</code> unintuitive and prefer <code>new Mock&lt;type&gt;</code> more obvious.</p>
<h2 id="heading-arrange-act-and-assert">Arrange, Act and Assert</h2>
<p>Following the testing principle of AAA (Arrange, Act and Assert) we can carefully structure our tests, making it obvious what we're doing and where. </p>
<p>The AAA approach to testing involves three steps:</p>
<ol>
<li><strong>Arrange</strong>: Set up the test environment, mocked services/external dependencies.</li>
<li><strong>Act</strong>: Perform the action being tested.</li>
<li><strong>Assert</strong>: Verify the expected outcome.</li>
</ol>
<h2 id="heading-using-mocks-to-simulate-returned-items">Using Mocks to Simulate Returned Items</h2>
<p>Let's test the <code>getAll</code> (GetAllTodoItems) endpoint by mocking the <code>TodoService.GetAllTodos</code> method to return a stubbed list of tasks. </p>
<p>This approach eliminates the need to set up and seed a database for each test scenario, ensuring focused testing of API endpoint returning values against specific criteria. </p>
<p>Mocks provide an ideal solution, allowing us to simulate the desired behavior without interference from other tests.   </p>
<p>We can do this like so (remember the full code is available in the repo):</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// FakeItEasy</span>
A.CallTo(() =&gt; _fakeTodoService.GetAllTodos()).Returns(expectedTodos);

<span class="hljs-comment">// NSubstitute</span>
 _substituteTodoService.GetAllTodos().Returns(expectedTodos);

 <span class="hljs-comment">// Moq</span>
 _moqTodoService.Setup(s =&gt; s.GetAllTodos()).Returns(expectedTodos);

 <span class="hljs-comment">// Rhino Mocks</span>
 _mockTodoService.Stub(s =&gt; s.GetAllTodos()).Return(expectedTodos);
</code></pre>
<h3 id="heading-what-are-these-methods-doing">What are these methods doing?</h3>
<p>A common feature you will see across the majority of libraries is the usage of lambda functions to dictate which method is being mocked.</p>
<p>The lambda function provided in the setup method is essentially a configuration step that defines what action should be taken when the mocked method is called. This configuration is stored and applied when the mocked method is invoked during the test.  </p>
<p>Let's break it down, what we're doing:</p>
<ol>
<li><p>The lambda specifies which method on the mocked service we wish to configure/setup.  </p>
</li>
<li><p>The lambda we pass in isn't ran straight away by the setup method. We're not telling the test to run the method immediately; we're saying, "Remember this instruction/setup for when the actual method is called during the test."  </p>
</li>
<li><p>When the method we're mocking gets called during the test then it checks if the call signature matches a setup configuration we've provided.  If it matches, the test follows the instructions given during setup. </p>
</li>
</ol>
<h3 id="heading-important-notes">Important Notes:</h3>
<p>NSubstitute, on the other hand, allows the developer to mock the method directly on the fake object. This means that you can access the fake <code>GetAllTodos</code> method and simply set the return value to your expected value.   </p>
<p>Although Moq uses a Setup method, it differs ever so slightly from the other methods. Moq internally creates a proxy object that represents the mocked object, and exposes a <code>.Object</code> property to access it. We'll see how this works in the next part. </p>
<h2 id="heading-how-to-call-the-system-under-test-sut">How to Call The System Under Test (SUT)</h2>
<pre><code class="lang-csharp"><span class="hljs-comment">// FakeItEasy</span>
<span class="hljs-keyword">var</span> sut = <span class="hljs-keyword">new</span> TodoController(_fakeTodoService);

<span class="hljs-comment">// NSubstitute</span>
<span class="hljs-keyword">var</span> sut = <span class="hljs-keyword">new</span> TodoController(_substituteTodoService);

<span class="hljs-comment">// Moq -- slightly different to the others</span>
 <span class="hljs-keyword">var</span> sut = <span class="hljs-keyword">new</span> TodoController(_moqTodoService.Object);

<span class="hljs-comment">// Rhino Mocks</span>
<span class="hljs-keyword">var</span> sut = <span class="hljs-keyword">new</span> TodoController(_mockTodoService);
</code></pre>
<p>In three of the four libraries, you can pass the mocked object directly. However, Moq requires accessing the <code>.Object</code> property on the mock to use it. Thus, we passed <code>moqTodoService.Object</code> as an argument to the controller.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>an image showing that all the tests passed</em></p>
<p>Running the tests, you can see they all pass. Should you change any of the code in the repository, it would not make any difference as the repo is mocked in these tests. Have a go, try changing the repo functionality and re-running the tests, they will continue to pass.   </p>
<p>We are concentrating on the functionality of the endpoint, not what the mocked repo is doing, and this is the beauty of mocking.   </p>
<h2 id="heading-the-options-with-mocking-are-endless">The Options with Mocking Are Endless</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Mocking doesn't just allow us to set what is returned from a mocked object, it can also allow us to mock the implementation, including the ability to throw specific errors so we can test our API error handling and unhappy paths too.</p>
<p>This is illustrated in the <code>Delete_Returns500_AndErrorMessageThrown_WhenExceptionThrown</code> test within each library test file. </p>
<pre><code class="lang-csharp"><span class="hljs-comment">// FakeItEasy</span>
A.CallTo(() =&gt; _fakeTodoService.Delete(<span class="hljs-number">1</span>)).Throws(<span class="hljs-keyword">new</span> Exception(errorMessage));

<span class="hljs-comment">// NSubstitute</span>
_substituteTodoService.When(x =&gt; x.Delete(<span class="hljs-number">1</span>)).Do(x =&gt; <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Exception(errorMessage));

<span class="hljs-comment">// Moq</span>
_moqTodoService.Setup(s =&gt; s.Delete(<span class="hljs-number">1</span>)).Throws(<span class="hljs-keyword">new</span> Exception(errorMessage));

<span class="hljs-comment">// Rhino Mocks</span>
 _mockTodoService.Stub(s =&gt; s.Delete(<span class="hljs-number">1</span>)).Throw(<span class="hljs-keyword">new</span> Exception(errorMessage));
</code></pre>
<p>Using the different libraries, we can make the <code>Delete</code> method on the service throw whatever exception we'd like to. This is ideal for when you want to return different status codes, or handle errors in different ways depending on the type of exception thrown. </p>
<p>As an example we could change <code>Throws(new Exception(errorMessage)</code> to <code>Throws(new UnauthorizedAccessException()</code> and test that if a 401 status code is returned when thrown.</p>
<h2 id="heading-global-setup">Global Setup</h2>
<p>You can assign multiple configurations to the same method. This is great in situations where you want to set up all your configurations of the mocked object in one place. For example, in the test class constructor. </p>
<p>In some test frameworks (like NUnit) you can use a <code>[OneTimeSetUp]</code> attribute above your method, which is ran before your test cases, or simply use your test class constructor.  </p>
<p>In this scenario you could do something (in Moq) like:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MoqApiTests</span>(<span class="hljs-params"></span>)</span>
{
        _mockTodoService = <span class="hljs-keyword">new</span> Mock&lt;ITodoService&gt;();
        _mockTodoService.Setup(x =&gt; x.Delete(<span class="hljs-number">1</span>)).Throws(<span class="hljs-keyword">new</span> Exception(<span class="hljs-string">"This is a generic exception"</span>));
        _mockTodoService.Setup(x =&gt; x.Delete(<span class="hljs-number">2</span>)).Throws(<span class="hljs-keyword">new</span> UnauthorizedAccessException(<span class="hljs-string">"You cannot perform this action on this item"</span>));
}
</code></pre>
<p>In this example, we demonstrate setting up mocked service calls to the same method with various arguments, each causing it to throw different exceptions. </p>
<p>This approach is beneficial for testing different outcomes when different exceptions occur in separate tests, without cluttering our test code with repetitive setup. </p>
<p>For example:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Test 1</span>
<span class="hljs-keyword">var</span> result = TodoController.Delete(<span class="hljs-number">1</span>);
<span class="hljs-comment">// Assert handles general exception</span>

<span class="hljs-comment">// Test 2</span>
<span class="hljs-keyword">var</span> result = TodoController.Delete(<span class="hljs-number">2</span>); 
<span class="hljs-comment">// Assert handles UnauthorizedAccessException</span>
</code></pre>
<p>I prefer to set up mocks within each individual tests to ensure there are no external factors influencing the mock. </p>
<p>This way, I can easily identify what is being mocked within the test without searching for the mocked object and setup elsewhere.</p>
<h2 id="heading-what-if-i-dont-care-what-im-passing-in">What If I Don't Care What I'm Passing In?</h2>
<p>In our deletion examples, we consistently passed an ID to the mock implementation. Consequently, if we were to call the method with a different ID like <code>101</code> through the <code>TodoController.DeleteTodoItem</code> call, we wouldn't receive the same result. </p>
<p>This is because we explicitly instructed the mocked object to throw an error when the stubbed method is called with an ID of 1.</p>
<p>To address this issue, we can be less specific. Each library has its own syntax for this, enabling us to specify that if any integer is passed to the method, it will throw a particular exception.</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// FakeItEasy</span>
A.CallTo(() =&gt; _fakeTodoService.Delete(A&lt;<span class="hljs-keyword">int</span>&gt;._)).Throws( <span class="hljs-keyword">new</span> Exception(errorMessage));

<span class="hljs-comment">// NSubstitute</span>
_substituteTodoService.When(x =&gt; x.Delete(Arg.Any&lt;<span class="hljs-keyword">int</span>&gt;())).Do(x =&gt; <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Exception(errorMessage));

<span class="hljs-comment">// Moq</span>
_mockTodoService.Setup(s =&gt; s.Delete(It.IsAny&lt;<span class="hljs-keyword">int</span>&gt;())).Throws(<span class="hljs-keyword">new</span> Exception(errorMessage));

<span class="hljs-comment">// Rhino Mocks</span>
_mockTodoService.Stub(s =&gt; s.Delete(Arg&lt;<span class="hljs-keyword">int</span>&gt;.Is.Anything)).Throw(<span class="hljs-keyword">new</span> Exception(errorMessage));
</code></pre>
<p>This code indicates that when any argument of type <code>int</code> is passed, it should throw this exception.</p>
<p>NSubstitute differs slightly in syntax: it requires explicit instruction to throw the specified error when encountering this scenario, unlike when were were informing it to return an object. This difference stems from the internal mechanisms of the library.</p>
<h2 id="heading-asserting-mocks-are-called">Asserting Mocks Are Called</h2>
<p>In some cases, you might want to verify that a mocked service is called with the correct arguments. This is particularly useful when dealing with a "fire-and-forget" service. </p>
<p>In this scenario, your API endpoint is called, and while it always returns true, it also triggers a service to perform some action independently, which doesn't affect the API's return type (perhaps an asynchronous notification service).</p>
<p>This is one of the few instances where you may want to perform a quick sanity check to ensure that your "fire-and-forget" service is invoked (although ideally, you'd conduct an integration test with that service).</p>
<p>If you take a look at the <code>DeleteTodoItem</code> endpoint, and the <code>DeleteAPI_CallsNotificationService_WithTaskId_AndUserId</code> test within each test file you can see full examples of how this can be done.   </p>
<p>We are verifying that when we call the <code>DeleteTodoItem</code>, on our happy path, the <code>NotificationService.NotifyUserTaskCompleted</code> is called with the ID of the item for deletion, and the hard-coded user ID.  </p>
<p>As an exercise, you could create a user service which returns an ID of logged in user, and this can be used to pass the ID to the service. This can also be mocked in the test. </p>
<pre><code class="lang-csharp"> <span class="hljs-comment">// FakeItEasy</span>
  A.CallTo(() =&gt; _fakeNotificationService.NotifyUserTaskCompleted(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>)).MustHaveHappened(<span class="hljs-number">1</span>, Times.Exactly);

<span class="hljs-comment">// NSubstitute _notificationService.Received().NotifyUserTaskCompleted(1,1);</span>

<span class="hljs-comment">// Moq </span>
 _moqNotificationService.Verify(x =&gt; x.NotifyUserTaskCompleted(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>)); <span class="hljs-comment">// Defaults to Times.AtLeastOnce</span>

<span class="hljs-comment">// Rhino Mock</span>
_mockNotificationService.AssertWasCalled(x=&gt;x.NotifyUserTaskCompleted(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>));
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, the versatility of mocked objects offers a myriad of applications, proving indispensable in the testing of individual units of code. </p>
<p>While I've covered several functionalities and validations achievable with mocks, there are more, such as method call order and negative validation.  </p>
<p>In my view, the choice of a mocking library for a project is subjective, with no definitive right or wrong option. While some libraries may offer more convenient extensions or clearer syntax, the decision ultimately boils down to personal preference.   </p>
<p>My hope is that this tutorial has provided you with a glimpse into the world of mocking and shed light on the syntax variances across different libraries.</p>
<p>As always, don't hesitate to reach out (links in bio). </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Unit Tests in Java ]]>
                </title>
                <description>
                    <![CDATA[ Let's say you are developing an application. After long hours of coding, you manage to create some cool features. Now, you want to make sure the features are working as you want. This involves testing if each and every piece of code works as expected... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/java-unit-testing/</link>
                <guid isPermaLink="false">66d8515c39c4dccc43d4d4c1</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kunal Nalawade ]]>
                </dc:creator>
                <pubDate>Mon, 03 Apr 2023 15:37:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/photo-1498050108023-c5249f4df085.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let's say you are developing an application. After long hours of coding, you manage to create some cool features. Now, you want to make sure the features are working as you want.</p>
<p>This involves testing if each and every piece of code works as expected. This procedure is known as Unit Testing. Different languages provide their own frameworks for testing.</p>
<p>In this article, I am going to show you how to write unit tests in Java. I'll first explain what testing involves and some concepts you'll need to know. Then, I'll show a few examples to help you understand better.</p>
<p>For this article, I assume you are familiar with Java and the IntelliJ IDE.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>For this project, I'll be using IntelliJ IDE. If you don't have it, follow <a target="_blank" href="https://www.jetbrains.com/help/idea/installation-guide.html#standalone">this</a> guide to install the IDE.</p>
<p>In this project, we'll be using the JUnit and Mockito libraries for testing. These are the most commonly used libraries for testing in Java. You'll understand how these libraries are used as you go through the post.</p>
<p>To setup JUnit, follow these steps <a target="_blank" href="https://www.jetbrains.com/help/idea/junit.html">as described in this guide</a>:</p>
<ol>
<li><p>From the main menu, select File &gt; New &gt; Project.</p>
</li>
<li><p>Select <strong>New Project.</strong> Specify a name for the project, I'll give it junit-testing-tutorial.</p>
</li>
<li><p>Select <strong>Maven</strong> as a build tool and in language, select Java.</p>
</li>
<li><p>From the <strong>JDK</strong> list, select the JDK you want to use in the project.</p>
</li>
<li><p>Click <strong>Create.</strong></p>
</li>
<li><p>Open <strong>pom.xml</strong> in the root directory of your project.</p>
</li>
<li><p>In pom.xml, press <code>⌘ + N</code>, and select <strong>Add dependency.</strong></p>
</li>
<li><p>This will open a tool window, type <code>org.junit.jupiter:junit-jupiter</code> in the search field. Locate the necessary dependency and click <strong>Add</strong> next to it.</p>
</li>
<li><p>Now, click <strong>Load Maven Changes</strong> in the notification that appears in the top-right corner in the editor.</p>
</li>
</ol>
<p>Now, to set up Mockito, add these two dependencies in your <code>pom.xml</code>:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mockito<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mockito-inline<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.2.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>compile<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mockito<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mockito-junit-jupiter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.2.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>compile<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</code></pre>
<p><strong>Note</strong>: The version may differ depending on the time you are reading this post.</p>
<p>To complete the setup, create a class <code>Welcome</code> and define your main function there.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-12-at-6.14.33-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Folder Structure and the Main Method</em></p>
<h2 id="heading-what-is-unit-testing">What is Unit Testing?</h2>
<p>Unit Testing involves testing each and every component of your code to see if they work as expected. It isolates each individual method of your code and performs tests on it. Unit tests helps make sure that your software is working as expected before releasing it.</p>
<p>As a developer, you'll write unit tests as soon as you finish writing a piece of code. Now, you might ask, isn't that the job of a tester? In a way, yes, a tester is responsible for testing software. But, covering every line of code adds a lot of pressure on the tester. So, it's a best practice for developers to write tests for their own code as well.</p>
<p>The goal of unit testing is to make sure that any new functionality does not break the existing functionality. It also helps identify any issues or bugs earlier in the development process and helps ensure that code meets quality standards set by the organisation.</p>
<h3 id="heading-dos-and-donts-of-unit-testing">Do's and Don'ts of Unit Testing</h3>
<p>Remember the following guidelines while writing tests for your methods:</p>
<ul>
<li><p>Do test if the expected output of a method matches the actual one.</p>
</li>
<li><p>Do test whether the function calls made inside the method are occurring the desired number of times.</p>
</li>
<li><p>Do not try to test code that is not a part of the method under test.</p>
</li>
<li><p>Do not make API calls, database connections, or network requests while writing your tests.</p>
</li>
</ul>
<p>Now, let's go over some concepts you need to know before we jump into writing tests.</p>
<h3 id="heading-assertions">Assertions</h3>
<p>Assertions determine whether your test passes or fails. They compare the expected return value of a method with the actual one. There are a number of assertions you can make at the end of your test.</p>
<p>The <code>Assertions</code> class in JUnit consists of static methods that provide various conditions deciding whether the test passes or not. We'll see these methods as I walk you through each example.</p>
<h3 id="heading-mocking">Mocking</h3>
<p>The class whose methods you are testing may have some external dependencies. As mentioned before, you should not try to test code that is not part of the function under test.</p>
<p>But in cases where your function uses an external class, it is a good practice to mock that class – that is, have mock values instead of the actual ones. We'll use the Mockito library for this purpose.</p>
<h3 id="heading-method-stubbing">Method Stubbing</h3>
<p>External dependencies may not be limited to just classes, but to certain methods as well. <a target="_blank" href="https://en.wikipedia.org/wiki/Method_stub">Method stubbing</a> should be done when your function is calling an external function in its code. In this case, you make that function return the value you want instead of calling the actual method.</p>
<p>For instance, the method you're testing (A) is calling an external method (B) in its implementation. B makes a database query, fetching all students with marks greater than 80. Making an actual database call isn't a good practice here. So, you stub the method and make it return a dummy list of students you need for testing.</p>
<p>You'll understand this better with examples. There are many other concepts that are a part of testing in Java. But, for now these three are enough for you to get started.</p>
<h2 id="heading-steps-to-perform-while-testing">Steps to Perform While Testing</h2>
<ol>
<li><p>Initialize the necessary parameters you'll need to perform the test.</p>
</li>
<li><p>Create mock objects and stub any methods if required.</p>
</li>
<li><p>Call the method you are testing with the parameters you initialized in Step 1.</p>
</li>
<li><p>Add an assertion to check the outcome of your test. This will decide if the test passes.</p>
</li>
</ol>
<p>You'll understand these steps more with examples. Let's start with a basic test first.</p>
<h2 id="heading-how-to-write-the-first-test">How to Write the First Test</h2>
<p>Let's write a simple function that compares two numbers. It returns <code>1</code> if the first number is greater than the second and returns <code>-1</code> otherwise.</p>
<p>We'll put this function inside a <code>Basics</code> class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Basics</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n1, <span class="hljs-keyword">int</span> n2)</span> </span>{
        <span class="hljs-keyword">if</span> (n1 &gt; n2) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
    }
}
</code></pre>
<p>Pretty simple! Let's write the test for this class. All your tests should be located inside the test folder.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-13-at-5.12.04-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Folder Structure</em></p>
<p>Inside the test folder, create a class <code>BasicTests</code> where you'll write your tests for this class. The name of the class doesn't matter, but it is a good practice to segregate tests according to each class. Also, follow a similar folder structure as the one in your main code.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BasicTests</span> </span>{
    <span class="hljs-comment">// Your tests come here</span>
}
</code></pre>
<p>Unit tests are basically a set of methods you define that test each method of your class. Inside the above class, create a method <code>compare()</code> with a return type of <code>void</code>. Again, you can name the method anything you want.</p>
<pre><code class="lang-python"><span class="hljs-meta">@Test</span>
public void compare() {

}
</code></pre>
<p>The <code>@Test</code> annotation indicates that this method is to be run as a test case.</p>
<p>Now, to test the method, you need to create the object of the above class and call the method by passing some values.</p>
<pre><code class="lang-java">Basics basicTests = <span class="hljs-keyword">new</span> Basics();
<span class="hljs-keyword">int</span> value = basicTests.compare(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>);
</code></pre>
<p>Now, use the <code>assertEquals()</code> method of the <code>Assertions</code> class to check if the expected value matches the expected one.</p>
<pre><code class="lang-java">Assertions.assertEquals(<span class="hljs-number">1</span>, value);
</code></pre>
<p>Our test should pass, as the value returned by the method matches the expected one. To check it, run the test by right clicking the green arrow next to the test method.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-13-at-5.30.14-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Running a Test</em></p>
<p>Your test results will be shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-13-at-5.32.06-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Test Results</em></p>
<h2 id="heading-more-test-examples">More Test Examples</h2>
<p>In the above test, we only tested one scenario. When there's branching in the function, you need to write tests for each condition. Let's introduce some more branching in the above function.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n1, <span class="hljs-keyword">int</span> n2)</span> </span>{
    <span class="hljs-keyword">if</span> (n1 &gt; n2) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (n1 &lt; n2) <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>We have already tested the first branch, so let's write tests for the other two.</p>
<pre><code class="lang-python"><span class="hljs-meta">@Test</span>
<span class="hljs-meta">@DisplayName("First number is less than the second")</span>
public void compare2() {
    Basics basicTests = new Basics();
    int value = basicTests.compare(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>);
    Assertions.assertEquals(<span class="hljs-number">-1</span>, value);
}
</code></pre>
<p>The <code>@DisplayName</code> annotation displays the text instead of the method name below. Let's run the test.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-13-at-6.01.15-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Test Passed</em></p>
<p>For the case where the two numbers are equal:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Test</span>
<span class="hljs-meta">@DisplayName("First number is equal to the second")</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">compare3</span><span class="hljs-params">()</span> </span>{
    Basics basicTests = <span class="hljs-keyword">new</span> Basics();
    <span class="hljs-keyword">int</span> value = basicTests.compare(<span class="hljs-number">2</span>, <span class="hljs-number">2</span>);
    Assertions.assertEquals(<span class="hljs-number">0</span>, value);
}
</code></pre>
<h3 id="heading-sorting-an-array">Sorting an Array</h3>
<p>Now, let's write the test for the following code that sorts an array.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sortArray</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] array)</span> </span>{
        <span class="hljs-keyword">int</span> n = array.length;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n-<span class="hljs-number">1</span>; i++) {
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; n-i-<span class="hljs-number">1</span>; j++) {
                <span class="hljs-keyword">if</span> (array[j] &gt; array[j+<span class="hljs-number">1</span>]) {
                    <span class="hljs-keyword">int</span> temp = array[j];
                    array[j] = array[j+<span class="hljs-number">1</span>];
                    array[j+<span class="hljs-number">1</span>] = temp;
                }
            }
        }
    }
</code></pre>
<p>To write the test for this, we'll follow a similar procedure: call the method and pass an array to it. Use the <code>assertArrayEquals()</code> to write your assertion.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Test</span>
<span class="hljs-meta">@DisplayName("Array sorted")</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sortArray</span><span class="hljs-params">()</span> </span>{
    Basics basicTests = <span class="hljs-keyword">new</span> Basics();
    <span class="hljs-keyword">int</span>[] array = {<span class="hljs-number">5</span>, <span class="hljs-number">8</span>, <span class="hljs-number">3</span>, <span class="hljs-number">9</span>, <span class="hljs-number">1</span>, <span class="hljs-number">6</span>};
    basicTests.sortArray(array);
    Assertions.assertArrayEquals(<span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[]{<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>}, array);
}
</code></pre>
<p>One challenge for you: write code that reverses a string and write a test case for it.</p>
<h2 id="heading-how-to-create-mocks-and-stubs-for-testing">How to Create Mocks and Stubs for Testing</h2>
<p>We have seen a few basic examples of unit tests where you made simple assertions. However, the functions you are testing may contain external dependencies like model classes and database or network connections.</p>
<p>Now, you can't make actual connections in your tests, as it would be very time consuming. In such cases, you mock such implementations. Let's see a few examples of mocking.</p>
<h3 id="heading-mocking-a-class">Mocking a Class</h3>
<p>Let's have a class User with the following properties:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String username;
    <span class="hljs-keyword">private</span> String password;
    <span class="hljs-keyword">private</span> String role;
    <span class="hljs-keyword">private</span> List&lt;String&gt; posts;    
}
</code></pre>
<p>Click on <code>⌘ + N</code> to generate getters and setters for the above properties.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-18-at-8.34.34-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Generate Options</em></p>
<p>Let's take a new class <code>Mocking</code> that uses the above object.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mocking</span> </span>{
    User user;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setUser</span><span class="hljs-params">(User user)</span> </span>{
        <span class="hljs-keyword">this</span>.user = user;
    }
}
</code></pre>
<p>This class has a method that assigns certain permissions based on the user's role. It returns <code>1</code> if the permission is assigned successfully, else it returns <code>-1</code>.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">assignPermission</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span>(user.getRole().equals(<span class="hljs-string">"admin"</span>)) {
            String username = user.getUsername();
            System.out.println(<span class="hljs-string">"Assign special permissions for user "</span> + username);
            <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
        } <span class="hljs-keyword">else</span> {
            System.out.println(<span class="hljs-string">"Cannot assign permission"</span>);
            <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
        }
    }
</code></pre>
<p>For demo purposes, I have only added <code>println()</code> statements. The actual implementation may involve setting certain properties.</p>
<p>In the tests file, we'll add an <code>@ExtendWith</code> annotation at the top since we are using Mockito. I have not shown the imports here as IntelliJ does them automatically.</p>
<pre><code class="lang-python"><span class="hljs-meta">@ExtendWith(MockitoExtension.class)</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockingTests</span> {

}</span>
</code></pre>
<p>So how do we write the test for the method? We'll need to mock the <code>User</code> object. You can do this by adding a <code>@Mock</code> annotation while declaring the object.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Mock</span>
User user;
</code></pre>
<p>You can also use the <code>mock()</code> method, as it's similar.</p>
<pre><code class="lang-java">User user = mock(User.class);
</code></pre>
<p>Let's write the test method.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Test</span>
<span class="hljs-meta">@DisplayName("Permission assigned successfully")</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">assignPermissions</span><span class="hljs-params">()</span> </span>{
    Mocking mocking = <span class="hljs-keyword">new</span> Mocking();
    Assertions.assertEquals(<span class="hljs-number">1</span>, mocking.assignPermission());
}
</code></pre>
<p>When you run the test, it throws a <code>NullPointerException</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-18-at-8.51.26-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>User Object is Null</em></p>
<p>This is because the user object hasn't been initialised yet. The method you called wasn't able to use the mocked object. For this, you'll need to call the <code>setUser</code> method.</p>
<pre><code class="lang-java">mocking.setUser(user);
</code></pre>
<p>Now, the test gives the following error as the mocked object is initially filled with null values.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-18-at-8.53.53-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Return Value of getRole() is Null</em></p>
<p>Does this mean you need to fill actual values in the mock object? No, you just need the <code>getRole()</code> method to return a non-null value. For that, we'll use <strong>method stubbing.</strong></p>
<pre><code class="lang-python">when(user.getRole()).thenReturn(<span class="hljs-string">"admin"</span>);
</code></pre>
<p>Using <code>when()...thenReturn()</code> tells the test to return a value when a method is called. You should stub methods only for mocked objects.</p>
<p>We'll do the same for the <code>getUsername()</code> method.</p>
<pre><code class="lang-python">when(user.getUsername()).thenReturn(<span class="hljs-string">"kunal"</span>);
</code></pre>
<p>Now, if you run the test, it will pass.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-18-at-9.00.21-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Test Passed</em></p>
<h3 id="heading-method-stubbing-example">Method Stubbing Example</h3>
<p>In the above example, I simply stubbed getter methods to demonstrate method stubbing. Instead of stubbing getters, you could set the role and username with a parameterised constructor or setter methods if they are available.</p>
<pre><code class="lang-java">user.setRole(<span class="hljs-string">"admin"</span>);
user.setUsername(<span class="hljs-string">"kunal"</span>);
</code></pre>
<p>But what if the user class has a method that returns all the posts containing a certain word in them?</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;String&gt; <span class="hljs-title">getAllPostsContainingWord</span><span class="hljs-params">(String word)</span> </span>{
        List&lt;String&gt; filteredPosts = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        <span class="hljs-keyword">for</span>(String post: posts) {
            <span class="hljs-keyword">if</span>(post.contains(word))
                filteredPosts.add(post);
        }
        <span class="hljs-keyword">return</span> filteredPosts;
    }
</code></pre>
<p>We want this method to return all posts containing the word "awesome". If you call the actual implementation of this method, it might take a long time as the number of posts could be huge. Also, if you are mocking the User object, the posts array would be null.</p>
<p>In this case, you stub the method and make it return the list you want.</p>
<pre><code class="lang-java">List&lt;String&gt; filteredPosts = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
filteredPosts.add(<span class="hljs-string">"Awesome Day"</span>);
filteredPosts.add(<span class="hljs-string">"This place is awesome"</span>);
when(user.getAllPostsContainingWord(<span class="hljs-string">"awesome"</span>)).thenReturn(filteredPosts);
</code></pre>
<h3 id="heading-method-stubbing-in-database-queries">Method Stubbing in Database Queries</h3>
<p>Let's see how to test methods that involve making database connections. First, create a class <code>ApplicationDao</code> that contains all the methods performing database queries.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationDao</span> </span>{  }
</code></pre>
<p>Define a method that fetches the user by <code>id</code> and returns <code>null</code> if the user is not found.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getUserById</span><span class="hljs-params">(String id)</span> </span>{
    <span class="hljs-comment">// Make database query here        </span>
}
</code></pre>
<p>Create another method to save a user into the database. This method throws an exception if the user object you are trying to save is <code>null</code>.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">save</span><span class="hljs-params">(User user)</span> <span class="hljs-keyword">throws</span> Exception </span>{
    <span class="hljs-comment">// Make database query here</span>
}
</code></pre>
<p>Our Mocking class will use these methods to implement its own functionalities. We'll implement one function that updates the name of a user.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">updateUsername</span><span class="hljs-params">(String id, String username)</span> <span class="hljs-keyword">throws</span> Exception</span>{
            ApplicationDao applicationDao = <span class="hljs-keyword">new</span> ApplicationDao();
            User user = applicationDao.getUserById(id);
            <span class="hljs-keyword">if</span>(user!=<span class="hljs-keyword">null</span>)
                user.setUsername(username);
            applicationDao.save(user);
            <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    }
</code></pre>
<p>The method implementation is pretty straightforward. First, get the user by <code>id</code>, change its username and save the updated user object. We'll write the test cases for this method.</p>
<p>There are two cases we need to test. The first is when the user is updated successfully. The second is when the update fails, that is when an exception is thrown.</p>
<p>Before writing the tests, create a mock of the <code>ApplicationDao</code> object as we do not want to make actual database connections.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Mock</span>
ApplicationDao applicationDao;
</code></pre>
<p>Let's write our first test.</p>
<pre><code class="lang-python"><span class="hljs-meta">@Test</span>
<span class="hljs-meta">    @DisplayName("User updated successfully")</span>
    public void updateUsername() throws Exception {
        ...
    }
</code></pre>
<p>Create a user object for testing.</p>
<pre><code class="lang-java">User user = <span class="hljs-keyword">new</span> User();
user.setUsername(<span class="hljs-string">"kunal"</span>);
</code></pre>
<p>Since we are calling an external method, let's stub the method so that it returns the above <code>User</code> object.</p>
<pre><code class="lang-java">when(applicationDao.getUserById(Mockito.anyString())).thenReturn(user);
</code></pre>
<p>Pass <code>Mockito.anyString()</code> to the method as we want the stub to work for any string parameter. Now, add an assertion to check if the method is working correctly.</p>
<pre><code class="lang-java">Assertions.assertEquals(<span class="hljs-number">1</span>, mocking.updateUsername(<span class="hljs-string">"3211"</span>, <span class="hljs-string">"allan"</span>));
</code></pre>
<p>The method returns 1 on successful update, so the test passes.</p>
<p>Now, let's test another scenario where the method fails and throws an exception. Simulate this scenario by making the method <code>getUserById()</code> return null.</p>
<pre><code class="lang-java">lenient().when(applicationDao.getUserById(Mockito.anyString())).thenReturn(<span class="hljs-keyword">null</span>);
</code></pre>
<p>This value is then passed to the <code>save()</code> method which in turn throws an exception. In our assertion, we'll use <code>assertThrows()</code> method to test whether an exception was thrown. This method takes the type of the exception and a lambda expression as parameters.</p>
<pre><code class="lang-java">Assertions.assertThrows(Exception.class, () -&gt; {
            mocking.updateUsername("<span class="hljs-number">3412</span><span class="hljs-string">","</span>allan<span class="hljs-string">");
        });</span>
</code></pre>
<p>Since the exception is thrown, our test passes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-26-at-4.27.07-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Tests Passed</em></p>
<p>You can find the complete code here on <a target="_blank" href="https://github.com/KunalN25/junit-testing-tutorial">GitHub</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As a developer, writing unit tests for your code is important. It helps you identify bugs earlier in the development process.</p>
<p>In this post, I started by introducing Unit Testing and explained three important concepts involved in the testing process. These gave you some background before jumping into the code.</p>
<p>After that, I showed you, with examples, how you can test different scenarios by using the same basic techniques in testing. I also showed how to use mock classes and methods for testing complex implementations.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Unit Tests for Instance Methods in Python ]]>
                </title>
                <description>
                    <![CDATA[ This tutorial will teach you how to write unit tests for instance methods in Python. In a previous tutorial, we covered how to write unit tests for Python functions. While unit testing for instance methods works similarly, you may have some challenge... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-unit-tests-for-instance-methods-in-python/</link>
                <guid isPermaLink="false">66bb8b3bcaaeb78feb34893b</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Bala Priya C ]]>
                </dc:creator>
                <pubDate>Tue, 31 Jan 2023 00:13:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/instance-methods-python.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This tutorial will teach you how to write unit tests for instance methods in Python.</p>
<p>In a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-write-unit-tests-for-python-functions/">previous tutorial</a>, we covered how to write unit tests for Python functions. While unit testing for instance methods works similarly, you may have some challenges creating and managing objects (instances of a class). </p>
<p>This tutorial will teach you how to use such methods for setting up and tearing down resources efficiently. </p>
<p>Let's begin!</p>
<h2 id="heading-classes-and-objects-in-python-a-quick-review">Classes and Objects in Python – A Quick Review</h2>
<p>If you're familiar with object-oriented programming, you know that classes let you group related <strong>data</strong> and <strong>behavior</strong> together. You can then use these classes as templates to create instances of the class. If a Python class is a cookie-cutter, then each instance is a cookie. 🍪</p>
<p>The data and behavior are described by the <strong>attributes</strong> and <strong>methods</strong> in the definition of the class, respectively. We'll look at an example to understad these better.</p>
<p>I know this section should have been named classes and objects explained for the impatient. 🙂 To brush up your Python OOP skills, you may check out <a target="_blank" href="https://www.youtube.com/watch?v=Ej_02ICOIgs">this course</a> on freeCodeCamp's YouTube channel.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Ej_02ICOIgs" 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-how-to-test-the-instance-methods-of-a-python-class">How to Test the Instance Methods of a Python Class</h2>
<p>Now, we'll learn how to set up unit tests for instances of Python classes. We'll write unit tests to check the functionality of the <code>Book</code> class shown below:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,title,author,pages,price,discount</span>):</span>
        self.title = title
        self.author = author
        self.pages = pages
        self.price = price
        self.discount = discount
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_reading_time</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">f"<span class="hljs-subst">{self.pages*<span class="hljs-number">1.5</span>}</span> minutes"</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">apply_discount</span>(<span class="hljs-params">self</span>):</span>
        discounted_price = self.price - (self.discount*self.price)
        <span class="hljs-keyword">return</span> <span class="hljs-string">f"$<span class="hljs-subst">{discounted_price}</span>"</span>
</code></pre>
<p>The <code>Book</code> class serves as a template or a blueprint with attributes: title, author, pages, price, and discount. <code>get_reading_time()</code> and <code>apply_discount()</code> are the instance methods that use the above attributes. </p>
<p>So we can create book objects from the <code>Book</code> class, each with their own attributes.</p>
<p><img src="https://lh6.googleusercontent.com/JRAfU2HbOIqGFPPEqBi1Wj0Uttbn_TBLgnl0CqnGaqonBaa2KYpBmcJu2aXywtT9eoFJb3H5q4AD8r3ce8oB8sTKX1Y9qkjIiCT4f0A5HHFblsZjtUiPF0kyTLDooVpQnH8HKtX-6joRG7JJTWm-L9Ss-nFBtOxQjHN8Y7LqCtNoR-jMl7rQrAPJ6g" alt="Image" width="600" height="400" loading="lazy">
<em>Illustration of book class and book objects</em></p>
<p>To test the instance methods <code>get_reading_time()</code> and <code>apply_discount()</code>, we can create two instances of the <code>Book</code> class inside the test methods. We can use the assertion method <code>assertEqual()</code> to check if the return values of the instance methods are correct.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> book <span class="hljs-keyword">import</span> Book
<span class="hljs-keyword">import</span> unittest

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestBook</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_reading_time</span>(<span class="hljs-params">self</span>):</span>
        book_1 = Book(<span class="hljs-string">'Deep Work'</span>,<span class="hljs-string">'Cal Newport'</span>,<span class="hljs-number">304</span>,<span class="hljs-number">15</span>,<span class="hljs-number">0.05</span>)
        book_2 = Book(<span class="hljs-string">'Grit'</span>,<span class="hljs-string">'Angela Duckworth'</span>,<span class="hljs-number">447</span>,<span class="hljs-number">16</span>,<span class="hljs-number">0.15</span>)
        self.assertEqual(book_1.get_reading_time(), <span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-number">304</span>*<span class="hljs-number">1.5</span>}</span> minutes"</span>)
        self.assertEqual(book_2.get_reading_time(), <span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-number">447</span>*<span class="hljs-number">1.5</span>}</span> minutes"</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_discount</span>(<span class="hljs-params">self</span>):</span>
        book_1 = Book(<span class="hljs-string">'Deep Work'</span>,<span class="hljs-string">'Cal Newport'</span>,<span class="hljs-number">304</span>,<span class="hljs-number">15</span>,<span class="hljs-number">0.05</span>)
        book_2 = Book(<span class="hljs-string">'Grit'</span>,<span class="hljs-string">'Angela Duckworth'</span>,<span class="hljs-number">447</span>,<span class="hljs-number">16</span>,<span class="hljs-number">0.15</span>)
        self.assertEqual(book_1.apply_discount(),<span class="hljs-string">f"$<span class="hljs-subst">{<span class="hljs-number">15</span> - <span class="hljs-number">15</span>*<span class="hljs-number">0.05</span>}</span>"</span>)
        self.assertEqual(book_2.apply_discount(),<span class="hljs-string">f"$<span class="hljs-subst">{<span class="hljs-number">16</span> - <span class="hljs-number">16</span>*<span class="hljs-number">0.15</span>}</span>"</span> )

<span class="hljs-keyword">if</span> __name__==<span class="hljs-string">'__main__'</span>:
    unittest.main()
</code></pre>
<h2 id="heading-how-to-set-up-and-tear-down-resources-during-unit-tests">How to Set Up and Tear Down Resources During Unit Tests</h2>
<p>When setting up tests for instance methods, we instantiate two book objects, then verify if the instance methods work as expected. And we need to do this for each of the methods.</p>
<p>But this is repetitive and suboptimal when you need to test a large number of instance methods. </p>
<p>In this case, it'll be more convenient if we can define a method that instantiates these objects for us before running each test. This is where the <code>setUp()</code> method comes into play. </p>
<h3 id="heading-how-the-setup-and-teardown-methods-work">How the <code>setUp()</code> and <code>tearDown()</code> Methods Work</h3>
<p>The <code>setUp()</code> and <code>tearDown()</code> methods are typically used for the complementary tasks of allocating and deallocating resources, before and after every unit test, respectively. </p>
<ul>
<li>The <code>setUp()</code> method runs before every test, and</li>
<li>The <code>tearDown()</code> method runs after every test.</li>
</ul>
<p>Here, we can use the <code>setUp()</code> method to instantiate the book objects. Sometimes, you'll need to use the <code>tearDown()</code> method as well. </p>
<p>For example, if each test adds files to a directory or creates multiple objects in memory, you may want to free up the directory and delete the created objects after each test. We'll add the <code>tearDown()</code> method to verify that it runs after each test.</p>
<p>To understand this better, let's add explanatory <code>print()</code> statements, as shown in the code below:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> book <span class="hljs-keyword">import</span> Book
<span class="hljs-keyword">import</span> unittest
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestBook</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">setUp</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"\nRunning setUp method..."</span>)
        self.book_1 = Book(<span class="hljs-string">'Deep Work'</span>,<span class="hljs-string">'Cal Newport'</span>,<span class="hljs-number">304</span>,<span class="hljs-number">15</span>,<span class="hljs-number">0.05</span>)
        self.book_2 = Book(<span class="hljs-string">'Grit'</span>,<span class="hljs-string">'Angela Duckworth'</span>,<span class="hljs-number">447</span>,<span class="hljs-number">16</span>,<span class="hljs-number">0.15</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tearDown</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Running tearDown method..."</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_reading_time</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Running test_reading_time..."</span>)
        self.assertEqual(self.book_1.get_reading_time(), <span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-number">304</span>*<span class="hljs-number">1.5</span>}</span> minutes"</span>)
        self.assertEqual(self.book_2.get_reading_time(), <span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-number">447</span>*<span class="hljs-number">1.5</span>}</span> minutes"</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_discount</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Running test_discount..."</span>)
        self.assertEqual(self.book_1.apply_discount(),<span class="hljs-string">f"$<span class="hljs-subst">{<span class="hljs-number">15</span> - <span class="hljs-number">15</span>*<span class="hljs-number">0.05</span>}</span>"</span>)
        self.assertEqual(self.book_2.apply_discount(),<span class="hljs-string">f"$<span class="hljs-subst">{<span class="hljs-number">16</span> - <span class="hljs-number">16</span>*<span class="hljs-number">0.15</span>}</span>"</span> )
<span class="hljs-keyword">if</span> __name__==<span class="hljs-string">'__main__'</span>:
    unittest.main()
</code></pre>
<p>Now, run the <code>test_book</code> module. Here's the output:</p>
<pre><code>Output
Running setUp method...
Running test_discount...
Running tearDown method...
.
Running setUp method...
Running test_reading_time...
Running tearDown method...
.
----------------------------------------------------------------------
Ran <span class="hljs-number">2</span> tests <span class="hljs-keyword">in</span> <span class="hljs-number">0.003</span>s
OK
</code></pre><h2 id="heading-how-to-use-the-setupclass-and-teardownclass-methods">How to Use the <code>setUpClass()</code> and <code>tearDownClass()</code> Methods</h2>
<p>In addition to the above methods, you can also use the class methods: <code>setUpClass()</code> and <code>tearDownClass()</code>. </p>
<p>In Python, class methods bind to a class and not to a particular instance. To define a method as a class method, you can use the <code>@classmethod</code> decorator. </p>
<p>So when should we use these class methods?</p>
<p>Instantiating objects, as in the above example, is a simple task and not computationally expensive. But you may sometimes have tasks that are too expensive to be performed before every test: for instance, spinning up an in-memory database.</p>
<p>If all subsequent tests in the test class only read in some data from the database, we can use the <code>setUpClass()</code> class method to spin up the database and the <code>tearDownClass()</code> class method to tear down the database after all tests have run.</p>
<p>Putting it all together:</p>
<ul>
<li>The <code>setUpClass()</code> class method is executed <strong>before</strong> <em>any</em> of the tests are run.</li>
<li>The <code>tearDownClass()</code> class method is executed <strong>after</strong> <em>all</em> the tests have run.</li>
<li>The <code>setUp()</code> and <code>tearDown()</code> methods are executed <strong>before</strong> and <strong>after</strong> <em>each</em> test, respectively. </li>
</ul>
<p>Let’s add the <code>setUpClass()</code> and <code>tearDownClass()</code> class methods to the <code>TestBook</code> class. </p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> book <span class="hljs-keyword">import</span> Book
<span class="hljs-keyword">import</span> unittest
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestBook</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
<span class="hljs-meta">    @classmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">setUpClass</span>(<span class="hljs-params">cls</span>):</span>
        print(<span class="hljs-string">"\nsetUpClass method: Runs before all tests..."</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">setUp</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"\nRunning setUp method..."</span>)
        self.book_1 = Book(<span class="hljs-string">'Deep Work'</span>,<span class="hljs-string">'Cal Newport'</span>,<span class="hljs-number">304</span>,<span class="hljs-number">15</span>,<span class="hljs-number">0.05</span>)
        self.book_2 = Book(<span class="hljs-string">'Grit'</span>,<span class="hljs-string">'Angela Duckworth'</span>,<span class="hljs-number">447</span>,<span class="hljs-number">16</span>,<span class="hljs-number">0.15</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tearDown</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Running tearDown method..."</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_reading_time</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Running test_reading_time..."</span>)
        self.assertEqual(self.book_1.get_reading_time(), <span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-number">304</span>*<span class="hljs-number">1.5</span>}</span> minutes"</span>)
        self.assertEqual(self.book_2.get_reading_time(), <span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-number">447</span>*<span class="hljs-number">1.5</span>}</span> minutes"</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_discount</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Running test_discount..."</span>)
        self.assertEqual(self.book_1.apply_discount(),<span class="hljs-string">f"$<span class="hljs-subst">{<span class="hljs-number">15</span> - <span class="hljs-number">15</span>*<span class="hljs-number">0.05</span>}</span>"</span>)
        self.assertEqual(self.book_2.apply_discount(),<span class="hljs-string">f"$<span class="hljs-subst">{<span class="hljs-number">16</span> - <span class="hljs-number">16</span>*<span class="hljs-number">0.15</span>}</span>"</span> )
<span class="hljs-meta">    @classmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tearDownClass</span>(<span class="hljs-params">cls</span>):</span>
        print(<span class="hljs-string">"\ntearDownClass method: Runs after all tests..."</span>)

<span class="hljs-keyword">if</span> __name__==<span class="hljs-string">'__main__'</span>:
    unittest.main()
</code></pre>
<p>Now, rerun <code>test_book.py</code>.</p>
<p>From the output below, we see that the <code>setUpClass()</code> and <code>tearDownClass()</code> methods run before and after all the tests, respectively.</p>
<pre><code>Output
setUpClass method: Runs before all tests...
Running setUp method...
Running test_discount...
Running tearDown method...
.
Running setUp method...
Running test_reading_time...
Running tearDown method...
.
tearDownClass method: Runs after all tests...
----------------------------------------------------------------------
Ran <span class="hljs-number">2</span> tests <span class="hljs-keyword">in</span> <span class="hljs-number">0.010</span>s
OK
</code></pre><h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this tutorial helped you learn how to set up unit tests for instance methods in Python. </p>
<p>If you're interested in learning more about the need for unit testing with a focus on doing it for Python functions, consider reading the article <a target="_blank" href="https://www.freecodecamp.org/news/how-to-write-unit-tests-for-python-functions/">How to Write Unit Tests for Python Functions</a>.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Unit Tests in React ]]>
                </title>
                <description>
                    <![CDATA[ When you're building a website and coding all the cool features you had planned, you'll want to test if everything works as expected. Now, you can’t do that just by going through the website yourself – you need to check if each unit of your code is w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-unit-tests-in-react/</link>
                <guid isPermaLink="false">66d8515392b237d9f6a7c528</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kunal Nalawade ]]>
                </dc:creator>
                <pubDate>Mon, 23 Jan 2023 15:35:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/unit-testing-in-react-image.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you're building a website and coding all the cool features you had planned, you'll want to test if everything works as expected.</p>
<p>Now, you can’t do that just by going through the website yourself – you need to check if each unit of your code is working as you want. For that, you need to write unit tests. And they can be quite a hassle when you actually get down to writing them.</p>
<p>So, in this post, I am going to show you how you can get started with writing unit tests in React. I will explain the process through several examples to help you understand better.</p>
<p>For this post, I assume you have a basic knowledge of React. If not, then head over to the <a target="_blank" href="https://reactjs.org/docs/getting-started.html">docs</a> to get started.</p>
<h2 id="heading-how-is-a-test-structured">How Is a Test Structured?</h2>
<p>Testing involves checking if your code is functioning as it's supposed to by comparing the expected output with the actual output.</p>
<h3 id="heading-what-to-test">What to Test</h3>
<p>In general, your tests should cover the following aspects of your code:</p>
<ol>
<li><p>If a component renders with or without props</p>
</li>
<li><p>How a component renders with state changes</p>
</li>
<li><p>How a component reacts to user interactions</p>
</li>
</ol>
<h3 id="heading-what-not-to-test">What Not to Test</h3>
<p>Testing most of your code is important, but here are some things you do not need to test:</p>
<ol>
<li><p><strong>Actual Implementation:</strong> You do not need to test the actual implementation of a functionality. Just test if the component is behaving correctly.<br> Let’s say you want to sort an array on the click of a button. There’s no need to test the actual sorting logic. You only test if the function was called and if the state changes are rendering correctly.</p>
</li>
<li><p><strong>Third Party libraries:</strong> If you are using any third party libraries like Material UI, no need to test those – they should already be tried and tested.</p>
</li>
</ol>
<p>This might seem a little complicated at the moment, but you should understand better through examples.</p>
<p>Any test in React, no matter how complicated, follows this structure:</p>
<ol>
<li><p>Render the component</p>
</li>
<li><p>Get an element from the component and simulate any user interactions</p>
</li>
<li><p>Write an assertion.</p>
</li>
</ol>
<h2 id="heading-how-to-set-up-our-project">How to Set Up Our Project</h2>
<p>First, create the app with <code>create-react-app</code>. We’ll be using <a target="_blank" href="https://jestjs.io/docs/getting-started">Jest</a> and <a target="_blank" href="https://testing-library.com/docs/react-testing-library/intro/">React Testing Library</a>. Both of them come pre - installed with <code>create-react-app</code>. You can see what it looks like here:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"dependencies"</span>: {
    <span class="hljs-string">"@testing-library/jest-dom"</span>: <span class="hljs-string">"^5.16.5"</span>,
    <span class="hljs-string">"@testing-library/react"</span>: <span class="hljs-string">"^13.4.0"</span>,
    <span class="hljs-string">"react"</span>: <span class="hljs-string">"^18.2.0"</span>,
    <span class="hljs-string">"react-dom"</span>: <span class="hljs-string">"^18.2.0"</span>,
    <span class="hljs-string">"react-scripts"</span>: <span class="hljs-string">"5.0.1"</span>,
    <span class="hljs-string">"web-vitals"</span>: <span class="hljs-string">"^2.1.4"</span>
},
</code></pre>
<p>As you can see, Jest is not visible here. But, if you go to the <code>node_modules</code> folder, you will see Jest there. So, no need to install it separately.</p>
<p>Also, make sure you have the following lines in your <code>setupTests.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">'@testing-library/jest-dom'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@testing-library/jest-dom/extend-expect'</span>;
</code></pre>
<p>Also, in your <code>package.json</code> file, modify your scripts like this:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"react-scripts start"</span>,
    <span class="hljs-string">"build"</span>: <span class="hljs-string">"react-scripts build"</span>,
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"react-scripts test --watchAll --coverage"</span>,
    <span class="hljs-string">"eject"</span>: <span class="hljs-string">"react-scripts eject"</span>
},
</code></pre>
<p>This will run your tests in watch mode and also show you the coverage (that is, the portion of the code covered by your tests). You can also define the coverage threshold by adding another property <code>jest</code>. For now, keep the threshold at 80%.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"jest"</span>: {
    <span class="hljs-string">"coverageThreshold"</span>: {
        <span class="hljs-string">"global"</span>: {
            <span class="hljs-string">"lines"</span>: <span class="hljs-number">80</span>
        }
    }
}
</code></pre>
<p>That’s it, now you are ready to start testing. Let’s first start with a basic test.</p>
<h2 id="heading-how-to-write-your-first-test-for-a-react-app">How to Write Your First Test for a React App</h2>
<p>Let’s write a test for the following component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> FirstTest = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span> First test <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>Here, we just need to test if the <code>h2</code> element renders. Now, where should we write the tests? We can write them inside a <code>__tests__</code> folder anywhere in the <code>src</code> folder. The test file just needs to have a <code>.test.js/jsx</code> extension and the test runner will pick it up.</p>
<p>This is how the test looks in our <code>FirstTest.test.jsx</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>
<span class="hljs-keyword">import</span> FirstTest <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/FirstTest'</span>;

test(<span class="hljs-string">"Example 1 renders successfully"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FirstTest</span>/&gt;</span></span>);

    <span class="hljs-keyword">const</span> element = screen.getByText(<span class="hljs-regexp">/first test/i</span>);

    expect(element).toBeInTheDocument();
})
</code></pre>
<p>First, import the required methods. The <code>test()</code> method contains an individual test. It takes the name of the test and a callback function as the two arguments.</p>
<p>Now, following the structure mentioned above, render the component you're testing using the <a target="_blank" href="https://testing-library.com/docs/react-testing-library/api/#render">render</a> method. Then, use the <code>screen</code> object to make a query for an element. In this case, it’s the <code>h2</code> element. Our query gets an element containing text that matches the regex <code>/first test/i</code> (<em>i</em> means ignore case).</p>
<p>Lastly, make the assertion using the <code>expect</code> method. We expect the element to be in the document and it is, so the test passes.</p>
<p>There are lots of other assertions you can make in your tests. You can read more about them <a target="_blank" href="https://jestjs.io/docs/using-matchers">here</a>. Also, you can find a list of ways to query an element <a target="_blank" href="https://testing-library.com/docs/queries/about">here</a>. We’ll use some of them in our further examples.</p>
<h2 id="heading-how-to-test-with-mock-data-in-react">How to Test With Mock Data in React</h2>
<p>Here, we have a component with a prop <code>data</code> that displays a list of items. Let’s assume this data comes from the backend and your component is displaying this data.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> TestWithMockData = <span class="hljs-function">(<span class="hljs-params">{data}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
            {data.map(item =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
                    {item.id}
                    {item.first_name},
                    {item.last_name},
                    {item.email}

                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TestWithMockData
</code></pre>
<p>While writing tests for a component with props, you need to pass some mock data while rendering this component that pertains to your functionality. Here, one object in our data contains four fields, so we pass some mock data here.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mockData = [
    {
        <span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>,
        <span class="hljs-string">"first_name"</span>: <span class="hljs-string">"Fletcher"</span>,
        <span class="hljs-string">"last_name"</span>: <span class="hljs-string">"McVanamy"</span>,
        <span class="hljs-string">"email"</span>: <span class="hljs-string">"mmcvanamy0@e-recht24.de"</span>,
        <span class="hljs-string">"age"</span>: <span class="hljs-number">30</span>
      }, {
        <span class="hljs-string">"id"</span>: <span class="hljs-number">2</span>,
        <span class="hljs-string">"first_name"</span>: <span class="hljs-string">"Clarice"</span>,
        <span class="hljs-string">"last_name"</span>: <span class="hljs-string">"Harrild"</span>,
        <span class="hljs-string">"email"</span>: <span class="hljs-string">"charrild1@dion.ne.jp"</span>,
        <span class="hljs-string">"age"</span>: <span class="hljs-number">35</span>
      }, 
]
</code></pre>
<p>Note that the actual data could contain thousands of records, but the mock data only needs to be relevant to what you want to test. Now, let’s write the test and check if the list renders.</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"List renders successfully"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestWithMockData</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{mockData}</span> /&gt;</span></span>)
    expect(screen.getByText(<span class="hljs-regexp">/fletcher/i</span>)).toBeInTheDocument();
})
</code></pre>
<h2 id="heading-how-to-test-with-mock-data-covering-all-branches-in-react">How to Test With Mock Data Covering All Branches in React</h2>
<p>Let’s introduce some branching in the above component. We’ll have another prop, <code>displayUnorderedList</code>, that determines whether to display an ordered or unordered list. We’ll also render <code>Senior</code> for <code>age &gt; 50</code> and <code>Not Senior</code> otherwise.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> TestWithMockData = <span class="hljs-function">(<span class="hljs-params">{data, displayUnorderedList, handleClick}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {displayUnorderedList ? 
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
                {data.map(item =&gt; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
                        {item.id}
                        {item.first_name},
                        {item.last_name},
                        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {
                            console.log("email link clicked")
                            handleClick()
                        }}&gt;{item.email}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>

                        {item.age &gt; 50 ? 'Senior' : 'Not senior'}

                    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        : 
            <span class="hljs-tag">&lt;<span class="hljs-name">ol</span>&gt;</span>
                {data.map(item =&gt; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
                        Last name: {item.last_name}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span>
        }
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TestWithMockData
</code></pre>
<p>Here's the coverage report so far:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-141.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Failed Test: Unable to find the element</em></p>
<p>You can see that Line 9 (that is, the unordered list part) is not covered by our existing tests. And our previous test has also failed since it is unable to find <code>fletcher</code> in the component.</p>
<p>Why is this so? In our previous test, we have not passed the <code>displayUnorderedList</code> prop to the component so it is <code>null</code>. So, the component renders the ordered list and it does not contain the <code>first_name</code>.</p>
<p>So, let’s write another test covering the ordered list part.</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"Ordered list renders"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestWithMockData</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{mockData}</span> <span class="hljs-attr">displayUnorderedList</span>=<span class="hljs-string">{false}</span> /&gt;</span></span>)

    expect(screen.getByText(<span class="hljs-regexp">/McVanamy/i</span>)).toBeInTheDocument()
})
</code></pre>
<p>Here, pass the prop’s value as <code>false</code> to render the ordered list. Also, add the <code>displayUnorderedList</code> prop to the failing test and pass the value <code>true</code>.</p>
<p>Now, all our tests pass with 100% coverage.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-142.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Uncovered Branch</em></p>
<p>One line is still not covered by the test cases, which is the branching logic for <code>age</code>. So, add another record to the mock data that has an age greater than 50.</p>
<pre><code class="lang-javascript">{
    <span class="hljs-string">"id"</span>: <span class="hljs-number">3</span>,
    <span class="hljs-string">"first_name"</span>: <span class="hljs-string">"Amby"</span>,
    <span class="hljs-string">"last_name"</span>: <span class="hljs-string">"Emmer"</span>,
    <span class="hljs-string">"email"</span>: <span class="hljs-string">"aemmer2@buzzfeed.com"</span>,
    <span class="hljs-string">"age"</span>: <span class="hljs-number">67</span>
}
</code></pre>
<p>Now, all our tests should pass with 100% coverage.</p>
<h2 id="heading-how-to-test-user-interactions-in-react">How to Test User Interactions in React</h2>
<p>The most important part of testing any UI app is testing its behaviour with various user interactions. Almost every functionality in a UI app involves user interactions.</p>
<p>You can use the <code>user-event</code> library to simulate user interactions. It has methods for simulating various user events such as <em>click</em>, <em>type</em>, <em>hover</em>, and so on.</p>
<p>First, we need to install the library:</p>
<pre><code class="lang-python">npm install --save-dev @testing-library/user-event
</code></pre>
<p>We can use this library to simulate user events. In our examples, we’ll interact with different elements, mostly <code>input</code> and <code>button</code> elements.</p>
<h3 id="heading-how-to-test-a-function-call-on-click-of-an-element">How to Test a Function Call on Click of an Element</h3>
<p>In our above component, we need to<code>TestWithMockData</code>, make the <code>email</code> field clickable and call a function <code>handleClick</code> on it. This will be passed as props to the component. There, replace <code>{item.email}</code> with:</p>
<pre><code class="lang-javascript">&lt;a onClick={<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"email link clicked"</span>)
    handleClick()
}}&gt;{item.email}&lt;/a&gt;
</code></pre>
<p>Now, our test coverage takes a hit. To cover this scenario, write the following test:</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"Email link click handler called"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> mockHandleClick = jest.fn();
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestWithMockData</span> 
                <span class="hljs-attr">data</span>=<span class="hljs-string">{mockData}</span> 
                <span class="hljs-attr">displayUnorderedList</span>=<span class="hljs-string">{true}</span>
                <span class="hljs-attr">handleClick</span> = <span class="hljs-string">{mockHandleClick}</span>
          /&gt;</span></span>)
    <span class="hljs-keyword">await</span> userEvent.click(screen.getByText(<span class="hljs-regexp">/mmcvanamy0@e-recht24.de/i</span>));
    expect(mockHandleClick).toHaveBeenCalled();
})
</code></pre>
<p>First, create the mock of the <code>handleClick</code> function using <code>jest.fn()</code>. We do not need the actual implementation of the method, as we only want to test the behaviour of the component. So, we create an empty mock and pass the same as props. Read more about mocking functions <a target="_blank" href="https://jestjs.io/docs/mock-functions">here</a>.</p>
<p>Now, query the <code>&lt;a&gt;</code> element by text (any <code>email</code> from the mock data). Use the <code>click()</code> method to simulate a click event. Use <code>await</code> as simulating a user event is an asynchronous operation.</p>
<p>Write an assertion in the end to check if the method was called. The method was called, so our test passes with 100% coverage.</p>
<h3 id="heading-how-to-query-input-fields-and-buttons">How to Query Input Fields and Buttons</h3>
<p>So far, we have used only one method of querying elements – <code>getByText()</code>. Now, let’s see how you can query input fields and buttons.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Enter name'</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span> Submit <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>To query these elements, you can do the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> inputElement = screen.getByRole(<span class="hljs-string">'textbox'</span>)
</code></pre>
<p><code>getByRole</code> finds an element by the given role. In this case, the <code>textbox</code> role means the <code>input</code> element.</p>
<p>How is role determined? Each element has a defined role, so you do not need to specify an explicit role attribute. You can see a list of roles for different elements <a target="_blank" href="https://www.w3.org/TR/html-aria/#docconformance">here</a>. Whatever element you want, just do <code>getByRole</code> and refer to the list.</p>
<p>For <code>button</code>, the default role is ‘button’ as you can see here:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> button = screen.getByRole(<span class="hljs-string">'button'</span>)
</code></pre>
<p>What if we add another <code>input</code> element, <code>&lt;input placeholder=’Enter description’/&gt;</code>? The test runner will now throw an error saying that there are two elements with the same role. What should we do in such a scenario? Use another query <code>getByPlaceholderText()</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> nameInput = screen.getByPlaceholderText(<span class="hljs-regexp">/enter name/i</span>);
<span class="hljs-keyword">const</span> descrInput = screen.getByPlaceholderText(<span class="hljs-regexp">/enter description/i</span>);
</code></pre>
<p>You can also use <code>getByLabelText()</code> if your <code>input</code> has a <code>label</code>.</p>
<pre><code class="lang-javascript">&lt;label htmlFor=<span class="hljs-string">'password'</span>&gt; Enter password&lt;/label&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'password'</span> <span class="hljs-attr">id</span>=<span class="hljs-string">'password'</span>/&gt;</span></span>
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> passwordInput = screen.getByLabelText(<span class="hljs-regexp">/enter password/i</span>);
</code></pre>
<p>For querying buttons, we can do <code>screen.getByRole('button')</code>.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span> Submit <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span> Apply<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>Since we have two buttons here, just doing <code>getByRole</code> will throw an error. So, we use a <code>name</code> option.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> submitButton = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/submit/i</span> });
<span class="hljs-keyword">const</span> applyButton = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/apply/i</span> });
</code></pre>
<p>The <code>name</code> option can contain the label of a form element, text of a button, or the value of the <code>aria-label</code> attribute of any element. We can also do <code>getByText()</code> for a button.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> submitButton = screen.getByText(<span class="hljs-regexp">/submit/i</span>);
</code></pre>
<h2 id="heading-how-to-test-state-updates-in-react">How to Test State Updates in React</h2>
<p>We have seen how to query form elements like <code>input</code> and <code>button</code>. Now, let’s simulate some user interactions and test state updates. What do I mean by testing state updates?</p>
<p>State updates cause a component to re-render. So, when your functionality performs a state update, you should test how the component is behaving due to the state change.</p>
<p>First, let’s take a simple example where we set the state as soon as the component is loaded – that is, in the <code>useEffect</code> block.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> TestingStateChange = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [loaded, setLoaded] = useState(<span class="hljs-literal">false</span>)
    useEffect(<span class="hljs-function">() =&gt;</span> {
        setLoaded(<span class="hljs-literal">true</span>)
    }, [])
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {loaded &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span> Page Loaded <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>Here, your entire component, starting from the <code>useEffect</code> statement to the end, is uncovered. When you write the following test, not only does the HTML part get covered but also the <code>useEffect</code> part where you set the state.</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"Testing page load"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestingStateChange</span>/&gt;</span></span>)
    expect(screen.getByText(<span class="hljs-regexp">/page loaded/i</span>)).toBeInTheDocument();
})
</code></pre>
<p>This is how you test state updates. You test whether the component behaves as you expect with a state change.</p>
<h3 id="heading-how-to-test-a-state-change-on-click-of-a-button">How to Test a State Change on Click of a Button</h3>
<p>Let’s have a button and a text that toggles on the click of the button.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [toggleTextVisible, setToggleTextVisible] = useState(<span class="hljs-literal">false</span>)<span class="hljs-string">`</span>
</code></pre>
<pre><code class="lang-html">{toggleTextVisible &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Text visible <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> }

<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> { setToggleTextVisible(!toggleTextVisible) }}&gt; 
    Toggle text 
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>We’ll write the test for this:</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"Toggle text visible"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestingStateChange</span>/&gt;</span></span>);
    <span class="hljs-keyword">await</span> userEvent.click(screen.getByText(<span class="hljs-regexp">/toggle text/i</span>));
    expect(screen.getByText(<span class="hljs-regexp">/text visible/i</span>)).toBeInTheDocument();
})
</code></pre>
<p>With <code>userEvent</code>, we have simulated the click of a button and asserted if the text is visible.</p>
<p>Now, let’s test another scenario where we check if the above button is disabled on the click of another button.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [btnDisabled, setBtnDisabled] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>Add a <code>disabled={btnDisabled}</code> attribute to the above button and create another button that controls its value.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> { setBtnDisabled(!btnDisabled) }}&gt; 
      Toggle button disabled 
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>Use the <code>toBeDisabled()</code> method to test if the button is disabled.</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"Button disabled on click"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestingStateChange</span>/&gt;</span></span>)
    <span class="hljs-keyword">await</span> userEvent.click(screen.getByText(<span class="hljs-regexp">/toggle button disabled/i</span>));
    expect(screen.getByText(<span class="hljs-regexp">/toggle text/i</span>)).toBeDisabled();
})
</code></pre>
<h3 id="heading-how-to-test-if-an-element-was-added-to-a-list">How to Test if an Element Was Added to a List</h3>
<p>Let’s perform another assertion. Here, we’ll check if an element was added to a list. We’ll have some data and create a state with the data as the initial value. We'll display it while also having a button to add an element to it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [elements, setElements] = useState(data);
</code></pre>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span> List <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
{elements.map(item =&gt; (
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>= <span class="hljs-string">{item.id}</span>&gt;</span>
       {item.id}: { item.name }
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
))}
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {
    setElements([...elements, {
        id: 4,
        name: 'abhinav'
    }])
}}&gt; Add to list <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>Add an attribute <code>data-testid='record'</code> to each record to help query the element. Let’s write the test for this:</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"Element added to the list"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestingStateChange</span>/&gt;</span></span>)
    expect(screen.getAllByTestId(<span class="hljs-string">'record'</span>).length).toBe(<span class="hljs-number">3</span>);

    <span class="hljs-keyword">await</span> userEvent.click(screen.getByText(<span class="hljs-regexp">/add to list/i</span>));
    expect(screen.getAllByTestId(<span class="hljs-string">'record'</span>).length).toBe(<span class="hljs-number">4</span>);
})
</code></pre>
<p>To get multiple elements with the same query, use the <code>getAllBy…</code> method. In this case, there are multiple elements with the test-id <code>record</code>, so using the <code>getAllByTestId()</code> method gets a list of all such elements.</p>
<p>Here, we have checked the length of the list. We can add another assertion to check if the new element is visible.</p>
<pre><code class="lang-javascript">expect(screen.getByText(<span class="hljs-regexp">/abhinav/i</span>)).toBeInTheDocument();
</code></pre>
<h3 id="heading-how-to-test-if-an-element-was-removed-from-a-list">How to Test if an Element Was Removed From a List</h3>
<p>Now, let’s add another button that removes an element from the list.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {
    setElements(elements.filter(item =&gt; item.id != 2))
}}&gt; Remove from list <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>The test for this:</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">"Element removed from list"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestingStateChange</span>/&gt;</span></span>)
    <span class="hljs-keyword">await</span> userEvent.click(screen.getByText(<span class="hljs-regexp">/remove from list/i</span>));
    expect(screen.getAllByTestId(<span class="hljs-string">'record'</span>).length).toBe(<span class="hljs-number">2</span>);
})
</code></pre>
<p>Here, we test whether the length of the list was reduced. All our tests pass with 100% coverage.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-143.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Coverage Report for Testing State Change: Tests Passed</em></p>
<h2 id="heading-how-to-test-api-calls-in-react">How to Test API Calls in React</h2>
<p>API calls are an important part of any UI application. Let’s understand how to test an API call.</p>
<p>In this example, we have a file <code>data.json</code> that has some data. We’ll make an API call to fetch this data.</p>
<p>For demonstration, we’ll save this file on the local server only (inside the <code>public</code> folder), but the procedure remains the same when fetching a file from a remote server.</p>
<p>We’ll use <code>fetch</code> to make the API call.</p>
<pre><code class="lang-javascript">fetch(<span class="hljs-string">"http://localhost:3000/data.json"</span>)
  .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
      <span class="hljs-keyword">return</span> res.json();
  })
  .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
      <span class="hljs-comment">// Store the data in state</span>
  })
</code></pre>
<p>Now, let’s have a state to store the data and render it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [data, setData] = useState([])
</code></pre>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    {data.map(item =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            {item.name}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    ))}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>How do we write the test for this? One way is to mock the <code>fetch</code> method and provide our own mock implementation. But what if there are multiple Fetch API calls in the component? You cannot have the same mock implementation for everyone.</p>
<p>So, we put the <code>fetch</code> call in a separate function and have a mock implementation of that function. We put our API call in a <code>FetchData</code> method that returns the promise returned by <code>fetch</code>.</p>
<p>We put the method in a separate <code>Services.js</code> file and export it from there.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> FetchData = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> fetch(<span class="hljs-string">"http://localhost:3000/data.json"</span>)
        .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
            <span class="hljs-keyword">return</span> res.json();
        }) 
}
</code></pre>
<p>Now, when we call this method inside our component, it looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [data, setData] = useState([])

useEffect(<span class="hljs-function">() =&gt;</span> {
    FetchData().then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
        setData(data);
    })
})

<span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {data.map(item =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
              {item.name}
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
)
</code></pre>
<p>Now, let’s write the test for this. The main thing is to mock the FetchData method. First, import all methods from <code>Services.js</code> as a module.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> services <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/Services'</span>
</code></pre>
<p>Let’s mock our function using <code>jest.spyOn()</code>. The method takes two arguments, the object and the method name as a string.</p>
<pre><code class="lang-python">const mockFetchData = jest.spyOn(services, <span class="hljs-string">'FetchData'</span>)
        .mockImplementation(<span class="hljs-keyword">async</span> () =&gt; {
            <span class="hljs-keyword">return</span> [{
                name: <span class="hljs-string">'kunal'</span>
            }];
        })
</code></pre>
<p><code>spyOn</code> creates an empty mock of the method. Now, we provide our mock implementation where we return some mock data. This will be called when our component renders.</p>
<pre><code class="lang-python">render(&lt;TestingAPICalls/&gt;)
expect(mockFetchData).toHaveBeenCalled();
</code></pre>
<p>We use <code>toHaveBeenCalled()</code> to test if the method was called. It was – so the test passes. Now, to test the behaviour of our component, let’s test if the name was rendered.</p>
<pre><code class="lang-javascript">expect(screen.getByText(<span class="hljs-regexp">/kunal/i</span>)).toBeInTheDocument();
</code></pre>
<p>In this case, the test fails as it is unable to find the element. Why is this so?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-144.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Failed Test: Unable to find the element</em></p>
<p>Since API calls and state updates are asynchronous, the text hasn’t been rendered yet. To test asynchronous behaviour, wrap the query in a <code>waitFor()</code> block.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> waitFor(<span class="hljs-function">() =&gt;</span> {
    expect(screen.getByText(<span class="hljs-regexp">/kunal/i</span>)).toBeInTheDocument();
})
</code></pre>
<p><code>waitFor</code> does exactly what the name suggests. It waits for the asynchronous behaviour to finish before making the query. Now, our test passes with 100% coverage.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-145.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>100% Coverage for Testing API Calls</em></p>
<p>You can find the complete code on <a target="_blank" href="https://github.com/KunalN25/react-testing-basics">GitHub</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Phew! That was a long one. But it needed to be. I have explained, through basic examples, how you can start writing tests in React.</p>
<p>This article started from a basic test with a simple assertion and explained how to use mock data to serve the purpose of your test.</p>
<p>I also explained how to simulate user interactions, how to test a component’s behaviour on state updates, and lastly how to test API calls. Hopefully, all these examples help you write tests for your upcoming project.</p>
<p>If you are unable to understand the content or find the explanation unsatisfactory, please let me know. New ideas are always appreciated! Feel free to DM me on <a target="_blank" href="https://www.linkedin.com/in/kunalnk25/">LinkedIn</a> if you want to discuss anything. Until then, Goodbye!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Testing Library Tutorial – How to Write Unit Tests for React Apps ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you will learn how to confidently write unit tests using the Testing Library. It is a very popular React testing library for writing unit tests. So let's get started. What We'll Cover: Why Do You Need to Write Unit Tests? What is t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/write-unit-tests-using-react-testing-library/</link>
                <guid isPermaLink="false">66bc553b95b2a9e41d4e968c</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Wed, 30 Nov 2022 16:53:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/cover_testing.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you will learn how to confidently write unit tests using the <a target="_blank" href="https://testing-library.com/">Testing Library</a>. It is a very popular React testing library for writing unit tests.</p>
<p>So let's get started.</p>
<h2 id="heading-what-well-cover">What We'll Cover:</h2>
<ol>
<li><a class="post-section-overview" href="#heading-why-do-you-need-to-write-unit-tests">Why Do You Need to Write Unit Tests?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-the-react-testing-library">What is the React Testing Library?</a></li>
<li><a class="post-section-overview" href="#heading-what-not-to-test-with-the-testing-library">What Not to Test with the Testing Library</a></li>
<li><a class="post-section-overview" href="#heading-how-to-setup-a-react-project-with-vite">How to Setup a React Project with Vite</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-the-testing-library-and-jest-in-a-react-project">How to Set Up the Testing Library and Jest in a React Project</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-ui-for-testing">How to Create the UI for Testing</a></li>
<li><a class="post-section-overview" href="#heading-how-to-write-unit-test-cases">How to Write Unit Test Cases</a></li>
<li><a class="post-section-overview" href="#heading-lets-write-some-more-tests">Let's Write Some More Tests</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<p>If you want to learn the React Testing Library in depth from scratch, you can check out my <a target="_blank" href="https://online-elearning-platform.netlify.app/">MERN stack course</a>. </p>
<h2 id="heading-why-do-you-need-to-write-unit-tests">Why Do You Need to Write Unit Tests?</h2>
<p>You might think that you don't need to write so many unit test cases and that it's a waste of time. Perhaps you can manually test the application instead.</p>
<p>Well, you're right – you can certainly do that. But as the application grows, it might be difficult to test all the scenarios in the application and you might miss something. Even a small change might break the application if all the major functionality is not tested properly.</p>
<p>That's why I recommend writing unit test cases covering all those scenarios which you're manually going through as a user.</p>
<p>So by executing just a single command you will be able to know if something is broken in your application or if some test is failing.</p>
<h2 id="heading-what-is-the-react-testing-library">What is the React Testing Library?</h2>
<p>The React <a target="_blank" href="https://testing-library.com/">Testing Library</a> has a set of packages that help you test UI components in a user-centric way. This means it tests based on how the user interacts with the various elements displayed on the page.</p>
<p>So what happens is when the user clicks any button or types in any of the input textboxes, that interaction is tested using this testing library.</p>
<p>So instead of the user doing this testing manually (which takes a lot of time, and the user might miss testing certain scenarios when the application grows), the testing is done by writing unit test cases and executing them by just a single command.</p>
<h2 id="heading-what-not-to-test-with-the-testing-library">What Not to Test with the Testing Library</h2>
<p>Testing Library encourages you to avoid testing implementation details like the internals of a component you're testing.</p>
<p>The guiding principles of this library emphasize a focus on tests that closely resemble how users interact with your web pages.</p>
<p>You may want to avoid testing the following implementation details:</p>
<ul>
<li>Internal state of a component</li>
<li>Internal methods of a component</li>
<li>Lifecycle methods of a component</li>
<li>Child components</li>
</ul>
<p>So if you have experience with <a target="_blank" href="https://enzymejs.github.io/enzyme/">enzyme testing</a>, you might be checking the value of state once you click any button or you might be checking the prop value If something changes.</p>
<p>But these types of checks are not necessary for testing with the React testing library. Instead, in the React testing library, you check the behavior of the DOM when the user clicks on a button or submits a form and so on.</p>
<h2 id="heading-how-to-setup-a-react-project-with-vite">How to Setup a React Project with Vite</h2>
<p>To set up our app that we'll test, we'll be using <a target="_blank" href="https://vitejs.dev/">Vite</a>. It's a popular and faster alternative to <a target="_blank" href="https://reactjs.org/docs/create-a-new-react-app.html">create-react-app</a>.</p>
<p>We'll use Vite because <code>create-react-app</code> becomes slow when the application grows and takes a lot of time to refresh the page when we make any changes in the application code. Also, by default, it also adds a lot of extra packages which we rarely need.</p>
<p>Vite just rebuilds the things we changed, instead of rebuilding the entire application which saves a lot of time during development.</p>
<p>Keep in mind that Vite requires Node.js version 14.18+, so make sure to install a Node version greater than or equal to 14.18.</p>
<p>The easiest and simplest way to install and switch Node.js versions is to use <a target="_blank" href="https://github.com/nvm-sh/nvm#installing-and-updating">nvm</a>.</p>
<p>Even if you're using <code>create-react-app</code>, all the tests you will learn in this tutorial should run exactly the same without any errors.</p>
<p>To create a new Vite project with React, execute the <code>npm init vite</code> command from the terminal.</p>
<p>It will ask you the <code>project name</code>, <code>framework</code>, and <code>variant</code>.</p>
<ul>
<li>For <code>project name</code>, you can enter <code>testing-library-demo</code> or any name of your choice.</li>
<li>For <code>framework</code>, select <code>React</code> from the list of options</li>
<li>For <code>variant</code>, select <code>JavaScript</code> from the list of options</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/1_setup.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new React project using Vite</em></p>
<p>Once the project is created, you can open that project in your favorite IDE.</p>
<p>The project folder structure will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/2_folder_structure.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder structure of React Vite project</em></p>
<p>Now, execute the <code>yarn</code> or <code>npm install</code> command to install all the packages from the <code>package.json</code> file.</p>
<p>Once all the packages are installed, you can execute the <code>yarn run dev</code> or <code>npm run dev</code> command to start the created React application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/3_app_started.png" alt="Image" width="600" height="400" loading="lazy">
<em>Running a React app</em></p>
<p>Now, if you access the displayed URL <code>http://127.0.0.1:5173/</code> you will be able to see the default React application created using Vite.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/4_app_loaded.png" alt="Image" width="600" height="400" loading="lazy">
<em>Default React page rendered using Vite</em></p>
<p>So let's see how we can set up the <a target="_blank" href="https://testing-library.com/docs/">Testing Library</a> in our Vite project.</p>
<h2 id="heading-how-to-set-up-the-testing-library-and-jest-in-a-react-project">How to Set Up the Testing Library and Jest in a React Project</h2>
<p>You can't just use the testing library alone – you also need to install <a target="_blank" href="https://jestjs.io/">Jest</a>. It exposes an extensively used global expect function and other things which help you make assertions in your test cases.</p>
<p>To set up <a target="_blank" href="https://testing-library.com/">Testing library</a> and <a target="_blank" href="https://jestjs.io/">Jest</a>, you need to install the Jest and Testing Library packages as dev dependencies.</p>
<p>So execute the following command from the <code>testing-library-demo</code> folder:</p>
<pre><code class="lang-js">yarn add @testing-library/jest-dom@<span class="hljs-number">5.16</span><span class="hljs-number">.5</span> @testing-library/react@<span class="hljs-number">13.4</span><span class="hljs-number">.0</span> @testing-library/user-event@<span class="hljs-number">14.4</span><span class="hljs-number">.3</span> jest@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> jest-environment-jsdom@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> vitest@<span class="hljs-number">0.25</span><span class="hljs-number">.3</span> --dev
</code></pre>
<p>or with npm:</p>
<pre><code class="lang-js">npm install @testing-library/jest-dom@<span class="hljs-number">5.16</span><span class="hljs-number">.5</span> @testing-library/react@<span class="hljs-number">13.4</span><span class="hljs-number">.0</span> @testing-library/user-event@<span class="hljs-number">14.4</span><span class="hljs-number">.3</span> jest@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> jest-environment-jsdom@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> vitest@<span class="hljs-number">0.25</span><span class="hljs-number">.3</span> --save-dev
</code></pre>
<p>I'm mentioning versions here for each package which are the latest versions at the time of writing this tutorial. So even if there is a newer breaking version release that happens for any of the packages in the future, your code will not break.</p>
<p>Here, we're installing the <code>jest-environment-jsdom</code> library because we will be running tests in the node environment. But we're testing browser interactions through the DOM – so to inform Jest about that, we need to add this library.</p>
<p>The <code>@testing-library/jest-dom</code> library is required because it contains assertions like <code>toBeInTheDocument</code>, <code>toHaveBeenCalled</code>, and others which make it easy to test for DOM elements, which you will see later in this tutorial.</p>
<p>We have also added the <code>vitest</code> package which is only required when you're using Vite for the application.</p>
<p>You don't need it if you're using <code>create-react-app</code> or your own webpack configuration.</p>
<p>Now that we have installed the required packages, let's add a script in the <code>package.json</code> file to run the tests.</p>
<p>Open the <code>package.json</code> file and add the <code>test</code> script inside it like this:</p>
<pre><code class="lang-js"><span class="hljs-string">"test"</span>: <span class="hljs-string">"vitest"</span>
</code></pre>
<p>Your <code>package.json</code> file will look like this now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/5_package_json.png" alt="Image" width="600" height="400" loading="lazy">
<em>Package.json file preview</em></p>
<p>If you're not using <code>vite</code> for creating the React app, then you will be using the following test script:</p>
<pre><code class="lang-js"><span class="hljs-string">"test"</span>: <span class="hljs-string">"jest --watch"</span>
</code></pre>
<p>Now, create a new file in the root of your project (<code>testing-library-demo</code>) with the name <code>setupTests.js</code> and add the following code inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">"@testing-library/jest-dom"</span>;
</code></pre>
<p>Now, open the <code>vite.config.js</code> file and add a new <code>test</code> object as shown in the below screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/9_vite_config.png" alt="Image" width="600" height="400" loading="lazy">
<em>vite.config.js file configuration</em></p>
<h2 id="heading-how-to-create-the-ui-for-testing">How to Create the UI for Testing</h2>
<p>Before writing tests, we need to have some components to test.</p>
<p>So let's create a simple registration page with some checkboxes, input fields, select dropdown, and buttons so we can write test cases for it.</p>
<p>We will use <a target="_blank" href="https://react-bootstrap.github.io/">react-bootstrap</a> to create the UI elements so we don't have to write all the CSS from scratch.</p>
<p>Install <code>bootstrap</code> and <code>react-bootstrap</code> by executing the following command from the terminal:</p>
<pre><code class="lang-js">yarn add bootstrap@<span class="hljs-number">5.2</span><span class="hljs-number">.3</span> react-bootstrap@<span class="hljs-number">2.6</span><span class="hljs-number">.0</span> react-select@<span class="hljs-number">5.6</span><span class="hljs-number">.1</span>
</code></pre>
<p>or with npm:</p>
<pre><code class="lang-js">npm install bootstrap@<span class="hljs-number">5.2</span><span class="hljs-number">.3</span> react-bootstrap@<span class="hljs-number">2.6</span><span class="hljs-number">.0</span> react-select@<span class="hljs-number">5.6</span><span class="hljs-number">.1</span>
</code></pre>
<p>Bootstrap provides a base CSS which we need for the UI to look nice, so we're also installing Bootstrap along with react-bootstrap.</p>
<p>Once installed, open <code>src/main.jsx</code> and add an import for the Bootstrap CSS file before any of your other CSS files as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">"bootstrap/dist/css/bootstrap.min.css"</span>;
</code></pre>
<p>Your <code>src/main.jsx</code> file will look like this now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/6_bootstrap_css.png" alt="Image" width="600" height="400" loading="lazy">
<em>bootstrap css imported</em></p>
<p>We don't need the <code>index.css</code> and <code>App.css</code> files so you can delete them.</p>
<p>Now, create a <code>components</code> folder inside the <code>src</code> folder and create a <code>register</code> folder inside the <code>components</code> folder. Inside the <code>register</code> folder, create <code>Register.jsx</code> and <code>register.css</code> files.</p>
<p>So your <code>Register.js</code> file path will be <code>src/components/register/Register.js</code>.</p>
<p>Add the content from <a target="_blank" href="https://github.com/myogeshchavan97/testing-library-demo/blob/master/src/components/register/Register.jsx">this repo</a> in the <code>Register.jsx</code> file and inside <code>register.css</code> file add contents from <a target="_blank" href="https://github.com/myogeshchavan97/testing-library-demo/blob/master/src/components/register/register.css">this repo</a>.</p>
<p>Now, open the <code>App.jsx</code> file and add the following contents inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Register"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now, if you run the application by executing the <code>yarn run dev</code> or <code>npm run dev</code> command, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/7_register_page.png" alt="Image" width="600" height="400" loading="lazy">
<em>Registration page</em></p>
<p>This tutorial is focused on the testing library, so I'm not going to explain the code from the <code>Register.js</code> file as it's basic React code. But If you're not familiar with React hooks, you can check out <a target="_blank" href="https://levelup.gitconnected.com/an-introduction-to-react-hooks-50281fd961fe?sk=89baff89ec8bc637e7c13b7554904e54">this article</a> to understand it better.</p>
<p>Also, instead of managing the state and onChange handler yourself, you can use the very popular <a target="_blank" href="https://react-hook-form.com/">react-hook-form</a> library.</p>
<p>It also allows you to add validations to your code without writing much code. Check out <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-forms-in-react-using-react-hook-form/">this article</a> if you want to learn about it in detail.</p>
<p>Now, we're all set to write unit test cases, so let's get started.</p>
<h2 id="heading-how-to-write-unit-test-cases">How to Write Unit Test Cases</h2>
<p>Before writing test cases, you should be aware of the different queries which you can make to access elements on the page.</p>
<p>The Testing Library provides a set of queries which you can see in the below screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/8_queries.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing getBy, queryBy, findBy, getAllBy, queryAllBy, and findAllBy queries. (<a target="_blank" href="https://testing-library.com/docs/queries/about">Source</a>)</em></p>
<p>To summarise:</p>
<ul>
<li>To select a single DOM element, you can use the <code>getBy</code>, <code>findBy</code>, or <code>queryBy</code> query</li>
<li>To select multiple DOM elements, you can use the <code>getAllBy</code>, <code>findAllBy</code> or <code>queryAllBy</code> query</li>
<li><code>getBy</code> and <code>findBy</code> return an error if there is no match or more than one match</li>
<li><code>queryBy</code> returns null if there is no match and returns an error if there is more than one match</li>
<li><code>findBy</code> works well with asynchronous code but not with <code>getBy</code> and <code>queryBy</code></li>
<li><code>getAllBy</code> returns an error if there is no match and returns an array of matches for one or more than one match</li>
<li><code>findAllBy</code> returns an error if there is no match and returns an array of matches for one or more than one match</li>
<li><code>queryAllBy</code> returns an empty array for no match and returns an array of matches for one or more than one match</li>
</ul>
<p>So if you don't want your test to fail if the element is not displayed on the UI, then always use <code>queryBy</code> or <code>queryAllBy</code>.</p>
<p>In other words, only use the <code>queryBy</code> or <code>queryAllBy</code> queries for asserting that an element cannot be found or is hidden.</p>
<p>Now that you're familiar with query methods, let's start writing test cases for the <code>Register</code> component.</p>
<p>Create a new <code>register.test.jsx</code> file in the <code>src/components/register</code> folder with the following content inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">"./Register"</span>;

describe(<span class="hljs-string">"Register component"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should render Register component correctly"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>);
    expect(element).toBeInTheDocument();
  });
});
</code></pre>
<p>Note that we're using Vite so the filename has to end with the <code>.jsx</code> extension even for test files. If you're not using vite then you can end the filename with the <code>.js</code> extension.</p>
<p>Now, if you execute the <code>npm run test</code> or <code>yarn run test</code> command you will see that the test passes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/1_test_result.png" alt="Image" width="600" height="400" loading="lazy">
<em>one test passed</em></p>
<p>In the above code, we're first rendering the <code>Register</code> component using the <code>render</code> method provided by the testing library.</p>
<p>As we have an h1 element with <code>Register</code> text in the <code>Register</code> component, we're using the <code>screen.getByRole</code> method to get the DOM element of the role <code>heading</code>.</p>
<p>If you don't know what role to use in the <code>getByRole</code> method, then you can use some random name and the testing library will show you all the available roles for each DOM element for that component as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/10_role.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Seeing the DOM structure of UI elements</em></p>
<p>Once we get that element using the <code>getByRole</code> method, then we're making an assertion to check if that element exists in the DOM using:</p>
<pre><code class="lang-js">expect(element).toBeInTheDocument();
</code></pre>
<p>You can see a list of all available <code>getBy</code>,<code>findBy</code> or <code>queryBy</code> methods by adding a dot after <code>screen</code> like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/11_query_methods.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Methods provided by screen object</em></p>
<p>Now, we have added one test to check if the <code>Register</code> component is getting rendered correctly or not.</p>
<p>Let's write some more tests.</p>
<p>If you run the application by running the <code>yarn dev</code> command, you will see that, once you click on the <code>Register</code> button without filling out all the details, you get an error message as shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/12_error_message.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Error message display on submitting form without entering data</em></p>
<p>So now, we need to test the same by writing a test case.</p>
<p>For that, we can use <code>userEvent</code> from the <code>@testing-library/user-event</code> package which we've already installed.</p>
<p>Now, add a new test in your <code>register.test.jsx</code> file as shown below:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should show error message when all the fields are not entered"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>);
    userEvent.click(buttonElement);
});
</code></pre>
<p>Your <code>register.test.jsx</code> file will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/13_new_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>New test added for testing error message display</em></p>
<p>So we're triggering the click event for the <code>Register</code> button in the above code.</p>
<p>Now, we need to find the element with the error message so we can add assertions for it in the test.</p>
<p>The error message is actually an <code>Alert</code> component from <code>react-bootstrap</code> which is not visible initially. It's only displayed when we submit the form without filling in all the data.</p>
<p>In such a case, we can call the <code>screen.debug</code> method to see the structure of the DOM at that moment when we trigger the click event.</p>
<p>So change the test case as shown below:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should show error message when all the fields are not entered"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>);
    userEvent.click(buttonElement);
    screen.debug();
});
</code></pre>
<p>Note that we have added <code>screen.debug</code> at the end of the test.</p>
<p>Now, if you run the <code>yarn run test</code> or <code>npm run test</code>, you will see the following DOM structure:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/14_debug_output.png" alt="Image" width="600" height="400" loading="lazy">
<em>DOM structure when after submitting the Form</em></p>
<p>As you can see from the screenshot, you directly see the name input label inside the form tag after the <code>Register</code> heading.</p>
<p>So we're not able to see the error message even if we have triggered the click event for the button.</p>
<p>This is because it takes some time to execute the validation code from the <code>handleFormSubmit</code> method. Before that we're only using the <code>screen.debug</code> method so we don't see the error message.</p>
<p>So to fix this, we can wait using async/await.</p>
<p>So declare the test function as <code>async</code> and before the <code>userEvent.click(buttonElement)</code> add an <code>await</code> keyword like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/15_await_event.png" alt="Image" width="600" height="400" loading="lazy">
<em>Added async/await</em></p>
<p>Now, if you check the console, you will be able to see the text <code>All the fields are required.</code> inside a div with the role <code>alert</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/error_message_dom.png" alt="Image" width="600" height="400" loading="lazy">
<em>Error message getting displayed in DOM structure</em></p>
<p>So we can use it in our assertion like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
expect(alertElement).toBeInTheDocument();
</code></pre>
<p>And now, you can see that the second test is also successful.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/16_success_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>test passed</em></p>
<p>Some points to note:</p>
<ul>
<li>Always remember to remove the <code>screen.debug</code> statement once you're done with your assertions, and never keep it in your code.</li>
<li>Always add an <code>await</code> keyword before triggering any event using <code>userEvent</code> as you may not know when the action will be completed.</li>
</ul>
<h2 id="heading-lets-write-some-more-tests">Let's Write Some More Tests</h2>
<p>Now that we're done with adding these two tests, we can add one more test to check if there is no error when the page is loaded like this:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should not show any error message when the component is loaded"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).not.toBeInTheDocument();
});
</code></pre>
<p>Here, instead of using this:</p>
<pre><code class="lang-js">expect(alertElement).toBeInTheDocument();
</code></pre>
<p>we're using this:</p>
<pre><code class="lang-js">expect(alertElement).not.toBeInTheDocument();
</code></pre>
<p>Because we want the alert element to be <strong>not</strong> present on the component load.</p>
<p>But if you check the console, you will see that the test is failing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/17_failed_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>Failed test when using getByRole</em></p>
<p>So, the test is not failing because of our assertion. Rather, it's failing because it can't find an element with role <code>alert</code> on page load which is expected, as there will not be any error on page load.</p>
<p>But how we can make the test pass?</p>
<p>If you remember from the list of queries in the screenshot shown before:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/8_queries-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing getBy, queryBy, findBy, getAllBy, queryAllBy, and findAllBy queries.</em></p>
<p>The <code>getBy</code> method throws an error if it does not find the matching element. So instead of using <code>getBy</code> we need to use <code>queryBy</code>. It does the same thing but it does not throw an error when there is no matching element.</p>
<p>So let's modify our test case to the below code:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should not show any error message when the component is loaded"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> alertElement = screen.queryByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).not.toBeInTheDocument();
});
</code></pre>
<p>Now, if you check the console, you will see that the test passes successfully.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/18_test_passed_query.png" alt="Image" width="600" height="400" loading="lazy">
<em>Passed test when using queryByRole</em></p>
<p>Now, let's write a test for successful registration when we fill out all the required fields.</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should show success message when the registration is successful."</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>);
    <span class="hljs-keyword">await</span> userEvent.click(buttonElement);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).toBeInTheDocument();
});
</code></pre>
<p>Now if you see the console, you will see that the test passes successfully.</p>
<p>Let's add a subheading to the registration page and see what happens when we run the tests again.</p>
<p>Add the following heading inside the <code>Form</code> tag in the <code>Register.jsx</code> file:</p>
<pre><code class="lang-js">&lt;h6 className=<span class="hljs-string">"subtitle"</span>&gt;
   Please enter your details below to register yourself.
&lt;/h6&gt;
</code></pre>
<p>So your code will now look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/20_subtitle.png" alt="Image" width="600" height="400" loading="lazy">
<em>Added new subheading</em></p>
<p>Now, if you run the tests again, you will see that one test fails:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/21_failed_multiple.png" alt="Image" width="600" height="400" loading="lazy">
<em>Failed test due to multiple headings on the page</em></p>
<p>The test failed because in the first test we're finding the <code>Register</code> heading text as shown below:</p>
<pre><code class="lang-js">screen.getByRole(<span class="hljs-string">"heading"</span>)
</code></pre>
<p>And as you know, <code>getBy</code> returns an error when you have more than one match. </p>
<p>Here, we have two headings on the <code>Register</code> component so the test failed.</p>
<p>So how can we fix it?</p>
<p>To fix it we need to identify how to accurately select elements while writing tests.</p>
<p>I have seen many developers changing the HTML structure by adding some <code>testid</code> so they can get the test passed like this:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should render Register component correctly"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByTestId(<span class="hljs-string">"title"</span>);
    expect(element).toBeInTheDocument();
});
</code></pre>
<p>Assuming you added an extra <code>data-testid</code> attribute to your JSX like this:</p>
<pre><code class="lang-js">&lt;h2 className=<span class="hljs-string">"title"</span> data-testid=<span class="hljs-string">"title"</span>&gt;
     Register
&lt;/h2&gt;
</code></pre>
<p>This will work and make your all tests pass. But this is not the correct way.</p>
<p>Just to make your test pass, <strong>you should not change your JSX by adding some extra <code>testid</code> or <code>class</code>.</strong></p>
<p>Instead, you should <strong>always try to use methods provided by <code>screen</code></strong> to make an accurate selection of DOM elements.</p>
<p>So now the question is how to make an accurate selection.</p>
<p>The <code>getByRole</code> method accepts optional options which you can use like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, { <span class="hljs-attr">level</span>: <span class="hljs-number">2</span> });
</code></pre>
<p>As our main <code>Register</code> heading is a <code>h2</code> heading, we specifically said to select <code>level 2</code> heading.</p>
<p>Now, if you update the first test case, you will see that all the tests are passing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/22_fixed_failing_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test passed by adding more specific query for heading</em></p>
<p>Now, let's add another test for testing the subheading.</p>
<p>As the subheading is of level 6, you can query it like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, { <span class="hljs-attr">level</span>: <span class="hljs-number">6</span> });
</code></pre>
<p>This will work, but there is another way we can target that element.</p>
<p>For that, you can install the <a target="_blank" href="https://chrome.google.com/webstore/detail/testing-playground/hejbmebodbijjdhflfknehhcgaklhano?hl=en">testing playground</a> Chrome browser extension.</p>
<p>Once it's installed, follow the below steps:</p>
<ul>
<li>open your Chrome dev tools using Ctrl + Alt + I or Cmd + Option + I (Mac)</li>
<li>select the <code>Testing Playground</code> tab</li>
<li>Click the cursor pointer and select the subheading of the <code>Register</code> component as shown below:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/23_accurate_subheading.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing Playground extension demo</em></p>
<p>As you can see, you will get the accurate DOM element query which you can use in your test like this:</p>
<pre><code class="lang-js">screen.getByRole(<span class="hljs-string">'heading'</span>, {
  <span class="hljs-attr">name</span>: <span class="hljs-regexp">/please enter your details below to register yourself\./i</span>
})
</code></pre>
<p>So you can write your test like this:</p>
<pre><code class="lang-js"> it(<span class="hljs-string">"should test for presence of subheading in the component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/please enter your details below to register yourself\./i</span>
    });
    expect(element).toBeInTheDocument();
 });
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/24_all_passed.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test result</em></p>
<p>Writing a test case for subheading is not necessary, because it does not affect the component behavior even if you don't test that. But just to show you how your tests will break for multiple elements, I have added that element on the UI along with its test case.</p>
<p>The <code>Testing Playground</code> Chrome extension is really useful to find out the exact matching query for any of the UI elements.</p>
<p>So instead of using the <code>screen.debug</code> method to see the DOM structure, you can use this Chrome extension to find out the role and other information for all the displayed elements as can be seen below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/25_extension_demo.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Finding out specific query using testing playground</em></p>
<p>As you can see, you can get any element by role, by placeholder text, or by label text with the methods provided by <code>screen</code>.</p>
<p>Now that you're aware of the more specific query selectors, let's update other test cases to use the specific selectors.</p>
<p>Wherever we're using just <code>screen.getByRole("button")</code>, replace it with the following:</p>
<pre><code class="lang-js">screen.getByRole(<span class="hljs-string">"button"</span>, {
  <span class="hljs-attr">name</span>: <span class="hljs-regexp">/register/i</span>
})
</code></pre>
<p>So now, if later someone adds another button in the same component, your test will not fail.</p>
<p>Your final <code>register.test.jsx</code> file will look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> userEvent <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/user-event"</span>;
<span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">"./Register"</span>;

describe(<span class="hljs-string">"Register component"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should render Register component correctly"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, {
      <span class="hljs-attr">level</span>: <span class="hljs-number">2</span>
    });
    expect(element).toBeInTheDocument();
  });

  it(<span class="hljs-string">"should test for presence of subheading in the component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/please enter your details below to register yourself\./i</span>
    });
    expect(element).toBeInTheDocument();
  });

  it(<span class="hljs-string">"should show error message when all the fields are not entered"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/register/i</span>
    });
    <span class="hljs-keyword">await</span> userEvent.click(buttonElement);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).toBeInTheDocument();
  });

  it(<span class="hljs-string">"should not show any error message when the component is loaded"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> alertElement = screen.queryByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).not.toBeInTheDocument();
  });

  it(<span class="hljs-string">"should show success message when the registration is successful."</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/register/i</span>
    });
    <span class="hljs-keyword">await</span> userEvent.click(buttonElement);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).toBeInTheDocument();
  });
});
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>React Testing library is amazing and has become a very popular tool with which to test React applications.</p>
<p>Just remember that unlike <a target="_blank" href="https://enzymejs.github.io/enzyme/">enzyme testing library</a>, you should not test for state changes when using React Testing Library.</p>
<p>So we have not written test cases to check if the state correctly changes after the user types some text in the <code>name</code>, <code>email</code>, or <code>password</code> fields.</p>
<p>In React Testing Library you check the behavior of DOM when the user clicks on a button or submits a form and so on instead of testing the internal state of the component.</p>
<h3 id="heading-thanks-for-reading">Thanks for Reading!</h3>
<p>You can find the complete source code for this tutorial in <a target="_blank" href="https://github.com/myogeshchavan97/testing-library-demo">this repository</a>.</p>
<p>If you want to become the best MERN stack developer (full stack developer), then do check out <a target="_blank" href="https://online-elearning-platform.netlify.app/">my course</a>.</p>
<ul>
<li>This is a pre-recorded video course that will be constantly updated for any future changes.</li>
<li>In this course, you will learn how to create React and Node.js applications from scratch and build an amazing online learning platform.</li>
<li>After learning through this course, you will be able to build any MERN stack application confidently and easily.</li>
<li>There is a separate section in this course, where you will learn how to test your entire React application using React testing library and jest.</li>
</ul>
<p>So do check out this amazing course.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Unit Test Handbook + Redux Testing Toolkit ]]>
                </title>
                <description>
                    <![CDATA[ In this step-by-step tutorial, you'll learn how to easily start with Unit Tests in React. You'll learn how to write tests for Redux states as well as fundamental Redux slice tests using the React Testing Library and Jest. 🔐 Here's What We'll Cover ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-unit-tests-in-react-redux/</link>
                <guid isPermaLink="false">66bb8f42fce17a7d998852db</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matthes B. ]]>
                </dc:creator>
                <pubDate>Wed, 09 Nov 2022 15:32:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/pexels-scott-webb-1527893.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this step-by-step tutorial, you'll learn how to easily start with Unit Tests in React. You'll learn how to write tests for Redux states as well as fundamental Redux slice tests using the React Testing Library and Jest.</p>
<h2 id="heading-heres-what-well-cover"><strong>🔐 Here's What We'll Cover</strong></h2>
<ul>
<li>You'll see how easy it is to set up your first unit tests in React.</li>
<li>You'll improve your general React knowledge.</li>
<li>You'll get the hang of why Test Driven Development (TDD) is helpful for your coding workflow.</li>
</ul>
<h2 id="heading-prerequisites"><strong>📝</strong> Prerequisites</h2>
<ul>
<li>You should be familiar with the basic React workflow structure (including functional components and hooks).</li>
<li>You should have a basic knowledge of Redux (I'm using Redux Toolkit for this guide).</li>
<li>You don't need any prior knowledge about testing.</li>
<li>I'm using the <code>npm</code> installation approach, not the <code>yarn</code> one.</li>
</ul>
<h2 id="heading-the-objective"><strong>🎯</strong> The Objective</h2>
<p>While learning advanced concepts of React, you'll probably stumble across the topic of testing. Being able to work with automatic tests is also quite handy for any upcoming frontend developers. </p>
<p>However, as I myself was learning React, I had a hard time finding information about how to implement tests for libraries like Redux (even though it's a library I work with all the time). </p>
<p>Beyond that, I found that doing any component testing in React is basically unfeasible when you don't know how to work with the Redux library.</p>
<p>So I took some time to read the Redux documentation and went back and forth with it a bit. Then I decided to write a practical starter guide for unit testing in React, including Redux, to share what I learned. </p>
<p>Since I would like to take a modern approach, I'm also going to use the Redux Toolkit. We'll cover the Redux implementation in this guide.</p>
<h3 id="heading-what-well-cover">What we'll cover:</h3>
<p>To start off, I will provide some general information about tests before I directly go into creating the first general unit tests. </p>
<p>Next I'll give a quick overview of how to implement some Redux Toolkit logic. </p>
<p>Then we will work on some unit tests within an application which uses Redux Toolkit. For this step we will adjust our previously created tests to the new Redux environment.</p>
<p>This is a step-by-step guide. If you are new to tests, I recommend following this guide in order from top to bottom.</p>
<p>I have also created a <a target="_blank" href="https://github.com/Matthes-Baer/unit-test-redux-article-app">public GitHub repository</a> for this guide with some commentary. You can use that if you want to look something up without scrolling through this guide in its full length again.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#what-different-kinds-of-tests-are-there">What Different Kinds of Tests Are There?</a></li>
<li><a class="post-section-overview" href="#how-to-set-up-your-react-testing-environment">How to Set Up Your React Testing Environment</a></li>
<li><a class="post-section-overview" href="#heading-check-out-your-created-react-application">Check Out Your Created React Application</a></li>
<li><a class="post-section-overview" href="#how-to-create-your-first-unit-test">How to Create Your First Unit Test</a></li>
<li><a class="post-section-overview" href="#how-to-create-a-failing-test-on-purpose">How to Create a Failing Test on Purpose</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-some-additional-tests">How to Create Some Additional Tests</a></li>
<li><a class="post-section-overview" href="#heading-how-to-perform-testing-with-the-react-redux-toolkit">How to Perform Testing with the React Redux Toolkit</a></li>
<li><a class="post-section-overview" href="#heading-outlook-for-advanced-testing">Outlook for Advanced Testing</a></li>
</ol>
<h2 id="heading-what-different-kinds-of-tests-are-there">📋 What Different Kinds of Tests Are There?</h2>
<p>This quick guide won't provide you with detailed theoretical knowledge about all the <a target="_blank" href="https://www.freecodecamp.org/news/types-of-software-testing/">different kinds of testing out there</a>. At this point, you should just understand that there are generally three kinds of tests:</p>
<ul>
<li>Unit Tests</li>
<li>Integration Tests</li>
<li>End-To-End Tests</li>
</ul>
<p>To put it in simple words: You can see these three types of tests as generally increasing in their complexity. </p>
<p>While <a target="_blank" href="https://www.freecodecamp.org/news/unit-tests-explained/">unit tests</a> cover single functions and components, integration tests typically focus on multiple functions and their connections to each other. <a target="_blank" href="https://www.freecodecamp.org/news/end-to-end-testing-tutorial/">End-to-end tests</a> are even more complex and give insights about multiple function and component structures. </p>
<p>There are other test concepts, but these three are the most important ones for web developers, for example.</p>
<p>Again, this is really put in simple words. But in this case it's sufficient to know that unit tests are basically the least complex tests out of these three. </p>
<p>It's also quite easy to work with unit tests as soon as you have a basic understanding of how testing in general works.</p>
<p>I would also like to quickly emphasize that there are mainly two ways of testing your application.</p>
<ul>
<li>Manual Testing</li>
<li>Automatic Testing</li>
</ul>
<p>Manual Testing is pretty much what you probably already do for all of your application which you create. When manually testing your application, you basically start your React application with <code>npm run start</code> and actually click on buttons to check if the corresponding function works.</p>
<p>Automatic Tests, on the other hand, are pretty much functions you create which automatically check your application to see if the respective steps work that you defined within these tests. This automatic kind of testing is extremely important for larger projects. </p>
<p>With this automatic approach, it's also way easier to scale your tests. In the end, you have a lot of tests which automatically test your whole application in a relatively short amount of time. These test can help you spot any potential errors which might have occurred during development. This would take much more time if you were to go back constantly to manually test your application.</p>
<p>Being able to work with automatic tests is also typically a big plus for your résumé as a frontend developer.</p>
<h2 id="heading-how-to-set-up-your-react-testing-environment">🔧 How to Set Up Your React Testing Environment</h2>
<p>In order to get a practical start, we are going to directly dive into our React application. </p>
<p>You will see that the setup of a testing environment is relatively easy in React – or, to be more precise, React does it all for you during the regular install setup.</p>
<p>Therefore, I'm creating a React application with the following line:</p>
<p><code>npx create-react-app &lt;name of your application&gt;</code></p>
<p>After this step, we need everything that should be added for using Redux in our React application:</p>
<ul>
<li><strong>React Redux:</strong> <code>npm install react-redux</code> (provides some mandatory hooks, for example)</li>
<li><strong>React Redux Toolkit:</strong> <code>npm install @reduxjs/toolkit</code> (provides logic for creating a store or slices, for example)</li>
</ul>
<p>It's worth mentioning that there also is the <strong>Redux core</strong> (<code>npm install redux</code>). But this is already part of the React Redux Toolkit installation, so we don't have to install it here too. </p>
<p>If you wanted to use React without the React Redux Toolkit, then you would have to separately reach out to the Redux core installation.</p>
<p>You can also create a new React application from scratch with <code>npx create-react-app my-app --template redux</code> which includes the React Redux Toolkit, the React core, React Redux, as well as a template from the React Redux Toolkit. </p>
<p>Choose this approach if you don't have any existing React applications, since it's probably more convenient.</p>
<p>Under the hood, you now have an application that uses the <strong>React Testing library</strong> combined with <strong>Jest</strong> (a testing framework). Together, they have pretty much everything that you will need for testing your React application. </p>
<p>You don't have to install anything else for this purpose. These tools come out of the box with a standard React installation.</p>
<h2 id="heading-check-out-your-created-react-application">🔎 Check Out Your Created React Application</h2>
<p>As you go into your newly created React application, you will find the folder and file structure you are likely familiar with. Besides others, there is the <code>App.js</code> file, which is created like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> logo <span class="hljs-keyword">from</span> <span class="hljs-string">'./logo.svg'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          Edit <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>src/App.js<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> and save to reload.
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"App-link"</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://reactjs.org"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
          <span class="hljs-attr">rel</span>=<span class="hljs-string">"noopener noreferrer"</span>
        &gt;</span>
          Learn React
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Within the <code>src</code> folder, you also have the file <code>App.test.js</code>. This file is actually a first test that came out of the box with React installation. This file is structured like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

test(<span class="hljs-string">'renders learn react link'</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> linkElement = screen.getByText(<span class="hljs-regexp">/learn react/i</span>);
  expect(linkElement).toBeInTheDocument();
});
</code></pre>
<p>Even without fully understanding what <code>render</code> or <code>screen</code> is, for example, we can see that something is going on with our <code>App</code> component in there. In fact, this is a unit test that is focusing on a specific part of the <code>App</code> component.</p>
<p>While this first template for a test is a handy representation of what a test looks like, I would like to create a test file from scratch.</p>
<p>Generally speaking, tests are separated into different test suites. These test suites are typically a group of tests that focus on the same component, for example. Tests within the same test suite basically have the same superordinate topic.</p>
<p>To check this, try to enter <code>npm run test</code> in your terminal when you are within your React application. </p>
<p>It could say something like "There are no new tests or changes since the last commit" – in this case, just enter <code>a</code> in the terminal to run all tests regardless.</p>
<p>In the end, you should be able to see this within the terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-124.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of <code>npm run test</code></em></p>
<p>At the top, you can see that the <code>App.test.js</code> file passed. Basically, all tests within this file were successful. </p>
<p>Below that, you can see <code>renders learn react link</code>: This is the description for this particular test, which we can define individually. We will get back to this later.</p>
<p>Further down, we can finally see the test suites and tests. As you can see, we have one test suite and one test. To be more precise, we have one test suite that includes this one test. </p>
<p>Later on, you will recognize that we will use like 1-3 test suites while there will be around 5+ tests, for example. Again, test suites basically provide a structure that groups single tests together.</p>
<p>The stuff with the snapshots is not important for your specific case.</p>
<p><a target="_blank" href="https://jestjs.io/docs/snapshot-testing">Snapshots</a> are an advanced concept for testing. So a reference snapshot (like an image that was taken) is being compared with the version after some actions took place. This can help to check whether the UI stays the same after some actions or if some changes happened all of a sudden.</p>
<p>I won't focus on testing with snapshots in this article. This is a topic that you might want to look up after understanding some unit testing basics.</p>
<h2 id="heading-how-to-create-your-first-unit-test">🔨 How to Create Your First Unit Test</h2>
<p>Now that we've looked at a unit test, lets dive into the first test which we'll build from scratch on our own.</p>
<p>For that, I would like to create a new folder called <code>__tests__</code>. This is common when you are working with tests or checking out other applications. </p>
<p>I'm also dragging the already-available <code>App.test.js</code> file into this folder. This doesn't change anything about the result.</p>
<p>Our folder structure now looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-125.png" alt="Image" width="600" height="400" loading="lazy">
<em>general folder structure with <code>__tests__</code></em></p>
<p>Within <code>__tests__</code>, we create the file <code>myFirstTesting.test.js</code>. We need this file structure of <code>&lt;test name&gt;.test.js</code>. You can also create a test file with <code>&lt;test name&gt;.spec.js</code> – both approaches will work the same.</p>
<p>Our first step is to import the <code>App.js</code> component: <code>import App from "../App";</code>.</p>
<p>To create our first test, we have to make use of the <code>test()</code> function. You could also use <code>it()</code>. Both will achieve the same result. </p>
<p>The first parameter of this function has to be a string, which describes what we are going to test (remember the stuff with "renders learn react link" within the test file we viewed?). This is going to help you have a more precise overview after running all the tests. </p>
<p>In this case, I will use the description <code>"renders logo in App component"</code>. The second parameter is another function for which we are using an anonymous arrow function. Our <code>myFirstTesting.test.js</code> file now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {

})
</code></pre>
<p>Even though there is not much going on, let's try entering <code>npm run test</code> again. We will find the following result in our terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-126.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Therefore, we now have two test files, resulting in two test suites and two tests.</p>
<p>Now we would actually like to test something. Since we added the description <code>"renders logo in App component"</code>, we are going to test exactly that. </p>
<p>In order to do that, we need the <code>render()</code> function, which we'll use whenever we actually want to render a component from our application.</p>
<p>In order to add the <code>render()</code> function, we have to import it from the React Testing library, which is already part of our React application without any other installations. </p>
<p>While we're at this step of importing, let's also import <code>screen</code> (also part of the React Testing library). It provides access to different functions that will look through the current screen after something gets rendered and find specific elements, for example.</p>
<p>After adding these two imports, our <code>myFirstTesting.test.js</code> file now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {

})
</code></pre>
<p>Now that we have all that, let's actually start working on our test.</p>
<p>First of all, we need to render our component. Remember that tests are self-contained and don't know that we have an <code>App.js</code> with the corresponding content in our React application. We have to individually tell the specific test that a component exists by rendering it with <code>render()</code> at the top of the test. This is going to look like this: <code>render(&lt;App /&gt;);</code>.</p>
<p>Now that we have rendered the <code>App.js</code> component in this test, we should try to check if a specific content part can be found by the test. This way, we can actually test if <code>App.js</code> was rendered like it was supposed to be. </p>
<p>Assuming something went wrong, we would not be able to find the React logo, for example, which is currently part of the <code>App.js</code> component.</p>
<p>So we will try to find this logo, which is an <code>img</code> element. To do this, we can make use of the <code>getByAltText()</code> function that finds an element by its specific <code>alt</code> attribute, which is commonly utilized for images. We have access to this function with <code>screen</code> that we imported earlier. </p>
<p>We now have this expression: <code>screen.getByAltText("logo")</code>. So the test looks at the screen where we rendered the <code>App.js</code> component beforehand, and then gets an element, which has an <code>alt</code> attribute of <code>"logo"</code>. We will connect all this to a variable. </p>
<p>Our test file now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
})
</code></pre>
<p>There are a bunch of different functions like <code>getByAltText()</code> that you can use to look for elements with a specific text content, a specific role like a button, or even with a test id that you can add to the actual element.</p>
<p>You also have the opportunity to look for multiple elements. Besides that, you don't have to use a string as parameter. A regular expression with <code>/logo/i</code> is also feasible, for example. We will use different ways to find elements throughout this starter guide.</p>
<p>For the last step, we have to utilize <code>expect()</code>, which we use to see what behavior we can expect. In this case, we expect that our <code>image</code> variable is part of the component and therefore exists. </p>
<p>For this approach, our file would look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
  expect(image).toBeInTheDocument();
})
</code></pre>
<h2 id="heading-how-to-create-a-failing-test-on-purpose">❗ How to Create a Failing Test on Purpose</h2>
<p>If we now run our tests with <code>npm run test</code>, everything will pass. Now, let's try to reverse this logic so that we actually create a failing test. This way, we can check if this test actually has some impact or not. </p>
<p>To do this, we can go into our <code>App.js</code> file and change the <code>alt</code> attribute for the logo image. If you change it to <code>alt="loo"</code>, the test will fail and it'll give you some information.</p>
<p>In our case, though, I would like to change something on the test itself to make it fail and show you another expression that is handy to know. Instead of <code>expect(image).toBeInTheDocument();</code> we can also type <code>expect(image).not.toBeInTheDocument();</code>. So here we added a <code>not</code>. This basically reversed the logic, and now the test expects that no such image element exists.</p>
<p>If we now try to run the test, we will find the following error message in our terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-127.png" alt="Image" width="600" height="400" loading="lazy">
<em>The error message we get</em></p>
<p>You can see that the test expected that there was no such element as <code>image</code>. However, it found something and therefore answered with an error message.</p>
<p>You don't have to make all your tests purposely fail to check if they work or not. I just wanted to show you what an actual failing test would look like.</p>
<h2 id="heading-how-to-create-some-additional-tests">✏️ How to Create Some Additional Tests</h2>
<p>Now we have finished with our first test and have some basic knowledge about what to expect when working with unit tests. Next, we will check out some other test examples.</p>
<p>In order to create a more realistic scenario, I will add one additional component, which we'll insert into the <code>App.js</code> component.</p>
<p>For this step, first we create a folder called <code>components</code> in our <code>src</code> folder. This is not a must, but it is common to structure your files like that.</p>
<p>Within the <code>components</code> folder, we create <code>List.js</code>. Our folder structure now looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-155.png" alt="Image" width="600" height="400" loading="lazy">
<em>current folder structure</em></p>
<p>Now, let's try to follow more of a test driven development (TDD) workflow, which is quite modern. I'm not necessarily sayint that this is always recommended. But a TDD approach is considered best practice by more and more people nowadays. </p>
<p>Of course, in this tutorial we'lre "only" talking about unit tests and not integration or end-to-end tests, but the general TDD workflow is similar for all three test categories.</p>
<p>So using this test driven development approach, we basically add tests and work on our application simultaneously. </p>
<p>To be more precise, we even create tests for single components and function parts before you even implement this tested logic in your application. </p>
<p>So there is a lot of going back and forth instead of creating all the tests at once at the end.</p>
<h3 id="heading-how-to-start-the-setup-for-listjs">How to Start the Setup for <code>List.js</code></h3>
<p>In our example, we have added the <code>List.js</code> component. Within this component, I would like to add a list with a button. When a user clicks on the button, it adds something to the list (an object with multiple keys and values).</p>
<p>In order to have some sort of frame, I will first add some <code>div</code> elements and similar stuff to our <code>List.js</code> component before we dive into the actual logic.</p>
<p>The <code>List.js</code> component now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>This is the first list entry<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>This button can add a new entry to the list<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> List;
</code></pre>
<p>I also added the <code>List.js</code> component as a child to <code>App.js</code> (below all the other stuff in <code>App.js</code>) so it will be visible without changing anything else.</p>
<p>The result looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-156.png" alt="Image" width="600" height="400" loading="lazy">
<em>How it looks</em></p>
<p>This won't win you any style competitions but it's sufficient for our case.</p>
<h3 id="heading-setup-for-the-test-for-listjs">Setup for the test for <code>List.js</code></h3>
<p>Since we want to test while we are working on our component, I will now jump directly to the testing part even if nothing really happened in our <code>List.js</code> component in terms of click functions, for example.</p>
<p>We could create a new test file, but I would like to show you a new function we can use for our test suites specifically. This function is called <code>describe()</code> and can be handy for further structuring our tests.</p>
<p>To use <code>describe()</code>, we jump to <code>myFirstTesting.test.js</code> within <code>__tests__</code>. Right now, this file basically serves as one test suite for the test we specifically created for the <code>App.js</code> component. But I would like to have two test suites within this test file: one for the <code>App.js</code> tests and one for the <code>List.js</code> tests.</p>
<p>For this step, I'm using the <code>describe()</code> function, which basically works like the <code>test()</code> function in terms of parameters. </p>
<p>The first parameter will be a string, describing the respective test suite. The second parameter is a function, which then includes our <code>test()</code> functions with their stuff.</p>
<p>It will look like this in our case:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    expect(image).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"example"</span>, <span class="hljs-function">() =&gt;</span> {});
});
</code></pre>
<p>Before we jump into this new test, I would actually like to add something for the <code>App.js</code> testing. Since we have this <code>describe()</code> block, we could just add a new <code>test()</code> function – and this is what I'm going to do.</p>
<p>See the following newly added test described with <code>"renders List.js component in App.js"</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    expect(image).toBeInTheDocument();
  });

   test(<span class="hljs-string">"renders List.js component in App.js"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"example"</span>, <span class="hljs-function">() =&gt;</span> {});
});
</code></pre>
<p>So I'm rendering the <code>App.js</code> component and looking for text via a regular expression, which is part of the <code>List.js</code> component. This test can basically be understood as a render test for <code>List.js</code>. If <code>List.js</code> had not been able to be rendered within <code>App.js</code>, this test would not pass.</p>
<p>If you are confused that this works without separately using <code>render()</code> on the <code>List.js</code> component, remember that <code>List.js</code> is part of <code>App.js</code> and everything inside <code>App.js</code> will be rendered under typical conditions. If you tried to look for a text phrase that doesn't exist in <code>List.js</code>, this new test would fail. Right now, in our case, it passes.</p>
<p>I would also like to emphasize that you can have multiple <code>expect()</code> functions within the same test. Therefore, we also could have structured this new test like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);

    expect(image).toBeInTheDocument();
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"example"</span>, <span class="hljs-function">() =&gt;</span> {});
});
</code></pre>
<p>This would also work perfectly fine in our case. And this can be handy in situations where you test for some small elements which are directly connected to each other and have the same requirements to be rendered. </p>
<p>But keep in mind that in our case, we should have adjusted the description for this test. That's because <code>"renders logo in App component"</code> is not correct anymore if we are testing more than that in this test. So let's head back to the structure with two separate tests for now. But have in mind that you are able to work like this.</p>
<h3 id="heading-back-to-the-test-for-listjs">Back to the test for <code>List.js</code></h3>
<p>Now I would like to work with the second <code>describe()</code> block that we created a few moments ago, where we want to work with tests specifically for the <code>List.js</code> component.</p>
<p>Since we are aiming for a test-driven development approach, we should think about what we are going to build, write a test, and then implement that logic in our component.</p>
<p>We want to create a simple list in our <code>List.js</code> component. So there will be an array, which we will go through with <code>map()</code>. </p>
<p>For this approach, we will utilize the <code>useState()</code> hook so we have a state that can dynamically adjust (the array of list items). Our first test will be to check if the length of this array in its initial state is equal to <code>1</code>.</p>
<p>To find the items within this state, we will make use of the <code>getAllByTestId()</code> method, which allows us to search for specific elements we marked with a <code>data-testid</code> in the frontend. </p>
<p>The test with the description <code>"renders initial state of listData state"</code> that I created is now included:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);

    expect(image).toBeInTheDocument();
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
   test(<span class="hljs-string">"renders initial state of listData state"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">List</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> list = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    expect(list.length).toEqual(<span class="hljs-number">1</span>);
  });
});
</code></pre>
<p>Right now this test will fail, of course, because we haven't added any of this logic to the component yet.</p>
<p>So I adjusted the <code>List.js</code> component. It now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> initialState = [
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is something"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">7</span>,
    },
  ];
  <span class="hljs-keyword">const</span> [listData, setListData] = useState(initialState);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listData.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          );
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>This button can add a new entry to the list<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> List;
</code></pre>
<p>Newly added was the <code>listData</code> state array via a <code>useState()</code> hook as well as an initialState, which I initialized with one object at the very top. I also made use of the <code>map()</code> function to go through this <code>listData</code> to create a list. </p>
<p>For each <code>&lt;li&gt;</code> element, I'm adding a key and a <code>data-testid</code>. This <code>data-testid</code> is the id we need for our test to find the respective elements.</p>
<p>On our actual application, we can see the <code>listItem.description</code> for this initial state:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-165.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So by manually testing (actually looking at our application in the browser), we can see that this should work. If we now run our tests, we will also see that the test we created passed.</p>
<h3 id="heading-how-to-add-an-object-to-the-state">How to add an object to the state</h3>
<p>Now let's test something more exciting: the logic to add a new object to this <code>listData</code> state. Again, we will start by working on our test first before actually implementing the required logic within the React component.</p>
<p>With this newly added test described by <code>"adds a new data entry to listData after button click"</code>, our test file now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> List <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/List"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

<span class="hljs-keyword">import</span> userEvent <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/user-event"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    expect(image).toBeInTheDocument();
  });

  test(<span class="hljs-string">"renders List.js component in App.js"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders initial state of listData state"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">List</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> list = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    expect(list.length).toEqual(<span class="hljs-number">1</span>);
  });

  test(<span class="hljs-string">"adds a new data entry to listData after button click"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">List</span> /&gt;</span></span>);
    <span class="hljs-keyword">let</span> listItems = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    <span class="hljs-keyword">const</span> button = screen.getByRole(<span class="hljs-string">"button"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/This button can add a new entry to the list/i</span>,
    });

    expect(list.length).toEqual(<span class="hljs-number">1</span>);
    userEvent.click(button);
    list = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    expect(list.length).toEqual(<span class="hljs-number">2</span>);
  });
});
</code></pre>
<p>At the bottom, you can see this test. Therefore, we are first rendering the <code>List.js</code> component before looking for all available list items we assigned a test id to. You will see exactly where we put the test id in a few moments.</p>
<p>We also have to look for the button that we want to test to see if clicking on it adds something to the list. We do this with <code>getByRole()</code> which expects a role like <code>"button"</code> or <code>"table"</code> as a first parameter, for example (there are a bunch of different roles you can target). The second parameter is optional and is an object that can receive a value for the <code>name</code> key.</p>
<p><code>name</code> is pretty much the text content we have specifically for the button in this case. This optional second parameter is handy when you have multiple elements of type <code>"button"</code> in your component and want to get a specific button out of these.</p>
<p>After getting the <code>listItems</code> as well as the <code>button</code>, we start off with a first <code>expect()</code> to basically test the initial state. In this initial state, we expect to have only one list item.</p>
<p>Then, with the help of <code>userEvent</code>, we are going to click on the button. You could also use <code>fireEvent</code> for this situation (<code>userEvent</code> is still pretty new compared to the <code>fireEvent</code> approach). Both will work, and both are helpful for any action where you want to interact with specific elements. In this case, I want to simulate clicking on a button.</p>
<p>Tests generally follow a "arrange -&gt; act -&gt; assert" pattern that you can follow to structure them. Within the "arrange" part, you initialize and get all required elements. With the "act" part, you would simulate a mouse click (as in our case), for example. With "assert," you are checking if it all behaves like you expected it to.</p>
<p>In another case, you could simulate changing the value of an input field with <code>fireEvent.change(inputField, { target: { value: someValueVariable } })</code>, for example. Maybe you want to focus an input field or even drag an element - such actions can be simulated via <code>fireEvent</code> and <code>userEvent</code>.</p>
<p>After the button click, it again looked for all <code>listItems</code> since the current value of this variable would still be <code>1</code> from the previous initialization. As soon as this step is completed, it uses another <code>expect()</code> function to check if the length of the <code>listItems</code> array is now equal to <code>2</code> and not <code>1</code>.</p>
<p>Now that we have our test logic, let's jump back to the <code>List.js</code> component and implement the corresponding logic:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> initialState = [
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is something"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">7</span>,
    },
  ];
  <span class="hljs-keyword">const</span> [listData, setListData] = useState(initialState);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listData.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          );
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span>
          setListData([
            ...listData,
            { id: 999, description: "999", significance: 100 },
          ])
        }
      &gt;
        This button can add a new entry to the list
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> List;
</code></pre>
<p>The only part that changed is the button at the bottom of this file. So I added a function that gets invoked when clicking on this button. The function then adjusts the current state of <code>listData</code> which is responsible for rendering our list. I copied the current state with a spread operator and then added another hard-coded object as the new entry for this list. </p>
<p>Of course, there are more creative ways to fill in the values for the <code>id</code>, <code>description</code>, and <code>significance</code> keys.</p>
<p>I would also like to emphasize that you have the opportunity to create a separate function outside of the <code>return()</code> and access this function like this: <code>onClick={separateFunctionToAddObjectToState}</code> on the same button element. This would also work without having to render something additional within the test.</p>
<p>If we now run our test, we will see that it passes. If you try to still expect a length of <code>1</code> after clicking on the button, the test will fail like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-192.png" alt="Image" width="600" height="400" loading="lazy">
<em>error alert for length of 1</em></p>
<p>So it actually does what it is supposed to do.</p>
<h2 id="heading-setup-for-redux">🔧 Setup for Redux</h2>
<p>After working with local states via the <code>useState()</code> hook, I would like to work on the same files and adjust them for Redux (or the Redux Toolkit, to be precise). </p>
<p>I'm not going to dive deep into what Redux actually is and what every term like <code>action</code>, <code>store</code>, or <code>reducer</code> means in detail – since this would be worthy of a whole new guide. If you want that, you can <a target="_blank" href="https://www.freecodecamp.org/news/redux-for-beginners/">read this guide to Redux basics</a>.</p>
<p>Instead, I will give just a quick rundown and show which files I'm adding and editing. Then I'll talk about how to handle the <code>render()</code> method, including the Redux store provider, which can cause a lot of frustration when testing if you don't know about it.</p>
<h3 id="heading-overall-folder-structure">Overall folder structure:</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-14.png" alt="Image" width="600" height="400" loading="lazy">
<em>current overall folder structure with the React Redux Toolkit</em></p>
<p>You can see that I added an <code>app</code> (for the store) as well as a <code>features</code> (for the slice) folder.</p>
<h3 id="heading-updated-indexjs-file">Updated <code>index.js</code> file:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;
<span class="hljs-keyword">import</span> reportWebVitals <span class="hljs-keyword">from</span> <span class="hljs-string">"./reportWebVitals"</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">"./app/store"</span>;

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>You can see that I added a <code>provider</code> and wrapped it around the application so we have access to the store from anywhere.</p>
<h3 id="heading-created-storejs-file">Created <code>store.js</code> file:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;
<span class="hljs-keyword">import</span> { ListSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

<span class="hljs-keyword">const</span> store = configureStore({
  <span class="hljs-attr">reducer</span>: {
    <span class="hljs-attr">listReducers</span>: listSlice.reducer,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>In this file, we have created the required store for the Redux implementation.</p>
<h3 id="heading-created-listslicejs-file-in-features-folder">Created <code>ListSlice.js</code> file in <code>features</code> folder:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">value</span>: [
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is something"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">7</span>,
    },
  ],
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ListSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">"listReducers"</span>,
  initialState,
  <span class="hljs-attr">reducers</span>: {},
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { } = ListSlice.actions;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ListSlice.reducer;
</code></pre>
<p>Here we have created the slice that we added to the store. Notice that I haven't added any reducer yet. This slice just contains the current corresponding state.</p>
<h3 id="heading-updated-listjs-file-in-components-folder">Updated <code>List.js</code> file in <code>components</code> folder:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;

<span class="hljs-keyword">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> listState = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.listReducers.value);
  <span class="hljs-keyword">const</span> dispatch = useDispatch(); <span class="hljs-comment">// not used right now</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listState.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          );
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>This button can add a new entry to the list<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> List;
</code></pre>
<p>On the frontend, we swapped the local state (using the useState hook) with the Redux state (using the useSelctor hook). You'll also see that I adjusted the button. There is no click function anymore (we will get back to that later on).</p>
<h2 id="heading-how-to-perform-testing-with-the-react-redux-toolkit">🔎 How to Perform Testing with the React Redux Toolkit</h2>
<p>Now that we have updated and created all the necessary files for the React Redux Toolkit logic, I would like to run a quick test of all the tests we previously created.</p>
<p>The result is that all tests have failed:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-15.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Keep in mind that I adjusted the button in <code>List.js</code>, for example, so the corresponding test was expected to fail. However, not all tests should have failed.</p>
<p>The test environments are working in their own world. They don't know if you wrap a provider somewhere in <code>index.js</code> and enable Redux logic. So the tests are still trying to make the rendering work without Redux. But our application now depends on Redux to manage our main state.</p>
<p>This means that we have to adjust the <code>render()</code> function so that this function is actually aligned with the Redux logic.</p>
<p>A method to make this work is to introduce a helper function, which we will store in a new folder called <code>utils</code>. The file will be called <code>utils-for-tests.jsx</code>. The content will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { render } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-comment">// As a basic setup, import your same slice reducers</span>
<span class="hljs-keyword">import</span> { ListSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">renderWithProviders</span>(<span class="hljs-params">
  ui,
  {
    preloadedState = {},
    <span class="hljs-regexp">//</span> Automatically create a store instance if no store was passed in
    store = configureStore({
      reducer: { listReducers: ListSlice.reducer },
      preloadedState,
    }),
    ...renderOptions
  } = {}
</span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Wrapper</span>(<span class="hljs-params">{ children }</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>;
  }

  <span class="hljs-comment">// Return an object with the store and all of RTL's query functions</span>
  <span class="hljs-keyword">return</span> { store, ...render(ui, { <span class="hljs-attr">wrapper</span>: Wrapper, ...renderOptions }) };
}
</code></pre>
<p>This code information can be found in the <a target="_blank" href="https://redux.js.org/usage/writing-tests">Redux documentation</a>. You can almost copy and paste it all for your application.</p>
<p>But you have to adjust the slices that are used in there. Since in our application there is only the <code>ListSlice</code> we don't have much to add. Just import that and update the content of the <code>configureStore()</code> function, like we managed it in our <code>store.js</code> file.</p>
<p>This step is necessary to basically mock the entire Redux logic and put it together into one new <code>render()</code> function.</p>
<p>With that, we can import this new function into our test files (<code>App.test.js</code> and <code>myFirstTesting.test.js</code>) and then replace all <code>render()</code> functions with <code>renderWithProviders()</code>. The <code>App.test.js</code> file, for example, now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;
<span class="hljs-keyword">import</span> { renderWithProviders } <span class="hljs-keyword">from</span> <span class="hljs-string">"../utils/utils-for-tests"</span>;

test(<span class="hljs-string">"renders learn react link"</span>, <span class="hljs-function">() =&gt;</span> {
  renderWithProviders(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> linkElement = screen.getByText(<span class="hljs-regexp">/learn react/i</span>);
  expect(linkElement).toBeInTheDocument();
});
</code></pre>
<p>There is not much more to do! If we now run our tests again (and comment out this one test, which is going to fail regardless because the button logic is not active anymore), it will work again.</p>
<h3 id="heading-slice-testing">Slice testing</h3>
<p>Another exciting part about testing with Redux is testing the slices. If you created your application with the React Redux Toolkit template, then you will be provided with some corresponding tests.</p>
<p>For our case, I also want to implement a new test file where we will specifically test <code>ListSlice.js</code> and its corresponding Redux logic.</p>
<p>For this slice, we have to import the slice and the corresponding reducers we want to test. To start, I will import the slice and test if it gets initialized with the initialState.</p>
<p>This is actually not the TDD approach since we already manually tested this part. Netherless, I would like to implement an automatic test as well:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ListSlice, { initialState } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

describe(<span class="hljs-string">"tests for ListSlice"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"initialize slice with initialValue"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> listSliceInit = ListSlice(initialState, { <span class="hljs-attr">type</span>: <span class="hljs-string">"unknown"</span> });
    expect(listSliceInit).toBe(initialState);
  });
});
</code></pre>
<p>Notice that I'm using <code>.spec</code> instead of <code>.test</code>. This doesn't matter. You can choose either. In this case, I'm going with <code>.spec</code> to remind you that this is also a viable option.</p>
<p>Also remember that we exported the initialState within our slice (see above). So we are able to import it here.</p>
<p>Other than that, we are already familiar with the <code>describe()</code> environment, which includes one <code>test()</code>. Within this test, I'm initializing a variable <code>listSliceInit</code>, which will hold the value we are receiving after the slice operation took place.</p>
<p>For this operation, we use <code>ListSlice</code> as a function and include the initial state as the first argument (in this case <code>initialState</code>). The second argument will be a reducer in most cases. </p>
<p>But in this case, we don't need to enter a reducer. Instead, we are using an object with <code>type: "unknown"</code>. This is basically telling the function that we don't want to perform any additional operations.</p>
<p>Therefore, <code>listSliceInit</code> should now include our state value, which includes an array with one entry. The corresponding test will pass.</p>
<p>To force a failure, I'm entering <code>expect(listSliceInit).toBe({ value: [] });</code> instead of the previous <code>expect()</code> function. So instead of our <code>initialState</code> we are expecting it to have an empty array. Now our test environment will tell us the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-24.png" alt="Image" width="600" height="400" loading="lazy">
<em>failing test</em></p>
<p>So it actually tells us what exactly it expected – in this case, it expected the <code>initialState</code>.</p>
<p>Next, I would like to test a reducer. However, we haven't added one yet. So I will adjust <code>ListSlice</code> in the <code>ListSlice.js</code> file like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ListSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">"listReducers"</span>,
  initialState,
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">testAddReducer</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.value.push(action.payload);
    },
  },
});
</code></pre>
<p>Thus, I added <code>testAddReducer()</code>, which is responsible for pushing one additional element to the current state value, which it receives via an input from the dispatch (through <code>action.payload</code>).</p>
<p>If we now jump back to the <code>listSlice.spec.js</code> file, I'm adding another unit test:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ListSlice, { initialState, testAddReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

describe(<span class="hljs-string">"tests for ListSlice"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"initialize slice with initialValue"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> listSliceInit = ListSlice(initialState, { <span class="hljs-attr">type</span>: <span class="hljs-string">"unknown"</span> });
    expect(listSliceInit).toBe(initialState);
  });

  test(<span class="hljs-string">"testAddReducer"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> testData = {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is for the test section"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">5</span>,
    };

    <span class="hljs-keyword">const</span> afterReducerOperation = ListSlice(
      initialState,
      testAddReducer(testData)
    );

    expect(afterReducerOperation).toStrictEqual({
      <span class="hljs-attr">value</span>: [initialState.value.at(<span class="hljs-number">0</span>), testData],
    });
  });
});
</code></pre>
<p>I added the test for <code>testAddReducer</code>. You can see that I imported the reducer as well.</p>
<p>Firstly, I'm initializing a new variable, <code>testData</code>, which contains the data I would like to push to the current state.</p>
<p>After that, we follow the same structure as before with <code>afterReducerOperation</code>. But instead of this <code>type: "unknown"</code> stuff, we add the reducer as the second argument. This receives the <code>testData</code> as a parameter – basically like you would see it in a dispatch.</p>
<p>Then, we expect this <code>afterReducerOperation</code> variable to be strictly equal to the value of an array, which has two entries: <code>initialState.value.at(0)</code> (the first entry of our <code>initialState</code>) and <code>testData</code>. And this test will pass like we actually expected it.</p>
<p>If we are trying to enter some other entries or change the current ones, you would be able to see this test failing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-25.png" alt="Image" width="600" height="400" loading="lazy">
<em>forced error: I added a third entry to the array</em></p>
<h3 id="heading-how-to-make-the-button-click-function-work-again">How to make the button click function work again</h3>
<p>Remember the button click within the <code>List.js</code> component (for adding something to the <code>listData</code> state) that wasn't working anymore after we changed to the Redux setup? Let's quickly update that to make that logic work within a Redux environment for the sake of completeness. Since we have the required reducer now, this will be an easy step.</p>
<p>To make the test work again, which added a new element to the state, we have to adjust it a little on the frontend to implement the Redux logic. (Previously we used the useState hook for a local state.)</p>
<p>For this step, we are making use of the <code>dispatch()</code> function in order to reach out to the <code>testAddReducer</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> { testAddReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

<span class="hljs-keyword">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> listState = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.listReducers.value);
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listState.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          );
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span>
          dispatch(
            testAddReducer({
              id: `${new Date().getSeconds()}1`,
              description: "This is added",
              significance: 5,
            })
          )
        }
      &gt;
        This button can add a new entry to the list
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> List;
</code></pre>
<p>Besides the button logic, nothing else has changed in this file.</p>
<p>In the corresponding test (within <code>myFirstTesting.test.js</code> nothing has changed), if we now test everything – including this updated test – we will see that everything works fine:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>final test run</em></p>
<p>And that's pretty much it for fundamental slice and general Redux unit testing!</p>
<h2 id="heading-outlook-for-advanced-testing">🔭 Outlook for Advanced Testing</h2>
<p>There are different topics like <a target="_blank" href="https://redux-toolkit.js.org/api/createAsyncThunk">thunks</a> (or <a target="_blank" href="https://redux-toolkit.js.org/rtk-query/overview">RTK Query</a> as an alternative) which could also be tested. But I'm considering this as an advanced topic, and it would take some more time to explain these processes.</p>
<p>If you are not aiming to be an expert in testing at this point, the topics we discussed for unit tests in Redux in this tutorial should be sufficient for you.</p>
<p>Generally speaking, I would recommend diving deeper into so-called mocks, spies, and also snapshots. These will be helpful if you are working on some other more advanced tests. </p>
<p>The stuff with <code>renderWithProvider()</code> is basically based on such a mock – there, we artificially created a store with reducers and a provider to create this new <code>render()</code> function. So mocks are especially helpful for any third-party libraries, for example. </p>
<p>As I said, though, mocks, spies, and snapshots are more of an advanced topic to wrap your head around.</p>
<h2 id="heading-further-learning-opportunities">📣 Further Learning Opportunities</h2>
<p>I recently started to work on my first <a target="_blank" href="https://www.udemy.com/user/matthes-bar/">free Udemy course</a>. While this first free course covers the basics of the React Redux Toolkit with German audio and manually added English subtitles, I'm also planning to publish other Udemy courses completely in English in the future. </p>
<p>I would really appreciate it if you would check out this cost-free course in order to provide me with some feedback.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Unit Tests for Python Functions ]]>
                </title>
                <description>
                    <![CDATA[ This guide will teach you how to write unit tests for Python functions. But why should you consider writing unit tests at all? Well, when working on a large project, you'll often have to update certain modules and refactor code as needed. But such ch... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-unit-tests-for-python-functions/</link>
                <guid isPermaLink="false">66bb8b3e0eaca026d8cfa5ce</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Bala Priya C ]]>
                </dc:creator>
                <pubDate>Thu, 27 Oct 2022 18:53:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/cover-image-unit-tests-python.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This guide will teach you how to write unit tests for Python functions. But why should you consider writing unit tests at all?</p>
<p>Well, when working on a large project, you'll often have to update certain modules and refactor code as needed. But such changes can have unintended consequences on other modules that use an updated module within them. This can sometimes break existing functionality. </p>
<p>As a developer, you should test your code to ensure that all modules in the application work as intended. Unit tests let you check if small isolated units of code function correctly and enable you to fix inconsistencies that arise from updates and refactoring.</p>
<p>This guide will help you get started with unit testing in Python. You'll learn how to use Python's built-in <code>unittest</code> module to set up and run unit tests and write test cases to test Python functions. You'll also learn how to test functions that raise exceptions.</p>
<p>Let's get started!</p>
<h2 id="heading-testing-in-python-first-steps">Testing in Python – First Steps</h2>
<p>We'll start by defining a <a target="_blank" href="https://www.freecodecamp.org/news/functions-in-python-a-beginners-guide/">Python function</a> and write unit tests to check if it works as expected. To focus on how to set up unit tests, we'll consider a simple function <code>is_prime()</code>, that takes in a number and checks whether or not it is prime.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> math

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_prime</span>(<span class="hljs-params">num</span>):</span>
    <span class="hljs-string">'''Check if num is prime or not.'''</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>,int(math.sqrt(num))+<span class="hljs-number">1</span>):
        <span class="hljs-keyword">if</span> num%i==<span class="hljs-number">0</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
</code></pre>
<p>Let’s start a Python REPL, call the function <code>is_prime()</code> with arguments, and verify the results.</p>
<pre><code class="lang-python"><span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> prime_number <span class="hljs-keyword">import</span> is_prime
<span class="hljs-meta">&gt;&gt;&gt; </span>is_prime(<span class="hljs-number">3</span>)
<span class="hljs-literal">True</span>
<span class="hljs-meta">&gt;&gt;&gt; </span>is_prime(<span class="hljs-number">5</span>)
<span class="hljs-literal">True</span>
<span class="hljs-meta">&gt;&gt;&gt; </span>is_prime(<span class="hljs-number">12</span>)
<span class="hljs-literal">False</span>
<span class="hljs-meta">&gt;&gt;&gt; </span>is_prime(<span class="hljs-number">8</span>)
<span class="hljs-literal">False</span>
<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">assert</span> is_prime(<span class="hljs-number">7</span>) == <span class="hljs-literal">True</span>
</code></pre>
<p>You can also use the <code>assert</code> statement to verify that <code>is_prime()</code> returns the expected Boolean value, as shown above. If the return value from the function is different than the expected Boolean value, an <code>AssertionError</code> is raised.</p>
<p>This type of <strong>manual testing</strong> is <em>inefficient</em> when you want to exhaustively check your function for a much larger list of arguments. You may want to set up automated testing that runs and validates the function’s output against test cases defined in the test suite. </p>
<h2 id="heading-how-to-use-pythons-unittest-module">How to Use Python's <code>unittest</code> Module</h2>
<p>Python ships with the <code>unittest</code> module that lets you configure automated tests for functions and classes in your application. The generic procedure to set up unit tests in Python is as follows:</p>
<pre><code class="lang-python"><span class="hljs-comment"># &lt;module-name&gt;.py</span>

<span class="hljs-keyword">import</span> unittest
<span class="hljs-keyword">from</span> &lt;module&gt; <span class="hljs-keyword">import</span> &lt;function_to_test&gt;
<span class="hljs-comment"># all entries within &lt;&gt; are placeholders</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestClass</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_</span>&lt;<span class="hljs-title">name_1</span>&gt;(<span class="hljs-params">self</span>):</span>
        <span class="hljs-comment"># check function_to_test</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_</span>&lt;<span class="hljs-title">name_2</span>&gt;(<span class="hljs-params">self</span>):</span>
        <span class="hljs-comment"># check function_to_test</span>
    :
    :
    :

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_</span>&lt;<span class="hljs-title">name_n</span>&gt;(<span class="hljs-params">self</span>):</span>
        <span class="hljs-comment"># check function_to_test</span>
</code></pre>
<p>The above code snippet <code>&lt;module-name&gt;.py</code> does the following:</p>
<ul>
<li>Imports Python’s built-in <code>unittest</code> module.</li>
<li>Imports the Python function to be tested, <code>&lt;function_to_test&gt;</code> from the module in which it’s defined, <code>&lt;module&gt;</code>.</li>
<li>Creates a test class (<code>TestClass</code>) that inherits from <code>unittest.TestCase</code> class.</li>
<li>Each of the tests that should be run should be defined as methods inside the test class.</li>
<li>💡 <strong>Note</strong>: For the <code>unittest</code> module to identify these methods as tests and run them, the names of these methods should start with <code>test_</code>.</li>
<li>The <code>TestCase</code> class in the <code>unittest</code> module provides useful assertion methods to check if the function under test returns the expected values.</li>
</ul>
<p>The most common assertion methods are listed below, and we’ll use some of them in this tutorial.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Method</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>assertEqual(expected_value,actual_value)</code></td><td>Asserts that <code>expected_value == actual_value</code></td></tr>
<tr>
<td><code>assertTrue(result)</code></td><td>Asserts that <code>bool(result)</code> is <code>True</code></td></tr>
<tr>
<td><code>assertFalse(result)</code></td><td>Asserts that <code>bool(result)</code> is <code>False</code></td></tr>
<tr>
<td><code>assertRaises(exception, function, *args, **kwargs)</code></td><td>Asserts that <code>function(*args, **kwargs)</code> raises the <code>exception</code></td></tr>
</tbody>
</table>
</div><p>📑 For a complete list of assertion methods, refer to the <a target="_blank" href="https://docs.python.org/3/library/unittest.html">unittest docs</a>.</p>
<p>To run these tests, we should run unittest as the main module, using the following command:</p>
<pre><code class="lang-bash">$ python -m unittest &lt;module-name&gt;.py
</code></pre>
<p>We can add the <code>if __name__=='__main__'</code> conditional to run <code>unittest</code> as the main module. </p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> __name__==<span class="hljs-string">'__main__'</span>:
    unittest.main()
</code></pre>
<p>Adding the above conditional will enable us to run tests by directly running the Python module containing the tests.</p>
<pre><code class="lang-bash">$ python &lt;module-name&gt;.py
</code></pre>
<h2 id="heading-how-to-define-test-cases-for-python-functions">How to Define Test Cases for Python Functions</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/unittesting-101.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In this section, we’ll write unit tests for the <code>is_prime()</code> function using the syntax we’ve learned.  </p>
<p>To test the <code>is_prime()</code> function that returns a Boolean, we can use the <code>assertTrue()</code> and <code>assertFalse()</code> methods. We define four test methods within the <code>TestPrime</code> class that inherits from <code>unittest.TestCase</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest
<span class="hljs-comment"># import the is_prime function</span>
<span class="hljs-keyword">from</span> prime_number <span class="hljs-keyword">import</span> is_prime
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestPrime</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_two</span>(<span class="hljs-params">self</span>):</span>
        self.assertTrue(is_prime(<span class="hljs-number">2</span>))
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_five</span>(<span class="hljs-params">self</span>):</span>
        self.assertTrue(is_prime(<span class="hljs-number">5</span>))
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_nine</span>(<span class="hljs-params">self</span>):</span>
        self.assertFalse(is_prime(<span class="hljs-number">9</span>))
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_eleven</span>(<span class="hljs-params">self</span>):</span>
        self.assertTrue(is_prime(<span class="hljs-number">11</span>))
<span class="hljs-keyword">if</span> __name__==<span class="hljs-string">'__main__'</span>:
    unittest.main()
</code></pre>
<pre><code class="lang-bash">$ python test_prime.py
</code></pre>
<p>In the output below, '.' indicates a successful test.</p>
<pre><code>Output
....
----------------------------------------------------------------------
Ran <span class="hljs-number">4</span> tests <span class="hljs-keyword">in</span> <span class="hljs-number">0.001</span>s
OK
</code></pre><p>In the above code, there are four test methods, each checking for a specific input. You can instead define a single test method that asserts if the output is correct, for all four inputs.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest
<span class="hljs-keyword">from</span> prime_number <span class="hljs-keyword">import</span> is_prime
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestPrime</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_prime_not_prime</span>(<span class="hljs-params">self</span>):</span>
        self.assertTrue(is_prime(<span class="hljs-number">2</span>))
        self.assertTrue(is_prime(<span class="hljs-number">5</span>))
        self.assertFalse(is_prime(<span class="hljs-number">9</span>))
        self.assertTrue(is_prime(<span class="hljs-number">11</span>))
</code></pre>
<p>Upon running the <code>test_prime</code> module, we see that one test has been run successfully. If any of the assert methods throw an <code>AssertionError</code>, then the test fails.</p>
<pre><code class="lang-bash">$ python test_prime.py
</code></pre>
<pre><code>Output
.
----------------------------------------------------------------------
Ran <span class="hljs-number">1</span> test <span class="hljs-keyword">in</span> <span class="hljs-number">0.001</span>s
OK
</code></pre><h2 id="heading-how-to-write-unit-tests-to-check-for-exceptions">How to Write Unit Tests to Check for Exceptions</h2>
<p>In the previous section, we tested the <code>is_prime()</code> function with prime and non-prime numbers as inputs. Specifically, the inputs were all positive integers.</p>
<p>We haven't yet enforced that the arguments in the function call to <code>is_prime()</code> should be positive integers. You can use type hinting to enforce types or raise exceptions for invalid inputs.</p>
<p>In testing the <code>is_prime()</code> function, we haven't accounted for the following:</p>
<ul>
<li>For a floating point argument, the <code>is_prime()</code> function would still run and return <code>True</code> or <code>False</code>, which is incorrect.</li>
<li>For arguments of other types, say, the string 'five' instead of the number 5, the function throws a <strong>TypeError.</strong></li>
<li>If the argument is a negative integer, then the <code>math.sqrt()</code> function throws a <strong>ValueError</strong>. The squares of all real numbers (positive, negative, or zero) are always non-negative. So square root is defined only for non-negative numbers. </li>
</ul>
<p>Let's verify the above by running some examples in a Python REPL.</p>
<pre><code class="lang-python"><span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> prime_number <span class="hljs-keyword">import</span> is_prime

<span class="hljs-meta">&gt;&gt;&gt; </span>is_prime(<span class="hljs-string">'five'</span>)
Traceback (most recent call last):
File <span class="hljs-string">"&lt;stdin&gt;"</span>, line <span class="hljs-number">1</span>, <span class="hljs-keyword">in</span> &lt;module&gt;
File <span class="hljs-string">"/home/bala/unit-test-1/prime_number.py"</span>, line <span class="hljs-number">5</span>, <span class="hljs-keyword">in</span> is_prime
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>,int(math.sqrt(num))+<span class="hljs-number">1</span>):
TypeError: must be real number, <span class="hljs-keyword">not</span> str

<span class="hljs-meta">&gt;&gt;&gt; </span>is_prime(<span class="hljs-number">-10</span>)
Traceback (most recent call last):
File <span class="hljs-string">"&lt;stdin&gt;"</span>, line <span class="hljs-number">1</span>, <span class="hljs-keyword">in</span> &lt;module&gt;
File <span class="hljs-string">"/home/bala/unit-test-1/prime_number.py"</span>, line <span class="hljs-number">5</span>, <span class="hljs-keyword">in</span> is_prime
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>,int(math.sqrt(num))+<span class="hljs-number">1</span>):
ValueError: math domain error

<span class="hljs-meta">&gt;&gt;&gt; </span>is_prime(<span class="hljs-number">2.5</span>)
<span class="hljs-literal">True</span>
</code></pre>
<h3 id="heading-how-to-raise-exceptions-for-invalid-inputs">How to Raise Exceptions for Invalid Inputs</h3>
<p>To address the above, we'll validate the value used in the function call for <code>num</code> and raise exceptions as needed.</p>
<ul>
<li>Check if <code>num</code> is an integer. If yes, proceed to the next check. Else, raise a <code>TypeError</code> exception.</li>
<li>Check if <code>num</code> is a negative integer. If yes, raise a <code>ValueError</code> exception.</li>
</ul>
<p>Modifying the function definition to validate the input and raise exceptions, we have:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> math
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_prime</span>(<span class="hljs-params">num</span>):</span>
    <span class="hljs-string">'''Check if num is prime or not.'''</span>
    <span class="hljs-comment"># raise TypeError for invalid input type</span>
    <span class="hljs-keyword">if</span> type(num) != int:
        <span class="hljs-keyword">raise</span> TypeError(<span class="hljs-string">'num is of invalid type'</span>)
    <span class="hljs-comment"># raise ValueError for invalid input value</span>
    <span class="hljs-keyword">if</span> num &lt; <span class="hljs-number">0</span>:
        <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">'Check the value of num; is num a non-negative integer?'</span>)
    <span class="hljs-comment"># for valid input, proceed to check if num is prime</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>,int(math.sqrt(num))+<span class="hljs-number">1</span>):
        <span class="hljs-keyword">if</span> num%i==<span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
</code></pre>
<p>Now that we've modified the function to raise ValueError and TypeError for invalid inputs, the next step is to test if these exceptions are raised.</p>
<h2 id="heading-how-to-use-the-assertraises-method-to-test-exceptions">How to Use the <code>assertRaises()</code> Method to Test Exceptions</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/test-exceptions.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the definition of the <code>TestPrime</code> class, let’s add methods to check if the exceptions are raised. </p>
<p>We define <code>test_typeerror_1()</code> and <code>test_typeerror_2()</code> methods to check if <code>TypeError</code> exception is raised and the <code>test_valueerror()</code> method to check if <code>ValueError</code> exception is raised.</p>
<p>📌 To call the <code>assertRaises()</code> method, we can use the following general syntax:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_exception</span>(<span class="hljs-params">self</span>):</span>
    self.assertRaises(exception-name,function-name,args)
</code></pre>
<p>We can also use the following syntax using context manager (we’ll use this syntax in this example):</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_exception</span>(<span class="hljs-params">self</span>):</span>
    <span class="hljs-keyword">with</span> self.assertRaises(exception-name):
        function-name(args)
</code></pre>
<p>Adding the test methods to check for exceptions, we have:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest
<span class="hljs-keyword">from</span> prime_number <span class="hljs-keyword">import</span> is_prime
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestPrime</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_prime_not_prime</span>(<span class="hljs-params">self</span>):</span>
        self.assertTrue(is_prime(<span class="hljs-number">2</span>))
        self.assertTrue(is_prime(<span class="hljs-number">5</span>))
        self.assertFalse(is_prime(<span class="hljs-number">9</span>))
        self.assertTrue(is_prime(<span class="hljs-number">11</span>))
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_typeerror_1</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">with</span> self.assertRaises(TypeError):
            is_prime(<span class="hljs-number">6.5</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_typeerror_2</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">with</span> self.assertRaises(TypeError):
            is_prime(<span class="hljs-string">'five'</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_valueerror</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">with</span> self.assertRaises(ValueError):
            is_prime(<span class="hljs-number">-4</span>)

<span class="hljs-keyword">if</span> __name__==<span class="hljs-string">'__main__'</span>:
    unittest.main()
</code></pre>
<p>Let's run the <code>test_prime</code> module and observe the output:</p>
<pre><code class="lang-bash">$ python test_prime.py
</code></pre>
<pre><code>Output
....
----------------------------------------------------------------------
Ran <span class="hljs-number">4</span> tests <span class="hljs-keyword">in</span> <span class="hljs-number">0.002</span>s
OK
</code></pre><p>In the examples we’ve coded thus far, all the tests succeeded. Let’s modify one of the methods, say, <code>test_typeerror_2()</code>, to the following:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_typeerror_2</span>(<span class="hljs-params">self</span>):</span>
    <span class="hljs-keyword">with</span> self.assertRaises(TypeError):
        is_prime(<span class="hljs-number">5</span>)
</code></pre>
<p>We call the function <code>is_prime()</code> with the number 5 as the argument. Here, 5 is a valid input for which the function returns <code>True</code>. Therefore, the function does not raise a <code>TypeError</code>. When we run the tests again, we’ll see that there’s one failing test.</p>
<pre><code class="lang-bash">$ python test_prime.py
</code></pre>
<pre><code>Output

..F.
======================================================================
FAIL: test_typeerror_2 (__main__.TestPrime)
----------------------------------------------------------------------
Traceback (most recent call last):
File <span class="hljs-string">"test_prime.py"</span>, line <span class="hljs-number">17</span>, <span class="hljs-keyword">in</span> test_typeerror_2
is_prime(<span class="hljs-number">5</span>)
<span class="hljs-attr">AssertionError</span>: <span class="hljs-built_in">TypeError</span> not raised
----------------------------------------------------------------------
Ran <span class="hljs-number">4</span> tests <span class="hljs-keyword">in</span> <span class="hljs-number">0.003</span>s
FAILED (failures=<span class="hljs-number">1</span>)
</code></pre><h2 id="heading-conclusion">Conclusion</h2>
<p>Thank you for reading this far! 😄 I hope this tutorial helped you understand the basics of unit testing in Python. </p>
<p>You've learned to set up tests that check if a function works as expected or raises an exception—all using Python's built-in <code>unittest</code> module. </p>
<p>Keep coding, and see you in the next tutorial!👩🏽‍💻</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Software Testing? A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ Software testing is essential to development. It saves you time and money in production mode.  But software testing is a complex topic and can be a bit difficult to understand. In this article, I'll explain the major topics in software testing and ho... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/software-testing-beginners-guide/</link>
                <guid isPermaLink="false">66c4c6501b22d2d8d9040ec8</guid>
                
                    <category>
                        <![CDATA[ beginner ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sophia Iroegbu ]]>
                </dc:creator>
                <pubDate>Wed, 21 Sep 2022 16:03:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/Tech-Blog-Cover--4-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Software testing is essential to development. It saves you time and money in production mode. </p>
<p>But software testing is a complex topic and can be a bit difficult to understand.</p>
<p>In this article, I'll explain the major topics in software testing and how this practice can help you. </p>
<h3 id="heading-table-of-contents">Table of Contents:</h3>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-software-testing">What is Software Testing?</a></li>
<li><a class="post-section-overview" href="#heading-types-of-software-testing">Types of Software Testing</a></li>
<li><a class="post-section-overview" href="#heading-different-types-of-functional-software-testing">Different Types of Functional Software Testing</a></li>
<li><a class="post-section-overview" href="#heading-software-testing-principles">Software Testing Principles</a></li>
<li><a class="post-section-overview" href="#heading-why-is-software-testing-needed">Why is Software Testing needed?</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-what-is-software-testing">What is Software Testing?</h2>
<p>Software testing is the process of making sure your software/app works as it should. There are various methods you can use to test your code, and each testing method has different requirements. </p>
<p>For instance, unit testing involves writing test cases to ensure the code works as it should, and Beta testing consists of testing the preview version of the software or app to make sure users can use the product.</p>
<p>Software testing is integral to the process of building good software that works as it should. It also helps improve productivity and performance. Testing is an important part of the <em>Software Development Life Cycle</em> (SDLC). </p>
<p>Other benefits of testing your code include preventing bugs, reducing cost, and reducing time of development.</p>
<h2 id="heading-types-of-software-testing">Types of Software Testing</h2>
<p>There are two general types of software testing:</p>
<h3 id="heading-functional-testing">Functional Testing:</h3>
<p>Functional Testing is a software testing method that validates the system against the customer's requirements or specifications. </p>
<p>This type of testing aims to test each function of the software by providing the correct input and ensuring the output is right. </p>
<p>For examples, let's say you write a test case to test creating a user. The test case provides the correct input (email, first name, last name and password) and ensures the output (success message) is accurate, as well.</p>
<p>Functional testing checks that everything is functioning properly by emulating business scenarios based on applicable requirements.</p>
<h3 id="heading-non-functional-testing">Non-functional Testing:</h3>
<p>Non-functional testing is a software testing method that tests for end-user experiences, such as performance and reliability under load. This could either make or break a user experience. </p>
<p>When your code fails at non-functional testing, it may not cause an issue that user would note but it can flag a problem in the system.</p>
<p>Non-functional testing is just about testing the software to know how it responds to load on the system.</p>
<p>In this guide, we will focus on Functional Software Testing.</p>
<h2 id="heading-different-types-of-functional-software-testing">Different Types of Functional Software Testing</h2>
<p>There are different types of software testing, and each has a specific aim. We'll look at each one quickly now. </p>
<h3 id="heading-unit-testing">Unit Testing:</h3>
<p>Unit testing is a type of software testing that validates how each software unit performs and whether that specific piece of code does what it should. A unit is the smallest testable component of an application.</p>
<p>The aim is to confirm that each unit of software code works as expected. You do unit testing during the coding (development) stage or phase. Developers write these tests as they go. </p>
<p>Unit tests isolate possible bugs in your code and help you correct them. A unit could be a single function, method, procedure, module, or object.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-404.png" alt="Image" width="600" height="400" loading="lazy">
<em>Code Snippet of a unit test case in Python</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-403.png" alt="Image" width="600" height="400" loading="lazy">
<em>Code Snippet of a unit test case in Java</em></p>
<h3 id="heading-integration-testing">Integration Testing:</h3>
<p>Integration Testing is software testing which helps ensure that software components or functions work together properly. This is the second phase of the software testing process that comes after unit testing.</p>
<p>In this type of testing, units or individual software components are tested in groups. This testing method mainly focuses on exposing defects in interactions between integrated components and units.</p>
<h3 id="heading-system-testing">System Testing:</h3>
<p>System testing involves the process of testing integrated software. The aim is to evaluate the system's compliance with specify requirements. </p>
<p>In system testing, the quality assurance team evaluates how each component of the application or software work together in a full, integrated environment.</p>
<h3 id="heading-acceptance-testing">Acceptance Testing:</h3>
<p>Acceptance testing is a software testing method where a system is tested or checked for acceptability. It evaluates the system's compatibility with the business requirements and assesses whether it is acceptable for delivery.</p>
<p>It is also known as formal testing performed to fit user needs, requirements, and business processes. It determines if a system satisfies the standard business criteria and if users or customers will be able to accept it. </p>
<p>Acceptance testing is the last stage of software testing done after system testing and before making the system available for public use.</p>
<h3 id="heading-regression-testing">Regression Testing:</h3>
<p>Regression testing ensures that a component continues working as it should, after including additional components in the program. You perform regression testing when something changes, such as adding a new module to the program.</p>
<p>This type of testing represents the complete testing of executed test cases that are re-executed to ensure the current functionalities still work just fine.</p>
<h3 id="heading-alpha-testing-and-beta-testing">Alpha Testing and Beta Testing:</h3>
<p>Alpha testing is also known as initial validation testing. It is an aspect of acceptance testing done before the product is given to the consumers or users. QA (Quality Assurance) testers usually do this. Alpha testing is done internally by the QA team.</p>
<p>Beta testing is also known as second phase of validation testing. But this type of testing is done externally, which means the public does it. </p>
<p>The version of the code/software for this phase of testing is released to a limited number of users for testing in a real-time scenario. For instance, freeCodeCamp's math curriculum is available for beta testing <a target="_blank" href="https://www.freecodecamp.org/news/freecodecamp-foundational-math-curriculum/">here</a>.</p>
<h2 id="heading-software-testing-principles">Software Testing Principles</h2>
<p>Everything in tech has principles. These are guidelines to help you build better software and avoid errors.</p>
<p>Here are some software testing principles you should follow when writing tests for your code:</p>
<h3 id="heading-testing-aims-to-show-the-presence-of-defects-not-the-absence">Testing aims to show the presence of defects, not the absence:</h3>
<p>Software testing aims to spot software failures. This reduces the presence of faults and errors. </p>
<p>Software testing ensures defects are visible to the developer but doesn't guarantee defect-free software. Multiple types of testing can't even ensure error-free software. Testing can only decrease the number of errors.</p>
<h3 id="heading-exhaustive-testing-is-not-possible">Exhaustive testing is not possible:</h3>
<p>Exhaustive Testing is the process of testing software for all valid and invalid inputs and pre-conditions. </p>
<p>This method of testing is not realistic because test cases presume that the software is correct and it produces the correct output in every test case. If you truly try to test every aspect and test case in your software, it will take too much time and effort, and it's not practical.</p>
<h3 id="heading-perform-early-testing">Perform early testing:</h3>
<p>Testing your software at an early phase helps avoid minor bugs or errors. When you can spot errors at an early stage of the Software Development Life Cycle(SDLC), it's always less expensive. It is best to start software testing from the beginning of the project.</p>
<h3 id="heading-defect-clustering">Defect clustering:</h3>
<p>Defect clustering refers to when most of the problems you find occur in just a few parts of the application or software. If you can identify the modules or areas where these defects occur, you can focus most of your testing efforts on them. </p>
<p>Keep the Pareto Principle in mind when testing your code: 80% of software defects tend to come from 20% of the modules.</p>
<h3 id="heading-beware-of-the-pesticide-paradox">Beware of the Pesticide paradox:</h3>
<p>This principle is based on a theory – "the more you use pesticide on a crop, the more immune the crop will eventually grow, and the pesticide will not be effective." </p>
<p>When you repeat particular test cases over and over, you will see fewer and fewer new bugs. So to find new bugs, update your test cases and run them once you add new test cases.</p>
<h3 id="heading-testing-is-context-dependent">Testing is context-dependent:</h3>
<p>Testing is context-dependent, which means that you should test your software based on its needs, functionalities, and requirements.</p>
<p>Your test approach should depend on what your software does. Not every software needs the same type/method of testing because every application has its unique functionalities.</p>
<p>For instance, when testing an eCommerce web app, you will focus on its functionality to display products, so you will test how it shows products to end-users. When dealing with an API, you will focus on the response the API returns when an endpoint is called. </p>
<p>You wouldn't necessarily use the same test cases for both – that is what it means that testing is context-dependent.</p>
<h3 id="heading-the-absence-of-errors-is-a-fallacy">The absence of errors is a fallacy:</h3>
<p>If you build software that is 99% bug-free, but it doesn't follow user requirements, it is not usable for end-users. </p>
<p>Know that it is very much necessary that your 99% bug-free software still meets or fulfills your user requirements. It is important to write test cases to find errors in the code, but you also need to test your software for your end-users (with them and how they'll use it in mind). The best way to do this is to carry out beta testing.</p>
<h2 id="heading-why-is-software-testing-needed">Why is Software Testing Needed?</h2>
<p>Besides making sure your software is bug-free and meets user requirements, software testing has other advantages. </p>
<h3 id="heading-software-testing-improves-security">Software testing improves security:</h3>
<p>When building software, security is a crucial part of your planning. This is because vulnerable software could jeopardize you users and their information, as hackers can use stolen info for malicious purposes.</p>
<p>As a product undergoes testing, the end-user can count on the fact that they will be getting a reliable product and their details will be secured and safe. So users are more likely to get a product that is free from vulnerabilities with the help of software testing.</p>
<h3 id="heading-software-testing-improves-product-quality">Software testing improves product quality:</h3>
<p>You want your software or product to be bug-free, low-risk, and effective at what it should do. And you can achieve this by including test cases and other testing methods when building out the code.</p>
<p>In addition, you won't know how good your product is until you test it. This helps you provide the best product version before it gets released (and discover any inconsistencies or pain points along the way – so you can improve them).</p>
<h3 id="heading-software-testing-improves-customer-satisfaction">Software testing improves customer satisfaction:</h3>
<p>For instance, let's say you download a new app and try to use some of its functionality – but it shows an error. This will probably frustrate you, and you might not want to use the app again, right?</p>
<p>This is exactly why software testing is important. It can help you discover such errors and detect them before you release the product to the user, and gives the developers a chance to prevent the error. </p>
<p>By investing in software testing early in the development stage, you are letting the users know that you care about their experience. It could also help you create a solid long-term customer relationship.</p>
<h3 id="heading-software-testing-saves-money">Software testing saves money:</h3>
<p>Software testing can save you a lot of money – but how?</p>
<p>Each stage of development involves many things, such as clear communication and coordination between multiple teams, and each step has a laundry list of things that could go awry.</p>
<p>Catching those errors when the product is live is a horrible experience because you may have to handle PR, retasking fixes, and trying to sort the problem in real time.</p>
<p>In addition, your users won't be able to access the app while you're fixing it, which defeats the app's purpose and provides a bad user experience in the meantime. Software testing helps resolve this stress, and once live, your user can enjoy your app/product to the fullest.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, software testing is a crucial part of development. It can help save your team a lot of trouble, and it feels great to create a usable, bug-free product that users enjoy and recommend.</p>
<p>If software testing interests you, you can check freeCodeCamp's QA certificate course <a target="_blank" href="https://www.freecodecamp.org/learn/quality-assurance/#quality-assurance-and-testing-with-chai">here</a> to learn more about QA testing. QA testers are techies that focus on testing softwares and apps for errors. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Unit Testing? How to Perform Unit Tests in Rust ]]>
                </title>
                <description>
                    <![CDATA[ By Menard Maranan Testing is an essential part of Software Development. Testing your code ensures that the software you develop works as expected and makes it less vulnerable to attackers. Software testing is a very broad topic. That's why in the sof... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/unit-testing-in-rust/</link>
                <guid isPermaLink="false">66d46040677cb8c6c15f3163</guid>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 27 Jul 2022 16:26:05 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/07/UNIT-TESTING-IN-RUST.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Menard Maranan</p>
<p>Testing is an essential part of Software Development. Testing your code ensures that the software you develop works as expected and makes it less vulnerable to attackers.</p>
<p>Software testing is a very broad topic. That's why in the software industry, there are separate professionals who specialize in just QA and testing alone. These professionals are often referred to as QA Engineers.</p>
<p>Although QA is its own thing, that doesn't mean developers don't do testing at all.</p>
<p>The most common tests that developers conduct are <strong>Unit Tests</strong>. Unit testing is a type of testing where you test small units of code (like functions) – hence the term, Unit Testing. You often do this by comparing the expected behavior of a unit of code against its actual behavior.</p>
<p>Unit testing is such an integral part of the development workflow that some companies' whole development culture is centered around what's called <a target="_blank" href="https://www.freecodecamp.org/news/test-driven-development-tutorial-how-to-test-javascript-and-reactjs-app/"><strong>Test-Driven Development</strong> (or TDD)</a>. </p>
<p>In TDD, developers first write test cases (from the feature requirements, often called the <strong>user story</strong>) and proceed to write the code that satisfies them. TDD shines mostly in projects where requirements are highly specific.</p>
<p>You can implement unit testing in different ways across different programming languages. But at its core, Unit Testing is just about comparing the expected vs the actual behavior of the code. </p>
<p>So regardless of how it's implemented in a particular language, the same principle generally applies when you work in any other language.</p>
<p>In this tutorial, you'll learn unit testing in the Rust programming language. That said, you should know at least the <a target="_blank" href="https://www.freecodecamp.org/news/rust-in-replit/">basics of programming in Rust</a> although you don't need advanced knowledge of it.</p>
<p>This article will cover:</p>
<ul>
<li>How unit testing works in Rust</li>
<li>How to write a unit test in Rust</li>
<li>How to test a function</li>
<li>Why failing tests are useful</li>
<li>How to handle expected error behavior so that your tests won't fail</li>
</ul>
<p>So, with all that said, let's proceed to learn unit testing with Rust!</p>
<h1 id="heading-how-unit-testing-works-in-rust">How Unit Testing Works in Rust</h1>
<p>Rust is built with code safety at its core. Rust's strict type annotation rules help eliminate a ton of bugs early on in the development phase. But still, it's not foolproof. </p>
<p>Like any other language, the business logic is on your shoulders and you have to help Rust understand what's acceptable in your code and what's not.</p>
<p>And yes, that's why we do testing.</p>
<p>You don't need to install a test suite to get started testing in Rust since it has built-in support for testing.</p>
<p>To get started, create a new cargo project (take note of the <code>--lib</code> flag) on your local machine and open it in the text editor or IDE of your choice. For this tutorial, I'll be using VS code.</p>
<pre><code class="lang-shell">cargo new --lib rust_unit_testing
code rust_unit_testing
</code></pre>
<p>Then, open the <code>src/lib.rs</code> file. This is where we'll spend the most time in this tutorial.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/1-2.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>src/lib.rs file of a Rust Library Project</em></p>
<p>In a newly created library project in Rust, you'll notice that the <code>lib.rs</code> file is already pre-populated by a sample test code by default. </p>
<p>The main purpose of this is for you to have a template to begin with when writing your tests. We'll dissect each part of this simple test and understand the basic testing concepts in Rust.</p>
<p>So first, let's understand what those lines of test code are doing. In this example, you'll see a test module defined in <code>lib.rs</code> with one test inside it which tests if 2 + 2 is equal to 4.</p>
<p>If you don't know the concept of modules and attributes in Rust yet, that's fine and you can ignore them for now. </p>
<p>But just to give you an idea, tests in Rust are written inside the <code>tests</code> module (the <code>mod tests</code> part says it's the tests module), and anything written inside this module tells cargo to run them only during testing (and that's essentially what the <code>#[cfg(test)]</code> attribute implies). </p>
<p>A test in Rust is essentially just a function annotated as a test. From the example above, you'll notice the <code>#[test]</code> attribute above the function <code>it_works</code>. This simply tells cargo that this function is a test, and should be invoked during testing.</p>
<p>Inside the <code>it_works</code> test function, it checks if the value of <code>result</code> derived from 2 + 2 is equal to 4. It performs the checking using the <code>assert_eq!</code> macro. The <code>assert_eq!</code> macro compares the equality ( <code>==</code> ) of the left and right values passed onto it. </p>
<p>In most programming languages, there's a rule that the left values passed to the assert should be the expected values, while the actual value should be in the right. With Rust, there are no hard rules for that and you can pass on either side the expected and actual results.</p>
<p>Now, try running your test using this command:</p>
<pre><code class="lang-bash">cargo <span class="hljs-built_in">test</span>
</code></pre>
<p>Here's what the result should look like for the example above:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/2-1.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>cargo test - results</em></p>
<p>By running <code>cargo test</code>, cargo will execute your test cases and output the report in your terminal. From that report, you'll see the tests run by cargo.</p>
<p>The first line in the report says <code>running 1 test</code> since we only have one test function <code>tests::it_works</code>. Alongside the tested function, you'll see the message <code>ok</code>, meaning, the test passed.</p>
<p>You can also see the summary of the results below that:</p>
<ul>
<li>1 passed</li>
<li>0 failed</li>
<li>0 ignored</li>
<li>0 measured</li>
<li>0 filtered out</li>
<li>and the status of the result that says <code>test result: ok</code></li>
</ul>
<p>The <code>1 passed</code> counter here represents that one test function (<code>tests::it_works</code>) that passed the test, while the <code>failed</code> counter tells how many failing tests we have. The same applies to the other counters as well.</p>
<p>You'll also see the results of the <strong>Doc-tests</strong> below. Since we don't have any doc tests here, you'll see <code>running 0 tests</code>. You can ignore this for now and just focus on the unit tests. But if you want to learn more, you can check <a target="_blank" href="https://doc.rust-lang.org/rust-by-example/testing/doc_testing.html">Rust's official documentation</a>.</p>
<h2 id="heading-how-to-write-tests-in-rust">How to Write Tests in Rust</h2>
<p>When writing a test, you generally need to go through these three steps:</p>
<ol>
<li>Mock the data or state needed for a test case. By this, I mean providing mock or sample data needed by the code you're testing (if necessary) and/or setting up the state or environment needed for the test case to run.</li>
<li>Run the code that needs to be tested (passing the mock data necessary). An example is invoking a function you want to test.</li>
<li>Check if the actual behavior of the code you're testing matches its expected behavior. For example, by passing an argument <code>x</code> to a function, you assert if its returned value is the same as what you're expecting for it to return. Or check if a unit of code raises <code>panic!</code>—which is the expected behavior, for example—if it's given a certain parameter.</li>
</ol>
<p>In Rust, unit tests are written in the exact file where the code being tested is written. Test functions are then grouped inside the <code>tests</code> module (which is named this way by convention).</p>
<h3 id="heading-how-to-test-functions-in-rust">How to test functions in Rust</h3>
<p>Now let's proceed to testing functions in Rust.</p>
<p>To begin with, we need a simple function to test. But first, remove the <code>it_works</code> test function since we no longer need it. Then, write this <code>adder</code> function above the <code>tests</code> module:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">adder</span></span>(x: <span class="hljs-built_in">i32</span>, y: <span class="hljs-built_in">i32</span>) -&gt; <span class="hljs-built_in">i32</span> {
    x + y
}

<span class="hljs-meta">#[cfg(test)]</span>
<span class="hljs-keyword">mod</span> tests {
<span class="hljs-comment">// ...</span>
</code></pre>
<p>The <code>adder</code> function from above is a simple public function that just adds two numbers and returns the sum. To test if it works as expected, let's write a unit test for this function.</p>
<p>From the three steps of writing unit tests we discussed earlier, the first two steps are:</p>
<ul>
<li>set the data for the code to be tested</li>
<li>run the code.</li>
</ul>
<p>So going back to the <code>tests</code> module, first, bring the <code>adder</code> function into its scope (using the <code>use</code> keyword). Then write a function named <code>it_adds</code> annotated with the <code>#[test]</code> attribute.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">adder</span> </span>(x: <span class="hljs-built_in">i32</span>, y: <span class="hljs-built_in">i32</span>) -&gt; <span class="hljs-built_in">i32</span> {
    x + y
}

<span class="hljs-meta">#[cfg(test)]</span>
<span class="hljs-keyword">mod</span> tests {
    <span class="hljs-comment">// this brings everything from parent's scope into this scope</span>
    <span class="hljs-keyword">use</span> super::*;

    <span class="hljs-meta">#[test]</span>
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">it_adds</span></span>() {
    }
}
</code></pre>
<p>Inside the <code>it_adds</code> test function is where we'll write the tests. So within it, declare a variable named <code>sum</code>, then call the function <code>adder</code> and pass 4 and 5 as its parameters (which are our mock data).</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-comment">// --snip--</span>

    <span class="hljs-meta">#[test]</span>
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">it_adds</span></span>() {
        <span class="hljs-keyword">let</span> sum = adder(<span class="hljs-number">4</span>, <span class="hljs-number">5</span>);
    }
}
</code></pre>
<p>And finally, the third step in writing unit tests is to check the expected vs actual behavior of the code we're testing. </p>
<p>So here, let's assert if the value of <code>sum</code> as returned by the <code>adder</code> function is equal to <code>9</code> (which is our expected return value) using the <code>assert_eq!</code> macro.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-comment">// --snip--</span>

    <span class="hljs-meta">#[test]</span>
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">it_adds</span></span>() {
        <span class="hljs-keyword">let</span> sum = adder(<span class="hljs-number">4</span>, <span class="hljs-number">5</span>);
        <span class="hljs-built_in">assert_eq!</span>(sum, <span class="hljs-number">9</span>);
    }
}
</code></pre>
<p>Here's the final version of our code and test in the <code>lib.rs</code> file:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">adder</span></span>(x: <span class="hljs-built_in">i32</span>, y: <span class="hljs-built_in">i32</span>) -&gt; <span class="hljs-built_in">i32</span> {
    x + y
}

<span class="hljs-meta">#[cfg(test)]</span>
<span class="hljs-keyword">mod</span> tests {
    <span class="hljs-comment">// this brings everything from parent's scope into this scope</span>
    <span class="hljs-keyword">use</span> super::*;

    <span class="hljs-meta">#[test]</span>
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">it_adds</span></span>() {
        <span class="hljs-keyword">let</span> sum = adder(<span class="hljs-number">4</span>, <span class="hljs-number">5</span>);
        <span class="hljs-built_in">assert_eq!</span>(sum, <span class="hljs-number">9</span>);
    }
}
</code></pre>
<p>As you learned earlier, you can run this test using this command:</p>
<pre><code class="lang-bash">cargo <span class="hljs-built_in">test</span>
</code></pre>
<p>If everything works well, we should get <code>test result: ok</code> stating that our tests passed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/3.JPG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can add more tests in the <code>tests</code> module for the <code>adder</code> function if you like (for example, adding negative numbers). Or better yet, create your own function and write a test (or tests) for it.</p>
<p>Moreover, there are a lot more built-in assertion macros in Rust that you can use besides the <code>assert_eq!</code> macro. Some of those include the <code>assert_ne!</code> macro for asserting not equal values (<code>!=</code>), and the <code>assert!</code> macro which just asserts if the code you're testing returns a <code>true</code> value.</p>
<p>If you need more assertion macros (for example, comparison assertions that support <code>&gt;</code>, <code>&lt;</code>, <code>&gt;=</code>, <code>&lt;=</code>), you can install external crates like this one: <a target="_blank" href="https://crates.io/crates/claim">claim</a>. You can check <a target="_blank" href="https://docs.rs/claim/latest/claim/">claim's documentation here</a> for more info.</p>
<h2 id="heading-why-failing-tests-are-useful">Why Failing Tests Are Useful</h2>
<p>So far we're always getting passing results on our tests.</p>
<p>Although it's good, the true power of unit tests comes from catching errors or bugs in our code and reporting them through failing tests. So for this time, let's intentionally write a 'buggy' code and see what happens.</p>
<p>Back in the <code>lib.rs</code> file, modify the <code>adder</code> function by replacing the <code>+</code> operator with <code>-</code>.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">adder</span></span>(x: <span class="hljs-built_in">i32</span>, y: <span class="hljs-built_in">i32</span>) -&gt; <span class="hljs-built_in">i32</span> {
    <span class="hljs-comment">// change the operator from '+' to '-'</span>
    x - y
}

<span class="hljs-comment">// --snip--</span>
</code></pre>
<p>Now run the tests again using <code>cargo test</code>. And as expected, you should see a failing test result like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/4.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>failing test by cargo</em></p>
<p>First off, notice that the status of the test function <code>tests::it_adds</code> is a big red <code>FAILED</code>. This is what failing tests with cargo look like.</p>
<p>Below that, you'll see the 'failures' report which lists out the failing tests and some information as to why they failed. </p>
<p>From our example, the <code>tests::it_adds</code> test failed and as the report said, the left and right values passed into the <code>assert_eq!</code> macro aren't equal (<code>==</code>). </p>
<p>That's because the left value is <code>-1</code> while the right value is <code>9</code>. Remember that on our <code>assert_eq!</code> assertion, the left value that we passed to it is the <code>sum</code> variable that contains the return value of <code>adder(4, 5)</code>. </p>
<p>Since our operator is wrong, the <code>adder</code> function performs <code>4 - 5</code> instead of the expected <code>4 + 5</code>. That's why instead of the expected value of <code>9</code>, we got <code>-1</code>. Cargo noticed this so it raised a failing test.</p>
<p>Below the failed tests report is its summary (sort of), still under the <code>failures</code> category, but just lists out the names of the test functions that failed.</p>
<p>And lastly, the entire summary of the overall test:</p>
<ul>
<li>Status is: <code>test result: FAILED</code></li>
<li>0 passed</li>
<li>1 failed</li>
<li>0 ignored</li>
<li>0 measured</li>
<li>0 filtered out</li>
</ul>
<p>This time, our <code>failed</code> counter is <code>1</code> (referring to our failed test function) while <code>passed</code> is <code>0</code>.</p>
<h2 id="heading-how-to-handle-expected-errors">How to Handle Expected Errors</h2>
<p>From the previous section, you learned that errors cause tests to fail.</p>
<p>But what if you are expecting the code you're testing to fail (like for example, by giving it an invalid parameter). If it gets an error, cargo will flag this as a failing test even though you're actually expecting it to fail.</p>
<p>Can you expect failing behaviors?</p>
<p>The short answer is: yes, you can!</p>
<p>To demonstrate this, let's go back to the <code>lib.rs</code> file and modify our <code>adder</code> function. This time, let's set a rule for it to only accept single-digit integers (positive, zero, and negative) – otherwise, it should 'panic'. And for readability purposes, let's rename our <code>adder</code> function to <code>single_digit_adder</code>.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-comment">// modify the `adder` function from earlier</span>
<span class="hljs-comment">// and turn it into `single_digit_adder`</span>
<span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">single_digit_adder</span></span>(x: <span class="hljs-built_in">i8</span>, y: <span class="hljs-built_in">i8</span>) -&gt; <span class="hljs-built_in">i8</span> {
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">is_single_digit</span></span>(x: <span class="hljs-built_in">i8</span>) -&gt; <span class="hljs-built_in">bool</span> {
        x &lt; <span class="hljs-number">10</span> &amp;&amp; x &gt; -<span class="hljs-number">10</span>
    }

    <span class="hljs-keyword">if</span> !(is_single_digit(x)) || !(is_single_digit(y)) {
        <span class="hljs-built_in">panic!</span>(<span class="hljs-string">"Only single digit integers are allowed!"</span>);
    } <span class="hljs-keyword">else</span> {
        x + y
    }
}

<span class="hljs-meta">#[cfg(test)]</span>
<span class="hljs-keyword">mod</span> tests {
<span class="hljs-comment">// --snip--</span>
</code></pre>
<p>Since we're expecting the <code>single_digit_adder</code> function to 'panic' whenever it receives a non-single digit integer, we need to specify that on the test function that's responsible for testing exactly this behavior.</p>
<p>To do that, we need to add another attribute to one of our test functions. And that is the <code>#[should_panic]</code> attribute.</p>
<p>Going back to the <code>tests</code> module, first, edit the <code>it_adds</code> test function by renaming the <code>adder</code> function call into <code>single_digit_adder</code>. </p>
<p>Then, create a new test function named <code>it_should_only_accept_single_digits</code> with both the <code>#[test]</code> and the <code>#[should_panic]</code> attribute. </p>
<p>Inside this new test function, call the <code>single_digit_adder</code> function with an invalid parameter (<code>11</code>) in this case.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/lib.rs</span>

<span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">single_digit_adder</span></span>(x: <span class="hljs-built_in">i8</span>, y: <span class="hljs-built_in">i8</span>) -&gt; <span class="hljs-built_in">i8</span> {
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-meta">#[cfg(test)]</span>
<span class="hljs-keyword">mod</span> tests {
    <span class="hljs-keyword">use</span> super::*;

    <span class="hljs-meta">#[test]</span>
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">it_adds</span></span>() {
        <span class="hljs-keyword">let</span> sum = single_digit_adder(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>);
        <span class="hljs-built_in">assert_eq!</span>(sum, <span class="hljs-number">5</span>);
    }

    <span class="hljs-comment">// our new test function that expects `panic!` with invalid param</span>
    <span class="hljs-meta">#[test]</span>
    <span class="hljs-meta">#[should_panic]</span>
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">it_should_only_accept_single_digits</span></span>() {
        single_digit_adder(<span class="hljs-number">11</span>, <span class="hljs-number">4</span>);
    }
}
</code></pre>
<p>You don't need any assert macros in the <code>it_should_only_accept_single_digits</code> test function since we just need <code>single_digit_adder</code> to 'panic'. So simply calling the function is enough. </p>
<p>By giving it an invalid parameter (<code>11</code>, which isn't a single digit), we're expecting it to 'panic'. The <code>#[should_panic]</code> attribute will then expect that something should panic inside the <code>it_should_only_accept_single_digits</code> test function. If it didn't catch any panic, this test will fail. It will only pass if <code>single_digit_adder</code> panics.</p>
<p>So to test if it really works, try commenting the <code>#[should_panic]</code> attribute first and then run <code>cargo test</code>. You should expect it to fail.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/6.JPG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now, uncomment the <code>#[should_panic]</code> attribute and re-run the test. Your tests should all pass as expected:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/5.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>The output of a test case expecting and actually catching a failing behavior</em></p>
<p>Notice that on the test <code>tests::it_should_only_accept_single_digits</code>, there's a <code>should panic</code> alongside it, and that it passed the test. This means that this test function caught a panic as expected.</p>
<p>And there you have it! You just learned what unit testing is and how to perform unit tests with the Rust programming language. Feel free to write your own tests using the knowledge you obtained from this article and use it in your future projects.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In this article, you learned what unit testing is and its importance in the software development process. You also learned how to write unit tests through the simple three steps process and actually perform testing in the Rust programming language. </p>
<p>We covered the structure of a test module in Rust and how to construct a test function, and then we wrote a simple Rust program and some test cases for it. We also covered failing tests and how to handle an expected failing behavior in the unit of code.</p>
<p>Testing is an important part of the software development process. Testing your code helps ensure that the software works as expected. As a developer, it's important that you test your code to ensure the quality of the software you're shipping and that those silly bugs don't reach the end-user!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Test PHP Code With PHPUnit ]]>
                </title>
                <description>
                    <![CDATA[ There are many different ways to test your software application, and unit testing is an important one. So what is unit testing and how can you do it? You'll learn that and more in this article. What is Unit Testing? Unit testing is a software develo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/test-php-code-with-phpunit/</link>
                <guid isPermaLink="false">66c4c6adbd556981b1bdc462</guid>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zubair Idris Aweda ]]>
                </dc:creator>
                <pubDate>Wed, 09 Mar 2022 01:15:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/120480919-metal-bolts-nuts-group-drawing-technical-drafting-steel-screws-threaded-parts-with-hexagonal-head-bl--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>There are many different ways to test your software application, and unit testing is an important one.</p>
<p>So what is unit testing and how can you do it? You'll learn that and more in this article.</p>
<h2 id="heading-what-is-unit-testing">What is Unit Testing?</h2>
<blockquote>
<p>Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinised for process operation. - <a target="_blank" href="https://searchsoftwarequality.techtarget.com/definition/unit-testing#:~:text=Unit%20testing%20is%20a%20software,developers%20and%20sometimes%20QA%20staff.">SearchSoftwareQuality</a></p>
</blockquote>
<p>In basic terms, unit testing means that you break your application down to its simplest pieces and test these small pieces to ensure that each part is error free (and secure). </p>
<p>This testing is automated and written by software engineers as part of their development process. This is a very important step during development as it helps developers build better applications with fewer bugs.</p>
<h2 id="heading-what-is-phpunit">What is PHPUnit?</h2>
<p>You can perform unit testing in PHP with <a target="_blank" href="https://phpunit.de">PHPUnit</a>, a programmer-oriented testing framework for PHP. PHPUnit is an instance of the xUnit architecture for unit testing frameworks. It is very easy to install and get started with.</p>
<h2 id="heading-phpunit-installation">PHPUnit Installation</h2>
<p>You can install PHPUnit globally on your server. You can also install it locally, on a per-project, development-time basis as a dependency to your project using composer. This article will explain how to use it on a per project basis.</p>
<p>To get started, create and initiate a new project with composer using these commands:</p>
<pre><code class="lang-bash">$ mkdir test-project
$ <span class="hljs-built_in">cd</span> test-project
$ composer init
</code></pre>
<p>The first command creates a folder in your current directory, <code>test-project</code> and the second command moves into it. The last command starts an interactive shell.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-08-at-11.08.39.png" alt="Image" width="600" height="400" loading="lazy">
<em>Composer init prompt</em></p>
<p>Follow the prompt, filling in the details as required (the default values are fine). You can set the project description, author name (or contributors' names), minimum stability for dependencies, project type, license, and define your dependencies.</p>
<p>You can skip the dependencies part, as we are not installing any dependencies. PHPUnit is supposed to be a <code>dev-dependency</code> because testing as a whole should only happen during development.</p>
<p>Now, when the prompt asks <code>Would you like to define your dev dependencies (require-dev) interactively [yes]?</code>, press enter to accept. Then type in <code>phpunit/phpunit</code> to install PHPUnit as a <code>dev-dependency</code>.</p>
<p>Accept the other defaults and proceed to generating the <code>composer.json</code> file. The generated file should look like this currently:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"zubair/test-project"</span>,
    <span class="hljs-attr">"require-dev"</span>: {
        <span class="hljs-attr">"phpunit/phpunit"</span>: <span class="hljs-string">"^9.5"</span>
    },
    <span class="hljs-attr">"autoload"</span>: {
        <span class="hljs-attr">"psr-4"</span>: {
            <span class="hljs-attr">"Zubair\\TestProject\\"</span>: <span class="hljs-string">"src/"</span>
        }
    },
    <span class="hljs-attr">"authors"</span>: [
        {
            <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Idris Aweda Zubair"</span>,
            <span class="hljs-attr">"email"</span>: <span class="hljs-string">"zubairidrisaweda@gmail.com"</span>
        }
    ],
    <span class="hljs-attr">"require"</span>: {}
}
</code></pre>
<p>To learn how to install PHPUnit globally on your server, read <a target="_blank" href="https://phpunit.readthedocs.io/en/9.5/installation.html#">here</a>.</p>
<h2 id="heading-how-to-write-tests-in-phpunit">How to Write Tests in PHPUnit</h2>
<p>Writing tests in PHPUnit is quite simple. Here are a few conventions to get you started:</p>
<ul>
<li>To test a class in PHP, you'll create a test class named after that class. For example, if I had some sort of <code>User</code> class, the test class would be named <code>UserTest</code>.</li>
<li>The test class, <code>UserTest</code>, will usually inherit the <code>PHPUnit\Framework\TestCase</code> class.</li>
<li>Individual tests on the class are public methods named with <code>test</code> as a prefix. For example, to test a <code>sayHello</code> method on the <code>User</code> class, the method will be named <code>testSayHello</code>.</li>
<li>Inside the test method, say <code>testSayHello</code>, you use PHPUnit's method like <code>assertSame</code> to see that some method returns some expected value.</li>
</ul>
<p>A popular convention is to have all tests in a <code>tests</code> directory, and all source code in the <code>src</code> directory. </p>
<h2 id="heading-phpunit-testing-example">PHPUnit Testing Example</h2>
<p>To help understand this article, here's a sample <code>User</code> class with simple methods that will be tested:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Zubair</span>\<span class="hljs-title">TestProject</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">InvalidArgumentException</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $age;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">array</span> $favorite_movies = [];
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> $name;

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> int $age
     * <span class="hljs-doctag">@param</span> string $name
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> $age, <span class="hljs-keyword">string</span> $name</span>)
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;age = $age;
        <span class="hljs-keyword">$this</span>-&gt;name = $name;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tellName</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"My name is "</span> . <span class="hljs-keyword">$this</span>-&gt;name . <span class="hljs-string">"."</span>;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tellAge</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"I am "</span> . <span class="hljs-keyword">$this</span>-&gt;age . <span class="hljs-string">" years old."</span>;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addFavoriteMovie</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $movie</span>): <span class="hljs-title">bool</span>
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;favorite_movies[] = $movie;

        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeFavoriteMovie</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $movie</span>): <span class="hljs-title">bool</span>
    </span>{
        <span class="hljs-keyword">if</span> (!in_array($movie, <span class="hljs-keyword">$this</span>-&gt;favorite_movies)) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">InvalidArgumentException</span>(<span class="hljs-string">"Unknown movie: "</span> . $movie);

        <span class="hljs-keyword">unset</span>(<span class="hljs-keyword">$this</span>-&gt;favorite_movies[array_search($movie, <span class="hljs-keyword">$this</span>-&gt;favorite_movies)]);

        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
}
</code></pre>
<p>This user class could be the <code>User</code> class in your movie streaming application. The user has a name, age, and a list of favourite movies that can be updated. For the rest of the article we will test that all these features work as they're expected to.</p>
<p>Create a <code>UserTest</code> class in the <code>tests</code> folder. Paste this in to start:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Zubair</span>\<span class="hljs-title">TestProject</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">PHPUnit</span>\<span class="hljs-title">Framework</span>\<span class="hljs-title">TestCase</span>;

<span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserTest</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">TestCase</span>
</span>{
    <span class="hljs-comment">// Tests will go here</span>
}
</code></pre>
<h3 id="heading-test-constructor">Test Constructor</h3>
<p>Normally, you wouldn't be testing the <code>__construct</code> method. However, since we're setting values in it, it only makes sense to be sure that the values are being set correctly. </p>
<p>This seems like a very small thing to test, but that's the whole point of unit tests – to ensure that the smallest parts of your application function as expected.</p>
<p>Create a <code>testClassConstructor</code> method to test the constructor:</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testClassConstructor</span>(<span class="hljs-params"></span>)
</span>{
    $user = <span class="hljs-keyword">new</span> User(<span class="hljs-number">18</span>, <span class="hljs-string">'John'</span>);

    <span class="hljs-keyword">$this</span>-&gt;assertSame(<span class="hljs-string">'John'</span>, $user-&gt;name);
    <span class="hljs-keyword">$this</span>-&gt;assertSame(<span class="hljs-number">18</span>, $user-&gt;age);
    <span class="hljs-keyword">$this</span>-&gt;assertEmpty($user-&gt;favorite_movies);
}
</code></pre>
<p>Let's take a quick break now, to see how to run the tests.</p>
<h2 id="heading-how-to-run-tests-in-phpunit">How to Run Tests in PHPUnit</h2>
<p>You can run all the tests in a directory using the PHPUnit binary installed in your vendor folder.</p>
<pre><code class="lang-bash">$ ./vendor/bin/phpunit --verbose tests
</code></pre>
<p>You can also run a single test by providing the path to the test file.</p>
<pre><code class="lang-bash">$ ./vendor/bin/phpunit --verbose tests/UserTest.php
</code></pre>
<p>You use the <code>--verbose</code> flag to get more information on the test status.</p>
<p>Now, we can run the test and see the output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-08-at-13.17.54.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test Output</em></p>
<p>The output shows that we ran 1 test, and made 3 assertions in it. We also see how long it took to run the test, as well as how much memory was used in running the test.</p>
<p>These assertions are what PHPUnit uses to compare values returned from the methods to their expected value. </p>
<p>This example uses <code>assertSame</code> to check if the <code>name</code> and <code>age</code> properties on the user object match the entered values. It also uses <code>assertEmpty</code> to check that the <code>favorite_movies</code> array is empty. </p>
<p>To see a list of all these assertions, you can check out PHPUnit's docs <a target="_blank" href="https://phpunit.readthedocs.io/en/9.5/assertions.html#appendixes-assertions">here</a>.</p>
<p>Edit the code to check if the user age is the same as <em>21</em>.</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testClassConstructor</span>(<span class="hljs-params"></span>)
</span>{
    $user = <span class="hljs-keyword">new</span> User(<span class="hljs-number">18</span>, <span class="hljs-string">'John'</span>);

    <span class="hljs-keyword">$this</span>-&gt;assertSame(<span class="hljs-string">'John'</span>, $user-&gt;name);
    <span class="hljs-keyword">$this</span>-&gt;assertSame(<span class="hljs-number">21</span>, $user-&gt;age);
    <span class="hljs-keyword">$this</span>-&gt;assertEmpty($user-&gt;favorite_movies);
}
</code></pre>
<p>Running the test again this time gives this output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-08-at-13.24.20.png" alt="Image" width="600" height="400" loading="lazy">
<em>Failed Assertion Output</em></p>
<p>The output now shows that we ran 1 test, with 2 successful assertions, and also a failed one. We can see some explanation of the failure, showing the expected value, the gotten value, and the line where the error is from.</p>
<h3 id="heading-test-testname-and-tellage">Test testName and tellAge</h3>
<p>Next, we can test the <code>testName</code> method. This method tells the name of a user as a sentence. So, we can write the test to check:</p>
<ul>
<li>If the returned value is a string.</li>
<li>If the returned string has the user's name in it (with or without case sensitivity).</li>
</ul>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testTellName</span>(<span class="hljs-params"></span>)
</span>{
    $user = <span class="hljs-keyword">new</span> User(<span class="hljs-number">18</span>, <span class="hljs-string">'John'</span>);

    <span class="hljs-keyword">$this</span>-&gt;assertIsString($user-&gt;tellName());
    <span class="hljs-keyword">$this</span>-&gt;assertStringContainsStringIgnoringCase(<span class="hljs-string">'John'</span>, $user-&gt;tellName());
}
</code></pre>
<p>The test uses the assertions <code>assertIsString</code>  and <code>assertStringContainsStringIgnoringCase</code> to check that the return value is a string and that it contains the string <em>John</em>, respectively.</p>
<p>The <code>testAge</code> method is very similar to <code>testName</code> and uses the same logic. Its test will be similar to the previous one:</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testTellAge</span>(<span class="hljs-params"></span>)
</span>{
    $user = <span class="hljs-keyword">new</span> User(<span class="hljs-number">18</span>, <span class="hljs-string">'John'</span>);

    <span class="hljs-keyword">$this</span>-&gt;assertIsString($user-&gt;tellAge());
    <span class="hljs-keyword">$this</span>-&gt;assertStringContainsStringIgnoringCase(<span class="hljs-string">'18'</span>, $user-&gt;tellAge());
}
</code></pre>
<h3 id="heading-test-addfavoritemovie">Test addFavoriteMovie</h3>
<p>We can test this method, too. This method adds a movie to the list of movies. To test it, we can check if the newly added movie is in the list, and that the number of items in the list actually increased. </p>
<p>The latter is for confirming that items are not being displaced. Also, since the function returns some value at the end, we can check that this value is correct too.</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testAddFavoriteMovie</span>(<span class="hljs-params"></span>)
</span>{
    $user = <span class="hljs-keyword">new</span> User(<span class="hljs-number">18</span>, <span class="hljs-string">'John'</span>);

    <span class="hljs-keyword">$this</span>-&gt;assertTrue($user-&gt;addFavoriteMovie(<span class="hljs-string">'Avengers'</span>));
    <span class="hljs-keyword">$this</span>-&gt;assertContains(<span class="hljs-string">'Avengers'</span>, $user-&gt;favorite_movies);
    <span class="hljs-keyword">$this</span>-&gt;assertCount(<span class="hljs-number">1</span>, $user-&gt;favorite_movies);
}
</code></pre>
<p>Here, we use a few new assertions – <code>assertTrue</code>, <code>assertContains</code>, and <code>assertCount</code> – to check that the returned value is true, that it contains the newly added string, and that the array now has one item in it.</p>
<h3 id="heading-test-removefavoritemovie">Test removeFavoriteMovie</h3>
<p>Finally, we can test that the method to remove a movie works. </p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testRemoveFavoriteMovie</span>(<span class="hljs-params"></span>)
</span>{
    $user = <span class="hljs-keyword">new</span> User(<span class="hljs-number">18</span>, <span class="hljs-string">'John'</span>);

    <span class="hljs-keyword">$this</span>-&gt;assertTrue($user-&gt;addFavoriteMovie(<span class="hljs-string">'Avengers'</span>));
    <span class="hljs-keyword">$this</span>-&gt;assertTrue($user-&gt;addFavoriteMovie(<span class="hljs-string">'Justice League'</span>));

    <span class="hljs-keyword">$this</span>-&gt;assertTrue($user-&gt;removeFavoriteMovie(<span class="hljs-string">'Avengers'</span>));
    <span class="hljs-keyword">$this</span>-&gt;assertNotContains(<span class="hljs-string">'Avengers'</span>, $user-&gt;favorite_movies);
    <span class="hljs-keyword">$this</span>-&gt;assertCount(<span class="hljs-number">1</span>, $user-&gt;favorite_movies);
}
</code></pre>
<p>Here, we're adding some movies to the list. Then, we remove one of them, and confirm that the function returned true. Next, we confirm the removal by checking that the value is no longer in the list. Finally, we confirm that we have only one movie in the list, instead of two.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now you know how to set up PHPUnit in your projects and how to test and ensure that you're building world class software. You can find all the code for this article <a target="_blank" href="https://github.com/Zubs/php-testing">here</a>.</p>
<p>If you have any questions or relevant advice, please get in touch with me to share them.</p>
<p>To read more of my articles or follow my work, you can connect with me on <a target="_blank" href="https://www.linkedin.com/in/idris-aweda-zubair-5433121a3/">LinkedIn</a>, <a target="_blank" href="https://twitter.com/AwedaIdris">Twitter</a>, and <a target="_blank" href="https://github.com/Zubs">Github</a>. It’s quick, it’s easy, and it’s free!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Software Testing – Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ What is Software Testing? Let's say you're working on a coding project. You have been writing a bunch of code and staying up late at night to fix bugs. All this is part of the process before you release that software product.  Then you'll check your ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/software-testing-for-beginners/</link>
                <guid isPermaLink="false">66c71fe2cfe24f9b8645574a</guid>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mabel Obadoni ]]>
                </dc:creator>
                <pubDate>Mon, 07 Mar 2022 23:14:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/Talk2Her-Foundation--4-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-is-software-testing">What is Software Testing?</h2>
<p>Let's say you're working on a coding project. You have been writing a bunch of code and staying up late at night to fix bugs. All this is part of the process before you release that software product. </p>
<p>Then you'll check your code to verify that it actually performs what it's been programmed to do. This is where software testing comes in.</p>
<p>This article will discuss the categories of Software Testing and the different types of testing developers most commonly use. You'll see that some of the tests are named for their function. So, when I say API test, I am referring to the tests carried out on the APIs consumed in your source code. </p>
<p>But before going further, let's make sure we know what we mean by Software Testing.</p>
<p>In simple terms, Software Testing is the process of checking the various aspects of a software product to validate the software’s specifications and make sure it's ready to use.</p>
<h2 id="heading-objectives-of-software-testing">Objectives of Software Testing</h2>
<p>From a single line code to a block of code, and even to the finished product, you test software to:</p>
<ul>
<li>check for defects and ensure that the product performs as specified</li>
<li>make sure that the product meets market standards</li>
<li>resolve any loopholes at the production stage</li>
<li>prevent future malfunctions of the product</li>
</ul>
<h2 id="heading-characteristics-of-software-testing">Characteristics of Software Testing</h2>
<p>When you test your software, you want to make sure that your tests are:</p>
<ul>
<li>Practical</li>
<li>Reliable</li>
<li>Authentic</li>
<li>Capable of finding errors</li>
<li>Capable of checking the validity of your software</li>
</ul>
<h2 id="heading-when-should-you-test-your-software">When Should You Test Your Software?</h2>
<p>When you test your software will depend on what test you're wanting to perform.</p>
<p>You can test your software during the software development phase – that is, when writing the source code, as in the case of unit testing, API testing, and others. </p>
<p>You can also test after the software has been developed such as in User Interface (UI) Testing.</p>
<h2 id="heading-when-should-testing-stop">When Should Testing Stop?</h2>
<p>You can stop testing your software when:</p>
<ul>
<li>All the necessary tests have been carried out efficiently</li>
<li>Bugs in the source codes have been reduced to the barest minimum or eradicated</li>
<li>Testers are done testing</li>
<li>Product is fully secured against threats</li>
<li>The product is released</li>
</ul>
<h2 id="heading-software-testing-methods"><strong>Software Testing Methods</strong></h2>
<p>Now that you know what Software Testing means, how exactly is it done? </p>
<p>Software Testing is done based on two main methods:</p>
<ol>
<li>Functional Testing</li>
<li>Non-functional Testing</li>
</ol>
<p>The major difference between these categories of  Software Testing is that Functional Testing tests the functionality of a software product while non-functional testing concentrates on the performance of the software product.  </p>
<h3 id="heading-functional-testing"><strong>Functional Testing</strong></h3>
<p>Functional testing is the process of testing software to validate its usefulness with regard to its specifications.</p>
<p>In simple terms, it consists of various tests carried out on the software generally to verify its functionalities.</p>
<p>Functional testing helps the software team know if the software is working as required. Mind you, Functional Testing doesn't mean testing unit functions or modules.</p>
<h3 id="heading-examples-of-functional-testing">Examples of Functional Testing</h3>
<h4 id="heading-unit-testing">Unit Testing</h4>
<p>In unit testing, you test individual units or functions of your software's source code. Unit testing can be done automatically or manually.</p>
<p>Automatic unit testing happens with human assistance while manual unit testing is actively done by humans.</p>
<p>The difference between these two methods is that the former is automated while the latter requires hard-coding.</p>
<p>The purpose of unit testing is to ensure that each unit component is working as expected.</p>
<h4 id="heading-api-testing">API Testing</h4>
<p>An application Programming Interface (or API) is a link between your program and an external source. So, if you want your program to do more than just what you code, you could employ the features of another program also. This is what consuming APIs is all about. </p>
<p>For instance, let's say that I want my application to have a map feature. Instead of coding one from the scratch, I could save myself some time and stress by using one of the readily available map APIs.   </p>
<p>Using APIs, especially from external sources, comes with its pros and cons, though. And I bet you want to reduce the cons as much as possible. Well, this is why you need to test the API prior to product release. </p>
<p>When you consume a public or private API, while developing your software, you should check for the API's reliability, security, and effectiveness in your product prior to release. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/API.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image representing API</em></p>
<h4 id="heading-ui-user-interface-testing">UI (User interface) Testing</h4>
<p>The User Interface is the channel of communication between the user and the software. </p>
<p>Every software product is developed with certain specifications for the User Interface. This means that the way the user interacts with the application is predetermined prior to developing the product.</p>
<p> In order to make sure that these specifications are met according to design, you can carry out tests on the UI – and this is known as UI Testing.</p>
<p>The UI Testing involves things like checking if the Sign-Up page is correctly accepting inputs, checking to see if the submit button is functional, and a host of other UI features. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Signup-page3--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image of a Payment Page</em></p>
<h4 id="heading-integration-testing">Integration Testing</h4>
<p>Putting components into groups for testing is known as integration testing. Integration testing involves checking how each separate component works together to achieve the common aim of the product. </p>
<p>For instance, in an e-commerce application, the integration tests can check how the Home page connects to the Carts page when the Cart menu is clicked. </p>
<p>The purpose of integration testing is to make sure that components are working in synchrony – that is, that component A works well with component B.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/LOGIN_SIGNUP-PAGE.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image of two UI pages</em></p>
<h4 id="heading-regression-testing">Regression Testing</h4>
<p>Software Development involves iteration, which often happens because of bugs in the source code. </p>
<p>After debugging your code, updating the software program, or making any other change to your code, you should test that software to validate its functionality. This testing is called Regression testing. </p>
<p>Examples of regression testing are corrective regression testing, selective regression testing, progressive regression testing, and others.</p>
<h3 id="heading-non-functional-or-performance-testing"><strong>Non-functional or Performance Testing</strong></h3>
<p>Non-functional testing refers to the various tests carried out on a product to check its readiness for the market. Non-functional Tests go a step further to ensure the viability of a product and its worth.</p>
<h3 id="heading-examples-of-non-functional-testing">Examples of Non-functional Testing</h3>
<h4 id="heading-volume-testing">Volume Testing</h4>
<p>The strength of every product lies in its ability to handle different volumes of data. Some software may not function with a large database. To avoid such breakage, you can do volume tests. </p>
<p>Volume test involves feeding a large database to the software to check its functionality based on the large volume of data. Testing your product on different volumes of data shows that your product can withstand more or fewer data at a given time.</p>
<h4 id="heading-security-testing">Security Testing</h4>
<p>In the world today, security is an important and much-discussed topic. Concerns range from physical security down to cyberspace – and everyone wants that assurance of safety when they are on the internet.</p>
<p>One of the issues you'll want to avoid as a software developer is threats to your application. You can perform security testing on your software product to check its level of vulnerability. </p>
<p>Security tests include authentication, authorization confidentiality, and other measures required to protect your software from risks and threats.</p>
<h2 id="heading-where-to-put-test-files-in-a-program-folder">Where to put test files in a program folder</h2>
<p>Your test files should be together in a test folder inside the root folder of your project. This is for easy navigation and integration into your project.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Now that you know the importance of testing in software development, you should make sure to write code that is error and bug-free when tested.</p>
<p>This will reduce the time you waste fixing bugs and will in turn make the product release date more achievable.</p>
<p>Lastly, be careful to put your test files in the same folder, especially for tests other than unit testing.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
