Version: 1.0
Date: 2026-08-14
This document defines the command-line interface contract for pgcov, including commands, flags, exit codes, and output formats.
Discover tests and source files, execute tests with coverage tracking, and generate coverage data.
Arguments:
[path]: Directory or pattern to search (default:.).- Current directory only./...- Recursive from current directory (Go-style)./tests/- Specific directory
Flags:
| Flag | Type | Default | Description |
|---|---|---|---|
--connection, -c |
string | (empty) | PostgreSQL connection string (URI or key=value format). When omitted, pgx falls back to its standard PG* environment variables (PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE, …). |
--timeout |
duration | 30s |
Per-test timeout |
--parallel |
int | 1 |
Maximum concurrent tests (1 = sequential) |
--coverage-file |
string | .pgcov/coverage.json |
Coverage data output path |
--setup |
string (repeatable) | (none) | SQL file(s) (globs allowed) executed verbatim in each test's temp database before loading instrumented sources. Use for prerequisite schema the sources depend on. Repeatable; order preserved. |
--verbose |
bool | false |
Enable debug output |
Exit Codes:
0: All tests passed — also returned when no*_test.sqlfiles are discovered (a message is printed)1: One or more tests failed, or a runtime error occurred (e.g. failed discovery, parse, instrumentation, database connection, or test execution)2: Configuration error (e.g. invalid flags, missing connection string, non-positive timeout, parallelism outside1..100)
stdout Output:
pgcov: discovering tests in .
Found 3 test file(s)
Found 5 source file(s)
Connected to PostgreSQL
Tests: 2 passed, 1 failed, 3 total
Coverage: 78.50%
Time: 4.1s
Coverage data written to .pgcov/coverage.json
When no test files are found:
No test files found (*_test.sql)
stderr Output (errors only):
Error: database connection failed: failed to connect to PostgreSQL: ...
Suggestion: Set via --connection flag or standard PG* environment variables (PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE).
Environment Variables:
Standard PostgreSQL / pgx environment variables are honored by the underlying connection layer when --connection is omitted or partial:
PGHOST— PostgreSQL hostPGPORT— PostgreSQL portPGUSER— PostgreSQL userPGPASSWORD— PostgreSQL passwordPGDATABASE— Template database
pgcov itself does not document per-flag PG* overrides; all connection configuration is funneled through --connection.
Generate coverage report from existing coverage data.
Arguments: None
Flags:
| Flag | Type | Default | Description |
|---|---|---|---|
--format |
string | json |
Output format (json, lcov, or html) |
--output, -o |
string | - |
Output file path (use - for stdout) |
--coverage-file |
string | .pgcov/coverage.json |
Coverage data input path |
Exit Codes:
0: Report generated successfully1: Coverage data file not found, failed to parse, unsupported format, or output write failure
stdout Output (--format=json):
{
"version": "1.0",
"timestamp": "2026-08-14T16:00:00Z",
"positions": {
"src/auth.sql": {
"0:42": 5,
"42:128": 5,
"170:37": 3
}
}
}Position keys are "<startByteOffset>:<byteLength>"; values are integer hit counts.
stdout Output (--format=lcov):
TN:
SF:src/auth.sql
DA:1,5
DA:2,5
DA:5,3
LF:3
LH:2
end_of_record
The LCOV reporter converts the stored byte-offset positions to line numbers by reading each source file (positions are accumulated onto the line they start on). When a source file cannot be read, it falls back to emitting DA:<startByteOffset>,<hitCount> instead.
Display help information.
Arguments:
[command]: Optional command name for detailed help
Exit Codes:
0: Always
stdout Output:
NAME:
pgcov - PostgreSQL test runner and coverage tool
USAGE:
pgcov [global options] command [command options] [arguments...]
VERSION:
1.0.0
COMMANDS:
run Run tests and collect coverage
report Generate coverage report
help Show help
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
Display version information.
Exit Codes:
0: Always
stdout Output:
pgcov version 1.0.0
Default: .pgcov/coverage.json
Configurable via: --coverage-file flag on run and report
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["version", "timestamp", "positions"],
"properties": {
"version": {
"type": "string",
"description": "Schema version (semantic versioning)"
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "RFC 3339 timestamp of coverage collection"
},
"positions": {
"type": "object",
"description": "Per-file position-based coverage. Key: relative file path. Value: position -> hit count map.",
"additionalProperties": {
"$ref": "#/definitions/PositionHits"
}
}
},
"definitions": {
"PositionHits": {
"type": "object",
"description": "Position key -> hit count. Keys use the form \"<startByteOffset>:<byteLength>\". Values are non-negative integers; a value of 0 means the instrumented position was not executed.",
"additionalProperties": {
"type": "integer",
"minimum": 0
}
}
}
}{
"version": "1.0",
"timestamp": "2026-08-14T16:00:00Z",
"positions": {
"src/auth.sql": {
"0:42": 5,
"42:128": 5,
"170:37": 3,
"207:41": 0
},
"src/user.sql": {
"0:120": 8,
"120:96": 8,
"216:48": 0
}
}
}All instrumented positions are seeded with 0 even if the test never executes them, so unexecuted branches (for example ELSIF/ELSE arms) are visible as 0 rather than being absent from the file.
LCOV trace file format (compatible with genhtml and coverage.py).
The reporter reads each source file referenced in positions and converts the stored byte-offset positions into line numbers (a position is attributed to the line on which its startByteOffset falls; multiple positions on the same line accumulate their hit counts). If a source file cannot be read, positions are emitted directly with DA:<startByteOffset>,<hitCount> as a fallback.
TN:
SF:src/auth.sql
DA:1,5
DA:2,5
DA:5,3
LF:3
LH:2
end_of_record
SF:src/user.sql
DA:1,8
DA:2,8
DA:3,0
LF:3
LH:2
end_of_record
Legend:
TN:- Test name (empty for pgcov)SF:- Source file pathDA:line,hitcount- Line coverage data (derived from byte-offset positions)LF:- Lines found (total)LH:- Lines hitend_of_record- End of file marker
BRDA, BRF, BRH records are not emitted; branch coverage is folded into the position map.
Contract: Files matching *_test.sql pattern are test files; all other .sql files are source files.
Examples:
- ✅
auth_test.sql→ Test - ✅
user_functions_test.sql→ Test - ✅
auth.sql→ Source - ❌
test_auth.sql→ Source (wrong pattern)
Contract: Each test runs in a unique temporary database.
Guarantees:
- Test execution order does not affect results
- Tests can run in parallel without interference
- No database artifacts persist after test completion
Contract: Same code and tests produce identical coverage results.
Guarantees:
- Deterministic hit counts
- Reproducible across runs
- No false positives (covered position must have executed)
- No false negatives (executed position must be marked covered)
Contract: All errors include actionable context.
Guarantees:
- Parse errors show file and underlying error
- Connection errors suggest configuration fixes (
--connectionor PG* env vars) - Test failures propagate SQL error code and message
- Timeout errors identify which test timed out
Contract Version: 1.0
Breaking Changes: Require major version bump
Breaking changes include:
- CLI flag removals or renames
- Exit code changes
- Coverage data JSON schema changes (incompatible with previous parsers)
- LCOV format deviations
Non-Breaking Changes: Minor/patch version bumps
Non-breaking changes include:
- New CLI flags
- New output formats
- Additional fields in JSON schema
- Performance improvements
- CLI Interface: Stable after v1.0 (flag additions only)
- Coverage Data Format: Backward-compatible schema evolution
- Exit Codes: Fixed contract (no reassignment)
- LCOV Format: Strict adherence to specification
Implementation must pass these contract validation tests:
- CLI Help Output:
pgcov helpreturns exit code 0 and shows all commands - Version Output:
pgcov --versionshows version string - Exit Code 0: All passing tests return exit code 0
- Exit Code 0 (no tests): A run that finds no
*_test.sqlfiles returns exit code 0 - Exit Code 1: Any failing test, runtime error, or missing coverage file in
reportreturns exit code 1 - Exit Code 2: Invalid configuration (e.g. missing
--connection, non-positive--timeout) returns exit code 2 - Coverage File:
pgcov runcreates.pgcov/coverage.jsoncontainingversion,timestamp, andpositions - LCOV Output:
pgcov report --format=lcovproduces parseable LCOV format - HTML Output:
pgcov report --format=htmlproduces an HTML report - Test Pattern:
*_test.sqlfiles discovered, others treated as source - Parallel Execution:
--parallel=Nrespects concurrency limit - Timeout Enforcement:
--timeout=Xsterminates test after X seconds - Deterministic Coverage: Multiple runs produce identical coverage data
This contract defines:
- ✅ CLI commands and flags
- ✅ Exit codes and their meanings
- ✅ Output formats (text, JSON, LCOV, HTML)
- ✅ Coverage data file schema
- ✅ Behavioral guarantees
- ✅ Versioning policy
All implementations must comply with this contract for v1.0 compatibility.