Home / Alt manpages / prove(1)

  • prove(1)
  • User command
  • linux

Run Perl Tests Reliably with prove

prove turns a folder of Perl test scripts into a pass or fail you can trust, and it has options most people never touch. You will finish with a repeatable way to run a test file or directory, read the TAP result, pass test arguments, and rerun only known failures. The examples use the locally installed prove from Perl 5.38.2, with TAP::Harness v3.44.

Allow about fifteen minutes. You need a shell, Perl, and a project containing tests written in the TAP format, commonly files ending in .t under t/. Nothing here needs elevated privileges: run tests as the same user who normally edits and builds the project.

1. Check the installed command

Start by checking which executable will run and which version it reports:

$ command -v prove
/usr/bin/prove
$ prove --version
TAP::Harness v3.44 and Perl v5.38.2

The exact version can differ on another host, so keep this check in any bug report where a test behaves differently between machines. The command ships as part of the installed perl package here:

$ dpkg-query -W -f='${Package} ${Version}\n' perl
perl 5.38.2-3.2ubuntu0.6

Checkpoint

If command -v prove prints nothing, stop and repair the Perl installation or your PATH. Do not work around an unknown executable by running a similarly named script from the current directory.

2. Run one test file first

Change to the project directory and name one test explicitly, so an unrelated failure does not distract you while you confirm the harness itself works:

$ cd /path/to/project
$ prove --norc -v t/basic.t
t/basic.t ..
1..2
ok 1 - first
ok 2 - arithmetic
ok
All tests successful.
Files=1, Tests=2,  0 wallclock secs
Result: PASS

Use the real path to one of your test files in place of /path/to/project and t/basic.t. -v prints each test line, and --norc keeps the run clean by stopping prove reading project or home configuration. Skip it, and ~/.proverc and ./.proverc get read before your command-line options do.

A zero exit status means the harness and the selected test both completed successfully. Check it directly when a script needs to act on it:

$ prove --norc t/basic.t
$ printf 'prove exit status: %s\n' "$?"
prove exit status: 0

A failing test makes prove exit non-zero. Preserve that status in CI or a shell script rather than piping the command into something else and quietly swallowing the failure.

3. Run the project's normal test set

Once one file passes, run the whole directory. With no file or directory argument, prove looks for files matching t/*.t; naming t/ keeps the scope obvious:

$ prove --norc t/
t/basic.t .. ok
t/paths.t  .. ok
All tests successful.
Files=2, Tests=7,  0 wallclock secs
Result: PASS

These file names and counts are just examples; yours will depend on the project. Tests buried several directory levels down need -r or --recurse to be found:

$ prove --norc -r t/

Do not turn on recursive discovery just because a project has other scripts nearby. Confirm the paths first: running an unintended test can create files, contact services, or chew through test data you did not mean to touch.

4. Separate prove options from test arguments

Arguments meant for the test itself must follow the separator ::. Everything before it belongs to prove:

$ prove --norc -v t/api.t :: --url https://staging.example.invalid
t/api.t ..
ok 1 - endpoint is reachable
ok
Result: PASS

Every selected test receives the same arguments. Quote values containing spaces or shell metacharacters, and treat URLs, file names and credentials as data, not shell syntax. Do not drop a secret directly into a command if your shell history or CI logs might record it: use the project's supported environment or secret mechanism instead.

Checkpoint

If a test complains about an unknown option, check the position of :: first. Leave it out, and prove may try to interpret the test's own option as one of its own.

5. Use project libraries and build output

Tests often need modules from the project's source or build directories. Use -l to add lib to the Perl include path, or -b to add blib/lib and blib/arch:

$ prove --norc -l t/
$ prove --norc -b t/

These affect how the Perl tests load; they do not build the project itself. Run the build step first when blib does not exist. If a test still cannot find a module, check the project's documented dependency and build process rather than bolting on random include paths.

6. Preview selection before running tests

Unsure which files a directory or recursive search will pick up? Use dry-run mode:

$ prove --norc --dry t/
t/basic.t
t/paths.t

Dry-run lists the tests that would run without executing them. It is a handy checkpoint before a broad or expensive test command, though it does not validate the tests themselves.

7. Rerun failures with saved state

For a larger suite, save the run state, then select only failures:

$ prove --norc -b --state=save t/
$ prove --norc -b --state=failed
t/paths.t .. Failed 1/3
Failed 1/2 test programs. 1/5 subtests failed.
$ prove --norc -b --state=failed,save

The saved state lives in .prove in the current directory. The last command reruns failures and updates that state, so tests that now pass drop out of the next failure-only run. This file is project state, not a test result you edit by hand. Need a clean run? Remove .prove only after confirming it is the state file prove created, or run from a clean working copy. Removing it loses the remembered selection but touches nothing in your source.

State trips people up: --state=failed needs a previous saved run, while --state=save saves the current one. For a complete rerun after fixing a failure, name t/ explicitly rather than trusting an old selection.

8. Diagnose output without changing the test

Use -f or --failures to show failed tests, -o to show comments, and -p for the full list of TAP parse errors. Reach for --merge only when you need standard error interleaved with standard output in diagnostic order:

$ prove --norc -v -f -p t/paths.t
$ prove --norc --merge t/paths.t

The merge option is deliberately specialised: if diagnostics written to standard error look like TAP test lines, the harness can misread them. Start with ordinary verbose output and add --merge only once ordering between diagnostics and results is actually the problem.

Parallel execution is available with -j N, but it can expose tests that share files, ports, databases or environment state. Start with one job. Add parallel jobs only once the tests are demonstrably independent, and use --rules for anything that must stay sequential. Parallel output and timing can make a failure much harder to reproduce.

Done means

  • You confirmed the installed prove executable and Perl version.
  • You ran one test file and checked its exit status.
  • You previewed or named the intended test set before a broad run.
  • You know --norc bypasses .proverc and that configuration can change defaults.
  • You used :: to separate test arguments from harness options.
  • You can save state and rerun failures without editing source or test results.
  • You left parallel execution disabled unless the suite is safe for it.