async def step(self, context, env, setup_py_data): # noqa: D102 cmd = [ sys.executable, 'setup.py', 'pytest', 'egg_info', '--egg-base', context.args.build_base, ] junit_xml_path = Path( context.args.test_result_base if context.args. test_result_base else context.args.build_base) / 'pytest.xml' # avoid using backslashes in the PYTEST_ADDOPTS env var on Windows args = [ '--tb=short', '--junit-xml=' + str(PurePosixPath(*junit_xml_path.parts)), '--junit-prefix=' + context.pkg.name, ] # use -o option only when available # https://github.com/pytest-dev/pytest/blob/3.3.0/CHANGELOG.rst from pytest import __version__ as pytest_version if parse_version(pytest_version) >= parse_version('3.3.0'): args += [ '-o', 'cache_dir=' + str( PurePosixPath(*(Path(context.args.build_base).parts)) / '.pytest_cache'), ] env = dict(env) if has_test_dependency(setup_py_data, 'pytest-cov'): args += [ '--cov=' + str(PurePosixPath(*(Path(context.args.path).parts))), '--cov-report=html:' + str( PurePosixPath(*(Path(context.args.build_base).parts)) / 'coverage.html'), '--cov-report=xml:' + str( PurePosixPath(*(Path(context.args.build_base).parts)) / 'coverage.xml'), ] # use --cov-branch option only when available # https://github.com/pytest-dev/pytest-cov/blob/v2.5.0/CHANGELOG.rst from pytest_cov import __version__ as pytest_cov_version if parse_version(pytest_cov_version) >= parse_version('2.5.0'): args += [ '--cov-branch', ] env['COVERAGE_FILE'] = os.path.join(context.args.build_base, '.coverage') if context.args.retest_until_fail: try: import pytest_repeat # noqa: F401 except ImportError: logger.warning( "Ignored '--retest-until-fail' for package " "'{context.pkg.name}' since the pytest extension 'repeat' " 'was not found'.format_map(locals())) else: count = context.args.retest_until_fail + 1 args += [ '--count={count}'.format_map(locals()), ] if context.args.retest_until_pass: try: import pytest_rerunfailures # noqa: F401 except ImportError: logger.warning("Ignored '--retest-until-pass' for package " "'{context.pkg.name}' since pytest extension " "'rerunfailures' was not found".format_map( locals())) else: args += [ '--reruns={context.args.retest_until_pass}'.format_map( locals()), ] if context.args.pytest_args is not None: args += context.args.pytest_args if args: env['PYTEST_ADDOPTS'] = ' '.join( a if ' ' not in a else '"{a}"'.format_map(locals()) for a in args) # create dummy result in case the invocation fails early # and doesn't generate a result file at all junit_xml_path.parent.mkdir(parents=True, exist_ok=True) junit_xml_path.write_text("""<?xml version="1.0" encoding="UTF-8"?> <testsuite name="{context.pkg.name}" tests="1" failures="1" time="0" errors="0" skip="0"> <testcase classname="{context.pkg.name}" name="pytest.missing_result" status="run" time="0"> <failure message="The test invocation failed without generating a result file."/> </testcase> </testsuite> """.format_map(locals())) # noqa: E501 rc = await check_call(context, cmd, cwd=context.args.path, env=env) # use local import to avoid a dependency on pytest from _pytest.main import EXIT_TESTSFAILED if rc and rc.returncode == EXIT_TESTSFAILED: context.put_event_into_queue(TestFailure(context.pkg.name)) from _pytest.main import EXIT_NOTESTSCOLLECTED if rc and rc.returncode not in (EXIT_NOTESTSCOLLECTED, EXIT_TESTSFAILED): return rc.returncode
def match(self, context, env, setup_py_data): # noqa: D102 return has_test_dependency(setup_py_data, 'pytest')