Test::Classy 0.01

というのを書いてみた。Test::Classの親戚みたいなもの。.tファイルのなかで

use strict;
use warnings;
use lib 't/lib';
use Test::Classy;

load_tests_from 'MyApp::Test';
run_tests;

と書いておくと、t/lib/MyApp/Test/以下にあるパッケージをごそっと読み込んでユニットテストしてくれるという寸法。
ユニットテストそのものは

package MyApp::Test::Something;
use strict;
use warnings;
use Test::Classy::Base;
use MyApp;

__PACKAGE__->mk_classdata( myapp => MyApp->new );

sub initialize {
  my ($class, @args) = @_;

  eval { require Some::Module };
  $class->skip_the_rest('Some::Module required') if $@;
}

sub test : Test {
  my ($class, @args) = @_;
  ok $class->myapp->do_something;
}

sub test2 : Tests(2) Model {
  my ($class, @args) = @_;
  ok $class->myapp->model->do_other_thing;
  ok $class->myapp->model->do_yet_another;
}

1;

のような感じで。面倒ならTest(no_plan)としておけばテストの数を勘定しなくても可。

Modelアトリビュートを持つテストだけ実行したい場合は

load_tests_from 'MyApp::Test';
limit_tests_by 'Model';
run_tests;

テストに引数を渡したければ

my $model = MyApp::Model->connect;

load_tests_from 'MyApp::Test';
limit_tests_by 'Model';
run_tests($model);

END { $model->disconnect; }

ユニットテストそのものを継承して使い回したければ

package MyApp::Test::Base;
use strict;
use warnings;
use Carp;
use Test::Classy::Base 'ignore';

sub fixture { croak "override this"; }

sub test_with_fixture : Test {
  my ($class, @args) = @_;

  ok $class->some_func($class->fixture);
}

1;

のようにしておいて、

package MyApp::Test::CaseA;
use strict;
use warnings;
use MyApp::Test::Base 'base';

sub fixture { 'something' }

1;

でOK。

なんぞありましたらcodereposへ。