@liemle3893/e2e-runner
v1.2.1
Published
E2E Test Runner - End-to-End Testing Framework for API and Database Testing
Maintainers
Readme
E2E Test Runner
A powerful, flexible end-to-end testing framework for API and database testing. Write tests in YAML or TypeScript, validate against multiple data stores, and generate comprehensive reports.
Features
- Multi-format tests: Write tests in YAML for simplicity or TypeScript for full control
- Database adapters: Built-in support for PostgreSQL, MongoDB, Redis, and Azure EventHub
- HTTP testing: Native HTTP adapter for REST API testing with JSONPath assertions
- Parallel execution: Run tests concurrently with configurable parallelism
- Multiple reporters: Console, JUnit XML, HTML, and JSON output formats
- Variable interpolation: Dynamic values with built-in functions (
${uuid()},${now()}, etc.) - Flexible filtering: Filter tests by tags, priority, or name patterns
Installation
Global Installation (recommended for CLI usage)
npm install -g @liemle3893/e2e-runnerLocal Installation (for project integration)
npm install --save-dev @liemle3893/e2e-runnerUsing npx (no installation)
npx @liemle3893/e2e-runner --help
npx @liemle3893/e2e-runner run --config ./e2e.config.yamlOptional Adapters
Install database adapters as needed:
# PostgreSQL
npm install pg
# MongoDB
npm install mongodb
# Redis
npm install ioredis
# Azure EventHub
npm install @azure/event-hubsQuick Start
1. Initialize Configuration
e2e initThis creates e2e.config.yaml in your current directory.
2. Create a Test
Create my-api.test.yaml:
name: Get Users API
description: Test the users endpoint
tags: [smoke, api]
priority: P1
execute:
- id: get-users
adapter: http
action: GET
params:
url: /api/users
assertions:
- path: $.status
operator: equals
expected: 200
- path: $.body.data
operator: isArray3. Run Tests
e2e runCLI Commands
e2e run
Execute E2E tests.
# Run all tests
e2e run
# Run with specific config
e2e run -c ./config/e2e.config.yaml
# Run tests from a specific directory
e2e run -d ./tests/integration
# Filter by tags
e2e run --tag smoke --tag regression
# Filter by priority
e2e run --priority P0 --priority P1
# Filter by name pattern
e2e run -g "user*"
# Parallel execution
e2e run -p 4
# Stop on first failure
e2e run --bail
# Dry run (show what would run)
e2e run --dry-rune2e validate
Validate test file syntax without running.
e2e validate
e2e validate -d ./testse2e list
List discovered tests.
e2e list
e2e list --tag smokee2e health
Check adapter connectivity.
e2e health
e2e health --adapter postgresqle2e init
Initialize configuration file.
e2e initCLI Options
| Option | Short | Description | Default |
|--------|-------|-------------|---------|
| --config | -c | Config file path | e2e.config.yaml |
| --env | -e | Environment name | local |
| --test-dir | -d | Test directory | . (current) |
| --report-dir | | Report output directory | ./reports |
| --verbose | -v | Verbose output | false |
| --quiet | -q | Errors only | false |
| --parallel | -p | Parallel test count | 1 |
| --timeout | -t | Timeout in ms | 30000 |
| --retries | -r | Retry count | 0 |
| --bail | | Stop on first failure | false |
| --grep | -g | Filter by name pattern | |
| --tag | | Filter by tag (repeatable) | |
| --priority | | Filter by P0/P1/P2/P3 | |
| --reporter | | Reporter type (repeatable) | console |
| --output | -o | Report output path | |
| --dry-run | | Show tests without running | false |
Environment Variables
| Variable | Description |
|----------|-------------|
| E2E_CONFIG | Config file path |
| E2E_ENV | Environment name |
| E2E_TEST_DIR | Test directory |
| E2E_REPORT_DIR | Report output directory |
| E2E_VERBOSE | Enable verbose output (1 or true) |
| NO_COLOR | Disable colored output (1 or true) |
Configuration File
version: "1.0"
environments:
local:
baseUrl: "http://localhost:3000"
adapters:
postgresql:
connectionString: "${POSTGRESQL_CONNECTION_STRING}"
mongodb:
connectionString: "${MONGODB_CONNECTION_STRING}"
redis:
connectionString: "${REDIS_CONNECTION_STRING}"
defaults:
timeout: 30000
retries: 1
retryDelay: 1000
parallel: 4
variables:
testPrefix: "e2e_test_"
reporters:
- type: console
verbose: true
- type: junit
output: "./reports/junit.xml"Writing Tests
YAML Format
name: Create User Flow
description: Test user creation and retrieval
tags: [integration, users]
priority: P1
timeout: 60000
variables:
testEmail: "test-${uuid()}@example.com"
setup:
- id: cleanup-existing
adapter: postgresql
action: exec
params:
query: "DELETE FROM users WHERE email LIKE 'test-%@example.com'"
execute:
- id: create-user
adapter: http
action: POST
params:
url: /api/users
body:
email: "${testEmail}"
name: "Test User"
capture:
userId: $.body.id
assertions:
- path: $.status
operator: equals
expected: 201
- id: get-user
adapter: http
action: GET
params:
url: "/api/users/${captured.userId}"
assertions:
- path: $.body.email
operator: equals
expected: "${testEmail}"
verify:
- id: check-database
adapter: postgresql
action: query
params:
query: "SELECT * FROM users WHERE id = $1"
params: ["${captured.userId}"]
assertions:
- path: $.rows[0].email
operator: equals
expected: "${testEmail}"
teardown:
- id: delete-user
adapter: postgresql
action: exec
params:
query: "DELETE FROM users WHERE id = $1"
params: ["${captured.userId}"]TypeScript Format
// users.test.ts
import type { TestDefinition } from '@liemle3893/e2e-runner';
export default {
name: 'Create User Flow',
tags: ['integration', 'users'],
priority: 'P1',
async execute(ctx) {
// Create user via API
const createRes = await ctx.http.post('/api/users', {
email: `test-${ctx.uuid()}@example.com`,
name: 'Test User',
});
ctx.expect(createRes.status).toBe(201);
ctx.capture('userId', createRes.body.id);
// Verify in database
const dbResult = await ctx.postgresql.query(
'SELECT * FROM users WHERE id = $1',
[ctx.captured.userId]
);
ctx.expect(dbResult.rows).toHaveLength(1);
ctx.expect(dbResult.rows[0].email).toContain('test-');
},
async teardown(ctx) {
await ctx.postgresql.exec(
'DELETE FROM users WHERE id = $1',
[ctx.captured.userId]
);
},
} as TestDefinition;Variable Interpolation
Built-in Functions
| Function | Description | Example |
|----------|-------------|---------|
| ${uuid()} | Generate UUID v4 | 550e8400-e29b-41d4-a716-446655440000 |
| ${now()} | Current timestamp (ISO) | 2024-01-15T10:30:00.000Z |
| ${timestamp()} | Unix timestamp (ms) | 1705315800000 |
| ${random()} | Random number 0-1 | 0.7234 |
| ${randomInt(min, max)} | Random integer | 42 |
Environment Variables
Access environment variables with ${env.VAR_NAME}:
params:
apiKey: "${env.API_KEY}"Captured Values
Access values captured from previous steps:
params:
url: "/api/users/${captured.userId}"Adapters
HTTP Adapter
- adapter: http
action: POST # GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
params:
url: /api/endpoint
headers:
Authorization: "Bearer ${token}"
body:
key: value
timeout: 5000PostgreSQL Adapter
- adapter: postgresql
action: query # or 'exec'
params:
query: "SELECT * FROM users WHERE id = $1"
params: [123]MongoDB Adapter
- adapter: mongodb
action: find # insertOne, updateOne, deleteOne, find, etc.
params:
collection: users
filter:
email: "[email protected]"Redis Adapter
- adapter: redis
action: get # set, del, hgetall, etc.
params:
key: "user:123"Assertions
| Operator | Description |
|----------|-------------|
| equals | Strict equality |
| notEquals | Not equal |
| contains | String/array contains |
| notContains | Does not contain |
| greaterThan | Numeric > |
| lessThan | Numeric < |
| matches | Regex match |
| isArray | Is array type |
| isObject | Is object type |
| hasLength | Array/string length |
| hasProperty | Object has property |
Reporters
Console Reporter
Default output to terminal with colors and progress.
JUnit Reporter
XML output for CI/CD integration:
reporters:
- type: junit
output: "./reports/junit.xml"HTML Reporter
Interactive HTML report:
reporters:
- type: html
output: "./reports/report.html"JSON Reporter
Machine-readable JSON:
reporters:
- type: json
output: "./reports/results.json"Programmatic API
import { runTests, validateTests, listTests, checkHealth } from '@liemle3893/e2e-runner';
// Run tests
const result = await runTests({
config: './e2e.config.yaml',
testDir: './tests',
tag: ['smoke'],
parallel: 4,
});
console.log(`Passed: ${result.passed}, Failed: ${result.failed}`);
// Validate test syntax
const validation = await validateTests({ testDir: './tests' });
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
}
// List available tests
const tests = await listTests({ tag: ['integration'] });
tests.forEach(t => console.log(`- ${t.name} (${t.tags.join(', ')})`));
// Check adapter health
const health = await checkHealth();
console.log('All adapters healthy:', health.healthy);License
MIT
