GitHub Copilot for Writing Tests

Writing tests is essential but time-consuming. GitHub Copilot speeds up the process dramatically — it can generate a full test suite for a function in seconds. This topic shows you how to use Copilot to write unit tests, edge case tests, and integration tests across popular testing frameworks.

Why Test Generation Is One of Copilot's Best Features

Tests follow predictable patterns. A test for a function typically includes: a description, a call to the function with specific input, and an assertion about the output. Because these patterns repeat in millions of test files, Copilot learned them very well. It can generate comprehensive test cases faster than any developer can type them.

WITHOUT COPILOT (manual test writing):
  - Think of test cases: ~10 minutes
  - Write each test by hand: ~15 minutes
  - Cover edge cases: ~10 more minutes
  Total: ~35 minutes for one function

WITH COPILOT:
  - Write one comment: 10 seconds
  - Accept and review suggestions: ~3 minutes
  - Add any missing cases: ~2 minutes
  Total: ~5 minutes for the same function

Generating Tests from a Comment

The fastest way to start: write a comment describing what you want to test, then let Copilot generate the test file.

// Tests for the shoppingCart module
// Test: addItem increases the cart length
// Test: addItem with duplicate product increases quantity
// Test: removeItem deletes the product from cart
// Test: getTotal returns sum of price * quantity
// Test: clear() resets the cart to empty

describe('ShoppingCart', () => {
→ Copilot generates all five test blocks

Right-Click to Generate Tests

The fastest method for an existing function is to highlight the function body, right-click, and select Copilot → Generate Tests. Copilot reads the function logic and creates tests that cover the expected behavior.

YOUR FUNCTION:
function divide(a, b) {
    if (b === 0) throw new Error('Division by zero');
    return a / b;
}

RIGHT-CLICK → Copilot → Generate Tests

COPILOT GENERATES:
describe('divide', () => {
    test('divides two numbers correctly', () => {
        expect(divide(10, 2)).toBe(5);
    });

    test('returns decimal result', () => {
        expect(divide(7, 2)).toBe(3.5);
    });

    test('throws error when dividing by zero', () => {
        expect(() => divide(10, 0)).toThrow('Division by zero');
    });

    test('handles negative numbers', () => {
        expect(divide(-10, 2)).toBe(-5);
    });
});

Notice that Copilot included the division-by-zero test because it saw the error condition in the function body. It tests what the code actually does — not just the happy path.

Testing Frameworks Copilot Knows

JAVASCRIPT / TYPESCRIPT:
  Jest         → most common, used by React and Node projects
  Mocha/Chai   → older projects and APIs
  Vitest       → modern Vite-based projects
  Jasmine      → Angular projects

PYTHON:
  unittest     → built-in Python module
  pytest       → most popular, cleaner syntax

JAVA:
  JUnit 5      → standard for Java projects
  TestNG       → enterprise testing

C# / .NET:
  xUnit        → modern, recommended
  MSTest       → Microsoft's built-in framework
  NUnit        → widely used alternative

GO:
  testing      → Go's built-in test package

Copilot detects which framework your project uses by looking at your package.json, requirements.txt, or existing test files. It matches the style and imports of the framework you already have set up.

Asking for Specific Test Types

You can ask Copilot to write specific categories of tests using comments or Chat.

// Write edge case tests for the parseDate function
→ Copilot: tests for null, empty string, invalid format,
           leap years, timezone edge cases

// Write tests for error handling in fetchUserData
→ Copilot: tests for 404, 500, network timeout, malformed JSON

// Write performance tests for the sortProducts function
→ Copilot: tests that measure execution time for large arrays

// Write parameterized tests for the currencyFormat function
→ Copilot: test.each() covering USD, EUR, GBP, JPY formats

Using Chat to Generate a Full Test Suite

For an entire module, Chat is more effective than inline suggestions. Paste your module code into Chat and ask for a complete test file.

YOU IN CHAT:
Here is my auth service:
[paste the file]

Write a complete Jest test file for this module.
Cover happy paths, error cases, and async behavior.

COPILOT CHAT RESPONSE:
Here is a complete test file for your auth service:

import { AuthService } from './auth.service';
import { prismaMock } from './__mocks__/prisma';

describe('AuthService', () => {
    describe('register', () => {
        it('creates a new user with hashed password', async () => { ... });
        it('throws if email already exists', async () => { ... });
        it('throws if password is too short', async () => { ... });
    });

    describe('login', () => {
        it('returns token for valid credentials', async () => { ... });
        it('throws for wrong password', async () => { ... });
        it('throws for unknown email', async () => { ... });
    });
});

Test-Driven Development with Copilot

Test-driven development (TDD) means writing tests before writing the function. Copilot supports this workflow well. Write the test cases first, and then ask Copilot to write the function that makes them pass.

STEP 1: You write the tests first
describe('slugify', () => {
    test('converts spaces to hyphens', () => {
        expect(slugify('Hello World')).toBe('hello-world');
    });
    test('removes special characters', () => {
        expect(slugify('Hello, World!')).toBe('hello-world');
    });
    test('collapses multiple spaces', () => {
        expect(slugify('Hello   World')).toBe('hello-world');
    });
});

STEP 2: Ask Copilot to implement the function
// Write the slugify function that passes the tests above
function slugify(text) {
→ Copilot:
    return text
        .toLowerCase()
        .replace(/[^\w\s-]/g, '')
        .replace(/\s+/g, '-')
        .trim();
}

Mock Generation

Copilot can generate mock objects and stubs for testing functions that depend on external services like databases or APIs.

// Mock the database module for unit testing
// User model should have: findById, create, update, delete
const mockUserModel = {
→ Copilot:
    findById: jest.fn(),
    create: jest.fn(),
    update: jest.fn(),
    delete: jest.fn(),
};

// Reset all mocks before each test
beforeEach(() => {
→ Copilot:
    jest.clearAllMocks();
});

Reading Test Coverage Gaps

After running your tests, paste the coverage report into Chat and ask Copilot to write tests for uncovered lines.

YOU IN CHAT:
My coverage report shows lines 45–52 in orders.js are uncovered.
Here is that section:
[paste lines 45–52]

Write tests that cover these lines.

→ Copilot identifies what conditions those lines require
  and writes tests that trigger them specifically.

Test writing is one of the areas where Copilot saves the most time. Developers often skip tests because writing them feels tedious after already writing the implementation. With Copilot handling the repetitive parts, test coverage becomes faster to achieve and easier to maintain.

Leave a Comment

Your email address will not be published. Required fields are marked *