diff options
| -rw-r--r-- | src/mailman/testing/documentation.py | 12 | ||||
| -rw-r--r-- | src/mailman/testing/helpers.py | 66 | ||||
| -rw-r--r-- | src/mailman/testing/i18n.py | 10 | ||||
| -rw-r--r-- | src/mailman/testing/layers.py | 27 | ||||
| -rw-r--r-- | src/mailman/testing/mta.py | 11 | ||||
| -rw-r--r-- | src/mailman/testing/nose.py | 20 |
6 files changed, 47 insertions, 99 deletions
diff --git a/src/mailman/testing/documentation.py b/src/mailman/testing/documentation.py index ccc34de1f..f3a6e335a 100644 --- a/src/mailman/testing/documentation.py +++ b/src/mailman/testing/documentation.py @@ -21,13 +21,8 @@ Note that doctest extraction does not currently work for zip file distributions. doctest discovery currently requires file system traversal. """ -__all__ = [ - 'setup', - 'teardown' - ] - - from inspect import isfunction, ismethod +from mailman import public from mailman.app.lifecycle import create_list from mailman.config import config from mailman.testing.helpers import call_api, specialized_message_from_string @@ -38,7 +33,6 @@ DOT = '.' COMMASPACE = ', ' - def stop(): """Call into pdb.set_trace()""" # Do the import here so that you get the wacky special hacked pdb instead @@ -138,7 +132,7 @@ def dump_json(url, data=None, method=None, username=None, password=None): print('{}: {}'.format(key, value)) - +@public def setup(testobj): """Test setup.""" # In general, I don't like adding convenience functions, since I think @@ -159,7 +153,7 @@ def setup(testobj): testobj.globs['cleanups'] = [] - +@public def teardown(testobj): for cleanup in testobj.globs['cleanups']: if isfunction(cleanup) or ismethod(cleanup): diff --git a/src/mailman/testing/helpers.py b/src/mailman/testing/helpers.py index e0d46cd20..302198396 100644 --- a/src/mailman/testing/helpers.py +++ b/src/mailman/testing/helpers.py @@ -17,28 +17,6 @@ """Various test helpers.""" -__all__ = [ - 'LogFileMark', - 'TestableMaster', - 'call_api', - 'chdir', - 'configuration', - 'digest_mbox', - 'event_subscribers', - 'get_lmtp_client', - 'get_nntp_server', - 'get_queue_messages', - 'make_digest_messages', - 'make_testable_runner', - 'reset_the_world', - 'set_preferred', - 'specialized_message_from_string', - 'subscribe', - 'temporary_db', - 'wait_for_webservice', - ] - - import os import json import time @@ -57,6 +35,7 @@ from contextlib import contextmanager from email import message_from_string from httplib2 import Http from lazr.config import as_timedelta +from mailman import public from mailman.bin.master import Loop as Master from mailman.config import config from mailman.database.transaction import transaction @@ -77,7 +56,7 @@ from zope.component import getUtility NL = '\n' - +@public def make_testable_runner(runner_class, name=None, predicate=None): """Create a runner that runs until its queue is empty. @@ -115,13 +94,13 @@ def make_testable_runner(runner_class, name=None, predicate=None): return EmptyingRunner(name) - class _Bag: def __init__(self, **kws): for key, value in kws.items(): setattr(self, key, value) +@public def get_queue_messages(queue_name, sort_on=None, expected_count=None): """Return and clear all the messages in the given queue. @@ -147,7 +126,7 @@ def get_queue_messages(queue_name, sort_on=None, expected_count=None): return messages - +@public def digest_mbox(mlist): """The mailing list's pending digest as a mailbox. @@ -158,8 +137,8 @@ def digest_mbox(mlist): return Mailbox(path) - # Remember, Master is mailman.bin.master.Loop. +@public class TestableMaster(Master): """A testable master loop watcher.""" @@ -228,7 +207,6 @@ class TestableMaster(Master): yield from self._started_kids - class LMTP(smtplib.SMTP): """Like a normal SMTP client, but for LMTP.""" def lhlo(self, name=''): @@ -238,12 +216,13 @@ class LMTP(smtplib.SMTP): return code, msg +@public def get_lmtp_client(quiet=False): """Return a connected LMTP client.""" # It's possible the process has started but is not yet accepting # connections. Wait a little while. lmtp = LMTP() - #lmtp.debuglevel = 1 + # lmtp.debuglevel = 1 until = datetime.datetime.now() + as_timedelta(config.devmode.wait) while datetime.datetime.now() < until: try: @@ -261,7 +240,7 @@ def get_lmtp_client(quiet=False): raise RuntimeError('Connection refused') - +@public def get_nntp_server(cleanups): """Create and start an NNTP server mock. @@ -272,14 +251,14 @@ def get_nntp_server(cleanups): cleanups.append(patcher.stop) nntpd = server_class() # A class for more convenient access to the posted message. - class NNTPProxy: + class NNTPProxy: # flake8: noqa def get_message(self): args = nntpd.post.call_args return specialized_message_from_string(args[0][0].read()) return NNTPProxy() - +@public def wait_for_webservice(): """Wait for the REST server to start serving requests.""" until = datetime.datetime.now() + as_timedelta(config.devmode.wait) @@ -298,6 +277,7 @@ def wait_for_webservice(): raise RuntimeError('Connection refused') +@public def call_api(url, data=None, method=None, username=None, password=None): """'Call a URL with a given HTTP method and return the resulting object. @@ -351,7 +331,7 @@ def call_api(url, data=None, method=None, username=None, password=None): return json.loads(content), response - +@public @contextmanager def event_subscribers(*subscribers): """Temporarily extend the Zope event subscribers list. @@ -368,7 +348,7 @@ def event_subscribers(*subscribers): event.subscribers[:] = old_subscribers - +@public class configuration: """A decorator/context manager for temporarily setting configurations.""" @@ -410,7 +390,7 @@ class configuration: return wrapper - +@public @contextmanager def temporary_db(db): real_db = config.db @@ -421,7 +401,7 @@ def temporary_db(db): config.db = real_db - +@public class chdir: """A context manager for temporary directory changing.""" def __init__(self, directory): @@ -438,16 +418,16 @@ class chdir: return False - +@public def subscribe(mlist, first_name, role=MemberRole.member, email=None): """Helper for subscribing a sample person to a mailing list. Returns the newly created member object. """ user_manager = getUtility(IUserManager) - email = ('{0}person@example.com'.format(first_name[0].lower()) + email = ('{}person@example.com'.format(first_name[0].lower()) if email is None else email) - full_name = '{0} Person'.format(first_name) + full_name = '{} Person'.format(first_name) with transaction(): person = user_manager.get_user(email) if person is None: @@ -464,7 +444,7 @@ def subscribe(mlist, first_name, role=MemberRole.member, email=None): return roster.get_member(email) - +@public def reset_the_world(): """Reset everything: @@ -504,7 +484,7 @@ def reset_the_world(): config.chains['header-match'].flush() - +@public def specialized_message_from_string(unicode_text): """Parse text into a message object. @@ -523,7 +503,7 @@ def specialized_message_from_string(unicode_text): return message - +@public class LogFileMark: def __init__(self, log_name): self._log = logging.getLogger(log_name) @@ -541,7 +521,7 @@ class LogFileMark: return fp.read() - +@public def make_digest_messages(mlist, msg=None): if msg is None: msg = specialized_message_from_string("""\ @@ -562,7 +542,7 @@ message triggering a digest runner.run() - +@public def set_preferred(user): # Avoid circular imports. from mailman.utilities.datetime import now diff --git a/src/mailman/testing/i18n.py b/src/mailman/testing/i18n.py index 92189302c..2031be307 100644 --- a/src/mailman/testing/i18n.py +++ b/src/mailman/testing/i18n.py @@ -17,19 +17,13 @@ """Internationalization for the tests.""" -__all__ = [ - 'TestingStrategy', - 'initialize', - ] - - from contextlib import closing from flufl.i18n import registry from gettext import GNUTranslations, NullTranslations +from mailman import public from pkg_resources import resource_stream - class TestingStrategy: """A strategy that finds catalogs in the testing directory.""" @@ -44,7 +38,7 @@ class TestingStrategy: return GNUTranslations(fp) - +@public def initialize(): """Install a global underscore function for testing purposes.""" # Avoid circular imports. diff --git a/src/mailman/testing/layers.py b/src/mailman/testing/layers.py index 494aeb35a..c282689d1 100644 --- a/src/mailman/testing/layers.py +++ b/src/mailman/testing/layers.py @@ -24,16 +24,6 @@ # the full test run. For now, I'll ignore that, but I do want to eventually # get rid of the layers and use something like testresources or some such. -__all__ = [ - 'ConfigLayer', - 'LMTPLayer', - 'MockAndMonkeyLayer', - 'RESTLayer', - 'SMTPLayer', - 'is_testing', - ] - - import os import sys import shutil @@ -42,6 +32,7 @@ import datetime import tempfile from lazr.config import as_boolean +from mailman import public from mailman.config import config from mailman.core import initialize from mailman.core.initialize import INHIBIT_CONFIG_FILE @@ -61,7 +52,7 @@ TEST_TIMEOUT = datetime.timedelta(seconds=5) NL = '\n' - +@public class MockAndMonkeyLayer: """Layer for mocking and monkey patching for testing.""" @@ -81,7 +72,7 @@ class MockAndMonkeyLayer: cls._resets.append(reset) - +@public class ConfigLayer(MockAndMonkeyLayer): """Layer for pushing and popping test configurations.""" @@ -120,11 +111,11 @@ class ConfigLayer(MockAndMonkeyLayer): [mailman] layout: testing [paths.testing] - var_dir: {0} + var_dir: {} [devmode] testing: yes [mta] - configuration: {1} + configuration: {} """.format(cls.var_dir, postfix_cfg)) # Read the testing config and push it. more = resource_bytes('mailman.testing', 'testing.cfg') @@ -228,7 +219,7 @@ class ConfigLayer(MockAndMonkeyLayer): cls.root_directory = directory - +@public class SMTPLayer(ConfigLayer): """Layer for starting, stopping, and accessing a test SMTP server.""" @@ -260,7 +251,7 @@ class SMTPLayer(ConfigLayer): cls.smtpd.clear() - +@public class LMTPLayer(ConfigLayer): """Layer for starting, stopping, and accessing a test LMTP server.""" @@ -289,7 +280,7 @@ class LMTPLayer(ConfigLayer): pass - +@public class RESTLayer(SMTPLayer): """Layer for starting, stopping, and accessing the test REST layer.""" @@ -308,7 +299,7 @@ class RESTLayer(SMTPLayer): cls.server = None - +@public def is_testing(): """Return a 'testing' flag for use with the predictable factories. diff --git a/src/mailman/testing/mta.py b/src/mailman/testing/mta.py index 9642803e2..c1327f428 100644 --- a/src/mailman/testing/mta.py +++ b/src/mailman/testing/mta.py @@ -17,15 +17,11 @@ """Fake MTA for testing purposes.""" -__all__ = [ - 'FakeMTA', - ] - - import logging from lazr.smtptest.controller import QueueController from lazr.smtptest.server import Channel, QueueServer +from mailman import public from mailman.interfaces.mta import IMailTransportAgentLifecycle from queue import Empty, Queue from zope.interface import implementer @@ -34,7 +30,7 @@ from zope.interface import implementer log = logging.getLogger('lazr.smtptest') - +@public @implementer(IMailTransportAgentLifecycle) class FakeMTA: """Fake MTA for testing purposes.""" @@ -49,7 +45,6 @@ class FakeMTA: pass - class StatisticsChannel(Channel): """A channel that can answers to the fake STAT command.""" @@ -134,7 +129,6 @@ class StatisticsChannel(Channel): super().found_terminator() - class ConnectionCountingServer(QueueServer): """Count the number of SMTP connections opened.""" @@ -210,7 +204,6 @@ class ConnectionCountingServer(QueueServer): self._oob_queue.put(arg) - class ConnectionCountingController(QueueController): """Count the number of SMTP connections opened.""" diff --git a/src/mailman/testing/nose.py b/src/mailman/testing/nose.py index c969f087d..0a5608c7a 100644 --- a/src/mailman/testing/nose.py +++ b/src/mailman/testing/nose.py @@ -17,16 +17,12 @@ """nose2 test infrastructure.""" -__all__ = [ - 'NosePlugin', - ] - - import os import re import doctest import importlib +from mailman import public from mailman.testing.documentation import setup, teardown from mailman.testing.layers import ConfigLayer, MockAndMonkeyLayer, SMTPLayer from nose2.events import Plugin @@ -38,7 +34,7 @@ FLAGS = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF TOPDIR = os.path.dirname(resource_filename('mailman', '__init__.py')) - +@public class NosePlugin(Plugin): configSection = 'mailman' @@ -46,7 +42,7 @@ class NosePlugin(Plugin): super().__init__() self.patterns = [] self.stderr = False - def set_stderr(ignore): + def set_stderr(ignore): # flake8: noqa self.stderr = True self.addArgument(self.patterns, 'P', 'pattern', 'Add a test matching pattern') @@ -55,7 +51,7 @@ class NosePlugin(Plugin): def startTestRun(self, event): MockAndMonkeyLayer.testing_mode = True - if ( self.stderr or + if (self.stderr or len(os.environ.get('MM_VERBOSE_TESTLOG', '').strip()) > 0): ConfigLayer.stderr = True @@ -115,8 +111,8 @@ class NosePlugin(Plugin): test.shortDescription = lambda: None event.extraTests.append(test) - ## def startTest(self, event): - ## import sys; print('vvvvv', event.test, file=sys.stderr) + # def startTest(self, event): + # import sys; print('vvvvv', event.test, file=sys.stderr) - ## def stopTest(self, event): - ## import sys; print('^^^^^', event.test, file=sys.stderr) + # def stopTest(self, event): + # import sys; print('^^^^^', event.test, file=sys.stderr) |
