Stubble

Stub classes

StubClass

class reahl.stubble.stub.StubClass(orig, check_attributes_also=False)

A stub class is a class you use in a test as a substitute for another class, but with some methods implemented differently to the real class for purposes of the current test.

You mark a class as a stub class by decorating it with @stubclass(TheRealClass).

If you do this, the signatures of the methods you supply on the stubclass are checked against those on the real class in order to ensure your tests will break if the signature of the methods provided on the stub no longer match that of the same methods in TheRealClass.

@exempt

class reahl.stubble.stub.Exempt(value)

A method on a stub class that is decorated with @exempt will not be checked against the real class.

This allows you to add methods on the stub that are NOT present on the real class.

@slotconstrained

class reahl.stubble.stub.SlotConstrained

Assign an instance of slotconstrained to a variable in class scope to check that a similarly named variable exists in the __slots__ of the real class:

class TheRealClass:
    __slots__ = ('a')

@stubclass(TheRealClass)
class Stub:
    a = slotconstrained()

@checkedInstance

class reahl.stubble.stub.CheckedInstance

Assign an instance of checkedinstance to a variable in class scope to check that a similarly named class variable exists on the real class:

class TheRealClass:
    a = 'something'

@stubclass(TheRealClass)
class Stub:
    a = checkedinstance()

Impostor

class reahl.stubble.stub.Impostor

A class that inherits from Impostor, and is also a @stubclass(TheRealClass) gains the dubious benefit that the following would be true:

isinstance(stub_class_instance, TheRealClass)

Delegate

class reahl.stubble.stub.Delegate(real)

A class that inherits from Delegate, and is an @stubclass(TheRealClass) can be constructed as a wrapper to an already existing instance of TheRealClass.

When methods are called on it that it defines itself, they will be called. When calling methods not defined on it, these are delegated to the wrapped TheRealClass.

Like an Impostor, the following is true for a Delegate:

isinstance(stub_class_instance, TheRealClass)

EasterEggs

EasterEgg

class reahl.stubble.easteregg.EasterEgg(name='test', location=None)

A stubbed-out Distribution that can be used to fake a Distribution for testing.

Once an EasterEgg has been constructed, it needs to be added to the global pkg_resources.working_set. If the location is changed after being added, it is necessary to .activate() the EasterEgg before it will be active on sys.path.

Parameters:
  • name – A unique name for this Distribution.

  • location – The location on disk where the contents of this Distribution reside.

Changed in version 3.2: Added the location keyword argument and deprecated set_module_path().

Changed in version 4.0: Removed set_module_path()

add_to_working_set()

Adds this EasterEgg to the global pkg_resources.working_set object.

get_entry_map(group=None)

Return the entry point map for group, or the full entry map

activate(**kwargs)

Ensure distribution is importable on path (default=sys.path)

Intercepting calls

SystemOutStub

class reahl.stubble.intercept.SystemOutStub

The SystemOutStub can be used as context manager to test output that some code sends to sys.stdout.

For example, the following code does not output anything to the console:

with SystemOutStub() as monitor:
    print('hello')

assert monitor.captured_output == 'hello\n'
captured_output

The output captured during the time the SystemOutStub was active.

CallMonitor

class reahl.stubble.intercept.CallMonitor(method)

The CallMonitor is a context manager which records calls to a single method of an object or class. The calls are recorded, but the original method is also executed.

For example:

class SomeClass:
    def foo(self, arg):
        return 'something'

s = SomeClass()

with CallMonitor(s.foo) as monitor:
    assert s.foo('a value') == 'something'

assert monitor.times_called == 1
assert monitor.calls[0].args == ('a value',)
assert monitor.calls[0].kwargs == {}
assert monitor.calls[0].return_value == 'something'
property times_called

The number of calls that were made during the time the CallMonitor was active.

calls

A list of MonitoredCalls made, one for each call made, in the order they were made

MonitoredCall

class reahl.stubble.intercept.MonitoredCall(args, kwargs, return_value)

The record of one call that was made to a method. This class is not intended to be instantiated by a programmer. Programmers can query instances of MonitoredCall returned by a reahl.stubble.intercept.CallMonitor or reahl.stubble.intercept.InitMonitor.

return_value

The value returned by the call

args

The tuple with positional arguments passed during the call

kwargs

The dictionary with keyword arguments passed during the call

InitMonitor

class reahl.stubble.intercept.InitMonitor(monitored_class)

An InitMonitor is like a reahl.stubble.intercept.CallMonitor, except it is used to intercept calls to the __init__ of a class. (See reahl.stubble.intercept.CallMonitor for attributes.)

property times_called

The number of calls that were made during the time the CallMonitor was active.

calls

A list of MonitoredCalls made, one for each call made, in the order they were made

@replaced

reahl.stubble.intercept.replaced(method, replacement, on=None)

A context manager which replaces the method passed in as method with the callable in replacement for the duration of the managed context.

class SomethingElse:
    def foo(self, n, y='yyy'):
        assert None, 'This should never be reached in this test'

s = SomethingElse()

def replacement(n, y=None):
    return y

with replaced(s.foo, replacement):
    assert s.foo(1, y='a') == 'a'
    assert s.foo(2) == None

assert s.foo(2) == 'yyy'