BYO Test Runner
t-req handles HTTP parsing and execution. Your test framework handles assertions. This separation means you can use the test runner you already know — Vitest, Jest, Bun test, pytest, or anything else.
Philosophy
Section titled “Philosophy”.http files are data, not test specs. They define what request to send, not what to assert. Your test framework provides:
- Test organization and naming
- Assertions and matchers
- Setup/teardown lifecycle
- Parallel execution
- Coverage and reporting
t-req provides:
.httpfile parsing with variable interpolation- Request execution with cookie handling
- Profile-based configuration
- Observer mode for TUI observability
Vitest example
Section titled “Vitest example”import { describe, it, expect, beforeAll, afterAll } from 'vitest';import { createClient } from '@t-req/core';
describe('User API', () => { const client = createClient({ variables: { baseUrl: 'https://api.example.com' }, });
let token: string;
beforeAll(async () => { const res = await client.run('./requests/auth/login.http', { variables: { username: 'admin', password: 'secret' }, }); const body = await res.json(); token = body.accessToken; client.setVariable('token', token); });
afterAll(async () => { await client.close(); });
it('lists users', async () => { const res = await client.run('./requests/users/list.http'); expect(res.status).toBe(200);
const users = await res.json(); expect(users).toBeInstanceOf(Array); expect(users.length).toBeGreaterThan(0); });
it('gets user profile', async () => { const res = await client.run('./requests/users/profile.http', { variables: { userId: '1' }, }); expect(res.status).toBe(200);
const profile = await res.json(); expect(profile).toHaveProperty('email'); });});Jest example
Section titled “Jest example”The same pattern works with Jest:
import { createClient } from '@t-req/core';
const client = createClient({ variables: { baseUrl: 'https://api.example.com' },});
afterAll(() => client.close());
test('lists users', async () => { const res = await client.run('./requests/users/list.http'); expect(res.status).toBe(200);
const users = await res.json(); expect(Array.isArray(users)).toBe(true);});Bun test example
Section titled “Bun test example”import { describe, it, expect, afterAll } from 'bun:test';import { createClient } from '@t-req/core';
const client = createClient({ variables: { baseUrl: 'https://api.example.com' },});
afterAll(() => client.close());
describe('API', () => { it('returns 200 for health check', async () => { const res = await client.run('./requests/health.http'); expect(res.status).toBe(200); });});pytest example
Section titled “pytest example”Python tests use the t-req server API directly via HTTP:
import requestsimport pytest
TREQ_SERVER = "http://localhost:4096"
@pytest.fixture(scope="session")def session_id(): res = requests.post(f"{TREQ_SERVER}/session", json={ "variables": {"baseUrl": "https://api.example.com"} }) sid = res.json()["id"] yield sid requests.delete(f"{TREQ_SERVER}/session/{sid}")
def test_list_users(session_id): res = requests.post(f"{TREQ_SERVER}/execute", json={ "sessionId": session_id, "path": "./requests/users/list.http" }) assert res.status_code == 200 data = res.json() assert data["response"]["status"] == 200Start the server before running tests:
treq serve &pytest tests/Auto-detection
Section titled “Auto-detection”When running tests from the TUI, t-req automatically detects the right test framework by looking at your project’s dependencies:
| Framework | Detection |
|---|---|
| bun test | bun.lockb present or bun in path |
| vitest | vitest in devDependencies |
| jest | jest in devDependencies |
| pytest | pytest or .py test files |
Observer mode tie-in
Section titled “Observer mode tie-in”When tests run through the TUI (via treq open), every createClient() call automatically connects to the server. All HTTP requests appear in real-time in the TUI — no extra configuration needed.
See Observer Mode for details on how this works.