1nickt has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, with the following test file how do I get prove to report 6 (assertions) rather than 2 (subtests)?

use Test::More; subtest foo => sub { ok 1; ok 2; ok 3; }; subtest bar => sub { ok 4; ok 5; ok 6; }; done_testing;

Thanks!


The way forward always starts with a minimal test.

Replies are listed 'Best First'.
Re: Count assertions
by choroba (Cardinal) on Mar 10, 2026 at 11:01 UTC
    Why do you need it?

    If you just want to be sure all the tests in the subtests have run, plan inside the subtests:

    subtest foo => sub { plan tests => 3; ok 1; ok 2; ok 3; };

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      We need it because we have to report to the overlords how much testing we are doing.

      Using the plan in the subtests doesn't work:

      $ cat test.t use Test::More; subtest foo => sub { plan_tests => 3; ok 1; ok 2; ok 3; }; $ prove -lrv test.t test.t .. # Subtest: foo ok 1 ok 2 ok 3 1..3 ok 1 - foo # Tests were run but no plan was declared and done_testing() was not s +een. Dubious, test returned 254 (wstat 65024, 0xfe00) All 1 subtests passed
      $ cat test.t use Test::More; subtest foo => sub { plan_tests => 3; ok 1; ok 2; ok 3; }; done_testing; $ prove -lrv test.t test.t .. # Subtest: foo ok 1 ok 2 ok 3 1..3 ok 1 - foo 1..1 ok All tests successful. Files=1, Tests=1, ...


      The way forward always starts with a minimal test.
        What to you mean by "doesn't work"? It clearly works in the second snippet. If you want to report the number of single tests, process the output for /\d+\.\.\d+/. Something like this:
        #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use List::Util qw{ sum }; my %test; while (<>) { if (/^( *)([0-9]+)\.\.([0-9]+)$/) { my $length = length $1; my ($from, $to) = ($2, $3); $test{$length} += $to - $from + 1; --$test{$length - 4} if $length; } } say sum(values %test), ' tests run.';

        I only did minimal testing, so test it properly.

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Count assertions
by hippo (Archbishop) on Mar 12, 2026 at 10:34 UTC
    how do I get prove to report 6 (assertions) rather than 2 (subtests)

    You don't :-)

    The point of subtests is so that the harness treats them as just one test regardless of how many components there are. From the Test::More doc (with my emphasis):

    "subtest()" runs the &code as its own little test with its own plan and its own result. The main test counts this as a single test using the result of the whole subtest to determine if its ok or not ok.

    If you want your harness to count everything inside the subtests, then just don't use subtests at all and promote all your tests to the top level.


    🦛

Re: Count assertions
by tobyink (Canon) on Mar 25, 2026 at 16:18 UTC

    Use yath instead of prove.

    $ cat example.t use Test::More; subtest foo => sub { ok 1; ok 2; ok 3; }; subtest bar => sub { ok 4; ok 5; }; done_testing; $ yath example.t ** Defaulting to the 'test' command ** ( PASSED ) job 1 example.t Yath Result Summary ---------------------------------------------------------------------- +------------- File Count: 1 Assertion Count: 7 Wall Time: 0.36 seconds CPU Time: 0.53 seconds (usr: 0.16s | sys: 0.01s | cusr: 0.31s | + csys: 0.05s) CPU Usage: 146% --> Result: PASSED <--

    Note assertion count is seven: five individual assertions plus the two subtest blocks grouping them.

    Yath is just a better test runner in so many ways. If you have a large test suite, you can set it to send a notification by email or by Slack when the test suite has finished running. You can add # HARNESS-DURATION-LONG comments to long-running tests then run yath --no-long to only run short/medium tests. You can create a JSON log of a test run, then run yath --rerun-failed to just re-run the tests that failed last time. And the default output is prettier.