Skip to content

Commit

Permalink
Tests: Use UTC-based utcnow().date() instead of local date.today()
Browse files Browse the repository at this point in the history
`datetime.date.today()` returns the current local date. So, its outcome
depends on the system time zone. Because we want to use UTC-based date
and time objects instead, `datetime.utcnow().date()` is a better choice.
  • Loading branch information
amotl committed Jul 22, 2022
1 parent a849cea commit 07b8d79
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def read(path):
'zope.testing>=4,<5',
'zope.testrunner>=5,<6',
'zc.customdoctests>=1.0.1,<2',
'time-machine>=2,<3',
'createcoverage>=1,<2',
'stopit>=1.1.2,<2',
'flake8>=4,<5'],
Expand Down
2 changes: 1 addition & 1 deletion src/crate/client/sqlalchemy/doctests/itests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ aren't set when the row is inserted as there is no default method::

The datetime and date can be set using a update statement::

>>> location.nullable_date = datetime.today()
>>> location.nullable_date = datetime.utcnow().date()
>>> location.nullable_datetime = datetime.utcnow()
>>> session.flush()

Expand Down
4 changes: 2 additions & 2 deletions src/crate/client/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import unittest
import doctest
from pprint import pprint
from datetime import datetime, date
from datetime import datetime
from http.server import HTTPServer, BaseHTTPRequestHandler
import ssl
import time
Expand Down Expand Up @@ -213,7 +213,7 @@ class Location(Base):
__tablename__ = 'locations'
name = sa.Column(sa.String, primary_key=True)
kind = sa.Column(sa.String)
date = sa.Column(sa.Date, default=date.today)
date = sa.Column(sa.Date, default=lambda: datetime.utcnow().date())
datetime_tz = sa.Column(sa.DateTime, default=datetime.utcnow)
datetime_notz = sa.Column(sa.DateTime, default=datetime.utcnow)
nullable_datetime = sa.Column(sa.DateTime)
Expand Down
90 changes: 90 additions & 0 deletions src/crate/testing/test_datetime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# -*- coding: utf-8; -*-
#
# Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
# license agreements. See the NOTICE file distributed with this work for
# additional information regarding copyright ownership. Crate licenses
# this file to you under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. You may
# obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# However, if you have executed another commercial license agreement
# with Crate these terms will supersede the license and you may use the
# software solely pursuant to the terms of the relevant commercial agreement.

import os
import sys
import unittest
from datetime import datetime, date
from unittest import TestCase, mock

import time_machine


class DateTodayTest(TestCase):
"""
`date.today()` returns the current local date, as advertised in the
documentation [1]. Thus, it depends on the system time zone.
The following test cases demonstrate that the test suite previously
failed around midnight, where the UTC vs. non-UTC days overlapped,
and when running on machines with non-UTC time zone.
On the other hand, `datetime.utcnow().date()` works equally well in all
situations, so we want to use that within the SQLAlchemy test cases.
Funny enough, the problem is not observable on Linux?
[1] https://docs.python.org/3/library/datetime.html#datetime.date.today
"""

@mock.patch.dict(os.environ, {"TZ": "UTC"})
@time_machine.travel("2022-07-22T00:42:00+0200")
def test_date_today_depends_on_system_timezone_success_on_utc(self):
today_local = date.today()
today_utc = datetime.utcnow().date()
self.assertEqual(today_local, today_utc)
self.assertEqual(today_local, date(2022, 7, 21))
self.assertEqual(today_utc, date(2022, 7, 21))

@unittest.skipIf(sys.platform == "linux", "Problem not observable on Linux")
@mock.patch.dict(os.environ, {"TZ": "Europe/Prague"})
@time_machine.travel("2022-07-22T00:42:00+0200")
def test_date_today_depends_on_system_timezone_failure_on_non_utc(self):
today_local = date.today()
today_utc = datetime.utcnow().date()
self.assertNotEqual(today_local, today_utc)
self.assertEqual(today_local, date(2022, 7, 22))
self.assertEqual(today_utc, date(2022, 7, 21))

@mock.patch.dict(os.environ, {"TZ": "UTC"})
@time_machine.travel("2022-07-22T00:42:00+0200")
def test_date_today_utc(self):
today_local = date.today()
self.assertEqual(today_local, date(2022, 7, 21))

@unittest.skipIf(sys.platform == "linux", "Problem not observable on Linux")
@mock.patch.dict(os.environ, {"TZ": "Europe/Prague"})
@time_machine.travel("2022-07-22T00:42:00+0200")
def test_date_today_non_utc(self):
today_local = date.today()
self.assertEqual(today_local, date(2022, 7, 22))

@mock.patch.dict(os.environ, {"TZ": "UTC"})
@time_machine.travel("2022-07-22T00:42:00+0200")
def test_utcnow_date_utc(self):
today_utc = datetime.utcnow().date()
self.assertEqual(today_utc, date(2022, 7, 21))

@mock.patch.dict(os.environ, {"TZ": "Europe/Prague"})
@time_machine.travel("2022-07-22T00:42:00+0200")
def test_utcnow_date_non_utc(self):
today_utc = datetime.utcnow().date()
self.assertEqual(today_utc, date(2022, 7, 21))
3 changes: 3 additions & 0 deletions src/crate/testing/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import unittest
import doctest
import tempfile

from .test_datetime import DateTodayTest
from .test_layer import LayerUtilsTest


Expand Down Expand Up @@ -64,4 +66,5 @@ def test_suite():
)
suite.addTest(s)
suite.addTest(unittest.makeSuite(LayerUtilsTest))
suite.addTest(unittest.makeSuite(DateTodayTest))
return suite

0 comments on commit 07b8d79

Please sign in to comment.