php-timecopを使って日時に関する動作テストを行う
テストの時に時間を止めるか、特定日時に変更できたら色々捗るよなーと思いました。
Google先生に頼んで探してみたら、やっぱりありました。
php-timecop というPHP拡張です。
http://www.slideshare.net/hnw/php-13502189
http://www.slideshare.net/hnw/phptimecop
makeとかphp.iniを触ったりとかがあるので自前のサーバが必要ですが、面白そうですね。
https://github.com/hnw/php-timecop
…うっ、公式の情報が圧倒的に少ない(白目)
という事で、簡単にまとめてみました。
(この記事の情報は、「version 1.0.4, 2013/03/11」を基にしています。)
GitHubのREADME.mdを読んでインストールとphp.iniの設定を行うと、
「timecop_freeze()」「timecop_travel()」「timecop_return()」の3関数が新たに使用できるようになると共に、元からある時刻系の関数とDateTimeクラスがtimecopに対応したものに書き換わります。
時刻系の関数とDateTimeクラスの使い方は変わりませんので、追加された関数のみ、それぞれ説明します。
boolean timecop_freeze ([ int $timestamp = time() ]);
timecop_freeze()関数は、PHPの現在時刻を仮想的に不変とします。
指定した$timestampのUNIX時刻で時間を固定できます。
$timestampを指定しなければ、現在時刻のまま仮想的に時間を停止できます。
timecop_travel()関数またはtimecop_return()関数を呼び出すまで、時間は固定されたままとなります。
返り値:
$timestampが無効なものであればFALSEを、それ以外の場合にTRUEを返します。
boolean timecop_travel ([ int $timestamp = time() ]);
timecop_travel()関数は、PHPの現在時刻を仮想的に変更します。timecop_freeze()関数とは違い、仮想時刻は変化していきます。
指定した$timestampのUNIX時刻に時間をズラす事ができます。
$timestampを指定しなければ、現在時刻のままとなります。(実質的にtimecop_return()関数を呼び出したのと同じになります。)
返り値:
$timestampが無効なものであればFALSEを、それ以外の場合にTRUEを返します。
boolean timecop_return();
timecop_return()関数は、PHPの現在時刻を通常通りに戻します。
返り値:
TRUEを返します。
(※フレームワーク等で時間計測を行なっている場合、正しくない時間経過となるため、
処理の最後にはtimecop_return()関数を呼び出すようにした方が良いと思います。)
という事で、使ってみましょう
<?php date_default_timezone_set('Asia/Tokyo'); echo date('Y-m-d H:i:s'). "\n"; echo "\ntimecop_freeze\n"; timecop_freeze(946749896); echo date('Y-m-d H:i:s'). "\n"; sleep(1); echo date('Y-m-d H:i:s'). "\n"; echo "\ntimecop_return\n"; timecop_return(); echo date('Y-m-d H:i:s'). "\n"; sleep(1); echo date('Y-m-d H:i:s'). "\n"; echo "\ntimecop_travel\n"; timecop_travel(946749896); echo date('Y-m-d H:i:s'). "\n"; sleep(1); echo date('Y-m-d H:i:s'). "\n"; echo "\ntimecop_return\n"; timecop_return(); echo date('Y-m-d H:i:s'). "\n";
2013-03-16 18:15:25timecop_freeze
2000-01-02 03:04:56
2000-01-02 03:04:56timecop_return
2013-03-16 18:15:26
2013-03-16 18:15:27timecop_travel
2000-01-02 03:04:56
2000-01-02 03:04:57timecop_return
2013-03-16 18:15:28
◆ハマったこと
timecop拡張とは全然関係ない所でドハマり。
FuelPHPのテストで使いたかったため、oilの呼び出し時に独自のphp.iniを呼びだそうと「php -c ~/php_timecop.ini oil test」とかやってたんですが、
どうやらPHPUnitの側で読み出し対象が「/etc/php.ini」に変更されてしまう模様。
(「php -c ~/php_timecop.ini oil console」では独自のphp.iniが読み出し対象になっていました)
うーん、不思議ー。