$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

Test::Time::AtというCPANモジュールをリリースしました

社内でテスト時の時間操作を便利にするTest::Time::At というモジュールがあったので、それをCPAN化してリリースしました。

テスト中の時間を止めて、sleepなどの操作をうまくハンドリングしてくれるモジュールにはTest::Time というモジュールがあります。このモジュールを使っている時に、たまに、ある時間を指定してテストを実行したい時があります。そのような場合は以下のようにすれば実現できます。

use Test::Time;
use DateTime;

my $target_dt = DateTime->new(year => 2015, month => 7, day => 15);
$Test::Time::time = $target_dt->epoch;
my $now = time;


Test::Time::Atを用いると、このような操作を少し便利にする事ができます。do_atという関数を用いると、特定のブロック内だけ時間を指定して実行することが出来ます。

use Test::More;
use Test::Time time => 1;
use Test::Time::At;

is time, 1, 'Test::Timeで指定したので、ここでは1になる';

do_at {
    is time, 1000, 'Test::Time::Atによって、このブロックは1000になる';
    sleep 10;
    is time, 1010, 'ブロック内でsleepすると時間が進む';
} 1000;

is time, 1, 'ブロックを外れると1に戻る';

Time::PieceやDateTimeなど、epochというメソッドを使えるインスタンスも同様に渡すことが出来ます。

use Test::Time;
use Test::Time::At;

use Time::Piece;
use DateTime;

do_at {
    my $now = gmtime;
} Time::Piece->strptime('2015-08-10T06:29:00', '%Y-%m-%dT%H:%M:%S');

do_at {
    my $now = DateTime->now;
} DateTime->new(year => 2015, month => 8, day => 10);

subtest内の時間を指定する場合は、sub_atを利用することでネストを浅くすることも出来ます。

use Test::More;
use Test::Time;
use Test::Time::At;

subtest 'この中の時間を指定したい' => sub_at {
    is time, 1000;
} 1000;


どうぞご利用ください。
https://metacpan.org/pod/Test::Time::At
https://github.com/hatena/Test-Time-At