mirror of
https://github.com/django/django.git
synced 2025-08-30 07:17:49 +00:00
Fixed #15796 -- Restructured the contributing documentation and added note about newly added Trac abilities. Many thanks to Julien Phalip.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16284 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
69cfee2f16
commit
407f62fd31
18 changed files with 1806 additions and 1750 deletions
180
docs/internals/contributing/writing-code/branch-policy.txt
Normal file
180
docs/internals/contributing/writing-code/branch-policy.txt
Normal file
|
@ -0,0 +1,180 @@
|
|||
=============
|
||||
Branch policy
|
||||
=============
|
||||
|
||||
In general, the trunk must be kept stable. People should be able to run
|
||||
production sites against the trunk at any time. Additionally, commits to trunk
|
||||
ought to be as atomic as possible -- smaller changes are better. Thus, large
|
||||
feature changes -- that is, changes too large to be encapsulated in a single
|
||||
patch, or changes that need multiple eyes on them -- must happen on dedicated
|
||||
branches.
|
||||
|
||||
This means that if you want to work on a large feature -- anything that would
|
||||
take more than a single patch, or requires large-scale refactoring -- you need
|
||||
to do it on a feature branch. Our development process recognizes two options
|
||||
for feature branches:
|
||||
|
||||
1. Feature branches using a distributed revision control system like
|
||||
Git_, Mercurial_, Bazaar_, etc.
|
||||
|
||||
If you're familiar with one of these tools, this is probably your best
|
||||
option since it doesn't require any support or buy-in from the Django
|
||||
core developers.
|
||||
|
||||
However, do keep in mind that Django will continue to use Subversion
|
||||
for the foreseeable future, and this will naturally limit the
|
||||
recognition of your branch. Further, if your branch becomes eligible
|
||||
for merging to trunk you'll need to find a core developer familiar
|
||||
with your DVCS of choice who'll actually perform the merge.
|
||||
|
||||
If you do decided to start a distributed branch of Django and choose to
|
||||
make it public, please add the branch to the `Django branches`_ wiki
|
||||
page.
|
||||
|
||||
2. Feature branches using SVN have a higher bar. If you want a branch
|
||||
in SVN itself, you'll need a "mentor" among the :doc:`core committers
|
||||
</internals/committers>`. This person is responsible for actually
|
||||
creating the branch, monitoring your process (see below), and
|
||||
ultimately merging the branch into trunk.
|
||||
|
||||
If you want a feature branch in SVN, you'll need to ask in
|
||||
`django-developers`_ for a mentor.
|
||||
|
||||
.. _git: http://git-scm.com/
|
||||
.. _mercurial: http://mercurial.selenic.com/
|
||||
.. _bazaar: http://bazaar.canonical.com/
|
||||
.. _django branches: http://code.djangoproject.com/wiki/DjangoBranches
|
||||
|
||||
Branch rules
|
||||
------------
|
||||
|
||||
We've got a few rules for branches born out of experience with what makes a
|
||||
successful Django branch.
|
||||
|
||||
DVCS branches are obviously not under central control, so we have no way of
|
||||
enforcing these rules. However, if you're using a DVCS, following these rules
|
||||
will give you the best chance of having a successful branch (read: merged back
|
||||
to trunk).
|
||||
|
||||
Developers with branches in SVN, however, **must** follow these rules. The
|
||||
branch mentor will keep on eye on the branch and **will delete it** if these
|
||||
rules are broken.
|
||||
|
||||
* Only branch entire copies of the Django tree, even if work is only
|
||||
happening on part of that tree. This makes it painless to switch to a
|
||||
branch.
|
||||
|
||||
* Merge changes from trunk no less than once a week, and preferably every
|
||||
couple-three days.
|
||||
|
||||
In our experience, doing regular trunk merges is often the difference
|
||||
between a successful branch and one that fizzles and dies.
|
||||
|
||||
If you're working on an SVN branch, you should be using `svnmerge.py`_
|
||||
to track merges from trunk.
|
||||
|
||||
* Keep tests passing and documentation up-to-date. As with patches,
|
||||
we'll only merge a branch that comes with tests and documentation.
|
||||
|
||||
.. _svnmerge.py: http://www.orcaware.com/svn/wiki/Svnmerge.py
|
||||
|
||||
Once the branch is stable and ready to be merged into the trunk, alert
|
||||
`django-developers`_.
|
||||
|
||||
After a branch has been merged, it should be considered "dead"; write access
|
||||
to it will be disabled, and old branches will be periodically "trimmed."
|
||||
To keep our SVN wrangling to a minimum, we won't be merging from a given
|
||||
branch into the trunk more than once.
|
||||
|
||||
Using branches
|
||||
--------------
|
||||
|
||||
To use a branch, you'll need to do two things:
|
||||
|
||||
* Get the branch's code through Subversion.
|
||||
|
||||
* Point your Python ``site-packages`` directory at the branch's version of
|
||||
the ``django`` package rather than the version you already have
|
||||
installed.
|
||||
|
||||
Getting the code from Subversion
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To get the latest version of a branch's code, check it out using Subversion:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
svn co http://code.djangoproject.com/svn/django/branches/<branch>/
|
||||
|
||||
...where ``<branch>`` is the branch's name. See the `list of branch names`_.
|
||||
|
||||
Alternatively, you can automatically convert an existing directory of the
|
||||
Django source code as long as you've checked it out via Subversion. To do the
|
||||
conversion, execute this command from within your ``django`` directory:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
svn switch http://code.djangoproject.com/svn/django/branches/<branch>/
|
||||
|
||||
The advantage of using ``svn switch`` instead of ``svn co`` is that the
|
||||
``switch`` command retains any changes you might have made to your local copy
|
||||
of the code. It attempts to merge those changes into the "switched" code. The
|
||||
disadvantage is that it may cause conflicts with your local changes if the
|
||||
"switched" code has altered the same lines of code.
|
||||
|
||||
(Note that if you use ``svn switch``, you don't need to point Python at the
|
||||
new version, as explained in the next section.)
|
||||
|
||||
.. _list of branch names: http://code.djangoproject.com/browser/django/branches
|
||||
|
||||
.. _pointing-python-at-the-new-django-version:
|
||||
|
||||
Pointing Python at the new Django version
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once you've retrieved the branch's code, you'll need to change your Python
|
||||
``site-packages`` directory so that it points to the branch version of the
|
||||
``django`` directory. (The ``site-packages`` directory is somewhere such as
|
||||
``/usr/lib/python2.4/site-packages`` or
|
||||
``/usr/local/lib/python2.4/site-packages`` or ``C:\Python\site-packages``.)
|
||||
|
||||
The simplest way to do this is by renaming the old ``django`` directory to
|
||||
``django.OLD`` and moving the trunk version of the code into the directory
|
||||
and calling it ``django``.
|
||||
|
||||
Alternatively, you can use a symlink called ``django`` that points to the
|
||||
location of the branch's ``django`` package. If you want to switch back, just
|
||||
change the symlink to point to the old code.
|
||||
|
||||
A third option is to use a `path file`_ (``<something>.pth``) which should
|
||||
work on all systems (including Windows, which doesn't have symlinks
|
||||
available). First, make sure there are no files, directories or symlinks named
|
||||
``django`` in your ``site-packages`` directory. Then create a text file named
|
||||
``django.pth`` and save it to your ``site-packages`` directory. That file
|
||||
should contain a path to your copy of Django on a single line and optional
|
||||
comments. Here is an example that points to multiple branches. Just uncomment
|
||||
the line for the branch you want to use ('Trunk' in this example) and make
|
||||
sure all other lines are commented::
|
||||
|
||||
# Trunk is a svn checkout of:
|
||||
# http://code.djangoproject.com/svn/django/trunk/
|
||||
#
|
||||
/path/to/trunk
|
||||
|
||||
# <branch> is a svn checkout of:
|
||||
# http://code.djangoproject.com/svn/django/branches/<branch>/
|
||||
#
|
||||
#/path/to/<branch>
|
||||
|
||||
# On windows a path may look like this:
|
||||
# C:/path/to/<branch>
|
||||
|
||||
If you're using Django 0.95 or earlier and installed it using
|
||||
``python setup.py install``, you'll have a directory called something like
|
||||
``Django-0.95-py2.4.egg`` instead of ``django``. In this case, edit the file
|
||||
``setuptools.pth`` and remove the line that references the Django ``.egg``
|
||||
file. Then copy the branch's version of the ``django`` directory into
|
||||
``site-packages``.
|
||||
|
||||
.. _path file: http://docs.python.org/library/site.html
|
||||
.. _django-developers: http://groups.google.com/group/django-developers
|
190
docs/internals/contributing/writing-code/coding-style.txt
Normal file
190
docs/internals/contributing/writing-code/coding-style.txt
Normal file
|
@ -0,0 +1,190 @@
|
|||
============
|
||||
Coding Style
|
||||
============
|
||||
|
||||
Please follow these coding standards when writing code for inclusion in Django.
|
||||
|
||||
Python style
|
||||
------------
|
||||
|
||||
* Unless otherwise specified, follow :pep:`8`.
|
||||
|
||||
You could use a tool like `pep8.py`_ to check for some problems in this
|
||||
area, but remember that PEP 8 is only a guide, so respect the style of
|
||||
the surrounding code as a primary goal.
|
||||
|
||||
* Use four spaces for indentation.
|
||||
|
||||
* Use underscores, not camelCase, for variable, function and method names
|
||||
(i.e. ``poll.get_unique_voters()``, not ``poll.getUniqueVoters``).
|
||||
|
||||
* Use ``InitialCaps`` for class names (or for factory functions that
|
||||
return classes).
|
||||
|
||||
* In docstrings, use "action words" such as::
|
||||
|
||||
def foo():
|
||||
"""
|
||||
Calculates something and returns the result.
|
||||
"""
|
||||
pass
|
||||
|
||||
Here's an example of what not to do::
|
||||
|
||||
def foo():
|
||||
"""
|
||||
Calculate something and return the result.
|
||||
"""
|
||||
pass
|
||||
|
||||
Template style
|
||||
--------------
|
||||
|
||||
* In Django template code, put one (and only one) space between the curly
|
||||
brackets and the tag contents.
|
||||
|
||||
Do this:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ foo }}
|
||||
|
||||
Don't do this:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{foo}}
|
||||
|
||||
View style
|
||||
----------
|
||||
|
||||
* In Django views, the first parameter in a view function should be called
|
||||
``request``.
|
||||
|
||||
Do this::
|
||||
|
||||
def my_view(request, foo):
|
||||
# ...
|
||||
|
||||
Don't do this::
|
||||
|
||||
def my_view(req, foo):
|
||||
# ...
|
||||
|
||||
Model style
|
||||
-----------
|
||||
|
||||
* Field names should be all lowercase, using underscores instead of
|
||||
camelCase.
|
||||
|
||||
Do this::
|
||||
|
||||
class Person(models.Model):
|
||||
first_name = models.CharField(max_length=20)
|
||||
last_name = models.CharField(max_length=40)
|
||||
|
||||
Don't do this::
|
||||
|
||||
class Person(models.Model):
|
||||
FirstName = models.CharField(max_length=20)
|
||||
Last_Name = models.CharField(max_length=40)
|
||||
|
||||
* The ``class Meta`` should appear *after* the fields are defined, with
|
||||
a single blank line separating the fields and the class definition.
|
||||
|
||||
Do this::
|
||||
|
||||
class Person(models.Model):
|
||||
first_name = models.CharField(max_length=20)
|
||||
last_name = models.CharField(max_length=40)
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = 'people'
|
||||
|
||||
Don't do this::
|
||||
|
||||
class Person(models.Model):
|
||||
first_name = models.CharField(max_length=20)
|
||||
last_name = models.CharField(max_length=40)
|
||||
class Meta:
|
||||
verbose_name_plural = 'people'
|
||||
|
||||
Don't do this, either::
|
||||
|
||||
class Person(models.Model):
|
||||
class Meta:
|
||||
verbose_name_plural = 'people'
|
||||
|
||||
first_name = models.CharField(max_length=20)
|
||||
last_name = models.CharField(max_length=40)
|
||||
|
||||
* The order of model inner classes and standard methods should be as
|
||||
follows (noting that these are not all required):
|
||||
|
||||
* All database fields
|
||||
* Custom manager attributes
|
||||
* ``class Meta``
|
||||
* ``def __unicode__()``
|
||||
* ``def __str__()``
|
||||
* ``def save()``
|
||||
* ``def get_absolute_url()``
|
||||
* Any custom methods
|
||||
|
||||
* If ``choices`` is defined for a given model field, define the choices as
|
||||
a tuple of tuples, with an all-uppercase name, either near the top of
|
||||
the model module or just above the model class. Example::
|
||||
|
||||
GENDER_CHOICES = (
|
||||
('M', 'Male'),
|
||||
('F', 'Female'),
|
||||
)
|
||||
|
||||
Use of ``django.conf.settings``
|
||||
-------------------------------
|
||||
|
||||
Modules should not in general use settings stored in ``django.conf.settings``
|
||||
at the top level (i.e. evaluated when the module is imported). The explanation
|
||||
for this is as follows:
|
||||
|
||||
Manual configuration of settings (i.e. not relying on the
|
||||
``DJANGO_SETTINGS_MODULE`` environment variable) is allowed and possible as
|
||||
follows::
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
settings.configure({}, SOME_SETTING='foo')
|
||||
|
||||
However, if any setting is accessed before the ``settings.configure`` line,
|
||||
this will not work. (Internally, ``settings`` is a ``LazyObject`` which
|
||||
configures itself automatically when the settings are accessed if it has not
|
||||
already been configured).
|
||||
|
||||
So, if there is a module containing some code as follows::
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import get_callable
|
||||
|
||||
default_foo_view = get_callable(settings.FOO_VIEW)
|
||||
|
||||
...then importing this module will cause the settings object to be configured.
|
||||
That means that the ability for third parties to import the module at the top
|
||||
level is incompatible with the ability to configure the settings object
|
||||
manually, or makes it very difficult in some circumstances.
|
||||
|
||||
Instead of the above code, a level of laziness or indirection must be used,
|
||||
such as `django.utils.functional.LazyObject``, ``django.utils.functional.lazy``
|
||||
or ``lambda``.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
* Mark all strings for internationalization; see the :doc:`i18n
|
||||
documentation </topics/i18n/index>` for details.
|
||||
|
||||
* Please don't put your name in the code you contribute. Our policy is to
|
||||
keep contributors' names in the ``AUTHORS`` file distributed with Django
|
||||
-- not scattered throughout the codebase itself. Feel free to include a
|
||||
change to the ``AUTHORS`` file in your patch if you make more than a
|
||||
single trivial change.
|
||||
|
||||
.. _pep8.py: http://pypi.python.org/pypi/pep8/
|
15
docs/internals/contributing/writing-code/index.txt
Normal file
15
docs/internals/contributing/writing-code/index.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
============
|
||||
Writing code
|
||||
============
|
||||
|
||||
So you'd like to write some code to improve Django. Awesome! Browse the
|
||||
following sections to find out how to give your code patches the best
|
||||
chances to be included in Django core:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
coding-style
|
||||
unit-tests
|
||||
submitting-patches
|
||||
branch-policy
|
160
docs/internals/contributing/writing-code/submitting-patches.txt
Normal file
160
docs/internals/contributing/writing-code/submitting-patches.txt
Normal file
|
@ -0,0 +1,160 @@
|
|||
==================
|
||||
Submitting patches
|
||||
==================
|
||||
|
||||
We're always grateful for patches to Django's code. Indeed, bug reports
|
||||
with associated patches will get fixed *far* more quickly than those
|
||||
without patches.
|
||||
|
||||
"Claiming" tickets
|
||||
------------------
|
||||
|
||||
In an open-source project with hundreds of contributors around the world, it's
|
||||
important to manage communication efficiently so that work doesn't get
|
||||
duplicated and contributors can be as effective as possible. Hence, our policy
|
||||
is for contributors to "claim" tickets in order to let other developers know
|
||||
that a particular bug or feature is being worked on.
|
||||
|
||||
If you have identified a contribution you want to make and you're capable of
|
||||
fixing it (as measured by your coding ability, knowledge of Django internals
|
||||
and time availability), claim it by following these steps:
|
||||
|
||||
* `Create an account`_ to use in our ticket system. If you have an account
|
||||
but have forgotten your password, you can reset it using the
|
||||
`password reset page`_.
|
||||
|
||||
* If a ticket for this issue doesn't exist yet, create one in our
|
||||
`ticket tracker`_.
|
||||
|
||||
* If a ticket for this issue already exists, make sure nobody else has
|
||||
claimed it. To do this, look at the "Assigned to" section of the ticket.
|
||||
If it's assigned to "nobody," then it's available to be claimed.
|
||||
Otherwise, somebody else is working on this ticket, and you either find
|
||||
another bug/feature to work on, or contact the developer working on the
|
||||
ticket to offer your help.
|
||||
|
||||
* Log into your account, if you haven't already, by clicking "Login" in
|
||||
the upper right of the ticket page.
|
||||
|
||||
* Claim the ticket by clicking the radio button next to "Accept ticket"
|
||||
near the bottom of the page, then clicking "Submit changes."
|
||||
|
||||
.. _Create an account: https://www.djangoproject.com/accounts/register/
|
||||
.. _password reset page: https://www.djangoproject.com/accounts/password/reset/
|
||||
|
||||
Ticket claimers' responsibility
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once you've claimed a ticket, you have a responsibility to work on that ticket
|
||||
in a reasonably timely fashion. If you don't have time to work on it, either
|
||||
unclaim it or don't claim it in the first place!
|
||||
|
||||
If there's no sign of progress on a particular claimed ticket for a week or
|
||||
two, another developer may ask you to relinquish the ticket claim so that it's
|
||||
no longer monopolized and somebody else can claim it.
|
||||
|
||||
If you've claimed a ticket and it's taking a long time (days or weeks) to code,
|
||||
keep everybody updated by posting comments on the ticket. If you don't provide
|
||||
regular updates, and you don't respond to a request for a progress report,
|
||||
your claim on the ticket may be revoked. As always, more communication is
|
||||
better than less communication!
|
||||
|
||||
Which tickets should be claimed?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Of course, going through the steps of claiming tickets is overkill in some
|
||||
cases. In the case of small changes, such as typos in the documentation or
|
||||
small bugs that will only take a few minutes to fix, you don't need to jump
|
||||
through the hoops of claiming tickets. Just submit your patch and be done with
|
||||
it.
|
||||
|
||||
.. _patch-style:
|
||||
|
||||
Patch style
|
||||
-----------
|
||||
|
||||
* Make sure your code matches our :doc:`coding-style`.
|
||||
|
||||
* Submit patches in the format returned by the ``svn diff`` command.
|
||||
An exception is for code changes that are described more clearly in
|
||||
plain English than in code. Indentation is the most common example; it's
|
||||
hard to read patches when the only difference in code is that it's
|
||||
indented.
|
||||
|
||||
Patches in ``git diff`` format are also acceptable.
|
||||
|
||||
* When creating patches, always run ``svn diff`` from the top-level
|
||||
``trunk`` directory -- i.e., the one that contains ``django``, ``docs``,
|
||||
``tests``, ``AUTHORS``, etc. This makes it easy for other people to
|
||||
apply your patches.
|
||||
|
||||
* Attach patches to a ticket in the `ticket tracker`_, using the "attach
|
||||
file" button. Please *don't* put the patch in the ticket description
|
||||
or comment unless it's a single line patch.
|
||||
|
||||
* Name the patch file with a ``.diff`` extension; this will let the ticket
|
||||
tracker apply correct syntax highlighting, which is quite helpful.
|
||||
|
||||
* Check the "Has patch" box on the ticket details. This will make it
|
||||
obvious that the ticket includes a patch, and it will add the ticket to
|
||||
the `list of tickets with patches`_.
|
||||
|
||||
* The code required to fix a problem or add a feature is an essential part
|
||||
of a patch, but it is not the only part. A good patch should also
|
||||
include a regression test to validate the behavior that has been fixed
|
||||
(and prevent the problem from arising again).
|
||||
|
||||
* If the code associated with a patch adds a new feature, or modifies
|
||||
behavior of an existing feature, the patch should also contain
|
||||
documentation.
|
||||
|
||||
Non-trivial patches
|
||||
-------------------
|
||||
|
||||
A "non-trivial" patch is one that is more than a simple bug fix. It's a patch
|
||||
that introduces Django functionality and makes some sort of design decision.
|
||||
|
||||
If you provide a non-trivial patch, include evidence that alternatives have
|
||||
been discussed on `django-developers`_. If you're not sure whether your patch
|
||||
should be considered non-trivial, just ask.
|
||||
|
||||
Javascript patches
|
||||
------------------
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
Django's admin system leverages the jQuery framework to increase the
|
||||
capabilities of the admin interface. In conjunction, there is an emphasis on
|
||||
admin javascript performance and minimizing overall admin media file size.
|
||||
Serving compressed or "minified" versions of javascript files is considered
|
||||
best practice in this regard.
|
||||
|
||||
To that end, patches for javascript files should include both the original
|
||||
code for future development (e.g. "foo.js"), and a compressed version for
|
||||
production use (e.g. "foo.min.js"). Any links to the file in the codebase
|
||||
should point to the compressed version.
|
||||
|
||||
To simplify the process of providing optimized javascript code, Django
|
||||
includes a handy script which should be used to create a "minified" version.
|
||||
This script is located at ``/contrib/admin/media/js/compress.py``.
|
||||
|
||||
Behind the scenes, ``compress.py`` is a front-end for Google's
|
||||
`Closure Compiler`_ which is written in Java. However, the Closure Compiler
|
||||
library is not bundled with Django directly, so those wishing to contribute
|
||||
complete javascript patches will need to download and install the library
|
||||
independently.
|
||||
|
||||
The Closure Compiler library requires Java version 6 or higher (Java 1.6 or
|
||||
higher on Mac OS X). Note that Mac OS X 10.5 and earlier did not ship with
|
||||
Java 1.6 by default, so it may be necessary to upgrade your Java installation
|
||||
before the tool will be functional. Also note that even after upgrading Java,
|
||||
the default `/usr/bin/java` command may remain linked to the previous Java
|
||||
binary, so relinking that command may be necessary as well.
|
||||
|
||||
Please don't forget to run ``compress.py`` and include the ``diff`` of the
|
||||
minified scripts when submitting patches for Django's javascript.
|
||||
|
||||
.. _Closure Compiler: http://code.google.com/closure/compiler/
|
||||
.. _django-developers: http://groups.google.com/group/django-developers
|
||||
.. _list of tickets with patches: http://code.djangoproject.com/query?status=new&status=assigned&status=reopened&has_patch=1&order=priority
|
||||
.. _ticket tracker: http://code.djangoproject.com/newticket
|
167
docs/internals/contributing/writing-code/unit-tests.txt
Normal file
167
docs/internals/contributing/writing-code/unit-tests.txt
Normal file
|
@ -0,0 +1,167 @@
|
|||
==========
|
||||
Unit tests
|
||||
==========
|
||||
|
||||
Django comes with a test suite of its own, in the ``tests`` directory of the
|
||||
Django tarball. It's our policy to make sure all tests pass at all times.
|
||||
|
||||
The tests cover:
|
||||
|
||||
* Models and the database API (``tests/modeltests/``).
|
||||
* Everything else in core Django code (``tests/regressiontests``)
|
||||
* Contrib apps (``django/contrib/<contribapp>/tests``, see below)
|
||||
|
||||
We appreciate any and all contributions to the test suite!
|
||||
|
||||
The Django tests all use the testing infrastructure that ships with Django for
|
||||
testing applications. See :doc:`Testing Django applications </topics/testing>`
|
||||
for an explanation of how to write new tests.
|
||||
|
||||
.. _running-unit-tests:
|
||||
|
||||
Running the unit tests
|
||||
----------------------
|
||||
|
||||
Quickstart
|
||||
~~~~~~~~~~
|
||||
|
||||
Running the tests requires a Django settings module that defines the
|
||||
databases to use. To make it easy to get started. Django provides a
|
||||
sample settings module that uses the SQLite database. To run the tests
|
||||
with this sample ``settings`` module, ``cd`` into the Django
|
||||
``tests/`` directory and run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./runtests.py --settings=test_sqlite
|
||||
|
||||
If you get an ``ImportError: No module named django.contrib`` error,
|
||||
you need to add your install of Django to your ``PYTHONPATH``. For
|
||||
more details on how to do this, read
|
||||
:ref:`pointing-python-at-the-new-django-version`.
|
||||
|
||||
Using another ``settings`` module
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The included settings module allows you to run the test suite using
|
||||
SQLite. If you want to test behavior using a different database (and
|
||||
if you're proposing patches for Django, it's a good idea to test
|
||||
across databases), you may need to define your own settings file.
|
||||
|
||||
To run the tests with different settings, ``cd`` to the ``tests/`` directory
|
||||
and type:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./runtests.py --settings=path.to.django.settings
|
||||
|
||||
The :setting:`DATABASES` setting in this test settings module needs to define
|
||||
two databases:
|
||||
|
||||
* A ``default`` database. This database should use the backend that
|
||||
you want to use for primary testing
|
||||
|
||||
* A database with the alias ``other``. The ``other`` database is
|
||||
used to establish that queries can be directed to different
|
||||
databases. As a result, this database can use any backend you
|
||||
want. It doesn't need to use the same backend as the ``default``
|
||||
database (although it can use the same backend if you want to).
|
||||
|
||||
If you're using a backend that isn't SQLite, you will need to provide other
|
||||
details for each database:
|
||||
|
||||
* The :setting:`USER` option for each of your databases needs to
|
||||
specify an existing user account for the database.
|
||||
|
||||
* The :setting:`PASSWORD` option needs to provide the password for
|
||||
the :setting:`USER` that has been specified.
|
||||
|
||||
* The :setting:`NAME` option must be the name of an existing database to
|
||||
which the given user has permission to connect. The unit tests will not
|
||||
touch this database; the test runner creates a new database whose name
|
||||
is :setting:`NAME` prefixed with ``test_``, and this test database is
|
||||
deleted when the tests are finished. This means your user account needs
|
||||
permission to execute ``CREATE DATABASE``.
|
||||
|
||||
You will also need to ensure that your database uses UTF-8 as the default
|
||||
character set. If your database server doesn't use UTF-8 as a default charset,
|
||||
you will need to include a value for ``TEST_CHARSET`` in the settings
|
||||
dictionary for the applicable database.
|
||||
|
||||
Running only some of the tests
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Django's entire test suite takes a while to run, and running every single test
|
||||
could be redundant if, say, you just added a test to Django that you want to
|
||||
run quickly without running everything else. You can run a subset of the unit
|
||||
tests by appending the names of the test modules to ``runtests.py`` on the
|
||||
command line.
|
||||
|
||||
For example, if you'd like to run tests only for generic relations and
|
||||
internationalization, type:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./runtests.py --settings=path.to.settings generic_relations i18n
|
||||
|
||||
How do you find out the names of individual tests? Look in
|
||||
``tests/modeltests`` and ``tests/regressiontests`` -- each directory name
|
||||
there is the name of a test.
|
||||
|
||||
If you just want to run a particular class of tests, you can specify a list of
|
||||
paths to individual test classes. For example, to run the ``TranslationTests``
|
||||
of the ``i18n`` module, type:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./runtests.py --settings=path.to.settings i18n.TranslationTests
|
||||
|
||||
Going beyond that, you can specify an individual test method like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./runtests.py --settings=path.to.settings i18n.TranslationTests.test_lazy_objects
|
||||
|
||||
Running all the tests
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to run the full suite of tests, you'll need to install a number of
|
||||
dependencies:
|
||||
|
||||
* PyYAML_
|
||||
* Markdown_
|
||||
* Textile_
|
||||
* Docutils_
|
||||
* setuptools_
|
||||
* memcached_, plus a :ref:`supported Python binding <memcached>`
|
||||
* gettext_ (:ref:`gettext_on_windows`)
|
||||
|
||||
If you want to test the memcached cache backend, you'll also need to define
|
||||
a :setting:`CACHES` setting that points at your memcached instance.
|
||||
|
||||
Each of these dependencies is optional. If you're missing any of them, the
|
||||
associated tests will be skipped.
|
||||
|
||||
.. _PyYAML: http://pyyaml.org/wiki/PyYAML
|
||||
.. _Markdown: http://pypi.python.org/pypi/Markdown/1.7
|
||||
.. _Textile: http://pypi.python.org/pypi/textile
|
||||
.. _docutils: http://pypi.python.org/pypi/docutils/0.4
|
||||
.. _setuptools: http://pypi.python.org/pypi/setuptools/
|
||||
.. _memcached: http://www.danga.com/memcached/
|
||||
.. _gettext: http://www.gnu.org/software/gettext/manual/gettext.html
|
||||
|
||||
Contrib apps
|
||||
------------
|
||||
|
||||
Tests for apps in ``django/contrib/`` go in their respective directories under
|
||||
``django/contrib/``, in a ``tests.py`` file. (You can split the tests over
|
||||
multiple modules by using a ``tests`` directory in the normal Python way.)
|
||||
|
||||
For the tests to be found, a ``models.py`` file must exist (it doesn't
|
||||
have to have anything in it). If you have URLs that need to be
|
||||
mapped, put them in ``tests/urls.py``.
|
||||
|
||||
To run tests for just one contrib app (e.g. ``markup``), use the same
|
||||
method as above::
|
||||
|
||||
./runtests.py --settings=settings markup
|
Loading…
Add table
Add a link
Reference in a new issue