aboutsummaryrefslogtreecommitdiffstats
path: root/library/python/pytest/plugins/ya.py
diff options
context:
space:
mode:
authorDmitry Kopylov <kopylovd@gmail.com>2022-02-10 16:48:18 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:48:18 +0300
commit7230275728d34873cba1ba78bb68669b0c5faa31 (patch)
treeb222e5ac2e2e98872661c51ccceee5da0d291e13 /library/python/pytest/plugins/ya.py
parentb2f5101486cc0de2e979c8ba9ada2109785bf5fd (diff)
downloadydb-7230275728d34873cba1ba78bb68669b0c5faa31.tar.gz
Restoring authorship annotation for Dmitry Kopylov <kopylovd@gmail.com>. Commit 2 of 2.
Diffstat (limited to 'library/python/pytest/plugins/ya.py')
-rw-r--r--library/python/pytest/plugins/ya.py862
1 files changed, 431 insertions, 431 deletions
diff --git a/library/python/pytest/plugins/ya.py b/library/python/pytest/plugins/ya.py
index c6b06478d9..1bde03042d 100644
--- a/library/python/pytest/plugins/ya.py
+++ b/library/python/pytest/plugins/ya.py
@@ -3,101 +3,101 @@
import base64
import errno
import re
-import sys
-import os
-import logging
-import fnmatch
-import json
-import time
+import sys
+import os
+import logging
+import fnmatch
+import json
+import time
import traceback
-import collections
+import collections
import signal
import inspect
import warnings
import attr
import faulthandler
-import py
-import pytest
+import py
+import pytest
import six
-import _pytest
+import _pytest
import _pytest._io
import _pytest.mark
import _pytest.outcomes
import _pytest.skipping
-
+
from _pytest.warning_types import PytestUnhandledCoroutineWarning
from yatest_lib import test_splitter
-try:
- import resource
-except ImportError:
- resource = None
-
-try:
- import library.python.pytest.yatest_tools as tools
-except ImportError:
- # fallback for pytest script mode
- import yatest_tools as tools
-
+try:
+ import resource
+except ImportError:
+ resource = None
+
+try:
+ import library.python.pytest.yatest_tools as tools
+except ImportError:
+ # fallback for pytest script mode
+ import yatest_tools as tools
+
try:
from library.python import filelock
except ImportError:
filelock = None
-import yatest_lib.tools
-
-import yatest_lib.external as canon
-
+import yatest_lib.tools
+
+import yatest_lib.external as canon
+
import yatest_lib.ya
from library.python.pytest import context
-console_logger = logging.getLogger("console")
-yatest_logger = logging.getLogger("ya.test")
-
-
-_pytest.main.EXIT_NOTESTSCOLLECTED = 0
+console_logger = logging.getLogger("console")
+yatest_logger = logging.getLogger("ya.test")
+
+
+_pytest.main.EXIT_NOTESTSCOLLECTED = 0
SHUTDOWN_REQUESTED = False
-
+
pytest_config = None
-
-def configure_pdb_on_demand():
- import signal
-
- if hasattr(signal, "SIGUSR1"):
- def on_signal(*args):
+
+def configure_pdb_on_demand():
+ import signal
+
+ if hasattr(signal, "SIGUSR1"):
+ def on_signal(*args):
import ipdb
ipdb.set_trace()
-
- signal.signal(signal.SIGUSR1, on_signal)
-
-
-class CustomImporter(object):
- def __init__(self, roots):
- self._roots = roots
-
- def find_module(self, fullname, package_path=None):
- for path in self._roots:
- full_path = self._get_module_path(path, fullname)
-
- if os.path.exists(full_path) and os.path.isdir(full_path) and not os.path.exists(os.path.join(full_path, "__init__.py")):
- open(os.path.join(full_path, "__init__.py"), "w").close()
-
- return None
-
- def _get_module_path(self, path, fullname):
- return os.path.join(path, *fullname.split('.'))
-
-
-class YaTestLoggingFileHandler(logging.FileHandler):
- pass
-
-
+
+ signal.signal(signal.SIGUSR1, on_signal)
+
+
+class CustomImporter(object):
+ def __init__(self, roots):
+ self._roots = roots
+
+ def find_module(self, fullname, package_path=None):
+ for path in self._roots:
+ full_path = self._get_module_path(path, fullname)
+
+ if os.path.exists(full_path) and os.path.isdir(full_path) and not os.path.exists(os.path.join(full_path, "__init__.py")):
+ open(os.path.join(full_path, "__init__.py"), "w").close()
+
+ return None
+
+ def _get_module_path(self, path, fullname):
+ return os.path.join(path, *fullname.split('.'))
+
+
+class YaTestLoggingFileHandler(logging.FileHandler):
+ pass
+
+
class _TokenFilterFormatter(logging.Formatter):
def __init__(self, fmt):
super(_TokenFilterFormatter, self).__init__(fmt)
@@ -123,141 +123,141 @@ class _TokenFilterFormatter(logging.Formatter):
return self._filter(super(_TokenFilterFormatter, self).format(record))
-def setup_logging(log_path, level=logging.DEBUG, *other_logs):
- logs = [log_path] + list(other_logs)
- root_logger = logging.getLogger()
- for i in range(len(root_logger.handlers) - 1, -1, -1):
- if isinstance(root_logger.handlers[i], YaTestLoggingFileHandler):
+def setup_logging(log_path, level=logging.DEBUG, *other_logs):
+ logs = [log_path] + list(other_logs)
+ root_logger = logging.getLogger()
+ for i in range(len(root_logger.handlers) - 1, -1, -1):
+ if isinstance(root_logger.handlers[i], YaTestLoggingFileHandler):
root_logger.handlers.pop(i).close()
- root_logger.setLevel(level)
- for log_file in logs:
- file_handler = YaTestLoggingFileHandler(log_file)
- log_format = '%(asctime)s - %(levelname)s - %(name)s - %(funcName)s: %(message)s'
+ root_logger.setLevel(level)
+ for log_file in logs:
+ file_handler = YaTestLoggingFileHandler(log_file)
+ log_format = '%(asctime)s - %(levelname)s - %(name)s - %(funcName)s: %(message)s'
file_handler.setFormatter(_TokenFilterFormatter(log_format))
- file_handler.setLevel(level)
- root_logger.addHandler(file_handler)
-
-
-def pytest_addoption(parser):
- parser.addoption("--build-root", action="store", dest="build_root", default="", help="path to the build root")
- parser.addoption("--dep-root", action="append", dest="dep_roots", default=[], help="path to the dep build roots")
- parser.addoption("--source-root", action="store", dest="source_root", default="", help="path to the source root")
- parser.addoption("--data-root", action="store", dest="data_root", default="", help="path to the arcadia_tests_data root")
- parser.addoption("--output-dir", action="store", dest="output_dir", default="", help="path to the test output dir")
- parser.addoption("--python-path", action="store", dest="python_path", default="", help="path the canonical python binary")
- parser.addoption("--valgrind-path", action="store", dest="valgrind_path", default="", help="path the canonical valgring binary")
- parser.addoption("--test-filter", action="append", dest="test_filter", default=None, help="test filter")
+ file_handler.setLevel(level)
+ root_logger.addHandler(file_handler)
+
+
+def pytest_addoption(parser):
+ parser.addoption("--build-root", action="store", dest="build_root", default="", help="path to the build root")
+ parser.addoption("--dep-root", action="append", dest="dep_roots", default=[], help="path to the dep build roots")
+ parser.addoption("--source-root", action="store", dest="source_root", default="", help="path to the source root")
+ parser.addoption("--data-root", action="store", dest="data_root", default="", help="path to the arcadia_tests_data root")
+ parser.addoption("--output-dir", action="store", dest="output_dir", default="", help="path to the test output dir")
+ parser.addoption("--python-path", action="store", dest="python_path", default="", help="path the canonical python binary")
+ parser.addoption("--valgrind-path", action="store", dest="valgrind_path", default="", help="path the canonical valgring binary")
+ parser.addoption("--test-filter", action="append", dest="test_filter", default=None, help="test filter")
parser.addoption("--test-file-filter", action="store", dest="test_file_filter", default=None, help="test file filter")
- parser.addoption("--test-param", action="append", dest="test_params", default=None, help="test parameters")
- parser.addoption("--test-log-level", action="store", dest="test_log_level", choices=["critical", "error", "warning", "info", "debug"], default="debug", help="test log level")
+ parser.addoption("--test-param", action="append", dest="test_params", default=None, help="test parameters")
+ parser.addoption("--test-log-level", action="store", dest="test_log_level", choices=["critical", "error", "warning", "info", "debug"], default="debug", help="test log level")
parser.addoption("--mode", action="store", choices=[yatest_lib.ya.RunMode.List, yatest_lib.ya.RunMode.Run], dest="mode", default=yatest_lib.ya.RunMode.Run, help="testing mode")
parser.addoption("--test-list-file", action="store", dest="test_list_file")
- parser.addoption("--modulo", default=1, type=int)
- parser.addoption("--modulo-index", default=0, type=int)
+ parser.addoption("--modulo", default=1, type=int)
+ parser.addoption("--modulo-index", default=0, type=int)
parser.addoption("--partition-mode", default='SEQUENTIAL', help="Split tests according to partitoin mode")
- parser.addoption("--split-by-tests", action='store_true', help="Split test execution by tests instead of suites", default=False)
- parser.addoption("--project-path", action="store", default="", help="path to CMakeList where test is declared")
- parser.addoption("--build-type", action="store", default="", help="build type")
+ parser.addoption("--split-by-tests", action='store_true', help="Split test execution by tests instead of suites", default=False)
+ parser.addoption("--project-path", action="store", default="", help="path to CMakeList where test is declared")
+ parser.addoption("--build-type", action="store", default="", help="build type")
parser.addoption("--flags", action="append", dest="flags", default=[], help="build flags (-D)")
parser.addoption("--sanitize", action="store", default="", help="sanitize mode")
- parser.addoption("--test-stderr", action="store_true", default=False, help="test stderr")
+ parser.addoption("--test-stderr", action="store_true", default=False, help="test stderr")
parser.addoption("--test-debug", action="store_true", default=False, help="test debug mode")
- parser.addoption("--root-dir", action="store", default=None)
- parser.addoption("--ya-trace", action="store", dest="ya_trace_path", default=None, help="path to ya trace report")
+ parser.addoption("--root-dir", action="store", default=None)
+ parser.addoption("--ya-trace", action="store", dest="ya_trace_path", default=None, help="path to ya trace report")
parser.addoption("--ya-version", action="store", dest="ya_version", default=0, type=int, help="allows to be compatible with ya and the new changes in ya-dev")
- parser.addoption(
- "--test-suffix", action="store", dest="test_suffix", default=None, help="add suffix to every test name"
- )
- parser.addoption("--gdb-path", action="store", dest="gdb_path", default="", help="path the canonical gdb binary")
- parser.addoption("--collect-cores", action="store_true", dest="collect_cores", default=False, help="allows core dump file recovering during test")
+ parser.addoption(
+ "--test-suffix", action="store", dest="test_suffix", default=None, help="add suffix to every test name"
+ )
+ parser.addoption("--gdb-path", action="store", dest="gdb_path", default="", help="path the canonical gdb binary")
+ parser.addoption("--collect-cores", action="store_true", dest="collect_cores", default=False, help="allows core dump file recovering during test")
parser.addoption("--sanitizer-extra-checks", action="store_true", dest="sanitizer_extra_checks", default=False, help="enables extra checks for tests built with sanitizers")
- parser.addoption("--report-deselected", action="store_true", dest="report_deselected", default=False, help="report deselected tests to the trace file")
- parser.addoption("--pdb-on-sigusr1", action="store_true", default=False, help="setup pdb.set_trace on SIGUSR1")
+ parser.addoption("--report-deselected", action="store_true", dest="report_deselected", default=False, help="report deselected tests to the trace file")
+ parser.addoption("--pdb-on-sigusr1", action="store_true", default=False, help="setup pdb.set_trace on SIGUSR1")
parser.addoption("--test-tool-bin", help="Path to test_tool")
parser.addoption("--test-list-path", dest="test_list_path", action="store", help="path to test list", default="")
-
-
+
+
def from_ya_test():
return "YA_TEST_RUNNER" in os.environ
-def pytest_configure(config):
+def pytest_configure(config):
global pytest_config
pytest_config = config
config.option.continue_on_collection_errors = True
-
+
config.addinivalue_line("markers", "ya:external")
config.from_ya_test = from_ya_test()
- config.test_logs = collections.defaultdict(dict)
- config.test_metrics = {}
+ config.test_logs = collections.defaultdict(dict)
+ config.test_metrics = {}
config.suite_metrics = {}
config.configure_timestamp = time.time()
- context = {
- "project_path": config.option.project_path,
- "test_stderr": config.option.test_stderr,
+ context = {
+ "project_path": config.option.project_path,
+ "test_stderr": config.option.test_stderr,
"test_debug": config.option.test_debug,
- "build_type": config.option.build_type,
- "test_traceback": config.option.tbstyle,
+ "build_type": config.option.build_type,
+ "test_traceback": config.option.tbstyle,
"flags": config.option.flags,
"sanitize": config.option.sanitize,
- }
+ }
if config.option.collectonly:
config.option.mode = yatest_lib.ya.RunMode.List
config.ya = yatest_lib.ya.Ya(
- config.option.mode,
- config.option.source_root,
- config.option.build_root,
- config.option.dep_roots,
- config.option.output_dir,
- config.option.test_params,
- context,
- config.option.python_path,
- config.option.valgrind_path,
- config.option.gdb_path,
- config.option.data_root,
- )
- config.option.test_log_level = {
- "critical": logging.CRITICAL,
- "error": logging.ERROR,
- "warning": logging.WARN,
- "info": logging.INFO,
- "debug": logging.DEBUG,
- }[config.option.test_log_level]
-
- if not config.option.collectonly:
- setup_logging(os.path.join(config.ya.output_dir, "run.log"), config.option.test_log_level)
- config.current_item_nodeid = None
- config.current_test_name = None
- config.test_cores_count = 0
- config.collect_cores = config.option.collect_cores
+ config.option.mode,
+ config.option.source_root,
+ config.option.build_root,
+ config.option.dep_roots,
+ config.option.output_dir,
+ config.option.test_params,
+ context,
+ config.option.python_path,
+ config.option.valgrind_path,
+ config.option.gdb_path,
+ config.option.data_root,
+ )
+ config.option.test_log_level = {
+ "critical": logging.CRITICAL,
+ "error": logging.ERROR,
+ "warning": logging.WARN,
+ "info": logging.INFO,
+ "debug": logging.DEBUG,
+ }[config.option.test_log_level]
+
+ if not config.option.collectonly:
+ setup_logging(os.path.join(config.ya.output_dir, "run.log"), config.option.test_log_level)
+ config.current_item_nodeid = None
+ config.current_test_name = None
+ config.test_cores_count = 0
+ config.collect_cores = config.option.collect_cores
config.sanitizer_extra_checks = config.option.sanitizer_extra_checks
try:
config.test_tool_bin = config.option.test_tool_bin
except AttributeError:
logging.info("test_tool_bin not specified")
-
- if config.sanitizer_extra_checks:
+
+ if config.sanitizer_extra_checks:
for envvar in ['LSAN_OPTIONS', 'ASAN_OPTIONS']:
if envvar in os.environ:
os.environ.pop(envvar)
if envvar + '_ORIGINAL' in os.environ:
os.environ[envvar] = os.environ[envvar + '_ORIGINAL']
- if config.option.root_dir:
+ if config.option.root_dir:
config.rootdir = py.path.local(config.option.root_dir)
config.invocation_params = attr.evolve(config.invocation_params, dir=config.rootdir)
-
+
extra_sys_path = []
# Arcadia paths from the test DEPENDS section of ya.make
extra_sys_path.append(os.path.join(config.option.source_root, config.option.project_path))
- # Build root is required for correct import of protobufs, because imports are related to the root
- # (like import devtools.dummy_arcadia.protos.lib.my_proto_pb2)
+ # Build root is required for correct import of protobufs, because imports are related to the root
+ # (like import devtools.dummy_arcadia.protos.lib.my_proto_pb2)
extra_sys_path.append(config.option.build_root)
-
+
for path in config.option.dep_roots:
if os.path.isabs(path):
extra_sys_path.append(path)
@@ -272,17 +272,17 @@ def pytest_configure(config):
os.environ["PYTHONPATH"] = os.pathsep.join(sys.path)
- if not config.option.collectonly:
- if config.option.ya_trace_path:
- config.ya_trace_reporter = TraceReportGenerator(config.option.ya_trace_path)
- else:
- config.ya_trace_reporter = DryTraceReportGenerator(config.option.ya_trace_path)
+ if not config.option.collectonly:
+ if config.option.ya_trace_path:
+ config.ya_trace_reporter = TraceReportGenerator(config.option.ya_trace_path)
+ else:
+ config.ya_trace_reporter = DryTraceReportGenerator(config.option.ya_trace_path)
config.ya_version = config.option.ya_version
-
- sys.meta_path.append(CustomImporter([config.option.build_root] + [os.path.join(config.option.build_root, dep) for dep in config.option.dep_roots]))
- if config.option.pdb_on_sigusr1:
- configure_pdb_on_demand()
-
+
+ sys.meta_path.append(CustomImporter([config.option.build_root] + [os.path.join(config.option.build_root, dep) for dep in config.option.dep_roots]))
+ if config.option.pdb_on_sigusr1:
+ configure_pdb_on_demand()
+
# Dump python backtrace in case of any errors
faulthandler.enable()
if hasattr(signal, "SIGQUIT"):
@@ -291,7 +291,7 @@ def pytest_configure(config):
if hasattr(signal, "SIGUSR2"):
signal.signal(signal.SIGUSR2, _graceful_shutdown)
-
+
session_should_exit = False
@@ -327,122 +327,122 @@ def _graceful_shutdown(*args):
_graceful_shutdown_on_log(not capman.is_globally_capturing())
-def _get_rusage():
- return resource and resource.getrusage(resource.RUSAGE_SELF)
-
-
-def _collect_test_rusage(item):
- if resource and hasattr(item, "rusage"):
- finish_rusage = _get_rusage()
+def _get_rusage():
+ return resource and resource.getrusage(resource.RUSAGE_SELF)
+
+
+def _collect_test_rusage(item):
+ if resource and hasattr(item, "rusage"):
+ finish_rusage = _get_rusage()
ya_inst = pytest_config.ya
-
- def add_metric(attr_name, metric_name=None, modifier=None):
- if not metric_name:
- metric_name = attr_name
- if not modifier:
- modifier = lambda x: x
- if hasattr(item.rusage, attr_name):
+
+ def add_metric(attr_name, metric_name=None, modifier=None):
+ if not metric_name:
+ metric_name = attr_name
+ if not modifier:
+ modifier = lambda x: x
+ if hasattr(item.rusage, attr_name):
ya_inst.set_metric_value(metric_name, modifier(getattr(finish_rusage, attr_name) - getattr(item.rusage, attr_name)))
-
- for args in [
- ("ru_maxrss", "ru_rss", lambda x: x*1024), # to be the same as in util/system/rusage.cpp
- ("ru_utime",),
- ("ru_stime",),
- ("ru_ixrss", None, lambda x: x*1024),
- ("ru_idrss", None, lambda x: x*1024),
- ("ru_isrss", None, lambda x: x*1024),
- ("ru_majflt", "ru_major_pagefaults"),
- ("ru_minflt", "ru_minor_pagefaults"),
- ("ru_nswap",),
- ("ru_inblock",),
- ("ru_oublock",),
- ("ru_msgsnd",),
- ("ru_msgrcv",),
- ("ru_nsignals",),
- ("ru_nvcsw",),
- ("ru_nivcsw",),
- ]:
- add_metric(*args)
-
-
-def _get_item_tags(item):
- tags = []
- for key, value in item.keywords.items():
+
+ for args in [
+ ("ru_maxrss", "ru_rss", lambda x: x*1024), # to be the same as in util/system/rusage.cpp
+ ("ru_utime",),
+ ("ru_stime",),
+ ("ru_ixrss", None, lambda x: x*1024),
+ ("ru_idrss", None, lambda x: x*1024),
+ ("ru_isrss", None, lambda x: x*1024),
+ ("ru_majflt", "ru_major_pagefaults"),
+ ("ru_minflt", "ru_minor_pagefaults"),
+ ("ru_nswap",),
+ ("ru_inblock",),
+ ("ru_oublock",),
+ ("ru_msgsnd",),
+ ("ru_msgrcv",),
+ ("ru_nsignals",),
+ ("ru_nvcsw",),
+ ("ru_nivcsw",),
+ ]:
+ add_metric(*args)
+
+
+def _get_item_tags(item):
+ tags = []
+ for key, value in item.keywords.items():
if key == 'pytestmark' and isinstance(value, list):
for mark in value:
tags.append(mark.name)
elif isinstance(value, _pytest.mark.MarkDecorator):
- tags.append(key)
- return tags
-
-
-def pytest_runtest_setup(item):
- item.rusage = _get_rusage()
+ tags.append(key)
+ return tags
+
+
+def pytest_runtest_setup(item):
+ item.rusage = _get_rusage()
pytest_config.test_cores_count = 0
pytest_config.current_item_nodeid = item.nodeid
- class_name, test_name = tools.split_node_id(item.nodeid)
+ class_name, test_name = tools.split_node_id(item.nodeid)
test_log_path = tools.get_test_log_file_path(pytest_config.ya.output_dir, class_name, test_name)
- setup_logging(
+ setup_logging(
os.path.join(pytest_config.ya.output_dir, "run.log"),
pytest_config.option.test_log_level,
- test_log_path
- )
+ test_log_path
+ )
pytest_config.test_logs[item.nodeid]['log'] = test_log_path
pytest_config.test_logs[item.nodeid]['logsdir'] = pytest_config.ya.output_dir
pytest_config.current_test_log_path = test_log_path
pytest_config.current_test_name = "{}::{}".format(class_name, test_name)
- separator = "#" * 100
- yatest_logger.info(separator)
- yatest_logger.info(test_name)
- yatest_logger.info(separator)
- yatest_logger.info("Test setup")
-
+ separator = "#" * 100
+ yatest_logger.info(separator)
+ yatest_logger.info(test_name)
+ yatest_logger.info(separator)
+ yatest_logger.info("Test setup")
+
test_item = CrashedTestItem(item.nodeid, pytest_config.option.test_suffix)
pytest_config.ya_trace_reporter.on_start_test_class(test_item)
pytest_config.ya_trace_reporter.on_start_test_case(test_item)
-
-
-def pytest_runtest_teardown(item, nextitem):
- yatest_logger.info("Test teardown")
-
-
-def pytest_runtest_call(item):
+
+
+def pytest_runtest_teardown(item, nextitem):
+ yatest_logger.info("Test teardown")
+
+
+def pytest_runtest_call(item):
class_name, test_name = tools.split_node_id(item.nodeid)
yatest_logger.info("Test call (class_name: %s, test_name: %s)", class_name, test_name)
-
-
-def pytest_deselected(items):
+
+
+def pytest_deselected(items):
config = pytest_config
- if config.option.report_deselected:
- for item in items:
- deselected_item = DeselectedTestItem(item.nodeid, config.option.test_suffix)
- config.ya_trace_reporter.on_start_test_class(deselected_item)
- config.ya_trace_reporter.on_finish_test_case(deselected_item)
- config.ya_trace_reporter.on_finish_test_class(deselected_item)
-
-
-@pytest.mark.trylast
-def pytest_collection_modifyitems(items, config):
-
- def filter_items(filters):
- filtered_items = []
- deselected_items = []
- for item in items:
+ if config.option.report_deselected:
+ for item in items:
+ deselected_item = DeselectedTestItem(item.nodeid, config.option.test_suffix)
+ config.ya_trace_reporter.on_start_test_class(deselected_item)
+ config.ya_trace_reporter.on_finish_test_case(deselected_item)
+ config.ya_trace_reporter.on_finish_test_class(deselected_item)
+
+
+@pytest.mark.trylast
+def pytest_collection_modifyitems(items, config):
+
+ def filter_items(filters):
+ filtered_items = []
+ deselected_items = []
+ for item in items:
canonical_node_id = str(CustomTestItem(item.nodeid, pytest_config.option.test_suffix))
- matched = False
- for flt in filters:
+ matched = False
+ for flt in filters:
if "::" not in flt and "*" not in flt:
- flt += "*" # add support for filtering by module name
- if canonical_node_id.endswith(flt) or fnmatch.fnmatch(tools.escape_for_fnmatch(canonical_node_id), tools.escape_for_fnmatch(flt)):
- matched = True
- if matched:
- filtered_items.append(item)
- else:
- deselected_items.append(item)
-
- config.hook.pytest_deselected(items=deselected_items)
- items[:] = filtered_items
-
+ flt += "*" # add support for filtering by module name
+ if canonical_node_id.endswith(flt) or fnmatch.fnmatch(tools.escape_for_fnmatch(canonical_node_id), tools.escape_for_fnmatch(flt)):
+ matched = True
+ if matched:
+ filtered_items.append(item)
+ else:
+ deselected_items.append(item)
+
+ config.hook.pytest_deselected(items=deselected_items)
+ items[:] = filtered_items
+
def filter_by_full_name(filters):
filter_set = {flt for flt in filters}
filtered_items = []
@@ -456,10 +456,10 @@ def pytest_collection_modifyitems(items, config):
config.hook.pytest_deselected(items=deselected_items)
items[:] = filtered_items
- # XXX - check to be removed when tests for peerdirs don't run
- for item in items:
- if not item.nodeid:
- item._nodeid = os.path.basename(item.location[0])
+ # XXX - check to be removed when tests for peerdirs don't run
+ for item in items:
+ if not item.nodeid:
+ item._nodeid = os.path.basename(item.location[0])
if os.path.exists(config.option.test_list_path):
with open(config.option.test_list_path, 'r') as afile:
chunks = json.load(afile)
@@ -490,39 +490,39 @@ def pytest_collection_modifyitems(items, config):
for item in chunk_items:
items.extend(item)
yatest_logger.info("Modulo %s tests are: %s", modulo_index, chunk_items)
-
+
if config.option.mode == yatest_lib.ya.RunMode.Run:
- for item in items:
- test_item = NotLaunchedTestItem(item.nodeid, config.option.test_suffix)
- config.ya_trace_reporter.on_start_test_class(test_item)
- config.ya_trace_reporter.on_finish_test_case(test_item)
- config.ya_trace_reporter.on_finish_test_class(test_item)
+ for item in items:
+ test_item = NotLaunchedTestItem(item.nodeid, config.option.test_suffix)
+ config.ya_trace_reporter.on_start_test_class(test_item)
+ config.ya_trace_reporter.on_finish_test_case(test_item)
+ config.ya_trace_reporter.on_finish_test_class(test_item)
elif config.option.mode == yatest_lib.ya.RunMode.List:
- tests = []
- for item in items:
+ tests = []
+ for item in items:
item = CustomTestItem(item.nodeid, pytest_config.option.test_suffix, item.keywords)
- record = {
- "class": item.class_name,
- "test": item.test_name,
- "tags": _get_item_tags(item),
- }
- tests.append(record)
+ record = {
+ "class": item.class_name,
+ "test": item.test_name,
+ "tags": _get_item_tags(item),
+ }
+ tests.append(record)
if config.option.test_list_file:
with open(config.option.test_list_file, 'w') as afile:
json.dump(tests, afile)
# TODO prettyboy remove after test_tool release - currently it's required for backward compatibility
- sys.stderr.write(json.dumps(tests))
-
-
-def pytest_collectreport(report):
- if not report.passed:
+ sys.stderr.write(json.dumps(tests))
+
+
+def pytest_collectreport(report):
+ if not report.passed:
if hasattr(pytest_config, 'ya_trace_reporter'):
test_item = TestItem(report, None, pytest_config.option.test_suffix)
pytest_config.ya_trace_reporter.on_error(test_item)
- else:
- sys.stderr.write(yatest_lib.tools.to_utf8(report.longrepr))
-
-
+ else:
+ sys.stderr.write(yatest_lib.tools.to_utf8(report.longrepr))
+
+
@pytest.mark.tryfirst
def pytest_pyfunc_call(pyfuncitem):
testfunction = pyfuncitem.obj
@@ -542,7 +542,7 @@ def pytest_pyfunc_call(pyfuncitem):
@pytest.hookimpl(hookwrapper=True)
-def pytest_runtest_makereport(item, call):
+def pytest_runtest_makereport(item, call):
def logreport(report, result, call):
test_item = TestItem(report, result, pytest_config.option.test_suffix)
if not pytest_config.suite_metrics and context.Ctx.get("YA_PYTEST_START_TIMESTAMP"):
@@ -554,24 +554,24 @@ def pytest_runtest_makereport(item, call):
if report.outcome == "failed":
yatest_logger.error(report.longrepr)
- if report.when == "call":
- _collect_test_rusage(item)
+ if report.when == "call":
+ _collect_test_rusage(item)
pytest_config.ya_trace_reporter.on_finish_test_case(test_item)
- elif report.when == "setup":
+ elif report.when == "setup":
pytest_config.ya_trace_reporter.on_start_test_class(test_item)
- if report.outcome != "passed":
+ if report.outcome != "passed":
pytest_config.ya_trace_reporter.on_start_test_case(test_item)
pytest_config.ya_trace_reporter.on_finish_test_case(test_item)
- else:
+ else:
pytest_config.ya_trace_reporter.on_start_test_case(test_item)
- elif report.when == "teardown":
- if report.outcome == "failed":
+ elif report.when == "teardown":
+ if report.outcome == "failed":
pytest_config.ya_trace_reporter.on_start_test_case(test_item)
pytest_config.ya_trace_reporter.on_finish_test_case(test_item)
else:
pytest_config.ya_trace_reporter.on_finish_test_case(test_item, duration_only=True)
pytest_config.ya_trace_reporter.on_finish_test_class(test_item)
-
+
outcome = yield
rep = outcome.get_result()
result = None
@@ -580,10 +580,10 @@ def pytest_runtest_makereport(item, call):
if not pytest_config.from_ya_test:
ti = TestItem(rep, result, pytest_config.option.test_suffix)
tr = pytest_config.pluginmanager.getplugin('terminalreporter')
- tr.write_line("{} - Validating canonical data is not supported when running standalone binary".format(ti), yellow=True, bold=True)
+ tr.write_line("{} - Validating canonical data is not supported when running standalone binary".format(ti), yellow=True, bold=True)
logreport(rep, result, call)
-
-
+
+
def pytest_make_parametrize_id(config, val, argname):
# Avoid <, > symbols in canondata file names
if inspect.isfunction(val) and val.__name__ == "<lambda>":
@@ -598,7 +598,7 @@ def get_formatted_error(report):
text += colorize(entry)
else:
text = colorize(report.longrepr)
- text = yatest_lib.tools.to_utf8(text)
+ text = yatest_lib.tools.to_utf8(text)
return text
@@ -616,9 +616,9 @@ def colorize(longrepr):
if hasattr(longrepr, 'reprtraceback') and hasattr(longrepr.reprtraceback, 'toterminal'):
longrepr.reprtraceback.toterminal(writer)
return io.getvalue().strip()
- return yatest_lib.tools.to_utf8(longrepr)
+ return yatest_lib.tools.to_utf8(longrepr)
- text = yatest_lib.tools.to_utf8(longrepr)
+ text = yatest_lib.tools.to_utf8(longrepr)
pos = text.find("E ")
if pos == -1:
return text
@@ -633,25 +633,25 @@ def colorize(longrepr):
return "{}[[bad]]{}".format(bt, error)
-class TestItem(object):
-
- def __init__(self, report, result, test_suffix):
- self._result = result
- self.nodeid = report.nodeid
- self._class_name, self._test_name = tools.split_node_id(self.nodeid, test_suffix)
- self._error = None
- self._status = None
- self._process_report(report)
- self._duration = hasattr(report, 'duration') and report.duration or 0
- self._keywords = getattr(report, "keywords", {})
-
- def _process_report(self, report):
- if report.longrepr:
- self.set_error(report)
- if hasattr(report, 'when') and report.when != "call":
- self.set_error(report.when + " failed:\n" + self._error)
- else:
- self.set_error("")
+class TestItem(object):
+
+ def __init__(self, report, result, test_suffix):
+ self._result = result
+ self.nodeid = report.nodeid
+ self._class_name, self._test_name = tools.split_node_id(self.nodeid, test_suffix)
+ self._error = None
+ self._status = None
+ self._process_report(report)
+ self._duration = hasattr(report, 'duration') and report.duration or 0
+ self._keywords = getattr(report, "keywords", {})
+
+ def _process_report(self, report):
+ if report.longrepr:
+ self.set_error(report)
+ if hasattr(report, 'when') and report.when != "call":
+ self.set_error(report.when + " failed:\n" + self._error)
+ else:
+ self.set_error("")
report_teststatus = _pytest.skipping.pytest_report_teststatus(report)
if report_teststatus is not None:
@@ -667,89 +667,89 @@ class TestItem(object):
self._status = 'skipped'
self.set_error(yatest_lib.tools.to_utf8(report.longrepr[-1]))
elif report.passed:
- self._status = 'good'
- self.set_error("")
+ self._status = 'good'
+ self.set_error("")
else:
self._status = 'fail'
-
- @property
- def status(self):
- return self._status
-
- def set_status(self, status):
- self._status = status
-
- @property
- def test_name(self):
- return tools.normalize_name(self._test_name)
-
- @property
- def class_name(self):
- return tools.normalize_name(self._class_name)
-
- @property
- def error(self):
- return self._error
-
+
+ @property
+ def status(self):
+ return self._status
+
+ def set_status(self, status):
+ self._status = status
+
+ @property
+ def test_name(self):
+ return tools.normalize_name(self._test_name)
+
+ @property
+ def class_name(self):
+ return tools.normalize_name(self._class_name)
+
+ @property
+ def error(self):
+ return self._error
+
def set_error(self, entry, marker='bad'):
if isinstance(entry, _pytest.reports.BaseReport):
- self._error = get_formatted_error(entry)
- else:
+ self._error = get_formatted_error(entry)
+ else:
self._error = "[[{}]]{}".format(yatest_lib.tools.to_str(marker), yatest_lib.tools.to_str(entry))
-
- @property
- def duration(self):
- return self._duration
-
- @property
- def result(self):
- if 'not_canonize' in self._keywords:
- return None
- return self._result
-
- @property
- def keywords(self):
- return self._keywords
-
- def __str__(self):
- return "{}::{}".format(self.class_name, self.test_name)
-
-
-class CustomTestItem(TestItem):
-
- def __init__(self, nodeid, test_suffix, keywords=None):
- self._result = None
- self.nodeid = nodeid
- self._class_name, self._test_name = tools.split_node_id(nodeid, test_suffix)
- self._duration = 0
- self._error = ""
- self._keywords = keywords if keywords is not None else {}
-
-
-class NotLaunchedTestItem(CustomTestItem):
-
- def __init__(self, nodeid, test_suffix):
- super(NotLaunchedTestItem, self).__init__(nodeid, test_suffix)
- self._status = "not_launched"
-
-
-class CrashedTestItem(CustomTestItem):
-
- def __init__(self, nodeid, test_suffix):
- super(CrashedTestItem, self).__init__(nodeid, test_suffix)
- self._status = "crashed"
-
-
-class DeselectedTestItem(CustomTestItem):
-
- def __init__(self, nodeid, test_suffix):
- super(DeselectedTestItem, self).__init__(nodeid, test_suffix)
- self._status = "deselected"
-
-
-class TraceReportGenerator(object):
-
- def __init__(self, out_file_path):
+
+ @property
+ def duration(self):
+ return self._duration
+
+ @property
+ def result(self):
+ if 'not_canonize' in self._keywords:
+ return None
+ return self._result
+
+ @property
+ def keywords(self):
+ return self._keywords
+
+ def __str__(self):
+ return "{}::{}".format(self.class_name, self.test_name)
+
+
+class CustomTestItem(TestItem):
+
+ def __init__(self, nodeid, test_suffix, keywords=None):
+ self._result = None
+ self.nodeid = nodeid
+ self._class_name, self._test_name = tools.split_node_id(nodeid, test_suffix)
+ self._duration = 0
+ self._error = ""
+ self._keywords = keywords if keywords is not None else {}
+
+
+class NotLaunchedTestItem(CustomTestItem):
+
+ def __init__(self, nodeid, test_suffix):
+ super(NotLaunchedTestItem, self).__init__(nodeid, test_suffix)
+ self._status = "not_launched"
+
+
+class CrashedTestItem(CustomTestItem):
+
+ def __init__(self, nodeid, test_suffix):
+ super(CrashedTestItem, self).__init__(nodeid, test_suffix)
+ self._status = "crashed"
+
+
+class DeselectedTestItem(CustomTestItem):
+
+ def __init__(self, nodeid, test_suffix):
+ super(DeselectedTestItem, self).__init__(nodeid, test_suffix)
+ self._status = "deselected"
+
+
+class TraceReportGenerator(object):
+
+ def __init__(self, out_file_path):
self._filename = out_file_path
self._file = open(out_file_path, 'w')
self._wreckage_filename = out_file_path + '.wreckage'
@@ -759,7 +759,7 @@ class TraceReportGenerator(object):
self._current_test = (None, None)
self._pid = os.getpid()
self._check_intricate_respawn()
-
+
def _check_intricate_respawn(self):
pid_file = self._filename + '.pid'
try:
@@ -803,40 +803,40 @@ class TraceReportGenerator(object):
# Test binary is launched without `ya make -t`'s testing machinery - don't rely on clean environment
pass
- def on_start_test_class(self, test_item):
+ def on_start_test_class(self, test_item):
pytest_config.ya.set_test_item_node_id(test_item.nodeid)
class_name = test_item.class_name.decode('utf-8') if sys.version_info[0] < 3 else test_item.class_name
self._current_test = (class_name, None)
self.trace('test-started', {'class': class_name})
-
- def on_finish_test_class(self, test_item):
+
+ def on_finish_test_class(self, test_item):
pytest_config.ya.set_test_item_node_id(test_item.nodeid)
self.trace('test-finished', {'class': test_item.class_name.decode('utf-8') if sys.version_info[0] < 3 else test_item.class_name})
-
- def on_start_test_case(self, test_item):
+
+ def on_start_test_case(self, test_item):
class_name = yatest_lib.tools.to_utf8(test_item.class_name)
subtest_name = yatest_lib.tools.to_utf8(test_item.test_name)
- message = {
+ message = {
'class': class_name,
'subtest': subtest_name,
- }
+ }
if test_item.nodeid in pytest_config.test_logs:
message['logs'] = pytest_config.test_logs[test_item.nodeid]
pytest_config.ya.set_test_item_node_id(test_item.nodeid)
self._current_test = (class_name, subtest_name)
- self.trace('subtest-started', message)
-
+ self.trace('subtest-started', message)
+
def on_finish_test_case(self, test_item, duration_only=False):
if test_item.result is not None:
- try:
+ try:
result = canon.serialize(test_item.result)
- except Exception as e:
- yatest_logger.exception("Error while serializing test results")
- test_item.set_error("Invalid test result: {}".format(e))
- test_item.set_status("fail")
- result = None
- else:
- result = None
+ except Exception as e:
+ yatest_logger.exception("Error while serializing test results")
+ test_item.set_error("Invalid test result: {}".format(e))
+ test_item.set_status("fail")
+ result = None
+ else:
+ result = None
if duration_only and test_item.nodeid in self._test_messages: # add teardown time
message = self._test_messages[test_item.nodeid]
@@ -860,7 +860,7 @@ class TraceReportGenerator(object):
self.trace('subtest-finished', message)
self._test_messages[test_item.nodeid] = message
-
+
def dump_suite_metrics(self):
message = {"metrics": pytest_config.suite_metrics}
self.trace("suite-event", message)
@@ -874,28 +874,28 @@ class TraceReportGenerator(object):
else:
self._test_duration[test_item.nodeid] = test_item._duration
- @staticmethod
- def _get_comment(test_item):
- msg = yatest_lib.tools.to_utf8(test_item.error)
- if not msg:
- return ""
+ @staticmethod
+ def _get_comment(test_item):
+ msg = yatest_lib.tools.to_utf8(test_item.error)
+ if not msg:
+ return ""
return msg + "[[rst]]"
-
+
def _dump_trace(self, name, value):
- event = {
- 'timestamp': time.time(),
- 'value': value,
- 'name': name
- }
+ event = {
+ 'timestamp': time.time(),
+ 'value': value,
+ 'name': name
+ }
data = yatest_lib.tools.to_str(json.dumps(event, ensure_ascii=False))
self._file.write(data + '\n')
self._file.flush()
-
+
def _check_sloppy_fork(self, name, value):
if self._pid == os.getpid():
return
-
+
yatest_logger.error("Skip tracing to avoid data corruption, name = %s, value = %s", name, value)
try:
@@ -950,14 +950,14 @@ class TraceReportGenerator(object):
self._dump_trace(name, value)
-class DryTraceReportGenerator(TraceReportGenerator):
- """
- Generator does not write any information.
- """
-
- def __init__(self, *args, **kwargs):
+class DryTraceReportGenerator(TraceReportGenerator):
+ """
+ Generator does not write any information.
+ """
+
+ def __init__(self, *args, **kwargs):
self._test_messages = {}
self._test_duration = {}
-
- def trace(self, name, value):
- pass
+
+ def trace(self, name, value):
+ pass