ansible/test/lib/ansible_test/_internal/coverage_util.py
Matt Clay f5d829392a
Overhaul ansible-test test path handling. (#61416)
* Remove .keep files from test/results/ dirs.

* Remove classification of test/results/ dir.

* Add results_relative to data context.

* Use variables in delegation paths.

* Standardize file writing and results paths.

* Fix issues reported by PyCharm.

* Clean up invocation of coverage command.

It now runs through the injector.

* Hack to allow intercept_command in cover.py.

* Simplify git ignore for test results.

* Use test result tmp dir instead of cache dir.

* Remove old .pytest_cache reference.

* Fix unit test docker delegation.

* Show HTML report link.

* Clean up more results references.

* Move import sanity test output to .tmp dir.

* Exclude test results dir from coverage.

* Fix import sanity test lib paths.

* Fix hard-coded import test paths.

* Fix most hard-coded integration test paths.

* Fix PyCharm warnings.

* Fix import placement.

* Fix integration test dir path.

* Fix Shippable scripts.

* Fix Shippable matrix check.

* Overhaul key pair management.
2019-08-27 23:40:06 -07:00

125 lines
3 KiB
Python

"""Utility code for facilitating collection of code coverage when running tests."""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import contextlib
import os
import tempfile
from .config import (
IntegrationConfig,
SanityConfig,
TestConfig,
)
from .util import (
COVERAGE_CONFIG_NAME,
remove_tree,
)
from .util_common import (
write_text_file,
)
from .data import (
data_context,
)
@contextlib.contextmanager
def coverage_context(args): # type: (TestConfig) -> None
"""Content to set up and clean up code coverage configuration for tests."""
coverage_setup(args)
try:
yield
finally:
coverage_cleanup(args)
def coverage_setup(args): # type: (TestConfig) -> None
"""Set up code coverage configuration before running tests."""
if not args.coverage:
return
coverage_config = generate_coverage_config(args)
if args.explain:
args.coverage_config_base_path = '/tmp/coverage-temp-dir'
else:
args.coverage_config_base_path = tempfile.mkdtemp()
write_text_file(os.path.join(args.coverage_config_base_path, COVERAGE_CONFIG_NAME), coverage_config)
def coverage_cleanup(args): # type: (TestConfig) -> None
"""Clean up code coverage configuration after tests have finished."""
if args.coverage_config_base_path and not args.explain:
remove_tree(args.coverage_config_base_path)
args.coverage_config_base_path = None
def generate_coverage_config(args): # type: (TestConfig) -> str
"""Generate code coverage configuration for tests."""
if data_context().content.collection:
coverage_config = generate_collection_coverage_config(args)
else:
coverage_config = generate_ansible_coverage_config()
return coverage_config
def generate_ansible_coverage_config(): # type: () -> str
"""Generate code coverage configuration for Ansible tests."""
coverage_config = '''
[run]
branch = True
concurrency = multiprocessing
parallel = True
omit =
*/python*/dist-packages/*
*/python*/site-packages/*
*/python*/distutils/*
*/pyshared/*
*/pytest
*/AnsiballZ_*.py
*/test/results/*
'''
return coverage_config
def generate_collection_coverage_config(args): # type: (TestConfig) -> str
"""Generate code coverage configuration for Ansible Collection tests."""
coverage_config = '''
[run]
branch = True
concurrency = multiprocessing
parallel = True
disable_warnings =
no-data-collected
'''
if isinstance(args, IntegrationConfig):
coverage_config += '''
include =
%s/*
*/%s/*
''' % (data_context().content.root, data_context().content.collection.directory)
elif isinstance(args, SanityConfig):
# temporary work-around for import sanity test
coverage_config += '''
include =
%s/*
omit =
*/test/results/*
''' % data_context().content.root
else:
coverage_config += '''
include =
%s/*
''' % data_context().content.root
return coverage_config