diff options
author | Petr Viktorin <pviktori@redhat.com> | 2014-10-10 14:56:29 +0200 |
---|---|---|
committer | Tomas Babej <tbabej@redhat.com> | 2014-11-21 12:14:44 +0100 |
commit | 3a9a98b2852d26fdc8257d20ef907ad8c47bcfe3 (patch) | |
tree | 794f36c63b64315a1f70e515ce5c945721f70827 /ipatests/pytest_plugins | |
parent | 0cb12f3cdef899df47e749ddaef937f7d1bd7a91 (diff) | |
download | freeipa-3a9a98b2852d26fdc8257d20ef907ad8c47bcfe3.tar.gz freeipa-3a9a98b2852d26fdc8257d20ef907ad8c47bcfe3.tar.xz freeipa-3a9a98b2852d26fdc8257d20ef907ad8c47bcfe3.zip |
Integration tests: Port the ordering plugin to pytest
Ordered integration tests may now be run with pytest.
https://fedorahosted.org/freeipa/ticket/4610
Reviewed-By: Tomas Babej <tbabej@redhat.com>
Diffstat (limited to 'ipatests/pytest_plugins')
-rw-r--r-- | ipatests/pytest_plugins/ordering.py | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/ipatests/pytest_plugins/ordering.py b/ipatests/pytest_plugins/ordering.py new file mode 100644 index 000000000..3af496a88 --- /dev/null +++ b/ipatests/pytest_plugins/ordering.py @@ -0,0 +1,88 @@ +# Authors: +# Petr Viktorin <pviktori@redhat.com> +# +# Copyright (C) 2014 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +"""Pytest plugin for IPA + +Adds support for the @pytest.mark.source_order decorator which, +when applied to a class, runs the test methods in source order. + +See test_ordering for an example. +""" + +import unittest + +import pytest + + +def ordered(cls): + """Decorator that marks a test class as ordered + + Methods within the marked class will be executed in definition order + (or more strictly, in ordered by the line number where they're defined). + + Subclasses of unittest.TestCase can not be ordered. + + Generator methods will not be ordered by this plugin. + """ + cls._order_plugin__ordered = True + assert not isinstance(cls, unittest.TestCase), ( + "A unittest.TestCase may not be ordered.") + cls = pytest.mark.source_order(cls) + return cls + + +def decorate_items(items): + node_indexes = {} + for index, item in enumerate(items): + try: + func = item.function + except AttributeError: + yield (index, ), item + continue + + key = (index, ) + for node in reversed(item.listchain()): + # Find the corresponding class + if isinstance(node, pytest.Class): + cls = node.cls + else: + continue + if getattr(cls, '_order_plugin__ordered', False): + node_index = node_indexes.setdefault(node, index) + # Find first occurence of the method in class hierarchy + for i, parent_class in enumerate(reversed(cls.mro())): + if getattr(parent_class, '_order_plugin__ordered', False): + method = getattr(parent_class, func.__name__, None) + if method: + # Sort methods as tuples (position of the class + # in the inheritance chain, position of the method + # within that class) + key = (node_index, 0, + i, method.func_code.co_firstlineno, node) + break + else: + # Weird case fallback + # Method name not in any of the classes in MRO, run it last + key = node_index, 1, func.func_code.co_firstlineno, node + break + yield key, item + + +def pytest_collection_modifyitems(session, config, items): + items[:] = [item for i, item in sorted(decorate_items(items))] |