Test::MockTime - 時間にまつわるtest

k12u
2011-12-07

はい、kawamotoです
blogは書いているとはとても言えないぐらいサボっております。

右も左もわからぬひよっこですので奇をてらわずにTest::名前空間のモジュールの紹介をしようと思います。

Test::MockTime は testの最中に実行される time, localtime, gmtime などの時間に関する関数の振る舞いを書き換える便利なモジュールです。

以下のような症状によく効きます。

使い方はこちらの記事でも説明されていますが、

$ cat ~/test.pl
use feature qw( say );
use Test::MockTime qw( :all );

say time;
set_absolute_time(0);
say "# set_absolute_time(0);";
say time;
say "# ----- sleep(2); -----";
sleep 2;
say time;

say "";

set_fixed_time(0);
say "# set_fixed__time(0);";
say time;
say "# ----- sleep(2); -----";
sleep 2;
say time;
$ perl test.pl
1323183883
# set_absolute_time(0);
0
# ----- sleep(2); -----
2

# set_fixed__time(0);
0
# ----- sleep(2); -----
0

こんな感じです。

time, gmtime, localtime の振る舞いが↓のようになります。

注意点としては time() などの関数の書き換えはコンパイルフェーズに行われるので、使う順番を間違えると正しく動かずはまることになります(xaicron++)。

「よくわかんねーぞ」という人は、このモジュールをなるべく早くuseし、BEGIN{} ブロックのなかで set_fixed_time() などを実行するとよいと思います!

あと、普通やらないと思いますがset_fixed_time()とset_absolute_time()を同じコードで使うのは避けたほうがよさそうです(上の例ではやっちゃっていますが)。

ちなみに違うレイヤーの同様のアプローチとして、MySQLで UNIX_TIMESTAMP()などを使っている場合にはテストの時だけSET TIMESTAMPを発行するという手もありますね。

明日は、実はもう書き上がっているという予感のするbayashiさんです。たぶん。