diff --git a/src/postorius/doc/_build/doctrees/development.doctree b/src/postorius/doc/_build/doctrees/development.doctree index 497bce1..c375a54 100644 --- a/src/postorius/doc/_build/doctrees/development.doctree +++ b/src/postorius/doc/_build/doctrees/development.doctree Binary files differ diff --git a/src/postorius/doc/_build/doctrees/environment.pickle b/src/postorius/doc/_build/doctrees/environment.pickle index d60ef22..6381f4a 100644 --- a/src/postorius/doc/_build/doctrees/environment.pickle +++ b/src/postorius/doc/_build/doctrees/environment.pickle Binary files differ diff --git a/src/postorius/doc/_build/html/_sources/development.txt b/src/postorius/doc/_build/html/_sources/development.txt index 3dc92b9..002310d 100644 --- a/src/postorius/doc/_build/html/_sources/development.txt +++ b/src/postorius/doc/_build/html/_sources/development.txt @@ -2,7 +2,6 @@ Development =========== - This is a short guide to help you get started with Postorius development. @@ -35,16 +34,52 @@ views.py # View classes and functions for all views connected # in urls.py generic.py # Generic class-based views; Currently holds a - # class for view based on a single mailing list + # class for views based on a single mailing list + + +Writing View Code +================= + +When the work on Postorius was started, the standard way to write view code in +Django was to write a single function for each different view. Since then +Django has introduced so-called 'class-based views' which make it much easier +to reuse view functionality. While using simple functions is not discuraged, it +makes sense to check if using a class-based approach could make sense. + +Check Postorius' ``views/views.py`` and ``views/generic.py`` for examples! Authentication/Authorization ============================ +Three of Django's default User roles are relvant for Postorius: + +- Superuser: Can do everything. +- AnonymousUser: Can view list index and info pages. +- Authenticated users: Can view list index and info pages. Can (un)subscribe + from lists. + +Apart from these default roles, there are two others relevant in Postorius: + +- List owners: Can change list settings, moderate messages and delete their + lists. +- List moderators: Can moderate messages. + +There are a number of decorators to protect views from unauthorized users. + +- ``@user_passes_test(lambda u: u.is_superuser)`` +- ``@login_required`` +- ``@list_owner_required`` +- ``@list_moderator_required`` + +Check out views/views.py for examples! + Testing ======= +Currently only some of the Postorius code is covered by a test. We should change that! + All test modules reside in the ``postorius/src/postorius/tests`` directory and this is where you should put your own tests, too. To make the django test runner find your tests, make sure to add them to the folder's ``__init__.py``: @@ -67,24 +102,39 @@ Running the tests ----------------- -To run the tests go to your project folder and run ``python manage.py test postorius`` from there. +To run the tests go to your project folder and run ``python manage.py test +postorius`` from there. -Mocking -------- +Testing mailman.client results +------------------------------ -Postorius uses Michael Foord's ``mock`` library for mocking. There are some -shortcuts you can use to quickly create mock objects that behave a little bit like -objects retreived from mailman.client, like: +Most of Postorius' code involves some results from calls to the mailman.client +library. mailman.client is itself covered by tests, so Postorius' own tests +don't need to check if mailman.client returns correct results. Instead we can +just mock them! This has the big advantage that you can run the test suite +without having to worry about the state of the local Mailman database. It also +makes the tests run faster, because we spare ourselves the HTTP calls to the +local Mailman REST API. -- Domains -- Mailing Lists -- Users -- Memberships -- Addresses +This approach has the obvious downside that the Postorius tests will not +recognize any changes to the Mailman API. So at some point there should be some +separate integration tests to test the whole chain. But let's not worry about +that for now. Mocking mailman.client objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------ + +Postorius uses Michael Foord's ``mock`` library for mocking. There are some +shortcuts you can use to quickly create mock objects that behave a little bit +like objects retreived from mailman.client, like: + +- create_mock_domain +- create_mock_list +- create_mock_member + +These ``create_mock_*`` functions are very simple tools that return MagigMock objects with the properties passed to them in a dictionary. They also set some defaults for properties that you didn't pass to its ``create_mock_*`` function. For instance, a mock list created with ``create_mock_list()`` will always have ``members``, ``moderators`` and ``owners`` properties. + .. automodule:: postorius.tests.test_utils diff --git a/src/postorius/doc/_build/html/development.html b/src/postorius/doc/_build/html/development.html index 0bd2271..96a9292 100644 --- a/src/postorius/doc/_build/html/development.html +++ b/src/postorius/doc/_build/html/development.html @@ -78,14 +78,45 @@ views.py # View classes and functions for all views connected # in urls.py generic.py # Generic class-based views; Currently holds a - # class for view based on a single mailing list + # class for views based on a single mailing list +
+

Writing View Code

+

When the work on Postorius was started, the standard way to write view code in +Django was to write a single function for each different view. Since then +Django has introduced so-called ‘class-based views’ which make it much easier +to reuse view functionality. While using simple functions is not discuraged, it +makes sense to check if using a class-based approach could make sense.

+

Check Postorius’ views/views.py and views/generic.py for examples!

+

Authentication/Authorization

+

Three of Django’s default User roles are relvant for Postorius:

+ +

Apart from these default roles, there are two others relevant in Postorius:

+ +

There are a number of decorators to protect views from unauthorized users.

+ +

Check out views/views.py for examples!

Testing

+

Currently only some of the Postorius code is covered by a test. We should change that!

All test modules reside in the postorius/src/postorius/tests directory and this is where you should put your own tests, too. To make the django test runner find your tests, make sure to add them to the folder’s __init__.py:

@@ -104,22 +135,90 @@

Running the tests

-

To run the tests go to your project folder and run python manage.py test postorius from there.

+

To run the tests go to your project folder and run python manage.py test +postorius from there.

-
-

Mocking

-

Postorius uses Michael Foord’s mock library for mocking. There are some -shortcuts you can use to quickly create mock objects that behave a little bit like -objects retreived from mailman.client, like:

- +
+

Testing mailman.client results

+

Most of Postorius’ code involves some results from calls to the mailman.client +library. mailman.client is itself covered by tests, so Postorius’ own tests +don’t need to check if mailman.client returns correct results. Instead we can +just mock them! This has the big advantage that you can run the test suite +without having to worry about the state of the local Mailman database. It also +makes the tests run faster, because we spare ourselves the HTTP calls to the +local Mailman REST API.

+

This approach has the obvious downside that the Postorius tests will not +recognize any changes to the Mailman API. So at some point there should be some +separate integration tests to test the whole chain. But let’s not worry about +that for now.

+
-

Mocking mailman.client objects

+

Mocking mailman.client objects

+

Postorius uses Michael Foord’s mock library for mocking. There are some +shortcuts you can use to quickly create mock objects that behave a little bit +like objects retreived from mailman.client, like:

+ +

These create_mock_* functions are very simple tools that return MagigMock objects with the properties passed to them in a dictionary. They also set some defaults for properties that you didn’t pass to its create_mock_* function. For instance, a mock list created with create_mock_list() will always have members, moderators and owners properties.

+
+

Domains

+

postorius.tests.utils.create_mock_domain creates a mock domain object:

+
>>> properties = dict(contact_address='postmaster@example.org',
+...                   description='Example dot Org',
+...                   mail_host='example.org',
+...                   url_host='www.example.org')
+>>> mock_domain = create_mock_domain(properties)
+>>> print mock_domain
+<MagicMock name='Domain' id='...'>
+>>> print mock_domain.contact_address
+postmaster@example.org
+>>> print mock_domain.description
+Example dot Org
+>>> print mock_domain.mail_host
+example.org
+>>> print mock_domain.url_host
+www.example.org
+
+
+
+
+

Mailing Lists

+

postorius.tests.utils.create_mock_list creates a mock list object:

+
>>> properties = dict(fqdn_listname='testlist@example.org',
+...                   mail_host='example.org',
+...                   list_name='testlist',
+...                   display_name='Test List')
+>>> mock_list = create_mock_list(properties)
+>>> print mock_list
+<MagicMock name='List' id='...'>
+>>> print mock_list.fqdn_listname
+testlist@example.org
+>>> print mock_list.mail_host
+example.org
+>>> print mock_list.list_name
+testlist
+>>> print mock_list.display_name
+Test List
+
+
+
+
+

Memberships

+

postorius.tests.utils.create_mock_list creates a mock list object:

+
>>> properties = dict(fqdn_listname='testlist@example.org',
+...                   address='les@example.org',)
+>>> mock_member = create_mock_member(properties)
+>>> print mock_member
+<MagicMock name='Member' id='...'>
+>>> print mock_member.fqdn_listname
+testlist@example.org
+>>> print mock_member.address
+les@example.org
+
+
@@ -135,11 +234,15 @@