summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBarry Warsaw2009-02-17 21:40:55 -0500
committerBarry Warsaw2009-02-17 21:40:55 -0500
commit1f4c4e107f24cbb36110e8cb88908b34bac74b01 (patch)
tree9879c2cc638b3c9517019af7b83388429274cf47 /src
parent9c28502b5d8b1fc2388354c19e81a18a0e3c0088 (diff)
downloadmailman-1f4c4e107f24cbb36110e8cb88908b34bac74b01.tar.gz
mailman-1f4c4e107f24cbb36110e8cb88908b34bac74b01.tar.zst
mailman-1f4c4e107f24cbb36110e8cb88908b34bac74b01.zip
Add a "mock and monkey" layer to set up testing infrastructure, e.g. for
predictable dates and times. Fill out the autorespond.txt test to show that when the date flips over, the response counts reset. Add a date/time factory which we should use rather than the built-in datetime for now() and today() so that they can be appropriately tested.
Diffstat (limited to 'src')
-rw-r--r--src/mailman/database/autorespond.py6
-rw-r--r--src/mailman/docs/autorespond.txt10
-rw-r--r--src/mailman/testing/layers.py21
-rw-r--r--src/mailman/utilities/datetime.py69
4 files changed, 102 insertions, 4 deletions
diff --git a/src/mailman/database/autorespond.py b/src/mailman/database/autorespond.py
index 9561e804c..0a22dfa14 100644
--- a/src/mailman/database/autorespond.py
+++ b/src/mailman/database/autorespond.py
@@ -27,7 +27,6 @@ __all__ = [
]
-from datetime import date
from storm.locals import And, Date, Int, Reference
from zope.interface import implements
@@ -37,6 +36,7 @@ from mailman.database.types import Enum
from mailman.interfaces.autorespond import (
IAutoResponseRecord, IAutoResponseSet, Response)
from mailman.interfaces.mailinglist import IMailingList
+from mailman.utilities.datetime import today
@@ -58,7 +58,7 @@ class AutoResponseRecord(Model):
self.mailing_list = mailing_list
self.address = address
self.response_type = response_type
- self.date_sent = date.today()
+ self.date_sent = today()
@@ -75,7 +75,7 @@ class AutoResponseSet:
And(AutoResponseRecord.address == address,
AutoResponseRecord.mailing_list == self._mailing_list,
AutoResponseRecord.response_type == response_type,
- AutoResponseRecord.date_sent == date.today())).count()
+ AutoResponseRecord.date_sent == today())).count()
def response_sent(self, address, response_type):
"""See `IAutoResponseSet`."""
diff --git a/src/mailman/docs/autorespond.txt b/src/mailman/docs/autorespond.txt
index 29af740ec..d2e4797f7 100644
--- a/src/mailman/docs/autorespond.txt
+++ b/src/mailman/docs/autorespond.txt
@@ -60,3 +60,13 @@ Let's send one more.
1
>>> response_set.todays_count(address, Response.command)
2
+
+Now the day flips over and all the counts reset.
+
+ >>> from mailman.utilities.datetime import factory
+ >>> factory.fast_forward()
+
+ >>> response_set.todays_count(address, Response.hold)
+ 0
+ >>> response_set.todays_count(address, Response.command)
+ 0
diff --git a/src/mailman/testing/layers.py b/src/mailman/testing/layers.py
index 19300ba1e..3f7e63406 100644
--- a/src/mailman/testing/layers.py
+++ b/src/mailman/testing/layers.py
@@ -22,6 +22,7 @@ from __future__ import absolute_import, unicode_literals
__metaclass__ = type
__all__ = [
'ConfigLayer',
+ 'MockAndMonkeyLayer',
'SMTPLayer',
]
@@ -40,6 +41,7 @@ from mailman.core import initialize
from mailman.core.logging import get_handler
from mailman.i18n import _
from mailman.testing.helpers import SMTPServer
+from mailman.utilities.datetime import factory
from mailman.utilities.string import expand
@@ -47,7 +49,24 @@ NL = '\n'
-class ConfigLayer:
+class MockAndMonkeyLayer:
+ """Layer for mocking and monkey patching for testing."""
+
+ @classmethod
+ def setUp(cls):
+ factory.testing_mode = True
+
+ @classmethod
+ def tearDown(cls):
+ factory.testing_mode = False
+
+ @classmethod
+ def testTearDown(cls):
+ factory.reset()
+
+
+
+class ConfigLayer(MockAndMonkeyLayer):
"""Layer for pushing and popping test configurations."""
var_dir = None
diff --git a/src/mailman/utilities/datetime.py b/src/mailman/utilities/datetime.py
new file mode 100644
index 000000000..764b2eecd
--- /dev/null
+++ b/src/mailman/utilities/datetime.py
@@ -0,0 +1,69 @@
+# Copyright (C) 2009 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Datetime utilities.
+
+Use these functions to produce variable times rather than the built-in
+datetime.datetime.now() and datetime.date.today(). These are better
+instrumented for testing purposes.
+"""
+
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ ]
+
+
+import datetime
+
+
+
+class DateFactory:
+ """A factory for today() and now() that works with testing."""
+
+ # Set to True to produce predictable dates and times.
+ testing_mode = False
+ # The predictable time.
+ predictable_now = None
+ predictable_today = None
+
+ def now(self, tz=None):
+ return (self.predictable_now
+ if self.testing_mode
+ else datetime.datetime.now(tz))
+
+ def today(self):
+ return (self.predictable_today
+ if self.testing_mode
+ else datetime.date.today())
+
+ @classmethod
+ def reset(cls):
+ cls.predictable_now = datetime.datetime(2005, 8, 1, 7, 49, 23)
+ cls.predictable_today = cls.predictable_now.today()
+
+ @classmethod
+ def fast_forward(cls, days=1):
+ cls.predictable_today += datetime.timedelta(days=days)
+
+
+factory = DateFactory()
+factory.reset()
+today = factory.today
+now = factory.now