Hello sekitaka.
Today I'll show you how to test a function that uses datetime.now ()
.
For example, suppose you want to create a function that returns the string "YYYYMMDD" the next day after running a program and test that function.
def get_tomorrow():
now_datetime = datetime.now()
tomorrow_datetime = now_datetime + timedelta(days=+1)
tomorrow = tomorrow_datetime.strftime("%Y%m%d")
return tomorrow
First, I briefly wrote the following test code. But as you can see, it only succeeds if you run the test on June 22, 2017. This will result in an error when testing daily with CI.
class Test(TestCase):
def test_get_tomorrow(self):
self.assertEqual("20170623", get_tomorrow())
The next idea was to dynamically generate the expected value. This will pass the test whenever you test it. However, in fact, I wrote the same code as get_tomorrow, and I feel that it has not been tested.
class Test(TestCase):
def test_get_tomorrow(self):
expect_tomorrow = (datetime.now() + timedelta(days=+1)).strftime("%Y%m%d")
self.assertEqual(expect_tomorrow, get_tomorrow())
Therefore, I thought that it would be better to Mock datetime.now ()
, set it to return an arbitrary datetime, and execute get_tomorrow
. And I wrote the following code.
from mock import Mock
class Test(TestCase):
def test_get_tomorrow(self):
datetime.now = Mock(return_value=datetime(year=2017, month=1, day=1))
self.assertEqual("20170102", get_tomorrow())
When I ran it with expectation, it seemed that I couldn't set attribute to the built-in datetime, so I couldn't run it.
TypeError: can't set attributes of built-in/extension type 'datetime.datetime'
When I was in trouble, I found a library called freezegun that mocked the datetime module.
from freezegun import freeze_time
class Test(TestCase):
@freeze_time("2017-01-01")
def test_get_tomorrow_4(self):
self.assertEqual("20170102", get_tomorrow())
The current is fixed to 2017/1/1 by the description of @freeze_time ("2017-01-01 ")
.
So get_tomorrow ()
will always return " 20170102 "
and will succeed whenever you run the test.
If you change the freeze_time date, you can check whether the program works normally over a year or in a leap year, which is convenient.
What did you think. I introduced how to test a function that depends on python's datetime.now ()
.
It is necessary to create a test case so that unit tests can be executed once and not finished, but can be executed at any time if CI is turned.
I would like to continue learning about test methods.
Recommended Posts