tsucchi’s diary(元はてなダイアリー)

はてなダイアリー(d.hatena.ne.jp/tsucchi1022)から移行したものです

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ですね。
最近入れたモジュールの中では、もっともお気に入り。ぜひ使ってみてくださいな。