Testing Guide¶
Testing best practices for Python, JavaScript, and shell scripts.
In This Section¶
| Document | Description |
|---|---|
| Python Testing | pytest and testing Python code |
| JavaScript Testing | Vitest, Jest, and frontend testing |
| Bash Testing | Testing shell scripts |
Testing Philosophy¶
The Testing Pyramid¶
/\
/ \
/ E2E\ Few, slow, expensive
/──────\
/ Integr-\ Some, medium speed
/ ation \
/────────────\
/ Unit \ Many, fast, cheap
/________________\
When to Write Tests¶
- Unit tests: Pure functions, business logic
- Integration tests: API endpoints, database operations
- E2E tests: Critical user flows
What Not to Test¶
- Third-party libraries
- Trivial code (getters, setters)
- Private implementation details
- Generated code
Quick Start¶
Python (pytest)¶
JavaScript (Vitest)¶
// example.test.js
import { describe, it, expect } from 'vitest'
describe('math', () => {
it('adds numbers', () => {
expect(1 + 1).toBe(2)
})
})
Bash (Bats)¶
Test Structure¶
Arrange-Act-Assert¶
def test_user_creation():
# Arrange
name = "Alice"
email = "alice@example.com"
# Act
user = create_user(name, email)
# Assert
assert user.name == name
assert user.email == email
Given-When-Then (BDD)¶
def test_user_login():
# Given a registered user
user = create_user("alice", "password123")
# When they attempt to login with correct credentials
result = login("alice", "password123")
# Then they should be authenticated
assert result.authenticated is True
Naming Conventions¶
Test Files¶
Python: test_module.py or module_test.py
JS: module.test.js or module.spec.js
Bash: test_script.bats
Test Functions¶
# Good - descriptive
def test_user_with_invalid_email_raises_error():
...
def test_calculate_discount_with_coupon_code():
...
# Bad - vague
def test_user():
...
def test_calculate():
...
Fixtures and Mocking¶
Python Fixtures¶
import pytest
@pytest.fixture
def sample_user():
return User(name="Test", email="test@example.com")
def test_user_greeting(sample_user):
assert sample_user.greet() == "Hello, Test!"
JavaScript Mocks¶
import { vi, describe, it, expect } from 'vitest'
const mockFetch = vi.fn()
global.fetch = mockFetch
describe('API', () => {
it('fetches data', async () => {
mockFetch.mockResolvedValueOnce({
json: () => Promise.resolve({ data: 'test' })
})
const result = await fetchData()
expect(result.data).toBe('test')
})
})
CI Integration¶
GitHub Actions¶
# .github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: pip install -e ".[dev]"
- name: Run tests
run: pytest --cov --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4