Context Navigation

Problem

When writing unit tests, it is often necessary to provide alternate implementations of APIs which are used by the code being tested. Relying on the real implementations of these APIs would expand the scope of the test such that it no longer tested only the relevant unit. Various techniques exist for inserting the alternate implementations into the runtime environment so they are used:

Parameterize the objects which provide the implementations, as to __init__ or as attributes on the object the methods of which are being tested.

Factor usage of these implementations into well-defined functions or methods and them override those to provide the alternates.

Replace names in the global scope of the functions being tested.

Replace attributes on module objects which are used by the functions being tested.

These all accomplish the desired goal. However, each requires a somewhat ad-hoc approach to the problem, and rarely is any of the resulting test fixture code reusable except across very similar test methods. The first involves expanding an API in a way often only exploited by test code. The second often requires the definition of a new subclass solely for the use of the test code. The third and fourth are less invasive, but require even more whitebox knowledge of the code being tested and are prone to unexpected failures when the implementation changes in an otherwise trivial or straightforward manner.

Solution

In Progress...

Trial should expose a declarative API for modifying a particular global scope during a particular test. The best form for such an API would be a function decorator, since that would preclude the need for matching bookends in setUp and tearDown.

Here, the 'mocked' decorator takes a single positional argument indicating the target for temporary rebinding and **kw indicating the names to temporarily rebind.

This doesn't address the fact that the implementation being tested might change to use different globals without the test being updated. Also, the use of a decorator might be a good idea, but eliminating the need for setUp/tearDown isn't the primary motivating concern here.