Commit c175a703 authored by Barry Warsaw's avatar Barry Warsaw

* Mailman 3 no longer uses ``zc.buildout`` and tests are now run by the

   ``nose2`` test runner.  See ``src/mailman/docs/START.rst`` for details on
   how to build Mailman and run the test suite.
parents 41059ed2 275748b9
......@@ -101,14 +101,14 @@ case second `m'. Any other spelling is incorrect.""",
'lazr.config',
'lazr.smtptest',
'mock',
'nose2',
'passlib',
'restish',
'storm',
'zc.buildout',
'zope.component',
'zope.configuration',
'zope.event',
'zope.interface',
'zope.testing<4',
],
test_suite = 'nose2.collector.collector',
)
......@@ -44,7 +44,7 @@ except ImportError:
#
# Do *not* do this if we're building the documentation.
if 'build_sphinx' not in sys.argv:
if sys.argv[0].split(os.sep)[-1] == 'test':
if any('nose2' in arg for arg in sys.argv):
from mailman.testing.i18n import initialize
else:
from mailman.core.i18n import initialize
......
......@@ -52,8 +52,9 @@ script that will produce no output to force the hooks to run.
>>> import subprocess
>>> from mailman.testing.layers import ConfigLayer
>>> def call():
... exe = os.path.join(os.path.dirname(sys.executable), 'mailman')
... proc = subprocess.Popen(
... 'bin/mailman lists --domain ignore -q'.split(),
... [exe, 'lists', '--domain', 'ignore', '-q'],
... cwd=ConfigLayer.root_directory,
... env=dict(MAILMAN_CONFIG_FILE=config_path,
... PYTHONPATH=config_directory),
......
......@@ -12,6 +12,12 @@ Here is a history of user visible changes to Mailman.
===============================
(2013-XX-XX)
Development
-----------
* Mailman 3 no longer uses ``zc.buildout`` and tests are now run by the
``nose2`` test runner. See ``src/mailman/docs/START.rst`` for details on
how to build Mailman and run the test suite.
REST
----
* Add ``reply_to_address`` and ``first_strip_reply_to`` as writable
......
......@@ -39,44 +39,43 @@ Python 2.7 is required. It can either be the default 'python' on your
If your operating system does not include Python, see http://www.python.org
downloading and installing it from source. Python 3 is not yet supported.
In this documentation, a bare ``python`` refers to the Python executable used
to invoke ``bootstrap.py``.
Mailman 3 is now based on the `zc.buildout`_ infrastructure, which greatly
simplifies testing Mailman. Buildout is not required for installation.
During the beta program, you may need some additional dependencies, such as a
C compiler and the Python development headers and libraries. You will need an
internet connection.
You may need some additional dependencies, which are either available from
your OS vendor, or can be downloaded automatically from the `Python
Cheeseshop`_.
Building Mailman 3
==================
We provide several recipes for building Mailman. All should generally work,
but some may provide a better experience for developing Mailman versus
deploying Mailman.
To build Mailman for development purposes, you will create a virtual
environment. You need to have the `virtualenv`_ program installed.
Building for development
------------------------
The best way to build Mailman for development is to use the `zc.buildout`_
tools. This will download all Mailman dependencies from the `Python
Cheeseshop`_. The dependencies will get installed locally, but isolated from
your system Python. Here are the commands to build Mailman for development::
First, create a virtual environment. By default ``virtualenv`` uses the
``python`` executable it finds first on your ``$PATH``. Make sure this is
Python 2.7. The directory you install the virtualenv into is up to you, but
for purposes of this document, we'll install it into ``/tmp/py27``::
% virtualenv --system-site-packages /tmp/py27
Now, activate the virtual environment and set it up for development::
% python bootstrap.py
% bin/buildout
% source /tmp/py27/bin/activate
% python setup.py develop
Sit back and have some Kombucha while you wait for everything to download and
install.
Now you can run the test suite via::
% bin/test -vv
% nose2 -v
You should see no failures.
You should see no failures. You can also run a subset of the full test suite
by filter tests on the module or test name using the ``-P`` option::
% nose2 -v -P user
Build the online docs by running::
......@@ -91,21 +90,6 @@ doctests by looking in all the 'doc' directories under the 'mailman' package.
Doctests are documentation first, so they should give you a pretty good idea
how various components of Mailman 3 work.
Building for deployment using virtualenv
----------------------------------------
`virtualenv`_ is a way to create isolated Python environments. You can use
virtualenv as a way to deploy Mailman without installing it into your system
Python. There are lots of ways to use virtualenv, but as described here, it
will be default use any dependencies which are already installed in your
system, downloading from the Cheeseshop only those which are missing. Here
are the steps to install Mailman using virtualenv::
$ virtualenv --system-site-packages /path/to/your/installation
$ source /path/to/your/installation/bin/activate
$ python setup.py install
Once everything is downloaded and installed, you can initialize Mailman and
get a display of the basic configuration settings by running::
......@@ -190,7 +174,6 @@ email application that speaks LMTP or SMTP will be able to use Hyperkitty.
A `five minute guide to Hyperkitty`_ is based on Toshio Kuratomi's README.
.. _`zc.buildout`: http://pypi.python.org/pypi/zc.buildout
.. _`Postorius`: https://launchpad.net/postorius
.. _`Hyperkitty`: https://launchpad.net/hyperkitty
.. _`Django`: http://djangoproject.org/
......
# Copyright (C) 2011-2013 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/>.
"""Set up testing.
This is used as an interface to buildout.cfg's [test] section.
zope.testrunner supports an initialization variable. It is set to import and
run the following test initialization method.
"""
from __future__ import absolute_import, unicode_literals
__metaclass__ = type
__all__ = [
'initialize',
]
def initialize(root_directory):
"""Initialize the test infrastructure."""
from mailman.testing import layers
layers.MockAndMonkeyLayer.testing_mode = True
layers.ConfigLayer.enable_stderr();
layers.ConfigLayer.set_root_directory(root_directory)
......@@ -25,23 +25,16 @@ from __future__ import absolute_import, unicode_literals
__metaclass__ = type
__all__ = [
'test_suite',
'setup',
'teardown'
]
import os
import sys
import doctest
import unittest
from inspect import isfunction, ismethod
import mailman
from mailman.app.lifecycle import create_list
from mailman.config import config
from mailman.testing.helpers import (
call_api, chdir, specialized_message_from_string)
from mailman.testing.helpers import call_api, specialized_message_from_string
from mailman.testing.layers import SMTPLayer
......@@ -181,53 +174,3 @@ def teardown(testobj):
cleanup()
else:
cleanup[0](*cleanup[1:])
def test_suite():
"""Create test suites for all .rst documentation tests.
.txt files are also tested, but .rst is highly preferred.
"""
suite = unittest.TestSuite()
topdir = os.path.dirname(mailman.__file__)
packages = []
for dirpath, dirnames, filenames in os.walk(topdir):
if 'docs' in dirnames:
docsdir = os.path.join(dirpath, 'docs')[len(topdir)+1:]
packages.append(docsdir)
# Under higher verbosity settings, report all doctest errors, not just the
# first one.
flags = (doctest.ELLIPSIS |
doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_NDIFF)
# Add all the doctests in all subpackages.
doctest_files = {}
with chdir(topdir):
for docsdir in packages:
# Look to see if the package defines a test layer, otherwise use
# SMTPLayer.
package_path = 'mailman.' + DOT.join(docsdir.split(os.sep))
try:
__import__(package_path)
except ImportError:
layer = SMTPLayer
else:
layer = getattr(sys.modules[package_path], 'layer', SMTPLayer)
for filename in os.listdir(docsdir):
base, extension = os.path.splitext(filename)
if os.path.splitext(filename)[1] in ('.txt', '.rst'):
module_path = package_path + '.' + base
doctest_files[module_path] = (
os.path.join(docsdir, filename), layer)
for module_path in sorted(doctest_files):
path, layer = doctest_files[module_path]
test = doctest.DocFileSuite(
path,
package='mailman',
optionflags=flags,
setUp=setup,
tearDown=teardown)
test.layer = layer
suite.addTest(test)
return suite
......@@ -154,7 +154,7 @@ class ConfigLayer(MockAndMonkeyLayer):
continue
logger_name = 'mailman.' + sub_name
log = logging.getLogger(logger_name)
log.propagate = True
#log.propagate = True
# Reopen the file to a new path that tests can get at. Instead of
# using the configuration file path though, use a path that's
# specific to the logger so that tests can find expected output
......
# Copyright (C) 2013 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/>.
"""nose2 test infrastructure."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'NosePlugin',
]
import os
import re
import doctest
import mailman
import importlib
from mailman.testing.documentation import setup, teardown
from mailman.testing.layers import ConfigLayer, MockAndMonkeyLayer, SMTPLayer
from nose2.events import Plugin
DOT = '.'
FLAGS = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF
TOPDIR = os.path.dirname(mailman.__file__)
class NosePlugin(Plugin):
configSection = 'mailman'
def __init__(self):
super(NosePlugin, self).__init__()
self.patterns = []
self.addArgument(self.patterns, 'P', 'pattern',
'Add a test matching pattern')
def startTestRun(self, event):
MockAndMonkeyLayer.testing_mode = True
ConfigLayer.enable_stderr()
def getTestCaseNames(self, event):
if len(self.patterns) == 0:
# No filter patterns, so everything should be tested.
return
# Does the pattern match the fully qualified class name?
for pattern in self.patterns:
full_name = '{}.{}'.format(
event.testCase.__module__, event.testCase.__name__)
if re.search(pattern, full_name):
# Don't suppress this test class.
return
names = filter(event.isTestMethod, dir(event.testCase))
for name in names:
for pattern in self.patterns:
if re.search(pattern, name):
break
else:
event.excludedNames.append(name)
def handleFile(self, event):
path = event.path[len(TOPDIR)+1:]
if len(self.patterns) > 0:
for pattern in self.patterns:
if re.search(pattern, path):
break
else:
# Skip this doctest.
return
base, ext = os.path.splitext(path)
if ext != '.rst':
return
# Look to see if the package defines a test layer, otherwise use the
# default layer. First turn the file system path into a dotted Python
# module path.
parent = os.path.dirname(path)
dotted = 'mailman.' + DOT.join(parent.split(os.path.sep))
try:
module = importlib.import_module(dotted)
except ImportError:
layer = SMTPLayer
else:
layer = getattr(module, 'layer', SMTPLayer)
test = doctest.DocFileTest(
path, package='mailman',
optionflags=FLAGS,
setUp=setup,
tearDown=teardown)
test.layer = layer
# Suppress the extra "Doctest: ..." line.
test.shortDescription = lambda: None
event.extraTests.append(test)
[unittest]
verbose = 2
plugins = mailman.testing.nose
nose2.plugins.layers
[mailman]
always-on = True
[log-capture]
always-on = False
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment