To run tests, they must be collected in a Tests instance. There are many ways this can be achieved, allowing flexibility and separation.
Collection of test functions.
Parameters: | tests – Iterable of other test collections to register with this one. |
---|
Run all tests in this collection.
Parameters: | reporter – An instance of AbstractReporter or a callable returning something implementing that API (not enforced). |
---|
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()
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.
Create a unittest.TestSuite from this collection.
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()
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
The wrapped object
The class of the wrapped object, also wrapped in Assert. Can be used for type testing:
Assert('Hello World').__class__.is_(str)
Context manager that fails if a particular exception is not raised. Yields the caught exception wrapped in Assert:
with Assert.raises(IOError) as error:
open('/etc/passwd', 'w')
error.errno == 13
Parameters: | exceptions – Expected exception classes. |
---|
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. |
---|
Wrapped proxy to the wrapped object’s __str__, can be used for testing the string adaption of the object:
Assert(1).__str__() == '1'
Allow calling of wrapped callables, wrapping the return value. Useful for testing methods on a wrapped object via attribute proxying:
Assert('Hello').upper() == 'HELLO'
Access an item on the wrapped object and return the result wrapped as well.
Assert([1, 2, 3])[1] == 2
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)
The negated form of is_(), corresponding to the is not operation:
Assert([]).is_not([])
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])
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 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.
Optional base for reporters, serves as documentation and improves errors for incomplete reporters.
Parameters: | tests – The list of test functions we will be running. |
---|
When a test succeeds, this method is called with the test function and the captured stdout and stderr output as lists of lines.
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.
Report the result of a testrun in an XML format. Not compatible with JUnit or XUnit.
Select a reporter based on the target output.
This is the default reporter.
Parameters: | style – Passed to FancyReporter if it is used. |
---|---|
Return type: | FancyReporter if output is a terminal otherwise a PlainReporter. |
Get an AbstractReporter by name, falling back on a default.
Available reporters:
Parameters: |
|
---|---|
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. |