# # Copyright (C) 2019 Codethink Limited # Copyright (C) 2019 Bloomberg Finance LP # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . """ This package contains various utilities which make it easier to test plugins. """ import os from collections import OrderedDict from buildstream.exceptions import ErrorDomain, LoadErrorReason from .repo import Repo from .runcli import cli, cli_integration, cli_remote_execution from .integration import integration_cache # To make use of these test utilities it is necessary to have pytest # available. However, we don't want to have a hard dependency on # pytest. try: import pytest except ImportError: module_name = globals()["__name__"] msg = "Could not import pytest:\n" "To use the {} module, you must have pytest installed.".format(module_name) raise ImportError(msg) # Of the form plugin_name -> (repo_class, plugin_package) ALL_REPO_KINDS = OrderedDict() # type: OrderedDict[Repo, str] def create_repo(kind, directory, subdir="repo"): """Convenience method for creating a Repo Args: kind (str): The kind of repo to create (a source plugin basename). This must have previously been registered using `register_repo_kind` directory (str): The path where the repo will keep a cache Returns: (Repo): A new Repo object """ try: constructor = ALL_REPO_KINDS[kind] except KeyError as e: raise AssertionError("Unsupported repo kind {}".format(kind)) from e return constructor[0](directory, subdir=subdir) def register_repo_kind(kind, cls, plugin_package): """Register a new repo kind. Registering a repo kind will allow the use of the `create_repo` method for that kind and include that repo kind in ALL_REPO_KINDS In addition, repo_kinds registred prior to `sourcetests_collection_hook` being called will be automatically used to test the basic behaviour of their associated source plugins using the tests in `testing._sourcetests`. Args: kind (str): The kind of repo to create (a source plugin basename) cls (cls) : A class derived from Repo. plugin_package (str): The name of the python package containing the plugin """ ALL_REPO_KINDS[kind] = (cls, plugin_package) def sourcetests_collection_hook(session): """ Used to hook the templated source plugin tests into a pyest test suite. This should be called via the `pytest_sessionstart hook `_. The tests in the _sourcetests package will be collected as part of whichever test package this hook is called from. Args: session (pytest.Session): The current pytest session """ def should_collect_tests(config): args = config.args rootdir = config.rootdir # When no args are supplied, pytest defaults the arg list to # just include the session's root_dir. We want to collect # tests as part of the default collection if args == [str(rootdir)]: return True # If specific tests are passed, don't collect # everything. Pytest will handle this correctly without # modification. if len(args) > 1 or rootdir not in args: return False # If in doubt, collect them, this will be an easier bug to # spot and is less likely to result in bug not being found. return True from . import _sourcetests source_test_path = os.path.dirname(_sourcetests.__file__) # Add the location of the source tests to the session's # python_files config. Without this, pytest may filter out these # tests during collection. session.config.addinivalue_line("python_files", os.path.join(source_test_path, "*.py")) # If test invocation has specified specic tests, don't # automatically collect templated tests. if should_collect_tests(session.config): session.config.args.append(source_test_path)