Fork me on GitHub

API Reference

Collecting tests

To run tests, they must be collected in a Tests instance. There are many ways this can be achieved, allowing flexibility and separation.

  • Register individual functions with the Tests.test() decorator.
  • Register other collections with Tests.register() or as arguments to the constructor. A collection according to Attest is an iterable yielding test callables, this includes:
    • Lists of lambdas and function references.
    • Tests instances.
    • Instances of subclasses of TestBase.
    • Classes are instantiated and returned, allowing Tests.register() to be used as a class decorator in Python 2.6 or later.
class attest.Tests(tests=(), contexts=None)[source]

Collection of test functions.

Parameters:
  • tests – Iterable of other test collections to register with this one.
  • contexts – Iterable of callables that take no arguments and return a context manager.
run(reporter=auto_reporter)[source]

Run all tests in this collection.

Parameters:reporter – An instance of AbstractReporter or a callable returning something implementing that API (not enforced).
main(argv=sys.argv)[source]

Interface to run() with command-line options.

-h, --help
Show a help message
-r NAME, --reporter NAME
Select reporter by name with get_reporter_by_name()
-l, --list-reporters
List the names of all installed reporters

Remaining arguments are passed to the reporter.

New in version 0.2.

Changed in version 0.4: --list-reporters was added.

test(func)[source]

Decorate a function as a test belonging to this collection.

test_if(condition)[source]

Returns test() if the condition is True.

New in version 0.4.

context(func)[source]

Decorate a function as a contextmanager() for running the tests in this collection in. Corresponds to setup and teardown in other testing libraries.

db = Tests()

@db.context
def connect():
    con = connect_db()
    try:
        yield con
    finally:
        con.disconnect()

@db.test
def using_connection(con):
    Assert(con).is_not(None)

The above corresponds to:

db = Tests()

@contextmanager
def connect():
    con = connect_db()
    try:
        yield con
    finally:
        con.disconnect()

@db.test
def using_connection():
    with connect() as con:
        Assert(con).is_not(None)

The difference is that this decorator applies the context to all tests defined in its collection, so it’s less repetitive.

Yielding None or nothing passes no arguments to the test, yielding a single value other than a tuple passes that value as the sole argument to the test, yielding a tuple splats the tuple as the arguments to the test. If you want to yield a tuple as the sole argument, wrap it in a one-tuple or unsplat the args in the test.

You can have more than one context, which will be run in order using contextlib.nested(), and their yields will be passed in order to the test functions.

New in version 0.2: Nested contexts.

register(tests)[source]

Merge in another test collection.

Parameters:tests
  • A class, which is then instantiated and return allowing it to be used as a decorator for TestBase classes.
  • A string, representing the import path to an iterable yielding tests, in the form of 'package.module.object'.
  • Otherwise any iterable object is assumed to yield tests.

Any of these can be passed in a list to the Tests constructor.

New in version 0.2: Refer to collections by import path as a string

register_if(condition)[source]

Returns register() if the condition is True.

New in version 0.4.

test_suite()[source]

Create a unittest.TestSuite from this collection.

class attest.TestBase[source]

Base for test classes. Decorate test methods with test(). Needs to be registered with a Tests collection to be run. For setup and teardown, override __context__() like a contextmanager() (without the decorator).

class Math(TestBase):

    def __context__(self):
        self.two = 1 + 1
        yield
        del self.two

    @test
    def arithmetics(self):
        Assert(self.two) == 2

suite = Tests([Math()])
suite.run()
attest.test(meth)[source]

Mark a TestBase method as a test and wrap it to run in the TestBase.__context__() of the subclass.

attest.test_if(condition)[source]

Returns test() if the condition is True.

New in version 0.4.

Asserting conditions

class attest.Assert(obj=None)[source]

Wrap an object such that boolean operations on it fails with an AssertionError if the operation results in False, with more helpful error messages on failure than assert.

A test failure is simply an unhandled exception, so it is completely optional to use this class.

Examples:

Assert(1 + 1) == 2
2 in Assert([1, 2, 3])

Attributes are proxied to the wrapped object, returning the result wrapped as well:

hello = Assert('hello')
hello == 'hello'
hello.upper() == 'HELLO'
hello.capitalize() == 'Hello'

Used in boolean context, fails if non-true. These all fail:

bool(Assert(0))
if Assert(0): pass
assert Assert(0)

Identical to, except for the more helpful failure message:

Assert(bool(0)) == True
obj

The wrapped object

Conditional tests

The normal conditional operators are supported:

  • Equality: == and !=
  • Comparison: <, <=, >, >=

Some keywords are also supported:

  • Containment: in, but beware that it is the container that should be wrapped and that the negated form, not in, will not work.

These operators and keywords are not natively supported:

  • Identity: is, is not
  • Negative containment: not in

They are instead supported via the following methods.

is_(obj)[source]

The is operator is not overridable, for good reasons (that would defeat its purpose), so you can use this method for asserting identity:

Assert(True).is_(True)

Changed in version 0.3: Checks the wrapped object for Assert instances.

is_not(obj)[source]

The negated form of is_(), corresponding to the is not operation:

Assert([]).is_not([])

Changed in version 0.3: Checks the wrapped object for Assert instances.

in_(obj)[source]

Assert membership. While you can use the in operator, its order is inconsistent with the rest of the operators and doesn’t work with the not in operation.

2 in Assert([1, 2, 3])
Assert(2).in_([1, 2, 3])
not_in(obj)[source]

The negated form of in_(), corresponding to the not in operation:

Assert(0).not_in([1, 2, 3])

Convinient helpers

json[source]

Parse the wrapped object as JSON. Requires Python 2.6 or the simplejson package.

New in version 0.4.

css(selector)[source]

Parse the wrapped object as HTML and return an assertive list of elements matching the CSS selector. Requires lxml 2.0 or newer.

Note

Not tested on Python 2.5 and PyPy due to difficulties installing lxml for these implementations.

New in version 0.4.

xpath(path)[source]

Parse the wrapped object as XML and return an assertive list of elements matching the XPath path. Requires lxml 2.0 or newer.

Note

Not tested on Python 2.5 and PyPy due to difficulties installing lxml for these implementations.

New in version 0.4.

Static methods

static raises(*exceptions)[source]

Context manager that fails if none of the exceptions are raised. Yields the captured exception as an assertive object.

with Assert.raises(IOError) as error:
    open('/etc/passwd', 'w')

error.errno == 13
Parameters:exceptions – Expected exception classes.
static not_raising(*exception)[source]

Context manager that fails if a particular exception is raised. A raised exception consitutes a failure anyway and this is mainly used for testing Attest itself.

with Assert.not_raising(IOError):
    open('/etc/passwd', 'r')
Parameters:exception – An exception class.
static isinstance(obj, classinfo)[source]

Test that an object is an instance of a class or a tuple() of classes. Corresponds to isinstance().

New in version 0.4.

static not_isinstance(obj, classinfo)[source]

Negated version of isinstance().

New in version 0.4.

static issubclass(obj, cls)[source]

Test that obj is a subclass of cls or a subclass of a class inside cls. Corresponds to issubclass().

New in version 0.4.

static not_issubclass(obj, cls)[source]

Negated version of issubclass().

New in version 0.4.

Proxying

Item and attribute access is proxied to the wrapped object, however in the latter case this can be unpredictable due to the wrapper class having its own attributes. Therefore there is a method for this, too.

attr(name)[source]

Safely get an attribute from the wrapped object.

New in version 0.4.

passed_to(func, *args, **kwargs)[source]

Pass the unwrapped object to a function and return its result as an assertive object.

These are identical:

Assert(len([1, 2, 3])) == 3
Assert([1, 2, 3]).passed_to(len) == 3

Mainly useful with Assert objects that comes from the outside, e.g. yielded from a context, from methods like css() etc.

New in version 0.4.

attest.assert_(expr, msg=None)[source]

Like assert, but counts the assertion.

attest.capture_output()[source]

Context manager capturing standard output and error. Yields a tuple of the two streams as lists of lines.

with capture_output() as (out, err):
    print 'Captured'

Assert(out) == ['Captured']
attest.disable_imports(*names)[source]

Context in which imports for names raises an ImportError. This is useful for testing import-dependent fallbacks.

>>> from attest import disable_imports
>>> with disable_imports('sys'): import sys
...
Traceback (most recent call last):
ImportError: 'sys' is disabled

New in version 0.4.

Running tests with distribute

class attest.Loader[source]

Run tests with Attest via distribute:

setup(
    test_loader='attest:Loader',
    test_suite='tests.collection',
)

Now, python setup.py -q test is equivalent to:

from tests import collection
collection.run()

If you want to run the tests as a normal unittest suite, try Tests.test_suite() instead:

setup(
    test_suite='tests.collection.test_suite'
)

Reporters

Reporters are in charge of handling the state and outcome of test-runs. They might output machine- or human-readable reports on the console, or display the results in a graphical user interface.

attest.get_reporter_by_name(name, default='auto')[source]

Get an AbstractReporter by name, falling back on a default.

Reporters are registered via setuptools entry points, in the 'attest.reporters' group. A third-party reporter can thus register itself using this in its setup.py:

setup(
    entry_points = {
        'attest.reporters': [
            'name = import.path.to:callable'
        ]
    }
)

Names for the built in reporters:

Parameters:
  • name – One of the above strings.
  • default – The fallback reporter if no reporter has the supplied name, defaulting to 'auto'.
Raises KeyError:
 

If neither the name or the default is a valid name of a reporter.

Return type:

Callable returning an instance of an AbstractReporter.

Changed in version 0.4: Reporters are registered via setuptools entry points.

attest.get_all_reporters()[source]

Iterable yielding the names of all registered reporters.

>>> from attest import get_all_reporters
>>> list(get_all_reporters())
['xml', 'plain', 'fancy', 'auto']

New in version 0.4.

attest.auto_reporter(style=None)[source]

Select a reporter based on the target output and installed dependencies.

This is the default reporter.

Parameters:style – Passed to FancyReporter if it is used.
Return type:FancyReporter if output is a terminal and the progressbar and pygments packages are installed, otherwise a PlainReporter.
class attest.FancyReporter(style='bw')[source]

Heavily uses ANSI escape codes for fancy output to 256-color terminals. Progress of running the tests is indicated by a progressbar and failures are shown with syntax highlighted tracebacks.

Parameters:stylePygments style for tracebacks, defaults to 'bw' because it looks good on most terminals.
class attest.PlainReporter[source]

Plain text ASCII output for humans.

class attest.XmlReporter[source]

Report the result of a testrun in an XML format. Not compatible with JUnit or XUnit.

class attest.AbstractReporter[source]

Optional base for reporters, serves as documentation and improves errors for incomplete reporters.

begin(tests)[source]

Called when a test run has begun.

Parameters:tests – The list of test functions we will be running.
success(result)[source]

Called when a test succeeds.

Parameters:result (TestResult) – Result data for the succeeding test.

Changed in version 0.4: Parameters changed to result.

failure(result)[source]

Called when a test fails.

Parameters:result (TestResult) – Result data for the failing test.

Changed in version 0.4: Parameters changed to result.

finished()[source]

Called when all tests have run.

class attest.TestResult[source]

Container for result data from running a test.

New in version 0.4.

error

The exception instance, if the test failed.

exc_info

The exc_info() of the exception, if the test failed.

stderr

A list of lines the test printed on the standard error.

stdout

A list of lines the test printed on the standard output.

test

The test callable.

test_name[source]

A representative name for the test, similar to its import path.

traceback[source]

The traceback for the exception, if the test failed, cleaned up.