nodev-io / pytest-nodev

Test-driven source code search for Python.
http://pytest-nodev.readthedocs.io
MIT License
27 stars 8 forks source link

Add support for instrumenting a test with a decorator #19

Closed alexamici closed 8 years ago

alexamici commented 8 years ago

Enhancement request by @calmomau to support something along the lines of:

@wish('parse_bool')
def test_parse_bool():
    assert not parse_bool('false')
    assert not parse_bool('0')
    assert parse_bool('true')
    assert parse_bool('1')

Upadate: Probably it can't be done see comments.

alexamici commented 8 years ago

Quite surprisingly in the simplest case the following decorator works:

def wish(target_name):
    def wish_decorator(test_func):
        def wish_wrapper(wish, *args, **kwargs):
            globals()[target_name] = wish
            return test_func(*args, **kwargs)
        return wish_wrapper
    return wish_decorator

The general case is significantly more complex:

alexamici commented 8 years ago

The decorator in the previous comment only works if it is defined inside the test file that uses it due to the fact that we assign to globals() and that always refer to the namespace of the module where the decorator is defined, not the one where it is run.

alexamici commented 8 years ago

Upon further investigation the decorator doesn't look feasible. The test variables to be overridden are global variable, not free variables and overriding them with a wish for a test will interfere with all other decorated tests. :(

alexamici commented 8 years ago

The monkeypatch fixture comes to the rescue:

def wish(target_name):
    def wish_decorator(test_func):
        def wish_wrapper(wish, monkeypatch, *args, **kwargs):
            monkeypatch.setattr(target_name, wish)
            return test_func(*args, **kwargs)
        return wish_wrapper
    return wish_decorator

It might be possible to use it. But apparently target_name must exist and must contain a dot ..

alexamici commented 8 years ago

This appears to work consistently:

import inspect

def wish(target_name):
    def wish_decorator(test_func):
        def wish_wrapper(wish, monkeypatch, *args, **kwargs):
            if '.' in target_name:
                monkeypatch.setattr(target_name, wish)
            else:
                monkeypatch.setattr(inspect.getmodule(test_func), target_name, wish)
            return test_func(*args, **kwargs)
        return wish_wrapper
    return wish_decorator
alexamici commented 8 years ago

Closed with fd401107692921d1540722695067fe60550ec3a0.