Sarunya Durai
Sarunya Durai

Reputation: 191

When is @pytest.hookimpl executes

I am new to pytest. When is @pytest.hookimpl executes? And what is the complete usage of it? I have tried with logs. For (hookwrapper=true), it is printing, 3 sets of after and before yield for a single test.

Upvotes: 5

Views: 14217

Answers (1)

curiousY
curiousY

Reputation: 186

pytest uses @pytest.hookimpl just to label hook methods. (So @pytest.hookimpl is executed when pytest collects the hook method.)

If you read the source code of pytest, you can find these codes:

def normalize_hookimpl_opts(opts):
    opts.setdefault("tryfirst", False)
    opts.setdefault("trylast", False)
    opts.setdefault("hookwrapper", False)
    opts.setdefault("optionalhook", False)

It means pytest will label the hook method with @pytest.hookimpl(tryfirst=False, trylast=False, hookwrapper=False, optionalhook=False) by default. Pytest will treat these hook methods in different ways according to this label(decorator) when executing them.

Take the hookwrapper parameter for example. If the hook method is labeled as hookwrapper=True, pytest will execute the part before yield first and then execute other same type hook methods. After these methods executed, the part after yield will be executed. (This feature is just like pytest fixtures.)

One usage of @pytest.hookimpl(hookwrapper=True) is that you can calculate the total cost time of some hook methods. (Here, the example code will calculate the tests collect time.)

@pytest.hookimpl(hookwrapper=True)
def pytest_collection(session):
    collect_timeout = 5
    collect_begin_time = time.time()
    yield
    collect_end_time = time.time()
    c_time = collect_end_time - collect_begin_time
    if c_time > collect_timeout:
        raise Exception('Collection timeout.')

Upvotes: 9

Related Questions