Time::Fake 可愛いよ、Time::Fake、
以前にtech note で紹介した Time::Fake。使ってみました。
時間をベースにディレクトリを作るクラスのテストに使ってみたのですが、ここではもうチョイ簡単に、「時間をベースにした名前を返すクラス」をテストしてみます。
まずはテストされ側、name() は(現在時刻が2008年 3/1 17:27 12秒として)「20080301172712」のような日付、時刻をベースにした文字列を返すメソッドです。
package NameMaker; sub new { bless {}, shift; } sub name { my $self = shift; my ($sec, $min, $hour, $mday, $mon, $year) = localtime(); return sprintf("%s%02s%02s%02s%02s%02s", $year+1900, $mon+1, $mday, $hour, $min, $sec); } 1;
と、まあ localtime を使うので、普通にテストしようとすると、テスト側でも localtime 使うくらいしか方法がない。でもそれじゃあテストの意味ないじゃん、つーわけで、Time::Fakeの出番。
use Time::Fake; use Time::Local; my $time_for_test = timelocal(56, 34, 12, 22, 10-1, 78);# 1978/10/22 12:34 56秒; Time::Fake->offset($time_for_test);
とすれば、Perl の時計がコメントにある「1978/10/22 12:34 56秒」にセットされます。任意の時刻にできるから、テストコードでは、
is($namemaker->name(), "19781022123456");
みたいに、期待される時刻を具体的に書けます。(ここがポイント!)
全体はこんな感じ。
#!/usr/bin/perl use strict; use warnings; NameMakerTests->runtests; package NameMakerTests; use base qw(Test::Class); use Test::More; use Time::Fake; my $namemaker; sub setup : Test(setup) { use Time::Local; my $time_for_test = timelocal(56, 34, 12, 22, 10-1, 78);# 1978/10/22 12:34 56秒; Time::Fake->offset($time_for_test); $namemaker = NameMaker->new(); } sub name_test : Test(1) { is($namemaker->name(), "19781022123456"); } 1; package NameMaker; sub new { bless {}, shift; } sub name { my $self = shift; my ($sec, $min, $hour, $mday, $mon, $year) = localtime(); return sprintf("%s%02s%02s%02s%02s%02s", $year+1900, $mon+1, $mday, $hour, $min, $sec); } 1;
一応、prove しておきましょう。
tsucchi@appears[104]% prove test.pl test....ok All tests successful. Files=1, Tests=1, 0 wallclock secs ( 0.20 cusr + 0.09 csys = 0.29 CPU)
OKですね。
最近入れたモジュールの中では、もっともお気に入り。ぜひ使ってみてくださいな。