| name | automated-test-writer |
| description | Generates executable test code in Pytest, Jest, Playwright, or Cypress from test cases. Includes setup/teardown, mocking, assertions, and error handling. Code is ready for CI/CD integration. |
| allowed-tools | Read, Write |
| effort | high |
Automated Test Writer
When to activate
After test cases are finalized and accepted. Convert test cases into executable test code for unit, integration, and end-to-end testing. Essential for regression suites and continuous integration.
When NOT to use
Not for one-off exploratory tests. Not without test cases as input. Not for manual testing workflows. Not without understanding of the target test framework (Pytest, Jest, Playwright, Cypress).
Supported Test Frameworks
- Pytest (Python unit/integration tests)
- Jest (JavaScript/Node.js unit tests)
- Playwright (Browser automation, end-to-end tests)
- Cypress (Browser automation, end-to-end tests)
Test Code Structure
Every test function must include:
- Test Setup (Arrange): Preconditions, test data, mocking
- Test Execution (Act): User actions, API calls, state changes
- Assertions (Assert): Verify expected results
- Cleanup (Teardown): Reset state, cleanup test data
Test Code Template
Pytest (Python)
import pytest
from unittest.mock import Mock, patch
from datetime import datetime, timedelta
class TestAuthenticationModule:
"""Test suite for OAuth 2.0 authentication."""
@pytest.fixture(autouse=True)
def setup_teardown(self):
"""Setup and cleanup for each test."""
self.test_user_email = "test@example.com"
self.test_password = "SecurePassword123!"
self.valid_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
yield
pass
def test_user_login_with_valid_credentials(self):
"""TC-AUTH-001: User logs in successfully with valid email and password."""
user_data = {
"email": self.test_user_email,
"password": self.test_password
}
response = self.client.post("/auth/login", json=user_data)
assert response.status_code == 200
assert "token" response.json()
response.json()[] ==
():
invalid_user_data = {
: ,
: .test_password
}
response = .client.post(, json=invalid_user_data)
response.status_code ==
response.json()[]
response.json()
():
expired_token = ._generate_jwt_token(expires_in=timedelta(seconds=-))
headers = {: }
response = .client.get(, headers=headers)
response.status_code ==
response.json()[]
():
expires_in :
expires_in = timedelta(hours=)
payload = {
: .test_user_email,
: datetime.utcnow() + expires_in,
: datetime.utcnow()
}
jwt.encode(payload, , algorithm=)
Jest (JavaScript)
describe('Authentication Module', () => {
let client;
const testUserEmail = 'test@example.com';
const testPassword = 'SecurePassword123!';
const validToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
beforeEach(() => {
client = createTestClient(app);
jest.clearAllMocks();
});
afterEach(() => {
jest.restoreAllMocks();
});
test('TC-AUTH-001: User logs in successfully with valid email and password', async () => {
const userData = {
email: testUserEmail,
password: testPassword
};
const response = await client.post('/auth/login').send(userData);
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('token');
expect(response.body.token_type).toBe();
(response.[]).();
});
(, () => {
invalidUserData = {
: ,
: testPassword
};
response = client.().(invalidUserData);
(response.).();
(response..).();
(response.)..();
});
(, () => {
expiredToken = ({ : - });
response = client
.()
.(, );
(response.).();
(response..).();
});
});
Playwright (Browser Automation)
const { test, expect } = require('@playwright/test');
test.describe('Authentication UI', () => {
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3000/login');
});
test('TC-AUTH-001: User logs in successfully', async ({ page }) => {
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'SecurePassword123!');
await page.click('button:has-text("Sign In")');
await expect(page).toHaveURL('http://localhost:3000/dashboard');
await expect(page.locator('text=Welcome, test@example.com')).toBeVisible();
});
test('TC-AUTH-002: Login fails with invalid email', async ({ page }) => {
await page.fill('input[name="email"]', 'not-an-email');
await page.fill(, );
page.();
(page.()).();
(page).();
});
(, ({ page, context }) => {
context.([{
: ,
: ,
: ,
: .(.() / ) -
}]);
page.();
(page.()).();
});
});
Test Code Best Practices
- Test Independence: Each test must be independent. No shared state between tests.
- Clear Naming: Test names should describe the scenario (what, given, when, then).
- Single Assertion Per Test (ideally): Multiple assertions are OK if they test one behavior.
- Mocking: Mock external services (API calls, database, third-party services).
- Fixtures/Factories: Use reusable setup code for test data and preconditions.
- Explicit Assertions: Use specific assertions (not vague checks).
- Error Messages: Assertions should include helpful error messages if they fail.
- Performance: Tests should complete quickly (<5 seconds each, ideally <1 second).
Test Execution Output Format
All generated test code includes:
- Test file naming:
test_<module>.py, <module>.test.js, <module>.spec.ts
- Test class/describe: Group related tests
- Docstrings: Include test case ID and description
- Comments: Explain complex setup or assertions
- Logging: Print meaningful debug info on failures
Example Test Suite Output
File: test_authentication.py
import pytest
from app.auth import authenticate, refresh_token
from app.models import User
class TestAuthenticationModule:
"""Test suite for OAuth 2.0 authentication."""
@staticmethod
def generate_fixture_user(email="test@example.com"):
"""Factory: Create a test user in database."""
return User.create(
email=email,
password_hash=hash_password("SecurePassword123!")
)