| # Copyright (C) 2021 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND |
| # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR |
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import warnings |
| import types |
| import sys |
| |
| import pytest |
| |
| |
| def pytest_configure(config): |
| config.addinivalue_line("markers", "serial: tests that must be run in serial") |
| config.addinivalue_line("markers", "integration: integration tests") |
| config.addinivalue_line("markers", "slow: tests that take a while to run") |
| |
| |
| def pytest_addoption(parser): |
| parser.addoption( |
| "--run-slow", action="store_true", default=False, help="run slow tests" |
| ) |
| |
| |
| @pytest.hookimpl(tryfirst=True) |
| def pytest_pycollect_makeitem(collector, name, obj): |
| try: |
| ut = sys.modules["unittest"] |
| if not issubclass(obj, ut.TestCase): |
| return None |
| except Exception: |
| return None |
| |
| if getattr(obj, "__pytest_no_rewrite__", False): |
| return None |
| |
| for attr_name in set(dir(obj)): |
| serial = False |
| integration = False |
| if attr_name.startswith("serial_integration_test_"): |
| serial = True |
| integration = True |
| elif attr_name.startswith("serial_test_"): |
| serial = True |
| elif attr_name.startswith("integration_test_"): |
| integration = True |
| else: |
| continue |
| |
| method = getattr(obj, attr_name) |
| if not callable(method): |
| continue |
| |
| new_attr_name = "test_" + attr_name |
| |
| existing_attr = getattr(obj, new_attr_name, None) |
| if existing_attr: |
| if method != existing_attr: |
| warnings.warn( |
| "attribute %r already defined on %r; %r might hide %r" |
| % (new_attr_name, obj, method, existing_attr) |
| ) |
| |
| if sys.version_info < (3,) and isinstance(method, types.MethodType): |
| method = method.im_func |
| |
| if serial: |
| method = pytest.mark.serial(method) |
| |
| if integration: |
| method = pytest.mark.integration(method) |
| |
| setattr(obj, new_attr_name, method) |
| |
| return None |
| |
| |
| def pytest_collection_modifyitems(config, items): |
| if hasattr(config, "workerinput"): |
| skip_serial = pytest.mark.skip(reason="cannot run in parallel") |
| for item in items: |
| if "serial" in item.keywords: |
| item.add_marker(skip_serial) |
| |
| if not config.getoption("--run-slow"): |
| skip_slow = pytest.mark.skip(reason="need --run-slow option to run") |
| for item in items: |
| if "slow" in item.keywords: |
| item.add_marker(skip_slow) |