datetime.date.todayの結果をfreezegunを使って固定する
以前freezegunというライブラリを紹介しました
http://d.hatena.ne.jp/yuheiomori0718/20121216/1355663947
昨日エントリ書いたdatetime.dateを固定するっていうのは、freezegunを使うと以下のように書けます。
import datetime from unittest import TestCase from dateutil.relativedelta import relativedelta from freezegun import freeze_time class DateTodayMockTest(TestCase): @freeze_time('2014-1-1') def test_today(self): today = datetime.date.today() self.assertEquals(today.year, 2014) self.assertEquals(today.month, 1) self.assertEquals(today.day, 1) tomorrow = today + relativedelta(days=1) self.assertEquals(tomorrow.year, 2014) self.assertEquals(tomorrow.month, 1) self.assertEquals(tomorrow.day, 2) day_after_day = tomorrow + relativedelta(days=1) self.assertEquals(day_after_day.year, 2014) self.assertEquals(day_after_day.month, 1) self.assertEquals(day_after_day.day, 3)
このコード、python -m unittestで動かすと成功するんですが、Pycharmから動かすと失敗しました。
Traceback (most recent call last): File "/Applications/PyCharm 2.7 EAP.app/helpers/pycharm/utrunner.py", line 152, in <module> TeamcityTestRunner().run(all, **options) File "/Applications/PyCharm 2.7 EAP.app/helpers/pycharm/tcunittest.py", line 197, in run test(result) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/suite.py", line 65, in __call__ return self.run(*args, **kwds) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/suite.py", line 103, in run test(result) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 376, in __call__ return self.run(*args, **kwds) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 355, in run result.stopTest(self) File "/Applications/PyCharm 2.7 EAP.app/helpers/pycharm/tcunittest.py", line 174, in stopTest d = datetime.datetime.now() - start File "/Users/yuhei/.virtualenvs/sandbox/lib/python2.7/site-packages/freezegun/api.py", line 56, in __sub__ return datetime_to_fakedatetime(result) File "/Users/yuhei/.virtualenvs/sandbox/lib/python2.7/site-packages/freezegun/api.py", line 79, in datetime_to_fakedatetime return FakeDatetime(datetime.year, AttributeError: 'datetime.timedelta' object has no attribute 'year'
Pycharmのutrunner内部でdatetimeの引き算をやっててそれがエラーになったみたいです。
freezegunのコード読んでみるとFakeDatetimeの__sub__でスーパークラスの減算の結果に対してこんな処理を書いてます
def datetime_to_fakedatetime(datetime): return FakeDatetime(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, datetime.microsecond, datetime.tzinfo)
減算の結果はdatetimeでなくてtimedeltaですんで、上記のようなエラーになるんですね。
なのでpycharmのテストランナーは別に悪くなくて、こんなテストだとpycharm関係なく失敗になります。
from dateutil.relativedelta import relativedelta import datetime import unittest from freezegun import freeze_time class DateTodaySubtractionTest(unittest.TestCase): @freeze_time('2014-1-1') def test_sub(self): today = datetime.date.today() tomorrow = today + relativedelta(days=1) self.assertEquals(tomorrow - today, datetime.timedelta(1))
明確なバグなのでもう直ってるかなと思ったら、やっぱ直ってました。
https://github.com/spulec/freezegun/commit/4884bd0a6017536a46895bde5cd04f621d93e42d
githubからpip installしたらちゃんとpycharmから動かせるようになりました。
pip install git+git://github.com/spulec/freezegun.git