From a32c5aeb41857815d183b96507315aef36ed67be Mon Sep 17 00:00:00 2001 From: Sergey Orlov Date: Jul 12 2021 17:55:19 +0000 Subject: Add support for decorated methods When a test method is wrapped using a decorator, it has attribute `__code__.co_firstlineno` of the decorator, not of the original method. This causes wrong sorting order of the test cases. --- diff --git a/pytest_sourceorder.py b/pytest_sourceorder.py index cfd1fa7..3c9bc7b 100644 --- a/pytest_sourceorder.py +++ b/pytest_sourceorder.py @@ -32,6 +32,12 @@ def ordered(cls): return cls +def unwrap_method(method): + while hasattr(method, '__wrapped__'): + method = method.__wrapped__ + return method + + def decorate_items(items): node_indexes = {} for index, item in enumerate(items): @@ -55,6 +61,7 @@ def decorate_items(items): if getattr(parent_class, '_order_plugin__ordered', False): method = getattr(parent_class, func.__name__, None) if method: + method = unwrap_method(method) # Sort methods as tuples (position of the class # in the inheritance chain, position of the method # within that class) diff --git a/test_sourceorder.py b/test_sourceorder.py index 79b9222..6d7b955 100644 --- a/test_sourceorder.py +++ b/test_sourceorder.py @@ -10,6 +10,8 @@ in a specific order: - Within a class, test methods are ordered according to source line """ +import functools + import pytest from pytest_sourceorder import ordered @@ -18,6 +20,13 @@ def log(): return [1] +def decorator(test_method): + @functools.wraps(test_method) + def wrapper(instance, *args, **kwargs): + test_method(instance, *args, **kwargs) + return wrapper + + @ordered class TestBase(object): def test_d_first(self, log): @@ -39,6 +48,11 @@ class TestChild(TestBase): assert log == [1, 2, 3, 4, 5, 6, 7] log.append(8) + @decorator + def test_decorated(self, log): + assert log == [1, 2, 3, 4, 5, 6, 7, 8] + log.append(9) + def test_c_second(self, log): assert log == [1, 2]