Skip to content
This repository has been archived by the owner on Jun 27, 2018. It is now read-only.

Commit

Permalink
Merge pull request boto#816 from jamesls/testguide
Browse files Browse the repository at this point in the history
Add support for testing multiple python versions
  • Loading branch information
mfschwartz committed Jun 14, 2012
2 parents 6a501a4 + d1fa49f commit 14bd3b4
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ dist/
MANIFEST
.DS_Store
.idea
.tox
.coverage
171 changes: 171 additions & 0 deletions docs/source/contributing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
====================
Contributing to Boto
====================


Setting Up a Development Environment
====================================

While not strictly required, it is highly recommended to do development
in a virtualenv. You can install virtualenv using pip::

$ pip install virtualenv

Once the package is installed, you'll have a ``virtualenv`` command you can
use to create a virtual environment::

$ virtualenv venv

You can then activate the virtualenv::

$ . venv/bin/activate

.. note::

You may also want to check out virtualenvwrapper_, which is a set of
extensions to virtualenv that makes it easy to manage multiple virtual
environments.

A requirements.txt is included with boto which contains all the additional
packages needed for boto development. You can install these packages by
running::

$ pip install -r requirements.txt


Running the Tests
=================

All of the tests for boto are under the ``tests/`` directory. The tests for
boto have been split into two main categories, unit and integration tests:

* **unit** - These are tests that do not talk to any AWS services. Anyone
should be able to run these tests without have any credentials
configured. These are the types of tests that could be run in something
like a public CI server. These tests tend to be fast.

* **integration** - These are tests that will talk to AWS services, and
will typically require a boto config file with valid credentials.
Due to the nature of these tests, they tend to take a while to run.
Also keep in mind anyone who runs these tests will incur any usage
fees associated with the various AWS services.

To run all the unit tests, run::

$ python tests/test.py tests/unit

You should see output like this::

$ python tests/test.py tests/unit
................................
----------------------------------------------------------------------
Ran 32 tests in 0.075s

OK

To run the integration tests, run::

$ python tests/test.py tests/integration

Note that running the integration tests may take a while.

Testing Details
---------------

The ``tests/test.py`` script is a lightweight wrapper around nose_. In
general, you should be able to run ``nosetests`` directly instead of
``tests/test.py``. The ``tests/unit`` and ``tests/integration`` args
in the commands above were referring to directories. The command line
arguments are forwarded to nose when you use ``tests/test.py``. For example,
you can run::

$ python tests/test.py -x -vv tests/unit/cloudformation

And the ``-x -vv tests/unit/cloudformation`` are forwarded to nose. See
the nose_ docs for the supported command line options, or run
``nosetests --help``.

The only thing that ``tests/test.py`` does before invoking nose is to
inject an argument that specifies that any testcase tagged with "notdefault"
should not be run. A testcase may be tagged with "notdefault" if the test
author does not want everyone to run the tests. In general, there shouldn't be
many of these tests, but some reasons a test may be tagged "notdefault"
include:

* An integration test that requires specific credentials.
* An interactive test (the S3 MFA tests require you to type in the S/N and
code).

Tagging is done using nose's tagging_ plugin. To summarize, you can tag a
specific testcase by setting an attribute on the object. Nose provides
an ``attr`` decorator for convenience::

from nose.plugins.attrib import attr

@attr('notdefault')
def test_s3_mfs():
pass

You can then run these tests be specifying::

nosetests -a 'notdefault'

Or you can exclude any tests tagged with 'notdefault' by running::

nosetests -a '!notdefault'

Conceptually, ``tests/test.py`` is injecting the "-a !notdefault" arg
into nosetests.


Testing Supported Python Versions
==================================

Boto supports python 2.6 and 2.7. An easy way to verify functionality
across multiple python versions is to use tox_. A tox.ini file is included
with boto. You can run tox with no args and it will automatically test
all supported python versions::

$ tox
GLOB sdist-make: boto/setup.py
py26 sdist-reinst: boto/.tox/dist/boto-2.4.1.zip
py26 runtests: commands[0]
................................
----------------------------------------------------------------------
Ran 32 tests in 0.089s

OK
py27 sdist-reinst: boto/.tox/dist/boto-2.4.1.zip
py27 runtests: commands[0]
................................
----------------------------------------------------------------------
Ran 32 tests in 0.087s

OK
____ summary ____
py26: commands succeeded
py27: commands succeeded
congratulations :)


Writing Documentation
=====================

The boto docs use sphinx_ to generate documentation. All of the docs are
located in the ``docs/`` directory. To generate the html documentation, cd
into the docs directory and run ``make html``::

$ cd docs
$ make html

The generated documentation will be in the ``docs/build/html`` directory.
The source for the documentation is located in ``docs/source`` directory,
and uses `restructured text`_ for the markup language.


.. _nose: http://readthedocs.org/docs/nose/en/latest/
.. _tagging: http://nose.readthedocs.org/en/latest/plugins/attrib.html
.. _tox: http://tox.testrun.org/latest/
.. _virtualenvwrapper: http://www.doughellmann.com/projects/virtualenvwrapper/
.. _sphinx: http://sphinx.pocoo.org/
.. _restructured text: http://sphinx.pocoo.org/rest.html
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Additional Resources
--------------------

* :doc:`Boto Config Tutorial <boto_config_tut>`
* :doc:`Contributing to Boto <contributing>`
* `Boto Source Repository`_
* `Boto Issue Tracker`_
* `Boto Twitter`_
Expand Down
11 changes: 9 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
requests
mock
mock==0.8.0
nose==1.1.2
M2Crypto==0.21.1
requests==0.13.1
tox==1.4
Sphinx==1.1.3
simplejson==2.5.2
argparse==1.2.1
unittest2==0.5.1
2 changes: 1 addition & 1 deletion tests/integration/s3/test_gsconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"""

import boto
import unittest
import time
import os
import re
Expand All @@ -39,6 +38,7 @@
from boto import handler
from boto import storage_uri
from boto.provider import Provider
from tests.unit import unittest


_HAS_GOOGLE_CREDENTIALS = None
Expand Down
11 changes: 8 additions & 3 deletions tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,22 @@
import logging
import sys
import unittest
import argparse

from nose.core import run
import argparse


def main():
parser = argparse.ArgumentParser()
known_args, remaining_args = parser.parse_known_args()
default_args = '-a !notdefault'
run(argv=[__file__, default_args] + remaining_args)
if run(argv=[__file__, default_args] + remaining_args):
# run will return True is all the tests pass. We want
# this to equal a 0 rc
return 0
else:
return 1


if __name__ == "__main__":
main()
sys.exit(main())
5 changes: 4 additions & 1 deletion tests/unit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
import httplib

from mock import Mock
Expand Down
5 changes: 4 additions & 1 deletion tests/unit/cloudformation/test_connection.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#!/usr/bin/env python
import unittest
import httplib
import json
from datetime import datetime
try:
import json
except ImportError:
import simplejson as json

from mock import Mock

Expand Down
8 changes: 8 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[tox]
envlist = py26,py27


[testenv]
commands =
pip install -qr requirements.txt
python tests/test.py tests/unit

0 comments on commit 14bd3b4

Please sign in to comment.