<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vittorio Banfi</title>
    <description>The latest articles on DEV Community by Vittorio Banfi (@vittorio_banfi_6d141586d5).</description>
    <link>https://dev.to/vittorio_banfi_6d141586d5</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2841313%2Fe3dd0a46-8d49-45a5-85d1-7ad95900f689.png</url>
      <title>DEV Community: Vittorio Banfi</title>
      <link>https://dev.to/vittorio_banfi_6d141586d5</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vittorio_banfi_6d141586d5"/>
    <language>en</language>
    <item>
      <title>ShowDev: CodeBeaver, open-source agent for testing</title>
      <dc:creator>Vittorio Banfi</dc:creator>
      <pubDate>Tue, 11 Mar 2025 17:16:28 +0000</pubDate>
      <link>https://dev.to/vittorio_banfi_6d141586d5/showdev-codebeaver-open-source-agent-for-testing-1ig9</link>
      <guid>https://dev.to/vittorio_banfi_6d141586d5/showdev-codebeaver-open-source-agent-for-testing-1ig9</guid>
      <description>&lt;p&gt;I just open-sourced &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai" rel="noopener noreferrer"&gt;CodeBeaver&lt;/a&gt;, a tool I built after LLM-generated code kept sneaking weird bugs into my projects.&lt;/p&gt;

&lt;p&gt;With just a few lines of YAML, CodeBeaver can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run end-to-end (E2E) tests written in natural language&lt;/li&gt;
&lt;li&gt;Generate, maintain, and execute unit tests automatically&lt;/li&gt;
&lt;li&gt;Analyze test failures to determine if it’s a bug or just a flaky test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can run it locally with a quick pip install, or integrate it into CI/CD with GitHub Actions, where it will even open PRs with missing tests.&lt;/p&gt;

&lt;p&gt;It's basically vibe testing :D&lt;/p&gt;

&lt;p&gt;We use BrowserUse for the E2E, O3-mini for the unit test generation, plus a bunch of shell scripts to make everything seamless.&lt;/p&gt;

&lt;p&gt;Currently supports Python &amp;amp; TypeScript, with more languages on the roadmap. Would love to hear your thoughts!&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai" rel="noopener noreferrer"&gt;check it out here on GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>showdev</category>
      <category>qa</category>
      <category>testing</category>
    </item>
    <item>
      <title>Adding Unit Tests to Your Django Project with CodeBeaver - Tutorial</title>
      <dc:creator>Vittorio Banfi</dc:creator>
      <pubDate>Mon, 17 Feb 2025 14:51:04 +0000</pubDate>
      <link>https://dev.to/vittorio_banfi_6d141586d5/from-zero-to-testing-hero-adding-unit-tests-to-your-django-project-with-codebeaver-117e</link>
      <guid>https://dev.to/vittorio_banfi_6d141586d5/from-zero-to-testing-hero-adding-unit-tests-to-your-django-project-with-codebeaver-117e</guid>
      <description>&lt;p&gt;Your Django project is growing. More users, more features, more complexity. You know you need a proper testing strategy, but who has time to write hundreds of unit tests? Between shipping features and fixing bugs, testing often takes a back seat - until something breaks in production.&lt;/p&gt;

&lt;p&gt;What if you could set up a complete testing infrastructure in minutes and have AI write and maintain your tests automatically?&lt;/p&gt;

&lt;p&gt;This tutorial shows you exactly that. We'll take your existing Django project from zero to fully tested by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setting up a professional testing infrastructure using pytest-django (10 minutes)&lt;/li&gt;
&lt;li&gt;Connecting your GitHub repository to CodeBeaver's AI testing pipeline (2 minutes)&lt;/li&gt;
&lt;li&gt;Learning the LLM-powered workflow we use at CodeBeaver to ship features faster and with fewer bugs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By the end of this tutorial, you'll have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A complete testing setup that automatically generates tests for new code&lt;/li&gt;
&lt;li&gt;AI-powered test maintenance that keeps your test suite up-to-date as your code evolves&lt;/li&gt;
&lt;li&gt;A modern development workflow that leverages LLMs to write better, more testable code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Best of all? The entire setup takes less than 15 minutes. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Django project (existing or new)&lt;/li&gt;
&lt;li&gt;Python 3.6+ installed (&lt;code&gt;python --version&lt;/code&gt; to check)&lt;/li&gt;
&lt;li&gt;pip installed (&lt;code&gt;pip --version&lt;/code&gt; to verify)&lt;/li&gt;
&lt;li&gt;A GitHub account (GitLab and Bitbucket also work)&lt;/li&gt;
&lt;li&gt;Basic familiarity with Django and pip&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting Up Your Django Project for Testing
&lt;/h2&gt;

&lt;p&gt;Remember how Django's &lt;code&gt;startproject&lt;/code&gt; command set up the foundation of your project? Setting up testing requires a similar foundation - a few key files and configurations that will make everything else smoother. Let's build this foundation step by step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Required Files and Project Structure
&lt;/h3&gt;

&lt;p&gt;In a typical Django project, your tests might live in a &lt;code&gt;tests.py&lt;/code&gt; file within each app. While this works for small projects, as your codebase grows, you'll want a more organized structure. Here's what we recommend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myproject/
├── manage.py
├── pyproject.toml      # New: Modern Python project configuration
├── pytest.ini         # New: pytest configuration
├── conftest.py       # New: Shared pytest fixtures
├── myproject/
│   ├── __init__.py
│   ├── settings.py
│   └── urls.py
└── myapp/
    ├── __init__.py
    ├── models.py
    ├── views.py
    ├── tests/        # Instead of tests.py, use a directory
    │   ├── __init__.py
    │   ├── test_models.py
    │   ├── test_views.py
    │   └── conftest.py  # App-specific fixtures
    └── factories/    # New: Factories for test data
        ├── __init__.py
        └── user_factory.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure separates your tests by component (models, views, etc.) while keeping them close to the code they're testing. Think of it like organizing your kitchen - you want your spices near your cooking area, but still sorted by type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing pytest-django and Friends
&lt;/h3&gt;

&lt;p&gt;While Django's built-in test framework is good, pytest offers more powerful features. Let's install the tools we'll need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pytest-django pytest-cov factory-boy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add these to your project's requirements. In the root of your repository add a &lt;code&gt;requirements-test.txt&lt;/code&gt; file and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest-django&amp;gt;=4.5.2
pytest-cov&amp;gt;=4.1.0
factory-boy&amp;gt;=3.3.0
-r requirements.txt  # Inherit your main requirements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of these packages as your testing toolkit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pytest-django: The power drill of Django testing&lt;/li&gt;
&lt;li&gt;pytest-cov: Your coverage measuring tape&lt;/li&gt;
&lt;li&gt;factory-boy: Your test data assembly line&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration: Making Everything Work Together
&lt;/h3&gt;

&lt;p&gt;Let's set up &lt;code&gt;pyproject.toml&lt;/code&gt; - think of this as your project's master configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.pytest.ini_options]&lt;/span&gt;
&lt;span class="py"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"myproject.settings"&lt;/span&gt;
&lt;span class="py"&gt;python_files&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"test_*.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"*_test.py"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;addopts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
    --ds=myproject.settings
    --reuse-db
    --cov=.
    --cov-report=term-missing
    --cov-fail-under=80
"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create &lt;code&gt;conftest.py&lt;/code&gt; in your project root. This file will hold fixtures (reusable test components) that any test can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;A Django test client instance.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;auth_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;django_user_model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;A Django test client logged in as a basic user.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;django_user_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;testuser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;testpass123&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;testuser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;testpass123&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting Up Your Test Database
&lt;/h3&gt;

&lt;p&gt;Django handles test databases automatically, but let's make them faster and more reliable. Add this to your test settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings/test.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;  &lt;span class="c1"&gt;# Import your base settings
&lt;/span&gt;
&lt;span class="n"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ENGINE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.db.backends.sqlite3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;:memory:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Use in-memory database for tests
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Speed up password hashing
&lt;/span&gt;&lt;span class="n"&gt;PASSWORD_HASHERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.hashers.MD5PasswordHasher&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Disable migrations for tests
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DisableMigrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__contains__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="n"&gt;MIGRATION_MODULES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DisableMigrations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating Your Test Files Manually (optional)
&lt;/h2&gt;

&lt;p&gt;CodeBeaver will create test files for you, so you can skip this section if you want.&lt;/p&gt;

&lt;p&gt;Some engineers like to write tests, and it can be a good idea to understand how to create them manually first. A workflow that we also see is that developers create one test file manually while developing the feature and then let CodeBeaver take over from there. In this case, CodeBeaver adds tests to cover edge cases. It will also maintain the test file as you change the code.&lt;/p&gt;

&lt;p&gt;Let's say you have a simple Django model for blog posts. Here's how you'd structure its tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# myapp/tests/test_models.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;myapp.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.mark.django_db&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestBlogPost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_create_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;published_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_post_str_representation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For views, you'll want separate test files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# myapp/tests/test_views.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.mark.django_db&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestBlogPostViews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_post_list_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blog:post_list&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_post_detail_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blog_post&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blog:post_detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blog_post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;blog_post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using Factories for Test Data
&lt;/h3&gt;

&lt;p&gt;Instead of creating test data manually in each test, use factories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# myapp/factories/blog_factory.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;myapp.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPostFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DjangoModelFactory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;

    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test Post &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Faker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paragraph&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;published_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LazyFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SubFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;myapp.factories.UserFactory&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your tests become much cleaner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_recent_posts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Create 5 posts at once
&lt;/span&gt;    &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPostFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;recent_posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recent_posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup might seem like a lot, but it's like mise en place in cooking - having everything prepared makes the actual work much smoother. In the next section, we'll see how CodeBeaver can help maintain and expand your test suite automatically, working within this structure we've created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your First Test-Driven PR: Watching CodeBeaver in Action
&lt;/h2&gt;

&lt;p&gt;Now that we have our testing infrastructure set up, let's see how CodeBeaver helps maintain your test suite. We'll walk through a real-world scenario: adding a new feature to track user engagement on blog posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing CodeBeaver
&lt;/h2&gt;

&lt;p&gt;Now that we have our Python project structured and ready, let's integrate CodeBeaver into our workflow. This integration will transform your repository from having no test coverage to maintaining comprehensive test suites automatically. The process is straightforward and takes just a few minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Authentication and Authorization
&lt;/h3&gt;

&lt;p&gt;First, navigate to &lt;a href="https://app.codebeaver.ai/login" rel="noopener noreferrer"&gt;codebeaver.ai&lt;/a&gt; and select "Sign up with GitHub". This initiates a secure OAuth flow that will allow CodeBeaver to interact with your repositories. If you're using GitLab or Bitbucket, you'll find similar options for those platforms.&lt;/p&gt;

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

&lt;p&gt;After authenticating, you'll be prompted to authorize CodeBeaver's access to your repositories. You'll see an installation screen that allows you to choose between personal and organizational repositories, select specific repositories or grant access to all.&lt;/p&gt;

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

&lt;p&gt;Click "Install CodeBeaver" to proceed. Don't worry about getting the permissions exactly right - you can always modify these settings later as your needs change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Repository Selection
&lt;/h3&gt;

&lt;p&gt;Once authorized, you'll be presented with a dashboard showing your available repositories. This is where you'll select the repository we just created and enable CodeBeaver for it.&lt;/p&gt;

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

&lt;p&gt;The repository selection interface presents a clear list of your repositories, with options to search and filter if you manage many projects. Select your Python risk calculator repository to proceed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Automatic Configuration
&lt;/h3&gt;

&lt;p&gt;CodeBeaver will now analyze your repository structure to determine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The programming language(s) in use&lt;/li&gt;
&lt;li&gt;Testing frameworks present (pytest in our case)&lt;/li&gt;
&lt;li&gt;Project structure and dependencies&lt;/li&gt;
&lt;li&gt;Existing test configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on this analysis, CodeBeaver will attempt to auto-configure itself. For a standard Python project like ours that uses pytest, this process should complete successfully.&lt;/p&gt;

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

&lt;p&gt;If auto-configuration succeeds, you'll see options for how you'd like to proceed with CodeBeaver. Select the Pull Request you just opened before. You are done! CodeBeaver will start working on your Pull Request.&lt;/p&gt;

&lt;h3&gt;
  
  
  What If Auto-Configuration Fails?
&lt;/h3&gt;

&lt;p&gt;If you are using your own project, it may happen that CodeBeaver will not be able to auto-configure itself. Don't worry! This usually happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your project uses a non-standard structure&lt;/li&gt;
&lt;li&gt;You have multiple testing frameworks&lt;/li&gt;
&lt;li&gt;You need custom test commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases, you can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.codebeaver.ai/troubleshooting/auto-configuration-failed" rel="noopener noreferrer"&gt;Check the troubleshooting guide in the CodeBeaver documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;codebeaver.yml&lt;/code&gt; configuration file to your repository&lt;/li&gt;
&lt;li&gt;Contact CodeBeaver support for assistance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With CodeBeaver installed and configured, you're ready to experience automated test generation in action. In the next section, we'll create our first pull request and watch as CodeBeaver automatically generates and maintains your tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying everything out
&lt;/h2&gt;

&lt;p&gt;Everything is set up, so let's try it out!&lt;/p&gt;

&lt;p&gt;Let's say we want to add a feature that tracks how many times each blog post is viewed. First, we'll modify our BlogPost model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# blog/models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;auth.User&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;published_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;view_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PositiveIntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# New field
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment_views&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Increment the view count for this post.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# Using F() to avoid race conditions
&lt;/span&gt;        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;view_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update_fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;view_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_engagement_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate an engagement score based on views and age.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;published_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="n"&gt;age_in_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;published_at&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age_in_days&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;age_in_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view_count&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;age_in_days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And update our view to use this new functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# blog/views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.views.generic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DetailView&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPostDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DetailView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;
    &lt;span class="n"&gt;template_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blog/post_detail.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queryset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment_views&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;engagement_score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_engagement_score&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's create a new branch and commit these changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/post-analytics
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat: add view tracking and engagement scoring to blog posts"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can open a pull request and watch CodeBeaver do its magic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Opening the Pull Request
&lt;/h3&gt;

&lt;p&gt;Create a new branch and commit these changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/post-analytics
git add blog/models.py blog/views.py
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat: add view tracking and engagement scoring to blog posts"&lt;/span&gt;
git push origin feature/post-analytics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a pull request on GitHub. You are done! CodeBeaver will start working on your Pull Request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding CodeBeaver's Analysis
&lt;/h3&gt;

&lt;p&gt;When CodeBeaver analyzes your PR, it looks for several key aspects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;New or modified model fields (&lt;code&gt;view_count&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Business logic methods (&lt;code&gt;increment_views&lt;/code&gt;, &lt;code&gt;get_engagement_score&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;View modifications that affect database state&lt;/li&gt;
&lt;li&gt;Potential race conditions&lt;/li&gt;
&lt;li&gt;Edge cases in calculations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Within a few minutes, CodeBeaver will create a new PR with generated tests. You can check &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai/pull/100" rel="noopener noreferrer"&gt;an example Pull Request here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices and Tips: Making Your Django Code Test-Friendly
&lt;/h2&gt;

&lt;p&gt;When writing testable code, many developers make the mistake of starting with implementation. The real breakthrough comes from starting with clear documentation and well-structured functions. In this section, we'll explore how to make your Django code not just testable, but a joy to test - focusing on powerful docstrings, clear function contracts, and code organization patterns that make testing natural and effective.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Power of Docstrings: Your Testing Blueprint
&lt;/h3&gt;

&lt;p&gt;Think of a docstring as a contract between you and future developers (including yourself!). But with CodeBeaver, it's more than that - it's your direct line of communication to the AI about what your code should do. Let's look at a poorly documented function and transform it into a testing-friendly version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Before: Hard to test, unclear expectations
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;processing&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# After: Clear expectations, easy to test
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Process a new order if the user is active.

    Args:
        order: Order instance to process
        user: User attempting to process the order

    Returns:
        bool: True if order was processed, False if user is inactive

    Raises:
        ValueError: If order is already processed
        TypeError: If order or user are incorrect types

    Example:
&lt;/span&gt;&lt;span class="gp"&gt;        &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;processing&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid order or user type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot process order with status &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;processing&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down why this docstring is so powerful for testing:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Input Documentation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Clear parameter descriptions&lt;/li&gt;
&lt;li&gt;Type hints that CodeBeaver can validate&lt;/li&gt;
&lt;li&gt;Explicit preconditions (order must be 'new')&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Output Contract
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Return value meaning is explicit&lt;/li&gt;
&lt;li&gt;All possible outcomes are documented&lt;/li&gt;
&lt;li&gt;Examples show expected behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Error Conditions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;All exceptions are documented&lt;/li&gt;
&lt;li&gt;Error scenarios are clearly defined&lt;/li&gt;
&lt;li&gt;Edge cases are mentioned&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Docstrings Matter More Than You Think
&lt;/h3&gt;

&lt;p&gt;Here's a real example of how good docstrings saved my team time. We had a payment processing function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_subscription_renewal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;renewal_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Calculate the next renewal amount and date for a subscription.

    Args:
        subscription: Subscription model instance
        renewal_date: Optional date to calculate renewal for
                     Defaults to subscription.current_period_end

    Returns:
        tuple: (
            renewal_amount: Decimal - The amount to charge
            renewal_date: datetime - When the renewal takes effect
            currency: str - Three-letter currency code
        )

    Examples:
        Basic renewal:
&lt;/span&gt;&lt;span class="gp"&gt;        &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_subscription_renewal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
        &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="s"&gt;        Prorated renewal:
&lt;/span&gt;&lt;span class="gp"&gt;        &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_subscription_renewal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="s"&gt;    Raises:
        ValueError: If subscription is cancelled or renewal_date is in the past
        TypeError: If renewal_date is not None or datetime
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When CodeBeaver saw this docstring, it generated comprehensive tests that caught several edge cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timezone handling around midnight&lt;/li&gt;
&lt;li&gt;Proration calculations at month boundaries&lt;/li&gt;
&lt;li&gt;Currency conversion edge cases&lt;/li&gt;
&lt;li&gt;Invalid date validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The examples in the docstring were particularly valuable - CodeBeaver used them as a starting point and then generated variations to test boundary conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of a complete LLM workflow
&lt;/h2&gt;

&lt;p&gt;Here's a workflow that has transformed how my team writes testable code. If you are using a &lt;a href="https://copilot.github.com/" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;, &lt;a href="https://www.cursor.com/" rel="noopener noreferrer"&gt;Cursor&lt;/a&gt; or &lt;a href="https://copilot.github.com/" rel="noopener noreferrer"&gt;VSCode Copilot&lt;/a&gt;, you can use it to help you write docstrings.&lt;/p&gt;

&lt;p&gt;Simply, you start by writing the name of your def. Then you add a simple docstring with the purpose of the function, nothing else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Process the order by matching the delivery address to the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s address. If the user has no address, we raise an error. If it takes more than 4 days, return that in the return object. otherwise the return object contains only the order
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not implemented yet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then select the def and ask the LLM to write a more detailed docstring, by defining return values and other details. For example, with Claude 3-5 I get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Process an order by validating and matching delivery address with user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s address.

    Args:
        order (Order): The order to be processed
        user (User): The user placing the order

    Returns:
        dict: Processing result containing:
            - &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; (Order): The processed order object
            - &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;processing_time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; (int, optional): Number of days for delivery,
              only included if exceeds 4 days
            - &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; (str): Processing status (&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; or &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;delayed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)

    Raises:
        ValueError: If user has no address configured
        TypeError: If order or user are not of correct type
        ValidationError: If order is already processed or invalid

    Examples:
        Standard processing:
&lt;/span&gt;&lt;span class="gp"&gt;        &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123 Main St&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#123&amp;gt;, 'status': 'success'}
&lt;/span&gt;
        &lt;span class="n"&gt;Delayed&lt;/span&gt; &lt;span class="n"&gt;processing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delayed_order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#124&amp;gt;,
&lt;/span&gt;            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;delayed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;processing_time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not implemented yet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I now review the docstring and make edits if the LLM hallucinated something or got something wrong.&lt;/p&gt;

&lt;p&gt;Once that's done, I just select the &lt;code&gt;NotImplementedError&lt;/code&gt; and ask the LLM to implement the function. Et voilà! I have a working function that you can review. Not only that: Thanks to the detailed docstring, CodeBeaver will generate tests for you that cover all the possible cases after you push your changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat: implement process_order"&lt;/span&gt;
git push origin feature/process-order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I open a PR and CodeBeaver will start working on the PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Your Journey to Testing Excellence
&lt;/h2&gt;

&lt;p&gt;You've come a long way from where we started! Remember that initial scenario - the Django developer pushing to production and hoping nothing breaks? That's no longer you. You've taken the first crucial steps toward building a robust, tested Django application. Let's reflect on your journey and plan your next steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You've Learned
&lt;/h3&gt;

&lt;p&gt;Think back to where we started. You now understand not just the mechanics of testing Django applications, but the deeper principles that make testing effective. You've learned how to structure your code with testing in mind, starting with those crucial docstrings that serve as both documentation and testing blueprints. You've seen how CodeBeaver can transform those docstrings into comprehensive test suites, catching edge cases you might never have thought about.&lt;/p&gt;

&lt;p&gt;The most important shift isn't in the tools or configurations - it's in how you think about your code. You're no longer writing functions that merely work; you're crafting well-documented, testable components that prove they work. That's a fundamental transformation in how you approach software development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your Next Testing Adventures
&lt;/h3&gt;

&lt;p&gt;Now that you have the foundation in place, here are some exciting directions to explore:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Expand Your Test Coverage Gradually
&lt;/h4&gt;

&lt;p&gt;Start with your most critical paths - user authentication, payment processing, data mutations. CodeBeaver can help you identify these areas by analyzing your codebase. Remember, you don't need to test everything at once. Focus on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# High-priority testing targets:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;This affects your bottom line - test it first!&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# Medium priority:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_user_preferences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Important but not critical - test after core functions&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# Lower priority:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user_avatar_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Nice to have tests, but not urgent&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Enhance Your Testing Infrastructure
&lt;/h4&gt;

&lt;p&gt;As your test suite grows, consider adding these powerful tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Factory Boy for more sophisticated test data generation&lt;/li&gt;
&lt;li&gt;pytest-xdist for parallel test execution&lt;/li&gt;
&lt;li&gt;pytest-cov for detailed coverage reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Build Testing into Your Workflow
&lt;/h4&gt;

&lt;p&gt;Make testing as natural as writing code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write your docstring&lt;/li&gt;
&lt;li&gt;Let your favorite LLM help implement the function&lt;/li&gt;
&lt;li&gt;Push to GitHub&lt;/li&gt;
&lt;li&gt;Let CodeBeaver generate and maintain your tests&lt;/li&gt;
&lt;li&gt;Review and merge&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Path Forward
&lt;/h3&gt;

&lt;p&gt;Remember that testing isn't a destination - it's a journey. Every test you add makes your application more reliable, every docstring makes your code more maintainable, and every PR becomes an opportunity to improve your test coverage.&lt;/p&gt;

&lt;p&gt;Don't feel pressured to achieve 100% coverage immediately. Start with the most critical parts of your application and let your test suite grow organically. CodeBeaver will be there to help you maintain and expand your tests as your codebase evolves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;p&gt;To continue your testing journey:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Join our &lt;a href="https://discord.gg/4QMwWdsMGt" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt; where you can share experiences and get help from other Django developers using CodeBeaver&lt;/li&gt;
&lt;li&gt;Check out &lt;a href="https://docs.djangoproject.com/en/stable/topics/testing/" rel="noopener noreferrer"&gt;Django's testing documentation&lt;/a&gt; for deep dives into specific testing features&lt;/li&gt;
&lt;li&gt;Explore &lt;a href="https://pytest-django.readthedocs.io/" rel="noopener noreferrer"&gt;pytest-django's documentation&lt;/a&gt; for advanced testing techniques&lt;/li&gt;
&lt;li&gt;Review real-world examples in our &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Testing might have seemed daunting when you started reading this tutorial, but look how far you've come! You now have the knowledge and tools to build reliable, well-tested Django applications. Remember, every great codebase started with a single test. Your journey to testing excellence is just beginning, and with CodeBeaver by your side, you're well-equipped for the road ahead.&lt;/p&gt;

&lt;p&gt;Now, how about opening that first PR and letting CodeBeaver help you write some tests? Your future self (and your users) will thank you!&lt;/p&gt;

</description>
      <category>django</category>
      <category>testing</category>
      <category>unittest</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Setting Up Your First Python Unit Testing Pipeline with CodeBeaver - Tutorial</title>
      <dc:creator>Vittorio Banfi</dc:creator>
      <pubDate>Fri, 14 Feb 2025 15:14:18 +0000</pubDate>
      <link>https://dev.to/vittorio_banfi_6d141586d5/from-zero-to-testing-hero-setting-up-your-first-python-unit-testing-pipeline-with-codebeaver-1ba</link>
      <guid>https://dev.to/vittorio_banfi_6d141586d5/from-zero-to-testing-hero-setting-up-your-first-python-unit-testing-pipeline-with-codebeaver-1ba</guid>
      <description>&lt;p&gt;Ever found yourself pushing code at 2 AM, crossing your fingers, and hoping nothing breaks in production? We've all been there. But as AI accelerates our development speed, the "push and pray" approach isn't cutting it anymore. That's where automated testing comes in - and we're going to show you how to set it up in minutes.&lt;/p&gt;

&lt;p&gt;This tutorial is perfect for Python developers who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know their way around Python but haven't tackled testing yet&lt;/li&gt;
&lt;li&gt;Are shipping code faster than ever thanks to AI tools&lt;/li&gt;
&lt;li&gt;Want to catch bugs before users do (and before that 2 AM emergency call)&lt;/li&gt;
&lt;li&gt;Would rather spend time building features than manually writing test cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll show you how to set up a complete testing pipeline powered by AI. CodeBeaver will automatically generate, run, and maintain your tests - think of it as having a testing expert on your team who never sleeps.&lt;/p&gt;

&lt;p&gt;The best part? It's completely free for open source projects, and you can try it on private repos with our 14-day trial. No credit card required.&lt;/p&gt;

&lt;p&gt;Ready to level up your Python development game? Let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;We're going to set up a complete Python testing workflow that will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically run tests whenever you push new code&lt;/li&gt;
&lt;li&gt;Generate missing tests to maintain solid coverage&lt;/li&gt;
&lt;li&gt;Help catch bugs before they reach production&lt;/li&gt;
&lt;li&gt;Work naturally with your existing GitHub workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best part? Once we set this up, it largely runs itself. No more hastily adding &lt;code&gt;# TODO: add tests&lt;/code&gt; comments at midnight before a release.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before we dive in, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.6 or higher installed (run &lt;code&gt;python --version&lt;/code&gt; to check)&lt;/li&gt;
&lt;li&gt;pip installed and working (run &lt;code&gt;pip --version&lt;/code&gt; to verify)&lt;/li&gt;
&lt;li&gt;A GitHub account (also GitLab or Bitbucket will work)&lt;/li&gt;
&lt;li&gt;Basic familiarity with Python and pip&lt;/li&gt;
&lt;li&gt;A willingness to level up your development game&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What's Coming Up
&lt;/h3&gt;

&lt;p&gt;Think of this tutorial as your journey from "what's a test fixture?" to "look at my beautiful test coverage report!" We'll progress through several key stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First, we'll set up a basic Python project with proper structure - similar to how you'd set up a new virtual environment and requirements.txt, but optimized for testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we'll introduce pytest - think of it as pip for testing. Just as pip manages your project's dependencies, pytest will manage your test execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, we'll connect CodeBeaver - your new AI testing assistant. Imagine having a senior developer who specializes in testing looking over your shoulder, but without the awkward coffee breath.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we'll create your first pull request and watch as CodeBeaver automatically generates tests for your code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Understanding the Value of Testing in Python
&lt;/h3&gt;

&lt;p&gt;Before we jump into the technical setup, let's talk about why testing matters specifically for Python projects. Unlike languages with static typing, Python's dynamic nature means we can't rely on the compiler to catch certain types of errors. Consider this seemingly innocent code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_user_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt;

&lt;span class="c1"&gt;# Works fine
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_user_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 150.0
&lt;/span&gt;
&lt;span class="c1"&gt;# Uh oh...
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_user_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# TypeError!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without tests, this type of error might only surface when a user enters string input instead of a number - possibly weeks after deployment. Good unit tests catch these issues before they reach production, saving you from those dreaded 3 AM "production is down" messages.&lt;/p&gt;

&lt;p&gt;Think of unit tests like the docstring checking feature in your IDE - they're there to catch problems early and document how your code should behave. Just as you wouldn't skip writing requirements.txt because managing dependencies manually is "faster," you shouldn't skip testing because writing features without tests feels quicker in the moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Makes Python Testing Different?
&lt;/h3&gt;

&lt;p&gt;Python's testing ecosystem has some unique advantages that make it particularly well-suited for automated testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python's assert statement makes test assertions readable and natural&lt;/li&gt;
&lt;li&gt;The pytest framework uses Python's introspection capabilities to make test discovery automatic&lt;/li&gt;
&lt;li&gt;Python's dynamic nature means we can easily mock and patch objects for testing&lt;/li&gt;
&lt;li&gt;The extensive use of duck typing in Python makes it crucial to test behavior rather than just types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next section, we'll start setting up our Python project with these advantages in mind. We'll create a structure that makes testing as natural as importing a module, and then we'll let CodeBeaver handle the heavy lifting of actually writing those tests.&lt;/p&gt;

&lt;p&gt;Remember: Just as pip revolutionized Python package management (remember the days of manually downloading and installing packages?), tools like CodeBeaver are revolutionizing how we approach testing. Ready to join the testing revolution? Let's dive into the setup in the next section!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your Python Project for Testing
&lt;/h2&gt;

&lt;p&gt;Remember how switching from &lt;code&gt;pip install&lt;/code&gt; commands to using a &lt;code&gt;requirements.txt&lt;/code&gt; file made your Python projects more organized and reproducible? We're about to do something similar for testing. Just as a well-structured requirements file makes dependency management smoother, a well-organized testing structure makes writing and maintaining tests much easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Your Python Project Structure
&lt;/h3&gt;

&lt;p&gt;Let's start with a project structure that separates our application code from our tests. While you might be used to seeing Python projects with just a src directory and requirements file, a test-friendly structure includes a few additional elements. Here's what we'll create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;my_project&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;my_project&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;test_core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;test_utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ini&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gitignore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create this structure step by step. First, make your project directory and navigate into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my_project
&lt;span class="nb"&gt;cd &lt;/span&gt;my_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's set up a virtual environment - this is probably familiar territory for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate  &lt;span class="c"&gt;# On Windows, use: venv\Scripts\activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding the Two-Requirements Approach
&lt;/h3&gt;

&lt;p&gt;You might be wondering why we have both &lt;code&gt;requirements.txt&lt;/code&gt; and &lt;code&gt;requirements-test.txt&lt;/code&gt;. This separation follows a important principle in software development: keeping production dependencies separate from development dependencies. Here's why this matters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# requirements.txt - Production dependencies
&lt;/span&gt;&lt;span class="n"&gt;pandas&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;2.28&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dotenv&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="c1"&gt;# requirements-test.txt - Testing dependencies
&lt;/span&gt;&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;7.3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cov&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;3.10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;  &lt;span class="c1"&gt;# This line inherits production dependencies
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it this way: when your code runs in production, it doesn't need testing libraries. Just as you wouldn't include your development IDE in your production environment, you don't need testing tools there either. This separation also makes your deployment pipelines faster and more secure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up pytest
&lt;/h3&gt;

&lt;p&gt;Now, let's create a &lt;code&gt;pytest.ini&lt;/code&gt; file. This is similar to how &lt;code&gt;setup.cfg&lt;/code&gt; configures your Python package behavior - it tells pytest how to run your tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[pytest]&lt;/span&gt;
&lt;span class="py"&gt;testpaths&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;tests&lt;/span&gt;
&lt;span class="py"&gt;python_files&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;test_*.py&lt;/span&gt;
&lt;span class="py"&gt;addopts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="py"&gt;--cov&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;src/my_project&lt;/span&gt;
    &lt;span class="py"&gt;--cov-report&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;term-missing&lt;/span&gt;
    &lt;span class="py"&gt;--cov-fail-under&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;80&lt;/span&gt;
&lt;span class="py"&gt;markers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="err"&gt;slow:&lt;/span&gt; &lt;span class="err"&gt;marks&lt;/span&gt; &lt;span class="err"&gt;tests&lt;/span&gt; &lt;span class="err"&gt;as&lt;/span&gt; &lt;span class="err"&gt;slow&lt;/span&gt; &lt;span class="err"&gt;(deselect&lt;/span&gt; &lt;span class="err"&gt;with&lt;/span&gt; &lt;span class="err"&gt;'-m&lt;/span&gt; &lt;span class="err"&gt;"not&lt;/span&gt; &lt;span class="err"&gt;slow"')&lt;/span&gt;
    &lt;span class="err"&gt;integration:&lt;/span&gt; &lt;span class="err"&gt;marks&lt;/span&gt; &lt;span class="err"&gt;tests&lt;/span&gt; &lt;span class="err"&gt;as&lt;/span&gt; &lt;span class="err"&gt;integration&lt;/span&gt; &lt;span class="err"&gt;tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down what each of these settings does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;testpaths = tests&lt;/code&gt; tells pytest where to look for test files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;python_files = test_*.py&lt;/code&gt; defines the naming pattern for test files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;addopts&lt;/code&gt; configures default command-line options:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--cov=src/my_project&lt;/code&gt; measures code coverage for your project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cov-report=term-missing&lt;/code&gt; shows which lines aren't tested&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cov-fail-under=80&lt;/code&gt; ensures at least 80% code coverage&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;markers&lt;/code&gt; lets you categorize tests (similar to how you might tag functions with decorators)&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding Some Initial Code to Test
&lt;/h3&gt;

&lt;p&gt;Let's add a simple Python module that we'll use as an example. Create &lt;code&gt;src/my_project/utils.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_risk_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;income&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credit_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;debt_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Calculate a risk score for a loan application.

    Args:
        income: Annual income in dollars
        credit_score: Credit score (300-850)
        debt_ratio: Monthly debt payments / monthly income

    Returns:
        risk_score: Score between 0 (highest risk) and 100 (lowest risk)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;credit_score&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;850&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Credit score must be between 300 and 850&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;debt_ratio&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;debt_ratio&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Debt ratio must be between 0 and 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;income&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Income must be positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Base score from credit score (40% weight)
&lt;/span&gt;    &lt;span class="n"&gt;credit_score_component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;credit_score&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;550&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;

    &lt;span class="c1"&gt;# Income component (30% weight)
&lt;/span&gt;    &lt;span class="n"&gt;income_component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;income&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

    &lt;span class="c1"&gt;# Debt ratio component (30% weight)
&lt;/span&gt;    &lt;span class="n"&gt;debt_component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;debt_ratio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;credit_score_component&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;income_component&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;debt_component&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function might look simple, but it has several aspects that need testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input validation for each parameter&lt;/li&gt;
&lt;li&gt;Edge cases (minimum and maximum values)&lt;/li&gt;
&lt;li&gt;The business logic of the scoring algorithm&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without proper testing, we might miss edge cases like what happens when someone enters negative income or a credit score of 900. This is exactly the kind of code where CodeBeaver shines - it can identify these edge cases automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running pytest
&lt;/h3&gt;

&lt;p&gt;Now that we have our project structure set up, let's run pytest to see where we stand with our testing. This step is important because it establishes our baseline and helps us understand what CodeBeaver will be working with.&lt;/p&gt;

&lt;p&gt;First, let's install our testing dependencies. Create a &lt;code&gt;requirements-test.txt&lt;/code&gt; file with these contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;7.3.1
pytest-cov&lt;span class="o"&gt;==&lt;/span&gt;4.0.0
pytest-mock&lt;span class="o"&gt;==&lt;/span&gt;3.10.0
&lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install these dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements-test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's run pytest for the first time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see output that looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;============================= test session starts ==============================
platform linux -- Python 3.9.7, pytest-7.3.1, pluggy-1.0.0
rootdir: /path/to/my_project, configfile: pytest.ini
plugins: cov-4.0.0, mock-3.10.0
collected 0 items

============================ no tests ran in 0.12s ============================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't worry about the "no tests ran" message – this is exactly what we expect! Remember, we haven't written any tests yet. This is where CodeBeaver will come in handy.&lt;/p&gt;

&lt;p&gt;Let's also try running pytest with coverage reporting enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pytest &lt;span class="nt"&gt;--cov&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src/my_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see additional output showing our current coverage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;============================= test session starts ==============================
platform linux -- Python 3.9.7, pytest-7.3.1, pluggy-1.0.0
rootdir: /path/to/my_project, configfile: pytest.ini
plugins: cov-4.0.0, mock-3.10.0
collected 0 items

---------- coverage: platform linux, python 3.9.7-final-0 -----------
Name                                      Stmts   Miss  Cover
-------------------------------------------------------------
src/my_project/utils.py                      20     20     0%
-------------------------------------------------------------
TOTAL                                        20     20     0%

============================ no tests ran in 0.12s ============================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This output tells us several important things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our project structure is correct (pytest found our code)&lt;/li&gt;
&lt;li&gt;We have 0% test coverage (all 20 statements in utils.py are untested)&lt;/li&gt;
&lt;li&gt;The testing environment is properly configured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly the situation where CodeBeaver shines. Rather than writing all these tests manually, we'll let CodeBeaver analyze our code and generate comprehensive tests that cover all these untested statements. In the next section, we'll push our code to GitHub and set up CodeBeaver to start generating these tests automatically.&lt;/p&gt;

&lt;p&gt;The structure we've created gives CodeBeaver everything it needs to understand our code and generate meaningful tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A clear project structure that follows Python best practices&lt;/li&gt;
&lt;li&gt;Well-documented functions with type hints and docstrings&lt;/li&gt;
&lt;li&gt;Properly configured testing tools (pytest and coverage reporting)&lt;/li&gt;
&lt;li&gt;A baseline coverage report showing what needs to be tested&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this foundation in place, we're ready to move on to setting up our GitHub repository and connecting CodeBeaver. This is where the magic begins – transforming our untested code into a well-tested, production-ready project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pushing a Pull Request on Github
&lt;/h3&gt;

&lt;p&gt;Before we move on to installing CodeBeaver, let's create a &lt;code&gt;.gitignore&lt;/code&gt; file to keep our repository clean. You can &lt;a href="https://github.com/github/gitignore/blob/main/Python.gitignore" rel="noopener noreferrer"&gt;copy this one from GitHub&lt;/a&gt;. Add it to the root of your proejct.&lt;/p&gt;

&lt;h3&gt;
  
  
  (Optional) Create a New Repository on GitHub
&lt;/h3&gt;

&lt;p&gt;This section applies only if you don't have a GitHub repository yet for this project. You can skip to the next chapter if you already have a repository.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into your GitHub account and click the "+" icon in the top right, then select "New repository"&lt;/li&gt;
&lt;li&gt;Name your repository "python-risk-calculator" (or another name that describes your project)&lt;/li&gt;
&lt;li&gt;Add a description like "A Python library for calculating financial risk scores"&lt;/li&gt;
&lt;li&gt;Choose "Public" if you want to use CodeBeaver's free tier for open source projects, or "Private" if you're using the trial/paid version&lt;/li&gt;
&lt;li&gt;Don't initialize with a README since we already have our local project&lt;/li&gt;
&lt;li&gt;Click "Create repository"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GitHub will show you commands to push your existing repository. Don't copy them just yet - we'll use our own sequence of commands.&lt;/p&gt;

&lt;h4&gt;
  
  
  Initialize Git and Push Your Code
&lt;/h4&gt;

&lt;p&gt;First, initialize Git in your project directory and create your initial commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Make sure you're in your project root directory&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;my_project

&lt;span class="c"&gt;# Initialize git&lt;/span&gt;
git init

&lt;span class="c"&gt;# Add all files&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Create initial commit&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat: initial project setup with risk calculator"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, connect your local repository to GitHub and push your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add the remote repository (replace with your repository URL)&lt;/span&gt;
git remote add origin https://github.com/yourusername/python-risk-calculator.git

&lt;span class="c"&gt;# Push your code to main branch&lt;/span&gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a Feature Branch
&lt;/h3&gt;

&lt;p&gt;Following Git best practices, let's create a feature branch for our risk calculator implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create and checkout a new branch&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feat/risk-calculator-implementation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we are in a feature branch, let's update our utils.py to include a new helper function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_loan_parameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loan_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loan_term_years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Validate basic loan parameters.

    Args:
        loan_amount: The requested loan amount in dollars
        loan_term_years: The loan term in years

    Raises:
        ValueError: If parameters are invalid
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;loan_amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loan amount must be positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;loan_term_years&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loan term must be between 1 and 30 years&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These changes add some functionality to our risk calculator. Let's commit the changes and push them to GitHub!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Commit the changes&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat: add risk calculator implementation"&lt;/span&gt;

&lt;span class="c"&gt;# Push the branch to GitHub&lt;/span&gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin feat/risk-calculator-implementation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Open Your Pull Request
&lt;/h3&gt;

&lt;p&gt;Now that we have a feature branch pushed to GitHub, we can open a Pull Request. A Pull Request is, in brief, a way to propose changes to a repository.&lt;br&gt;
To open one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit your repository on GitHub&lt;/li&gt;
&lt;li&gt;You should see a banner saying "feat/risk-calculator-implementation had recent pushes" with a "Compare &amp;amp; pull request" button&lt;/li&gt;
&lt;li&gt;Click the "Compare &amp;amp; pull request" button&lt;/li&gt;
&lt;li&gt;Fill in your pull request description.&lt;/li&gt;
&lt;li&gt;Click "Create pull request"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now your code is ready for CodeBeaver to analyze and generate tests! The pull request we've created follows several best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's focused on a single feature&lt;/li&gt;
&lt;li&gt;It has a clear description of what's being implemented&lt;/li&gt;
&lt;li&gt;It mentions testing expectations&lt;/li&gt;
&lt;li&gt;It's based on well-documented code (thanks to our detailed docstrings)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These practices help CodeBeaver generate more relevant and comprehensive tests for your code. In the next section, we'll see how to install CodeBeaver and watch it work its magic on this pull request.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing CodeBeaver
&lt;/h2&gt;

&lt;p&gt;Now that we have our Python project structured and ready, let's integrate CodeBeaver into our workflow. This integration will transform your repository from having no test coverage to maintaining comprehensive test suites automatically. The process is straightforward and takes just a few minutes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Authentication and Authorization
&lt;/h3&gt;

&lt;p&gt;First, navigate to &lt;a href="https://app.codebeaver.ai/login" rel="noopener noreferrer"&gt;codebeaver.ai&lt;/a&gt; and select "Sign up with GitHub". This initiates a secure OAuth flow that will allow CodeBeaver to interact with your repositories. If you're using GitLab or Bitbucket, you'll find similar options for those platforms.&lt;/p&gt;

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

&lt;p&gt;After authenticating, you'll be prompted to authorize CodeBeaver's access to your repositories. You'll see an installation screen that allows you to choose between personal and organizational repositories, select specific repositories or grant access to all.&lt;/p&gt;

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

&lt;p&gt;Click "Install CodeBeaver" to proceed. Don't worry about getting the permissions exactly right - you can always modify these settings later as your needs change.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Repository Selection
&lt;/h3&gt;

&lt;p&gt;Once authorized, you'll be presented with a dashboard showing your available repositories. This is where you'll select the repository we just created and enable CodeBeaver for it.&lt;/p&gt;

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

&lt;p&gt;The repository selection interface presents a clear list of your repositories, with options to search and filter if you manage many projects. Select your Python risk calculator repository to proceed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Automatic Configuration
&lt;/h3&gt;

&lt;p&gt;CodeBeaver will now analyze your repository structure to determine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The programming language(s) in use&lt;/li&gt;
&lt;li&gt;Testing frameworks present (pytest in our case)&lt;/li&gt;
&lt;li&gt;Project structure and dependencies&lt;/li&gt;
&lt;li&gt;Existing test configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on this analysis, CodeBeaver will attempt to auto-configure itself. For a standard Python project like ours that uses pytest, this process should complete successfully.&lt;/p&gt;

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

&lt;p&gt;If auto-configuration succeeds, you'll see options for how you'd like to proceed with CodeBeaver. Select the Pull Request you just opened before. You are done! CodeBeaver will start working on your Pull Request.&lt;/p&gt;
&lt;h3&gt;
  
  
  What If Auto-Configuration Fails?
&lt;/h3&gt;

&lt;p&gt;If you are using your own project, it may happen that CodeBeaver will not be able to auto-configure itself. Don't worry! This usually happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your project uses a non-standard structure&lt;/li&gt;
&lt;li&gt;You have multiple testing frameworks&lt;/li&gt;
&lt;li&gt;You need custom test commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases, you can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.codebeaver.ai/troubleshooting/auto-configuration-failed" rel="noopener noreferrer"&gt;Check the troubleshooting guide in the CodeBeaver documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;codebeaver.yml&lt;/code&gt; configuration file to your repository&lt;/li&gt;
&lt;li&gt;Contact CodeBeaver support for assistance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With CodeBeaver installed and configured, you're ready to experience automated test generation in action. In the next section, we'll create our first pull request and watch as CodeBeaver automatically generates and maintains your tests.&lt;/p&gt;
&lt;h2&gt;
  
  
  Your First Test-Driven Pull Request
&lt;/h2&gt;

&lt;p&gt;In around 5 minutes, CodeBeaver will add a comment to your Pull Request. It will look something like this:&lt;/p&gt;

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

&lt;p&gt;If you click on the Pull Request link in the comment you will go to the Pull Request opened by CodeBeaver. You will notice that it’s a Pull Request opened on top of your original Pull Request:&lt;/p&gt;

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

&lt;p&gt;To review the files, you can check out the diff in GitHub (same as any other Pull Request). Click on “Files Changed”&lt;/p&gt;

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

&lt;p&gt;You can now review the code that CodeBeaver wrote for you.&lt;/p&gt;

&lt;p&gt;Once you are ready, you can merge the Pull Request opened by CodeBeaver by clicking on the “Merge pull request”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzj84u1gaurip1jtsmi9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzj84u1gaurip1jtsmi9.png" alt="Image description" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Working with CodeBeaver: Best Practices
&lt;/h2&gt;

&lt;p&gt;Just as following PEP 8 makes your Python code more maintainable, following certain practices with CodeBeaver will help you get the most out of automated testing. Let's explore some key strategies that will help CodeBeaver generate more accurate and comprehensive tests for your Python code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Documentation is Your Testing Superpower
&lt;/h3&gt;

&lt;p&gt;Remember how helpful a well-written docstring is when you're trying to understand someone else's code? For CodeBeaver, good documentation is even more crucial. Here's why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Less helpful for CodeBeaver:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_tax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;

&lt;span class="c1"&gt;# Much better for CodeBeaver:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_tax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Calculate tax amount based on a given rate.

    Args:
        amount: Base amount in dollars (must be positive)
        rate: Tax rate as decimal (e.g., 0.07 for 7%)

    Returns:
        float: Calculated tax amount

    Examples:
&lt;/span&gt;&lt;span class="gp"&gt;        &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;calculate_tax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="mf"&gt;7.0&lt;/span&gt;

&lt;span class="s"&gt;    Raises:
        ValueError: If amount is negative or rate is not between 0 and 1
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Amount must be positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rate must be between 0 and 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second version gives CodeBeaver crucial information about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expected input types and ranges&lt;/li&gt;
&lt;li&gt;Example usage and expected outputs&lt;/li&gt;
&lt;li&gt;Error conditions that should be tested&lt;/li&gt;
&lt;li&gt;Business rules (like valid ranges for tax rates)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Leveraging Real-World Data in Tests
&lt;/h3&gt;

&lt;p&gt;When you have access to real-world data that represents actual use cases, you can help CodeBeaver generate more realistic tests. There are two effective ways to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Include examples in your docstrings:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_user_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Validate user registration data.

    Args:
        age: User&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s age in years
        email: User&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s email address

    Example Data:
        Valid cases:
        - age=25, email=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;
        - age=18, email=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;student.2024@university.edu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;

        Invalid cases:
        - age=12, email=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tooyoung@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  # Age below minimum
        - age=25, email=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not-an-email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  # Invalid email format
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a separate test data file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tests/test_data/sample_users.py
&lt;/span&gt;&lt;span class="n"&gt;SAMPLE_USERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected_valid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invalid@test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected_valid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Managing the Testing Workflow
&lt;/h3&gt;

&lt;p&gt;Think of CodeBeaver as a meticulous code reviewer who specializes in testing. Here's how to make the most of this collaboration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Review Generated Tests First
Before merging your feature PR, always review and merge CodeBeaver's test PR first. This ensures that:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Your code is thoroughly tested before reaching production&lt;/li&gt;
&lt;li&gt;You can catch any misunderstandings about the intended behavior&lt;/li&gt;
&lt;li&gt;You might discover edge cases you hadn't considered&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Iterative Testing
If CodeBeaver's initial tests reveal gaps or misunderstandings:

&lt;ul&gt;
&lt;li&gt;Update your docstrings to clarify the expected behavior&lt;/li&gt;
&lt;li&gt;Add more examples or edge cases to the documentation&lt;/li&gt;
&lt;li&gt;Push these changes and let CodeBeaver generate updated tests&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Special Considerations for Large Codebases
&lt;/h3&gt;

&lt;p&gt;When installing CodeBeaver in an existing large Python project, consider this gradual approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with New Code&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Initially configure CodeBeaver to focus on new PRs and modified files&lt;/li&gt;
&lt;li&gt;This prevents overwhelming reviews with massive test PRs&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Incremental Coverage&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Gradually expand coverage by adding tests for existing code&lt;/li&gt;
&lt;li&gt;Focus on critical paths and high-risk areas first&lt;/li&gt;
&lt;li&gt;Use CodeBeaver's file-specific testing feature for targeted improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Documentation Updates

&lt;ul&gt;
&lt;li&gt;Systematically improve docstrings in existing code&lt;/li&gt;
&lt;li&gt;Prioritize modules that will need tests soon&lt;/li&gt;
&lt;li&gt;Include real-world examples from your production system&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember: Just as you wouldn't push to production without reviewing your code, always review CodeBeaver's generated tests. They're not just a safety net – they're documentation of your code's intended behavior and edge cases.&lt;/p&gt;

&lt;p&gt;By following these practices, you'll create a virtuous cycle: better documentation leads to better tests, which lead to more reliable code, which makes future development faster and safer. It's like compound interest for your codebase's quality!&lt;/p&gt;

&lt;h3&gt;
  
  
  Looking Forward
&lt;/h3&gt;

&lt;p&gt;As your test suite grows, consider setting up test coverage goals in your &lt;code&gt;pytest.ini&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[pytest]&lt;/span&gt;
&lt;span class="py"&gt;addopts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="py"&gt;--cov&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;src/my_project&lt;/span&gt;
    &lt;span class="py"&gt;--cov-report&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;term-missing&lt;/span&gt;
    &lt;span class="py"&gt;--cov-fail-under&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;90  # Gradually increase this as coverage improves&lt;/span&gt;
&lt;span class="py"&gt;markers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="err"&gt;api:&lt;/span&gt; &lt;span class="err"&gt;marks&lt;/span&gt; &lt;span class="err"&gt;tests&lt;/span&gt; &lt;span class="err"&gt;that&lt;/span&gt; &lt;span class="err"&gt;require&lt;/span&gt; &lt;span class="err"&gt;API&lt;/span&gt; &lt;span class="err"&gt;access&lt;/span&gt;
    &lt;span class="err"&gt;integration:&lt;/span&gt; &lt;span class="err"&gt;marks&lt;/span&gt; &lt;span class="err"&gt;integration&lt;/span&gt; &lt;span class="err"&gt;tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives your team clear targets while letting CodeBeaver help you reach them systematically and efficiently.&lt;/p&gt;

&lt;p&gt;Remember: The goal isn't just to have tests – it's to have meaningful tests that catch real issues and document your code's behavior. With these practices and CodeBeaver's help, you're well on your way to achieving both!&lt;/p&gt;

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

&lt;p&gt;Congratulations! You've just transformed your Python project from "we'll add tests someday" to "fully tested and ready for production." Just as virtual environments revolutionized Python development by making dependency management painless, CodeBeaver is changing how we approach testing by making it automatic and maintainable.&lt;/p&gt;

&lt;p&gt;Throughout this tutorial, we've seen how combining good Python practices with AI-powered testing can create a robust development workflow. We started with a basic Python project structure, added proper documentation, and let CodeBeaver handle the heavy lifting of test creation and maintenance. The result? A testing pipeline that catches bugs before they reach production, without requiring you to become a testing expert overnight.&lt;/p&gt;

&lt;p&gt;The real power here isn't just in having tests – it's in having a sustainable, scalable way to maintain test coverage as your codebase grows. Just as Git tracks your code changes, CodeBeaver now tracks your testing needs, automatically updating and expanding your test suite with each pull request.&lt;/p&gt;

&lt;p&gt;Want to explore more automated testing approaches? Check out our React testing tutorial, which shows how to set up a similar pipeline for frontend development. Whether you're working with Python, JavaScript, or both, CodeBeaver has you covered.&lt;/p&gt;

&lt;p&gt;Remember: Good tests aren't just a safety net – they're documentation, quality control, and peace of mind all rolled into one. With CodeBeaver watching your back, you can focus on what you do best: building great software.&lt;/p&gt;

&lt;p&gt;Happy coding, and may all your tests be green! 🚀&lt;/p&gt;

</description>
      <category>python</category>
      <category>unittest</category>
      <category>testing</category>
      <category>github</category>
    </item>
    <item>
      <title>Setting up your first frontend Unit Tests workflow with GitHub + React + CodeBeaver</title>
      <dc:creator>Vittorio Banfi</dc:creator>
      <pubDate>Wed, 12 Feb 2025 07:57:33 +0000</pubDate>
      <link>https://dev.to/vittorio_banfi_6d141586d5/setting-up-your-first-frontend-unit-tests-workflow-with-github-react-codebeaver-5faa</link>
      <guid>https://dev.to/vittorio_banfi_6d141586d5/setting-up-your-first-frontend-unit-tests-workflow-with-github-react-codebeaver-5faa</guid>
      <description>&lt;p&gt;Let’s face it – unit testing in frontend development often feels like trying to nail jelly to a wall. Many frontend developers have traditionally focused on crafting pixel-perfect UIs and smooth user experiences, leaving testing as that thing we’ll “definitely get to next sprint” 😅&lt;/p&gt;

&lt;p&gt;But here’s the truth: solid unit testing isn’t just a nice-to-have anymore – it’s becoming as essential as that morning coffee ritual that powers our debugging sessions. In this tutorial, we’re going to transform your React project from “yeah, we should probably write tests someday” to having a professional, automated testing workflow that would make your backend colleagues jealous. To do so we will use CodeBeaver, the AI agent for Unit Tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Before we dive into the technical setup, let’s address the elephant in the room: frontend testing has historically been… complicated. Between component lifecycles, state management, and asynchronous operations, there’s a lot to consider. But that’s exactly why having automated tools like CodeBeaver in your arsenal is a game-changer.&lt;/p&gt;

&lt;p&gt;On average, engineering teams save 30 minutes per developer per day thanks to CodeBeaver. That’s not just coffee-break time – that’s significant bandwidth you can redirect toward building features that actually matter to your users.&lt;/p&gt;

&lt;h3&gt;
  
  
  What We’ll Build
&lt;/h3&gt;

&lt;p&gt;We’re setting up a complete unit testing workflow that will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically run tests on every pull request&lt;/li&gt;
&lt;li&gt;Generate missing tests to maintain 90% coverage&lt;/li&gt;
&lt;li&gt;Help identify and fix bugs before they hit production&lt;/li&gt;
&lt;li&gt;Integrate seamlessly with your GitHub workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best part? Once we set this up, it practically runs itself. No more “I forgot to write tests” commits at 4:59 PM on a Friday.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before we start, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub account&lt;/li&gt;
&lt;li&gt;Basic familiarity with git commands&lt;/li&gt;
&lt;li&gt;Node.js installed on your machine&lt;/li&gt;
&lt;li&gt;A desire to write better code (check ✅)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What’s Coming Up
&lt;/h3&gt;

&lt;p&gt;In the following sections, we’ll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up your repository with the right testing infrastructure&lt;/li&gt;
&lt;li&gt;Configure CodeBeaver to automate your testing workflow&lt;/li&gt;
&lt;li&gt;Create your first test-driven PR&lt;/li&gt;
&lt;li&gt;Review and merge automatically generated tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of this as your “testing zero to hero” journey. By the end, you’ll have a professional-grade testing setup that makes maintaining test coverage as natural as running npm start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your React (or NextJS) project for testing
&lt;/h2&gt;

&lt;p&gt;Alright, fellow code wranglers, let’s set up our repository to be test-friendly. Think of this as Marie Kondo-ing your codebase, but instead of asking “does it spark joy?” we’re asking “will this make our tests cry?” 😅&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Your GitHub Repository
&lt;/h3&gt;

&lt;p&gt;If you’re starting from scratch, head over to GitHub and create a new repository. Here’s the TL;DR version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click that shiny “New repository” button&lt;/li&gt;
&lt;li&gt;Name it something clever (but professional – sorry, definitely-not-another-todo-app will have to wait)&lt;/li&gt;
&lt;li&gt;Initialize with a README because we’re not savages&lt;/li&gt;
&lt;li&gt;Choose the Node .gitignore template – trust me, your node_modules folder thanks you&lt;/li&gt;
&lt;li&gt;Setting Up Your Package.json for Testing Glory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Time to beef up your package.json with some testing superpowers. Here’s a complete package.json as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-awesome-project"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test:coverage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --coverage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"testEnvironment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jsdom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"setupFilesAfterEnv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/src/setupTests.ts"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleNameMapper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"\\.(css|less|scss|sass)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"identity-obj-proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"^@/(.*)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/src/$1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"collectCoverageFrom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.{js,jsx,ts,tsx}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"!src/**/*.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"!src/index.tsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"!src/reportWebVitals.ts"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"coverageThreshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"global"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"branches"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"functions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"lines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"statements"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@testing-library/jest-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5.16.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@testing-library/react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^13.4.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@testing-library/user-event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^14.4.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^29.3.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jest-environment-jsdom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^29.3.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"identity-obj-proxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.0.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have a project, your package.json may look a lot different, and you may need to update it. To make updating easier, let’s break down the important sections of the JSON above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test:coverage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --coverage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is important as it declares how to test your code. As you see, for this tutorial we are using Jest.&lt;/p&gt;

&lt;p&gt;After that, you can find some Jest own settings. You can remove them or not have them altogether, but they are useful in setting up how you want Jest to test your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"testEnvironment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jsdom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"setupFilesAfterEnv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/src/setupTests.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleNameMapper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"\\.(css|less|scss|sass)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"identity-obj-proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"^@/(.*)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/src/$1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"collectCoverageFrom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.{js,jsx,ts,tsx}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"!src/**/*.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"!src/index.tsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"coverageThreshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"global"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"branches"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"functions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"lines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"statements"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Woha this a lot! Let’s break down this Jest configuration like we’re reviewing a PR at 4:55 PM on a Friday (but with actual attention to detail 😉).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"testEnvironment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jsdom"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First up, we’re telling Jest to use jsdom – think of it as a browser simulator for your Node environment. Without this, your DOM-related tests would throw more tantrums than a project manager during sprint planning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"setupFilesAfterEnv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/src/setupTests.ts"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where you put your test setup code that runs before your test suite kicks off. Perfect for importing @testing-library/jest-dom and setting up those sweet custom matchers. It’s like the pre-workout routine for your tests! 💪&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"moduleNameMapper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"\\.(css|less|scss|sass)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"identity-obj-proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"^@/(.*)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/src/$1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s where we handle those pesky imports that Jest would otherwise get stuck on:&lt;/p&gt;

&lt;p&gt;The first line handles your style imports (because let’s face it, Jest doesn’t care about your CSS-in-JS prowess)&lt;br&gt;
The second line maps your fancy @/components absolute imports to their actual locations. No more ../../../ nonsense!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"collectCoverageFrom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.{js,jsx,ts,tsx}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"!src/**/*.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"!src/index.tsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Jest which files to include in coverage reports. Notice those ! patterns? That’s us saying “hey, let’s not waste time testing TypeScript declaration files and boilerplate code.” Because life’s too short to test index.tsx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"coverageThreshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"global"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"branches"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"functions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"statements"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The money maker! 🎯 This sets the bar at 80% coverage across all metrics. It’s like setting a high score for your codebase – miss these thresholds, and your CI pipeline will give you the same look your tech lead gives you when you push directly to main.&lt;/p&gt;

&lt;p&gt;In essence, this configuration turns Jest from a simple test runner into a sophisticated testing powerhouse that would make even your backend colleagues nod in approval. And with CodeBeaver watching your back, maintaining these coverage thresholds becomes less of a chore and more of an automated victory lap! 🏃‍♂️🏆&lt;/p&gt;

&lt;h3&gt;
  
  
  File Structure
&lt;/h3&gt;

&lt;p&gt;There are a lot of ways of organizing your test files, depending on the language and framework in which you are writing your code. In this case, since we are writing a Typescript and React project, my folder structure will be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── components/
│   ├── Button/
│   │   ├── Button.tsx
│   │   ├── Button.test.tsx
│   │   └── index.ts
│   └── Dropdown/
│       ├── Dropdown.tsx
│       ├── Dropdown.test.tsx
│       └── index.ts
├── utils/
│   ├── formatters.ts
│   └── formatters.test.ts
└── setupTests.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, I’m keeping my test files right next to their implementation. It’s like keeping your coffee cup next to your keyboard – it just makes sense!&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding some components (Optional)
&lt;/h3&gt;

&lt;p&gt;Note: Do this step only if you are starting from an empty project!&lt;/p&gt;

&lt;p&gt;Let’s add a main page and some components to get it started. &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai/tree/react-typescript-components" rel="noopener noreferrer"&gt;I open-sourced a repository to get you started&lt;/a&gt;. My suggestion is to copy/paste some files into your project. It’s a great way to gain familiarity with the structure above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Button.tsx in src/components/Button&lt;/li&gt;
&lt;li&gt;Add Button.test.tsx in src/components/Button&lt;/li&gt;
&lt;li&gt;Add Dropdown.tsx in src/componenets/Dropdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can of course check how I set up my repository &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai/pull/19/files" rel="noopener noreferrer"&gt;here on this Pull Request&lt;/a&gt;. Feel free to copy any file to your project!&lt;/p&gt;

&lt;h3&gt;
  
  
  The GitHub PR Template (Optional)
&lt;/h3&gt;

&lt;p&gt;You don’t actually need this, but it’s super useful. It adds a template to the Pull Request, so that every time you add a new Pull Request, its description will start from the template itself. This way, all of your Pull Request’s descriptions will contain a similar structure.&lt;/p&gt;

&lt;p&gt;To add the template, open your text editor and add a file at this path: .github/pull_request_template.md&lt;/p&gt;

&lt;p&gt;You can now add any markdown, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## 🎯 What does this PR do?

&amp;lt;!-- Quick bullet points about the changes --&amp;gt;

## 🧪 Testing Instructions

&amp;lt;!-- How can reviewers test your changes? --&amp;gt;

## 📸 Screenshots (if applicable)

&amp;lt;!-- Drop some visual goodness here --&amp;gt;

## ✅ Checklist

- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] CodeBeaver checks passed
- [ ] No coffee was harmed in the making of this PR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more info, &lt;a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository" rel="noopener noreferrer"&gt;check out the GitHub documentation on this topic&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monorepo or subfolder examples (optional)
&lt;/h3&gt;

&lt;p&gt;If your project is a monorepo, or if your React project is not on the root, you will also need a codebeaver.yml configuration file. For example, let’s say that your repository has the react project in projects/react.&lt;/p&gt;

&lt;p&gt;You will add a new file in the root of your repository called codebeaver.yml. It’s a YAML file that tells CodeBeaver where your React project is. This will work also with NextJS. This is how it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workspaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;projects/react&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to replace projects/react with the path of your React project relative to the root of your repository. You can check the full documentation on the codebeaver.yml file if you want more information about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Final Boss: Push to Main
&lt;/h3&gt;

&lt;p&gt;Now that we have everything, time to commit these changes to main:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: add testing infrastructure (and hopes and dreams) 🚀"&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it! Your repository is now ready to embrace tests like a Java developer embraces design patterns. In the next section, we’ll connect CodeBeaver and watch it work its magic.&lt;/p&gt;

&lt;p&gt;Remember: The best code is tested code, and the second-best code is the one that passes the tests we forgot to write. But with CodeBeaver, we won’t have to worry about the latter! 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing CodeBeaver: Where the Magic Gets Real 🪄
&lt;/h2&gt;

&lt;p&gt;Alright, let’s get CodeBeaver installed and running. This is where your repository transforms from “tests? what tests?” to “look at my beautiful test coverage” in less time than it takes to explain why we need semantic versioning to product managers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: The Grand Login 🔐
&lt;/h3&gt;

&lt;p&gt;Head over &lt;a href="https://app.codebeaver.ai/login" rel="noopener noreferrer"&gt;to the login page codebeaver.ai&lt;/a&gt; and look for those magical words: “Sign up with GitHub”. Click that faster than you click “Mark All as Read” in your work email. You can also use CodeBeaver with GitLab or Bitbucket!&lt;/p&gt;

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

&lt;p&gt;Great! Now CodeBeaver needs to access your GitHub repository in order to start writing tests. You will see a screen like this:&lt;/p&gt;

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

&lt;p&gt;Click on Install CodeBeaver. You can give CodeBeaver access to the repositories of a GitHub organization you have access to, or to your personal Repositories. You can choose some repositories only or some of them. Don’t worry, you can add or remove repositories later at any time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Repository Selection 🎯
&lt;/h3&gt;

&lt;p&gt;Now you can select the Repository you want to activate CodeBeaver for. The screen will look like this (this is mine, I have a lot of repos!)&lt;/p&gt;

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

&lt;p&gt;As before, you will be able to change this selection later, so don’t worry. For the sake of this tutorial, pick the repository we created!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: CodeBeaver auto-configures itself 👽
&lt;/h3&gt;

&lt;p&gt;Once you’ve added your repository, CodeBeaver will start analyzing your codebase and see if it can auto-configure itself. If you started from a blank project or if you added a codebeaver.yml file, the autoconfiguration should run smoothly and you will be ready to go. If it did not end up configuring itself, don’t worry! Check out the last chapter to see what to do from there.&lt;/p&gt;

&lt;p&gt;Otherwise, you will see something like this:&lt;/p&gt;

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

&lt;p&gt;Pick the option you prefer to try out CodeBeaver.&lt;/p&gt;

&lt;h2&gt;
  
  
  The “It’s Working!” Moment 🎉
&lt;/h2&gt;

&lt;p&gt;Alright fellow code warriors, we’ve set up our testing infrastructure and got CodeBeaver watching our repository like a QA engineer after their fifth espresso. Now comes the fun part – let’s see this automation ballet in action!&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Your First Feature Branch 🌿
&lt;/h3&gt;

&lt;p&gt;First, let’s create a branch that would make our git history proud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create and checkout your feature branch&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feat/add-user-avatar-component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s add a simple Avatar component that we’ll intentionally leave untested (don’t worry, CodeBeaver’s got our back!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Avatar/Avatar.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AvatarProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;away&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AvatarProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h-8 w-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h-12 w-12&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h-16 w-16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;relative inline-block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; 
        &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; rounded-full object-cover`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; 
          &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`absolute bottom-0 right-0 h-3 w-3 rounded-full border-2 border-white
            &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-green-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; 
              &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;away&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-yellow-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-gray-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s commit this beauty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(components): add Avatar component with status indicator"&lt;/span&gt;
git push origin feat/add-user-avatar-component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Watching CodeBeaver Do Its Thing
&lt;/h3&gt;

&lt;p&gt;Head over to your GitHub repository. You will see a dialog to create a new Pull Request. Go ahead and create a Pull Request. If you added a Pull Request template, you will see that as well! Once you click on “Create Pull Request”, here’s where the magic starts happening. You will see CodeBeaver working like this in GitHub:&lt;/p&gt;

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

&lt;p&gt;CodeBeaver working on your GitHub Pull Request - Screenshot&lt;br&gt;
What will happen is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CodeBeaver will detect your new PR&lt;/li&gt;
&lt;li&gt;It’ll notice there’s no test file for our Avatar component (tsk tsk!)&lt;/li&gt;
&lt;li&gt;Start analyzing the component’s props, behavior, and edge cases&lt;/li&gt;
&lt;li&gt;Generate comprehensive tests that would make TDD purists weep with joy&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reviewing the Generated Tests 🔍
&lt;/h3&gt;

&lt;p&gt;CodeBeaver will add a comment to your Pull Request. It will look something like this:&lt;/p&gt;

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

&lt;p&gt;If you click on the Pull Request link in the comment you will go to the Pull Request opened by CodeBeaver. You will notice that it’s a Pull Request opened on top of your original Pull Request:&lt;/p&gt;

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

&lt;p&gt;To review the files, you can check out the diff in GitHub (same as any other Pull Request). Click on “Files Changed”&lt;/p&gt;

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

&lt;p&gt;You can now review the code that CodeBeaver wrote for you.&lt;/p&gt;

&lt;p&gt;Once you are ready, you can merge the Pull Request opened by CodeBeaver by clicking on the “Merge pull request”&lt;/p&gt;

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

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

&lt;p&gt;Well, fellow code warriors, we’ve come a long way from “we should probably write some tests” to having a fully automated testing workflow that would make even the most zealous TDD advocate nod in approval. Let’s take a victory lap and see what we’ve accomplished! 🏃‍♂️&lt;/p&gt;

&lt;h3&gt;
  
  
  What We Built Together 🏗️
&lt;/h3&gt;

&lt;p&gt;We didn’t just set up tests – we established a complete testing ecosystem that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transforms your React codebase from test-optional to test-mandatory (in the best possible way)&lt;/li&gt;
&lt;li&gt;Automates the tedious parts of testing (because life’s too short to write edge cases at 4:59 PM)&lt;/li&gt;
&lt;li&gt;Integrates seamlessly with your GitHub workflow (like a well-configured git hooks, but actually useful)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Real MVP: Your Future Self 🦸‍♂️
&lt;/h3&gt;

&lt;p&gt;Remember that feeling of dread when you had to modify a component and all its tests started failing faster than a junior dev’s first production deploy? Well, those days are now officially in your git history. With CodeBeaver watching your back:&lt;/p&gt;

&lt;p&gt;Your tests evolve with your code (no more “it worked on my machine” moments)&lt;br&gt;
Coverage stays high without manual intervention (like your coffee intake, but automated)&lt;br&gt;
Bugs get caught before they can make it to production (and before your PM can schedule an emergency meeting)&lt;/p&gt;

&lt;h3&gt;
  
  
  The Path Forward 🛣️
&lt;/h3&gt;

&lt;p&gt;Remember: CodeBeaver isn’t just a test writer – it’s your partner in maintaining code quality. When tests fail, it’ll help you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify if it’s a bug in your new code (before your code reviewer does). &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai/pull/8" rel="noopener noreferrer"&gt;Check out an example here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Determine if existing tests need updates (because your awesome new feature changed the game). &lt;a href="https://github.com/codebeaver-ai/codebeaver-ai/pull/17" rel="noopener noreferrer"&gt;Check out an example here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Maintain that sweet, sweet test coverage without breaking a sweat&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Bottom Line 💯
&lt;/h3&gt;

&lt;p&gt;We’ve transformed your React project from “tests are optional” to “tests are automatic” – and did it without sacrificing your development velocity or your sanity. That’s not just a win; that’s a paradigm shift in how we approach frontend testing.&lt;/p&gt;

&lt;p&gt;Remember: The best code isn’t just the code that works – it’s the code that proves it works through comprehensive tests. And now, thanks to CodeBeaver, you can have both without doubling your coffee budget! ☕&lt;/p&gt;

&lt;p&gt;Happy coding, and may your tests be ever green! 🚀&lt;/p&gt;

&lt;p&gt;P.S. If your team starts wondering how you became a testing guru overnight, just wink and let them think it’s all those extra hours you’ve been putting in (instead of CodeBeaver doing the heavy lifting) 😉&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>[I just published a complete tutorial on how to set up your first frontend Unit Testing workflow! ](https://www.codebeaver.ai/blog/tutorials/frontend-unit-tests-with-github-react-codebeaver/)</title>
      <dc:creator>Vittorio Banfi</dc:creator>
      <pubDate>Wed, 12 Feb 2025 07:31:56 +0000</pubDate>
      <link>https://dev.to/vittorio_banfi_6d141586d5/i-just-published-a-complete-tutorial-on-how-to-set-up-your-first-frontend-unit-testing-workflow-314k</link>
      <guid>https://dev.to/vittorio_banfi_6d141586d5/i-just-published-a-complete-tutorial-on-how-to-set-up-your-first-frontend-unit-testing-workflow-314k</guid>
      <description></description>
    </item>
    <item>
      <title>Unit Testing Without Tears: How CodeBeaver Turned Testing from 'pytest run pain' to 'git push joy' 🚀</title>
      <dc:creator>Vittorio Banfi</dc:creator>
      <pubDate>Mon, 10 Feb 2025 10:17:52 +0000</pubDate>
      <link>https://dev.to/vittorio_banfi_6d141586d5/unit-testing-without-tears-how-codebeaver-turned-testing-from-pytest-run-pain-to-git-push-joy-3nd4</link>
      <guid>https://dev.to/vittorio_banfi_6d141586d5/unit-testing-without-tears-how-codebeaver-turned-testing-from-pytest-run-pain-to-git-push-joy-3nd4</guid>
      <description>&lt;p&gt;Let's face it, fellow devs - we'd rather debug a production outage at 3 AM than write unit tests. Okay, maybe not &lt;em&gt;that&lt;/em&gt; extreme, but you get the point! 😅 Today, I'm going to share how the folks at &lt;a href="https://github.com/ScrapeGraphAI/Scrapegraph-ai" rel="noopener noreferrer"&gt;ScrapegraphAI&lt;/a&gt; (18k stars!) solved their testing woes with a solution so smooth, it's like they found a cheat code for the matrix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Testing Struggle is Real™
&lt;/h2&gt;

&lt;p&gt;Meet &lt;a href="https://scrapegraphai.com/" rel="noopener noreferrer"&gt;ScrapegraphAI&lt;/a&gt; - the absolute wizards who created a tool that turns web pages into structured data faster than you can say "DOM manipulation." With 17k+ GitHub stars (flex much? 💪), they're kind of a big deal. But they faced the classic open-source dilemma: how do you keep your code base stable without becoming the testing police?&lt;/p&gt;

&lt;p&gt;You know the drill - contributors show up with amazing features, but unit tests? &lt;em&gt;crickets chirping&lt;/em&gt; 🦗&lt;/p&gt;

&lt;p&gt;Let's be honest, writing tests for LLM integrations is about as fun as explaining to your PM why "it works on my machine" isn't a valid deployment strategy. The usual workflow looks something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write test&lt;/li&gt;
&lt;li&gt;Run test&lt;/li&gt;
&lt;li&gt;Question life choices&lt;/li&gt;
&lt;li&gt;Repeat until caffeine runs out&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Enter CodeBeaver: The Testing Hero We Didn't Know We Needed
&lt;/h2&gt;

&lt;p&gt;Picture this: You push your code, and automagically, unit tests appear like pizza at a hackathon. Sounds too good to be true? That's what the ScrapegraphAI team thought until they gave CodeBeaver a shot.&lt;/p&gt;

&lt;p&gt;Here's the secret sauce of how it works (no actual beavers were involved):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You open a PR (and maybe grab a coffee ☕)&lt;/li&gt;
&lt;li&gt;CodeBeaver analyzes your code like that one colleague who actually reads the documentation&lt;/li&gt;
&lt;li&gt;It mocks your LLM calls because nobody wants to pay OpenAI's bills for running tests&lt;/li&gt;
&lt;li&gt;If tests fail, CodeBeaver's like "Is it you? Is it me? Let's figure this out" and fixes itself&lt;/li&gt;
&lt;li&gt;Commits only the good stuff, neat and tidy&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One PR went from "trust me bro, it works" to 90.7% test coverage faster than you can say "dependency conflict." 🎯&lt;br&gt;
&lt;a href="https://github.com/ScrapeGraphAI/Scrapegraph-ai/pull/908" rel="noopener noreferrer"&gt;Check out an example PR here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should You Care? (Besides the Obvious Time-Saving Magic)
&lt;/h2&gt;

&lt;p&gt;Because let's be real - we all want to write good code, but nobody wakes up thinking "YES! Today I get to write mock functions!" With CodeBeaver, you can have your cake and test it too. The ScrapegraphAI team now spends more time building cool features and less time playing "guess what this function does."&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to Level Up Your Testing Game?
&lt;/h2&gt;

&lt;p&gt;If you're running an open-source project, &lt;a href="https://www.codebeaver.ai" rel="noopener noreferrer"&gt;CodeBeaver&lt;/a&gt; is FREE (yes, FREE as in "free pizza at tech meetups" free). For private repos, it's $12/month per dev - probably less than your monthly coffee budget.&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://www.codebeaver.ai" rel="noopener noreferrer"&gt;codebeaver.ai&lt;/a&gt; and say goodbye to the days of "I'll write the tests later" (narrator: they never did).&lt;/p&gt;

&lt;p&gt;Remember: Life's too short for manual testing. Let the beaver do the heavy lifting! 🦫✨&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>tooling</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
