Another solution is the use of BEGIN blocks. In case you don't know, code that is placed in a BEGIN block will be executed as soon as it gets compiled. Even before the rest of the code gets compiled. So in the next example the array @tests will already have content when perl tries to compile the "use Test::Simple ..." statement. This way "scalar @tests" will already return the number of elements in the array. Please note, we have to declare "my @tests" outside the BEGIN block or it will be scoped inside that block. This is a good solution, though it requires the use of BEGIN, which might be considered as somewhat advanced feature of Perl.

examples/perl/tests/t23.pl
use strict;
use warnings;

use FindBin;
use lib "$FindBin::Bin/../lib";
use MyTools;

my @tests;
BEGIN {
    @tests = (
        [ 1,  1,  2    ],
        [ 2,  2,  4    ],
        [ 2,  2,  2, 6 ],
        [ 3,  3,  6    ],
        [-1, -1, -2    ],
        [ 1, -1,  0    ],
    );
}

use Test::Simple tests => scalar @tests;

foreach my $t (@tests) {
    my $expected = pop @$t;
    my $real     = sum(@$t);
    my $name     = join " + ", @$t;

    ok( $real == $expected, $name );
}

Output:

examples/perl/tests/t23.pl.out
1..6
ok 1 - 1 + 1
ok 2 - 2 + 2
not ok 3 - 2 + 2 + 2

#   Failed test '2 + 2 + 2'
#   at examples/perl/tests/t23.pl line 27.
ok 4 - 3 + 3
ok 5 - -1 + -1
ok 6 - 1 + -1
# Looks like you failed 1 test of 6.