Automating Unit Tests with AI: Let the Vibes Handle QA
Automating Unit Tests with AI: Let the Vibes Handle QA
Writing tests is important but tedious. It's the vegetables of software development—you know you should do it, but it's not fun.
With AI-powered Vibe Coding, you can generate comprehensive test suites in minutes instead of hours.
Why AI-Generated Tests Matter
The Traditional Problem
* Writing tests takes 2-3x longer than writing the actual code
* Developers skip tests when under deadline pressure
* Test coverage suffers
* Bugs slip into production
The AI Solution
* Generate tests as fast as you generate code
* Achieve high test coverage effortlessly
* Catch bugs before they reach production
* Refactor with confidence
What We'll Cover
1. Generating unit tests for functions
2. Generating integration tests for APIs
3. Generating E2E tests for user flows
4. Best practices for AI-generated tests
Step 1: Set Up Your Testing Framework
For JavaScript/TypeScript Projects
Install Vitest (modern, fast alternative to Jest):
“`bash
npm install -D vitest @vitest/ui
“`
Update `package.json`:
“`json
{
“scripts”: {
“test”: “vitest”,
“test:ui”: “vitest –ui”
}
}
“`
For Python Projects
Install pytest:
“`bash
pip install pytest pytest-cov
“`
Step 2: Generate Tests for a Simple Function
Example Function (`utils/math.js`)
“`javascript
export function calculateDiscount(price, discountPercent) {
if (price < 0 || discountPercent < 0 || discountPercent > 100) {
throw new Error(‘Invalid input');
}
return price * (1 – discountPercent / 100);
}
“`
Prompt to Cursor
Highlight the function and press `Cmd+L`:
> “Generate comprehensive unit tests for this function using Vitest. Cover:
> – Normal cases
> – Edge cases (0%, 100% discount)
> – Error cases (negative values, invalid percentages)
> – Boundary conditions”
Generated Test (`utils/math.test.js`)
“`javascript
import { describe, it, expect } from ‘vitest';
import { calculateDiscount } from ‘./math';
describe(‘calculateDiscount', () => {
it(‘should calculate discount correctly for normal values', () => {
expect(calculateDiscount(100, 20)).toBe(80);
expect(calculateDiscount(50, 10)).toBe(45);
});
it(‘should handle 0% discount', () => {
expect(calculateDiscount(100, 0)).toBe(100);
});
it(‘should handle 100% discount', () => {
expect(calculateDiscount(100, 100)).toBe(0);
});
it(‘should throw error for negative price', () => {
expect(() => calculateDiscount(-10, 20)).toThrow(‘Invalid input');
});
it(‘should throw error for negative discount', () => {
expect(() => calculateDiscount(100, -5)).toThrow(‘Invalid input');
});
it(‘should throw error for discount > 100', () => {
expect(() => calculateDiscount(100, 150)).toThrow(‘Invalid input');
});
it(‘should handle decimal values', () => {
expect(calculateDiscount(99.99, 15)).toBeCloseTo(84.99, 2);
});
});
“`
Step 3: Generate Tests for React Components
Example Component (`Button.jsx`)
“`jsx
export function Button({ onClick, disabled, children }) {
return (
);
}
“`
Prompt to Cursor
> “Generate tests for this React component using Vitest and React Testing Library. Test:
> – Rendering with different props
> – Click events
> – Disabled state
> – Accessibility”
Generated Test
“`javascript
import { render, screen, fireEvent } from ‘@testing-library/react';
import { describe, it, expect, vi } from ‘vitest';
import { Button } from ‘./Button';
describe(‘Button', () => {
it(‘renders children correctly', () => {
render();
expect(screen.getByText(‘Click me')).toBeInTheDocument();
});
it(‘calls onClick when clicked', () => {
const handleClick = vi.fn();
render();
fireEvent.click(screen.getByText(‘Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it(‘does not call onClick when disabled', () => {
const handleClick = vi.fn();
render();
fireEvent.click(screen.getByText(‘Click me'));
expect(handleClick).not.toHaveBeenCalled();
});
it(‘has correct accessibility attributes when disabled', () => {
render();
expect(screen.getByRole(‘button')).toBeDisabled();
});
});
“`
Step 4: Generate API Integration Tests
Example API Route (`api/users.js`)
“`javascript
export async function GET(req) {
const users = await db.query(‘SELECT * FROM users');
return Response.json(users);
}
export async function POST(req) {
const { name, email } = await req.json();
const user = await db.query(
‘INSERT INTO users (name, email) VALUES (?, ?) RETURNING *',
[name, email]
);
return Response.json(user, { status: 201 });
}
“`
Prompt to Cursor
> “Generate integration tests for these API routes. Mock the database. Test:
> – Successful GET request
> – Successful POST request
> – POST with missing fields
> – Database errors”
Generated Test
“`javascript
import { describe, it, expect, vi, beforeEach } from ‘vitest';
import { GET, POST } from ‘./users';
vi.mock(‘../db', () => ({
db: {
query: vi.fn()
}
}));
describe(‘Users API', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe(‘GET /api/users', () => {
it(‘returns all users', async () => {
const mockUsers = [
{ id: 1, name: ‘Alice', email: ‘[email protected]' },
{ id: 2, name: ‘Bob', email: ‘[email protected]' }
];
db.query.mockResolvedValue(mockUsers);
const response = await GET();
const data = await response.json();
expect(data).toEqual(mockUsers);
});
});
describe(‘POST /api/users', () => {
it(‘creates a new user', async () => {
const newUser = { name: ‘Charlie', email: ‘[email protected]' };
const createdUser = { id: 3, …newUser };
db.query.mockResolvedValue(createdUser);
const req = new Request(‘http://localhost/api/users', {
method: ‘POST',
body: JSON.stringify(newUser)
});
const response = await POST(req);
const data = await response.json();
expect(response.status).toBe(201);
expect(data).toEqual(createdUser);
});
});
});
“`
Step 5: Generate E2E Tests
Prompt to Cursor
> “Generate Playwright E2E tests for the user signup flow:
> 1. Navigate to /signup
> 2. Fill in name, email, password
> 3. Click submit
> 4. Verify redirect to /dashboard
> 5. Verify welcome message appears”
Generated Test (`e2e/signup.spec.js`)
“`javascript
import { test, expect } from ‘@playwright/test';
test.describe(‘User Signup Flow', () => {
test(‘should allow a new user to sign up', async ({ page }) => {
await page.goto(‘/signup');
await page.fill(‘input[name=”name”]', ‘Test User');
await page.fill(‘input[name=”email”]', ‘[email protected]');
await page.fill(‘input[name=”password”]', ‘SecurePass123');
await page.click(‘button[type=”submit”]');
await expect(page).toHaveURL(‘/dashboard');
await expect(page.locator(‘h1')).toContainText(‘Welcome, Test User');
});
test(‘should show error for invalid email', async ({ page }) => {
await page.goto(‘/signup');
await page.fill(‘input[name=”email”]', ‘invalid-email');
await page.click(‘button[type=”submit”]');
await expect(page.locator(‘.error')).toContainText(‘Invalid email');
});
});
“`
Step 6: Achieve High Test Coverage
Check Coverage
“`bash
npm run test — –coverage
“`
Prompt for Missing Tests
> “Analyze the coverage report. Generate tests for any uncovered code paths in the `auth` module.”
Best Practices for AI-Generated Tests
1. Review Generated Tests
Don't blindly accept. Make sure tests actually test the right things.
2. Add Descriptive Test Names
Bad: `it(‘works', …)`
Good: `it(‘should calculate discount correctly for normal values', …)`
3. Test Behavior, Not Implementation
Focus on what the code does, not how it does it.
4. Use Mocks Wisely
Mock external dependencies (APIs, databases) but don't over-mock.
5. Keep Tests Fast
Unit tests should run in milliseconds. If they're slow, you won't run them often.
Conclusion
AI-generated tests aren't perfect, but they're a massive productivity boost. You can achieve 80% test coverage in the time it used to take to write 20%.
At BYS Marketing, we use AI to generate test suites for all our projects. This allows us to ship faster while maintaining high quality.
—
Need help with test automation?
Contact BYS Marketing. We'll set up comprehensive testing for your codebase.
🚀 Elevate Your Business with BYS Marketing
From AI Coding to Media Production, we deliver excellence.
Contact Us: Get a Quote Today