From 8edd7c00fceaf70ee5b0f04b6a70b12c02cbfda7 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 4 Dec 2021 11:33:50 +0000 Subject: [PATCH 1/2] Switch from freezegun to time-machine. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s [more accurate](https://adamj.eu/tech/2020/06/03/introducing-time-machine/) and [faster](https://adamj.eu/tech/2021/02/19/freezegun-versus-time-machine/). --- requirements.txt | 2 +- tests/test_fields/test_monitor_field.py | 14 ++++++------ tests/test_models/test_status_model.py | 12 +++++------ tests/test_models/test_timestamped_model.py | 24 ++++++++++----------- tox.ini | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/requirements.txt b/requirements.txt index f7c07a6..0aa03cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,5 @@ tox sphinx +time-machine twine -freezegun diff --git a/tests/test_fields/test_monitor_field.py b/tests/test_fields/test_monitor_field.py index cca6762..21d8e80 100644 --- a/tests/test_fields/test_monitor_field.py +++ b/tests/test_fields/test_monitor_field.py @@ -1,7 +1,7 @@ from datetime import datetime +import time_machine from django.test import TestCase -from freezegun import freeze_time from model_utils.fields import MonitorField from tests.models import DoubleMonitored, Monitored, MonitorWhen, MonitorWhenEmpty @@ -9,7 +9,7 @@ from tests.models import DoubleMonitored, Monitored, MonitorWhen, MonitorWhenEmp class MonitorFieldTests(TestCase): def setUp(self): - with freeze_time(datetime(2016, 1, 1, 10, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 10, 0, 0)): self.instance = Monitored(name='Charlie') self.created = self.instance.name_changed @@ -18,7 +18,7 @@ class MonitorFieldTests(TestCase): self.assertEqual(self.instance.name_changed, self.created) def test_save_changed(self): - with freeze_time(datetime(2016, 1, 1, 12, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0)): self.instance.name = 'Maria' self.instance.save() self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0)) @@ -40,7 +40,7 @@ class MonitorWhenFieldTests(TestCase): Will record changes only when name is 'Jose' or 'Maria' """ def setUp(self): - with freeze_time(datetime(2016, 1, 1, 10, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 10, 0, 0)): self.instance = MonitorWhen(name='Charlie') self.created = self.instance.name_changed @@ -49,13 +49,13 @@ class MonitorWhenFieldTests(TestCase): self.assertEqual(self.instance.name_changed, self.created) def test_save_changed_to_Jose(self): - with freeze_time(datetime(2016, 1, 1, 12, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0)): self.instance.name = 'Jose' self.instance.save() self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0)) def test_save_changed_to_Maria(self): - with freeze_time(datetime(2016, 1, 1, 12, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0)): self.instance.name = 'Maria' self.instance.save() self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0)) @@ -111,7 +111,7 @@ class MonitorDoubleFieldTests(TestCase): def test_monitor_still_works_with_deferred_fields_filtered_out_of_save_initial(self): obj = DoubleMonitored.objects.defer('name').get(name='Charlie') - with freeze_time("2016-12-01"): + with time_machine.travel("2016-12-01"): obj.name = 'Charlie2' obj.save() self.assertEqual(obj.name_changed, datetime(2016, 12, 1)) diff --git a/tests/test_models/test_status_model.py b/tests/test_models/test_status_model.py index 2e31143..8cd2a9b 100644 --- a/tests/test_models/test_status_model.py +++ b/tests/test_models/test_status_model.py @@ -1,7 +1,7 @@ from datetime import datetime +import time_machine from django.test.testcases import TestCase -from freezegun import freeze_time from tests.models import Status, StatusCustomManager, StatusPlainTuple @@ -13,7 +13,7 @@ class StatusModelTests(TestCase): self.active = Status.STATUS.active def test_created(self): - with freeze_time(datetime(2016, 1, 1)): + with time_machine.travel(datetime(2016, 1, 1)): c1 = self.model.objects.create() self.assertTrue(c1.status_changed, datetime(2016, 1, 1)) @@ -43,10 +43,10 @@ class StatusModelTests(TestCase): accordingly when update_fields is used as an argument and status_changed is provided ''' - with freeze_time(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1)): t1 = Status.objects.create() - with freeze_time(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2)): t1.status = Status.on_hold t1.save(update_fields=['status', 'status_changed']) @@ -58,10 +58,10 @@ class StatusModelTests(TestCase): accordingly when update_fields is used as an argument with status and status_changed is not provided ''' - with freeze_time(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1)): t1 = Status.objects.create() - with freeze_time(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2)): t1.status = Status.on_hold t1.save(update_fields=['status']) diff --git a/tests/test_models/test_timestamped_model.py b/tests/test_models/test_timestamped_model.py index 0d13914..afaa022 100644 --- a/tests/test_models/test_timestamped_model.py +++ b/tests/test_models/test_timestamped_model.py @@ -1,14 +1,14 @@ from datetime import datetime, timedelta +import time_machine from django.test import TestCase -from freezegun import freeze_time from tests.models import TimeStamp, TimeStampWithStatusModel class TimeStampedModelTests(TestCase): def test_created(self): - with freeze_time(datetime(2016, 1, 1)): + with time_machine.travel(datetime(2016, 1, 1)): t1 = TimeStamp.objects.create() self.assertEqual(t1.created, datetime(2016, 1, 1)) @@ -20,10 +20,10 @@ class TimeStampedModelTests(TestCase): self.assertEqual(t1.created, t1.modified) def test_modified(self): - with freeze_time(datetime(2016, 1, 1)): + with time_machine.travel(datetime(2016, 1, 1)): t1 = TimeStamp.objects.create() - with freeze_time(datetime(2016, 1, 2)): + with time_machine.travel(datetime(2016, 1, 2)): t1.save() self.assertEqual(t1.modified, datetime(2016, 1, 2)) @@ -104,10 +104,10 @@ class TimeStampedModelTests(TestCase): for update_fields in tests: with self.subTest(update_fields=update_fields): - with freeze_time(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1)): t1 = TimeStamp.objects.create() - with freeze_time(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2)): t1.save(update_fields=update_fields) self.assertEqual(t1.modified, datetime(2020, 1, 2)) @@ -120,10 +120,10 @@ class TimeStampedModelTests(TestCase): for update_fields in tests: with self.subTest(update_fields=update_fields): - with freeze_time(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1)): t1 = TimeStamp.objects.create() - with freeze_time(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2)): t1.test_field = 1 t1.save(update_fields=update_fields) @@ -132,19 +132,19 @@ class TimeStampedModelTests(TestCase): self.assertEqual(t1.modified, datetime(2020, 1, 1)) def test_save_updates_modified_value_when_update_fields_explicitly_set_to_none(self): - with freeze_time(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1)): t1 = TimeStamp.objects.create() - with freeze_time(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2)): t1.save(update_fields=None) self.assertEqual(t1.modified, datetime(2020, 1, 2)) def test_model_inherit_timestampmodel_and_statusmodel(self): - with freeze_time(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1)): t1 = TimeStampWithStatusModel.objects.create() - with freeze_time(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2)): t1.save(update_fields=['test_field', 'status']) self.assertEqual(t1.modified, datetime(2020, 1, 2)) diff --git a/tox.ini b/tox.ini index 40a0556..adcc2e5 100644 --- a/tox.ini +++ b/tox.ini @@ -16,7 +16,7 @@ python = [testenv] deps = - freezegun==0.3.12 + time-machine==2.4.1 -rrequirements-test.txt dj22: Django==2.2.* dj31: Django==3.1.* From 262ac384ac2933741055ec979adfc978d6239753 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 4 Apr 2022 12:04:38 +0100 Subject: [PATCH 2/2] explicit timezones --- tests/test_fields/test_monitor_field.py | 22 ++++++------- tests/test_models/test_status_model.py | 14 ++++---- tests/test_models/test_timestamped_model.py | 36 ++++++++++----------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/test_fields/test_monitor_field.py b/tests/test_fields/test_monitor_field.py index 21d8e80..3d08174 100644 --- a/tests/test_fields/test_monitor_field.py +++ b/tests/test_fields/test_monitor_field.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone import time_machine from django.test import TestCase @@ -9,7 +9,7 @@ from tests.models import DoubleMonitored, Monitored, MonitorWhen, MonitorWhenEmp class MonitorFieldTests(TestCase): def setUp(self): - with time_machine.travel(datetime(2016, 1, 1, 10, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 10, 0, 0, tzinfo=timezone.utc)): self.instance = Monitored(name='Charlie') self.created = self.instance.name_changed @@ -18,10 +18,10 @@ class MonitorFieldTests(TestCase): self.assertEqual(self.instance.name_changed, self.created) def test_save_changed(self): - with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)): self.instance.name = 'Maria' self.instance.save() - self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0)) + self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)) def test_double_save(self): self.instance.name = 'Jose' @@ -40,7 +40,7 @@ class MonitorWhenFieldTests(TestCase): Will record changes only when name is 'Jose' or 'Maria' """ def setUp(self): - with time_machine.travel(datetime(2016, 1, 1, 10, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 10, 0, 0, tzinfo=timezone.utc)): self.instance = MonitorWhen(name='Charlie') self.created = self.instance.name_changed @@ -49,16 +49,16 @@ class MonitorWhenFieldTests(TestCase): self.assertEqual(self.instance.name_changed, self.created) def test_save_changed_to_Jose(self): - with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)): self.instance.name = 'Jose' self.instance.save() - self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0)) + self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)) def test_save_changed_to_Maria(self): - with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0)): + with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)): self.instance.name = 'Maria' self.instance.save() - self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0)) + self.assertEqual(self.instance.name_changed, datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)) def test_save_changed_to_Pedro(self): self.instance.name = 'Pedro' @@ -111,7 +111,7 @@ class MonitorDoubleFieldTests(TestCase): def test_monitor_still_works_with_deferred_fields_filtered_out_of_save_initial(self): obj = DoubleMonitored.objects.defer('name').get(name='Charlie') - with time_machine.travel("2016-12-01"): + with time_machine.travel(datetime(2016, 12, 1, tzinfo=timezone.utc)): obj.name = 'Charlie2' obj.save() - self.assertEqual(obj.name_changed, datetime(2016, 12, 1)) + self.assertEqual(obj.name_changed, datetime(2016, 12, 1, tzinfo=timezone.utc)) diff --git a/tests/test_models/test_status_model.py b/tests/test_models/test_status_model.py index 8cd2a9b..67d2951 100644 --- a/tests/test_models/test_status_model.py +++ b/tests/test_models/test_status_model.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone import time_machine from django.test.testcases import TestCase @@ -43,14 +43,14 @@ class StatusModelTests(TestCase): accordingly when update_fields is used as an argument and status_changed is provided ''' - with time_machine.travel(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1, tzinfo=timezone.utc)): t1 = Status.objects.create() - with time_machine.travel(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2, tzinfo=timezone.utc)): t1.status = Status.on_hold t1.save(update_fields=['status', 'status_changed']) - self.assertEqual(t1.status_changed, datetime(2020, 1, 2)) + self.assertEqual(t1.status_changed, datetime(2020, 1, 2, tzinfo=timezone.utc)) def test_save_with_update_fields_overrides_status_changed_not_provided(self): ''' @@ -58,14 +58,14 @@ class StatusModelTests(TestCase): accordingly when update_fields is used as an argument with status and status_changed is not provided ''' - with time_machine.travel(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1, tzinfo=timezone.utc)): t1 = Status.objects.create() - with time_machine.travel(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2, tzinfo=timezone.utc)): t1.status = Status.on_hold t1.save(update_fields=['status']) - self.assertEqual(t1.status_changed, datetime(2020, 1, 2)) + self.assertEqual(t1.status_changed, datetime(2020, 1, 2, tzinfo=timezone.utc)) class StatusModelPlainTupleTests(StatusModelTests): diff --git a/tests/test_models/test_timestamped_model.py b/tests/test_models/test_timestamped_model.py index afaa022..853bc76 100644 --- a/tests/test_models/test_timestamped_model.py +++ b/tests/test_models/test_timestamped_model.py @@ -1,4 +1,4 @@ -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone import time_machine from django.test import TestCase @@ -8,9 +8,9 @@ from tests.models import TimeStamp, TimeStampWithStatusModel class TimeStampedModelTests(TestCase): def test_created(self): - with time_machine.travel(datetime(2016, 1, 1)): + with time_machine.travel(datetime(2016, 1, 1, tzinfo=timezone.utc)): t1 = TimeStamp.objects.create() - self.assertEqual(t1.created, datetime(2016, 1, 1)) + self.assertEqual(t1.created, datetime(2016, 1, 1, tzinfo=timezone.utc)) def test_created_sets_modified(self): ''' @@ -20,13 +20,13 @@ class TimeStampedModelTests(TestCase): self.assertEqual(t1.created, t1.modified) def test_modified(self): - with time_machine.travel(datetime(2016, 1, 1)): + with time_machine.travel(datetime(2016, 1, 1, tzinfo=timezone.utc)): t1 = TimeStamp.objects.create() - with time_machine.travel(datetime(2016, 1, 2)): + with time_machine.travel(datetime(2016, 1, 2, tzinfo=timezone.utc)): t1.save() - self.assertEqual(t1.modified, datetime(2016, 1, 2)) + self.assertEqual(t1.modified, datetime(2016, 1, 2, tzinfo=timezone.utc)) def test_overriding_created_via_object_creation_also_uses_creation_date_for_modified(self): """ @@ -104,12 +104,12 @@ class TimeStampedModelTests(TestCase): for update_fields in tests: with self.subTest(update_fields=update_fields): - with time_machine.travel(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1, tzinfo=timezone.utc)): t1 = TimeStamp.objects.create() - with time_machine.travel(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2, tzinfo=timezone.utc)): t1.save(update_fields=update_fields) - self.assertEqual(t1.modified, datetime(2020, 1, 2)) + self.assertEqual(t1.modified, datetime(2020, 1, 2, tzinfo=timezone.utc)) def test_save_is_skipped_for_empty_update_fields_iterable(self): tests = ( @@ -120,31 +120,31 @@ class TimeStampedModelTests(TestCase): for update_fields in tests: with self.subTest(update_fields=update_fields): - with time_machine.travel(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1, tzinfo=timezone.utc)): t1 = TimeStamp.objects.create() - with time_machine.travel(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2, tzinfo=timezone.utc)): t1.test_field = 1 t1.save(update_fields=update_fields) t1.refresh_from_db() self.assertEqual(t1.test_field, 0) - self.assertEqual(t1.modified, datetime(2020, 1, 1)) + self.assertEqual(t1.modified, datetime(2020, 1, 1, tzinfo=timezone.utc)) def test_save_updates_modified_value_when_update_fields_explicitly_set_to_none(self): - with time_machine.travel(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1, tzinfo=timezone.utc)): t1 = TimeStamp.objects.create() - with time_machine.travel(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2, tzinfo=timezone.utc)): t1.save(update_fields=None) - self.assertEqual(t1.modified, datetime(2020, 1, 2)) + self.assertEqual(t1.modified, datetime(2020, 1, 2, tzinfo=timezone.utc)) def test_model_inherit_timestampmodel_and_statusmodel(self): - with time_machine.travel(datetime(2020, 1, 1)): + with time_machine.travel(datetime(2020, 1, 1, tzinfo=timezone.utc)): t1 = TimeStampWithStatusModel.objects.create() - with time_machine.travel(datetime(2020, 1, 2)): + with time_machine.travel(datetime(2020, 1, 2, tzinfo=timezone.utc)): t1.save(update_fields=['test_field', 'status']) - self.assertEqual(t1.modified, datetime(2020, 1, 2)) + self.assertEqual(t1.modified, datetime(2020, 1, 2, tzinfo=timezone.utc))