def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config)) self.collection_ignored = set() self.testmon_save = True self.config = config
def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config)) self.testmon_save = True self.config = config self.lastfailed = self.testmon_data.lastfailed
def track_it(testdir, func): testmon = Testmon(project_dirs=[testdir.tmpdir.strpath], testmon_labels=set()) testmon_data = TestmonData(testdir.tmpdir.strpath) testmon.start() func() testmon.stop_and_save(testmon_data, testdir.tmpdir.strpath, 'testnode') return testmon_data.node_data['testnode']
def track_it(testdir, func): testmon = Testmon(project_dirs=[testdir.tmpdir.strpath], testmon_labels=set()) testmon_data = TestmonData(testdir.tmpdir.strpath) _result, coverage_data = testmon.track_dependencies(func, 'testnode') testmon_data.set_dependencies('testnode', coverage_data, testdir.tmpdir.strpath) return testmon_data.node_data['testnode']
def track_it(testdir, func): testmon = CoreTestmon(project_dirs=[testdir.tmpdir.strpath], testmon_labels=set()) testmon_data = CoreTestmonData(testdir.tmpdir.strpath) testmon_data.read_source() testmon.start() func() testmon.stop_and_save(testmon_data, testdir.tmpdir.strpath, 'testnode') return testmon_data._fetch_node_data()[0]['testnode']
def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config)) self.collection_ignored = set() self.testmon_save = True self.config = config self.reports = defaultdict(lambda: {}) self.selected, self.deselected = [], set() self.file_data = self.testmon_data.file_data() self.f_to_ignore = self.testmon_data.stable_files if self.config.getoption('tlf'): self.f_to_ignore -= self.testmon_data.f_last_failed
def test_subprocess_testmon(self): testmon = CoreTestmon("") testmon.setup_coverage(subprocess=True) path1 = self.make_file( "subprocesstest.py", """\ a=1 """, ) self.run_command(f"python {path1}") assert testmon.sub_cov_file in "{}".format( os.listdir(os.path.join(os.getcwd(), ".tmontmp"))) testmon.close()
def pytest_configure(config): coverage_stack = None plugin = None testmon_config = TestmonConfig() message, should_collect, should_select = testmon_config.header_collect_select( config, coverage_stack, cov_plugin=plugin) config.testmon_config = (message, should_collect, should_select) if should_select or should_collect: config.option.continue_on_collection_errors = True try: init_testmon_data(config) if should_select: config.pluginmanager.register( TestmonSelect(config, config.testmon_data), "TestmonSelect") if should_collect: config.pluginmanager.register( TestmonCollect( Testmon( config.rootdir.strpath, testmon_labels=testmon_options(config), cov_plugin=plugin, ), config.testmon_data, ), "TestmonCollect", ) except TestmonException as e: pytest.exit(str(e))
def pytest_configure(config): coverage_stack = None testmon_config = TestmonConfig() message, should_collect, should_select = testmon_config.header_collect_select( config, coverage_stack ) config.testmon_config = (message, should_collect, should_select) if should_select or should_collect: config.option.continue_on_collection_errors = True init_testmon_data(config) if should_select: config.pluginmanager.register( TestmonSelect(config, config.testmon_data), "TestmonSelect" ) if should_collect: config.pluginmanager.register( TestmonCollect( Testmon( config.project_dirs, testmon_labels=testmon_options(config) ), config.testmon_data, ), "TestmonCollect", )
def register_plugins(config, should_select, should_collect, cov_plugin): if should_select: config.pluginmanager.register( TestmonSelect(config, config.testmon_data), "TestmonSelect") if should_collect: config.pluginmanager.register( TestmonCollect( Testmon( config.rootdir.strpath, testmon_labels=testmon_options(config), cov_plugin=cov_plugin, ), config.testmon_data, ), "TestmonCollect", )
def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config) ) self.testmon_save = True self.config = config self.lastfailed = self.testmon_data.lastfailed
class TestmonDeselect(object): def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config) ) self.testmon_save = True self.config = config self.lastfailed = self.testmon_data.lastfailed def pytest_report_header(self, config): changed_files = ",".join([os.path.relpath(path, config.rootdir.strpath) for path in self.testmon_data.modules_cache]) if changed_files=='' or len(changed_files)>100: changed_files = len(self.testmon_data.modules_cache) active_message = "testmon={}, changed files: {}, skipping collection of {} items".format(config.getoption('testmon'), changed_files, sum(self.testmon_data.unaffected_paths.values())) if self.testmon_data.variant: return active_message + ", run variant: {}".format(self.testmon_data.variant) else: return active_message + "." def pytest_collection_modifyitems(self, session, config, items): selected, deselected = [], [] self.testmon_data.collect_garbage(allnodeids=[item.nodeid for item in items]) for item in items: if item.nodeid in self.lastfailed or self.testmon_data.test_should_run(item.nodeid): selected.append(item) else: deselected.append(item) items[:] = selected if deselected: config.hook.pytest_deselected(items=deselected) def pytest_runtest_protocol(self, __multicall__, item, nextitem): if self.config.getoption('testmon') == u'readonly': return __multicall__.execute() result, coverage_data = self.testmon.track_dependencies(__multicall__.execute, item.nodeid) self.testmon_data.set_dependencies(item.nodeid, coverage_data, item.config.rootdir.strpath) return result def pytest_runtest_logreport(self, report): if report.failed and "xfail" not in report.keywords: if report.nodeid not in self.lastfailed: self.lastfailed.append(report.nodeid) elif not report.failed: if report.when == "call": try: if report.nodeid in self.lastfailed: self.lastfailed.remove(report.nodeid) except KeyError: pass def pytest_ignore_collect(self, path, config): strpath = path.strpath if strpath in self.testmon_data.unaffected_paths: config.hook.pytest_deselected(items=['1'] * self.testmon_data.unaffected_paths[strpath]) return True def pytest_internalerror(self, excrepr, excinfo): self.testmon_save = False def pytest_keyboard_interrupt(self, excinfo): self.testmon_save = False def pytest_sessionfinish(self, session): if self.testmon_save: self.testmon_data.write_data() self.testmon.close()
class TestmonDeselect(object): def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config)) self.collection_ignored = set() self.testmon_save = True self.config = config def pytest_report_header(self, config): changed_files = ",".join(self.testmon_data.source_tree.changed_files) if changed_files == '' or len(changed_files) > 100: changed_files = len(self.testmon_data.source_tree.changed_files) active_message = "testmon={}, changed files: {}, skipping collection of {} items".format( config.getoption('testmon'), changed_files, len(self.testmon_data.unaffected_nodeids)) if self.testmon_data.variant: return active_message + ", run variant: {}".format( self.testmon_data.variant) else: return active_message + "." def report_if_failed(self, nodeid): if nodeid in self.testmon_data.fail_reports: for report in self.testmon_data.fail_reports[nodeid]: test_report = unserialize_report('testreport', report) self.config.hook.pytest_runtest_logreport(report=test_report) def pytest_collection_modifyitems(self, session, config, items): removed_nodeids = set( self.testmon_data.node_data) - self.collection_ignored - set( [item.nodeid for item in items]) if removed_nodeids: self.testmon_data.collect_garbage(removed_nodeids) selected, deselected = [], [] for item in items: assert item.nodeid not in self.collection_ignored if self.testmon_data.test_should_run(item.nodeid): selected.append(item) else: self.report_if_failed(item.nodeid) deselected.append(item) for nodeid in self.collection_ignored: self.report_if_failed(nodeid) items[:] = selected if deselected: config.hook.pytest_deselected(items=deselected) @pytest.mark.hookwrapper def pytest_runtest_protocol(self, item, nextitem): if self.config.getoption('testmon') == u'readonly': yield self.testmon.start() result = yield if result.excinfo and issubclass(result.excinfo[0], KeyboardInterrupt): self.testmon.stop() else: self.testmon.stop_and_save(self.testmon_data, item.config.rootdir.strpath, item.nodeid, self.testmon_data.reports[item.nodeid]) del self.testmon_data.reports[item.nodeid] def pytest_runtest_logreport(self, report): self.testmon_data.reports[report.nodeid].append( serialize_report(report)) class FakeItemFromTestmon(object): def __init__(self, config): self.config = config def pytest_ignore_collect(self, path, config): strpath = os.path.relpath(path.strpath, config.rootdir.strpath) if strpath in self.testmon_data.unaffected_files: if os.path.split(strpath)[1].startswith('test_'): for nodeid in self.testmon_data.file_data()[strpath]: self.collection_ignored.add(nodeid) config.hook.pytest_deselected( items=([self.FakeItemFromTestmon(config)] * len(self.testmon_data.file_data()[strpath]))) return True def pytest_internalerror(self, excrepr, excinfo): self.testmon_save = False def pytest_keyboard_interrupt(self, excinfo): self.testmon_save = False def pytest_sessionfinish(self, session): if self.testmon_save: self.testmon_data.write_data() self.testmon.close()
from testmon.testmon_core import get_variant_inifile, Testmon ancestor = get_common_ancestor(sys.argv[1:]) rootdir, inifile, inicfg = getcfg( [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"]) if rootdir is None: for rootdir in ancestor.parts(reverse=True): if rootdir.join("setup.py").exists(): break else: rootdir = ancestor variant = get_variant_inifile(inifile) testmon = Testmon([str(rootdir)], variant=variant ) testmon.read_fs() node_files = testmon.modules_test_counts().keys() changed_files = [] for node_file in node_files: if testmon.old_mtimes.get(node_file) != testmon.mtimes.get(node_file): changed_files.append(node_file) print "Changed files:%s " % changed_files print rootdir, inifile, inicfg
class TestmonDeselect(object): def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config)) self.testmon_save = True self.config = config self.lastfailed = self.testmon_data.lastfailed def pytest_report_header(self, config): changed_files = ",".join([ os.path.relpath(path, config.rootdir.strpath) for path in self.testmon_data.modules_cache ]) if changed_files == '' or len(changed_files) > 100: changed_files = len(self.testmon_data.modules_cache) active_message = "testmon={}, changed files: {}, skipping collection of {} items".format( config.getoption('testmon'), changed_files, sum(self.testmon_data.unaffected_paths.values())) if self.testmon_data.variant: return active_message + ", run variant: {}".format( self.testmon_data.variant) else: return active_message + "." def pytest_collection_modifyitems(self, session, config, items): selected, deselected = [], [] self.testmon_data.collect_garbage( allnodeids=[item.nodeid for item in items]) for item in items: if item.nodeid in self.lastfailed or self.testmon_data.test_should_run( item.nodeid): selected.append(item) else: deselected.append(item) items[:] = selected if deselected: config.hook.pytest_deselected(items=deselected) @pytest.mark.hookwrapper def pytest_runtest_protocol(self, item, nextitem): if self.config.getoption('testmon') == u'readonly': yield self.testmon.start() result = yield # NOTE: pytest-watch also sends KeyboardInterrupt when changes are # detected. This should still save the collected data up until then. if result.excinfo and issubclass(result.excinfo[0], KeyboardInterrupt): self.testmon.stop() else: self.testmon.stop_and_save(self.testmon_data, item.config.rootdir.strpath, item.nodeid) def pytest_runtest_logreport(self, report): if report.failed and "xfail" not in report.keywords: if report.nodeid not in self.lastfailed: self.lastfailed.append(report.nodeid) elif not report.failed: if report.when == "call": try: if report.nodeid in self.lastfailed: self.lastfailed.remove(report.nodeid) except KeyError: pass class FakeItemFromTestmon(object): def __init__(self, config): self.config = config def pytest_ignore_collect(self, path, config): strpath = path.strpath if strpath in self.testmon_data.unaffected_paths: config.hook.pytest_deselected( items=([self.FakeItemFromTestmon(config)] * self.testmon_data.unaffected_paths[strpath])) return True def pytest_internalerror(self, excrepr, excinfo): self.testmon_save = False def pytest_sessionfinish(self, session): if self.testmon_save: self.testmon_data.write_data() self.testmon.close() def pytest_terminal_summary(self, terminalreporter, exitstatus=None): if (not self.testmon_save and terminalreporter.config.getvalue('verbose')): terminalreporter.line('testmon: not saving data')
from testmon.testmon_core import get_variant_inifile, Testmon ancestor = get_common_ancestor(sys.argv[1:]) rootdir, inifile, inicfg = getcfg( [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"]) if rootdir is None: for rootdir in ancestor.parts(reverse=True): if rootdir.join("setup.py").exists(): break else: rootdir = ancestor variant = get_variant_inifile(inifile) testmon = Testmon([str(rootdir)], variant=variant ) testmon.read_fs() node_files = testmon.file_data().keys() changed_files = [] for node_file in node_files: if testmon.old_mtimes.get(node_file) != testmon.mtimes.get(node_file): changed_files.append(node_file) print "Changed files:%s " % changed_files print rootdir, inifile, inicfg
class TestmonDeselect(object): def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config)) self.collection_ignored = set() self.testmon_save = True self.config = config self.reports = defaultdict(lambda: {}) self.selected, self.deselected = [], set() self.file_data = self.testmon_data.file_data() self.f_to_ignore = self.testmon_data.stable_files if self.config.getoption('tlf'): self.f_to_ignore -= self.testmon_data.f_last_failed def test_should_run(self, nodeid): if self.config.getoption('tlf'): if nodeid in self.testmon_data.fail_reports: return True if nodeid in self.testmon_data.stable_nodeids: return False else: return True def report_if_failed(self, nodeid): node_reports = self.testmon_data.fail_reports.get(nodeid, {}) for phase in ('setup', 'call', 'teardown'): if phase in node_reports: test_report = runner.TestReport(**node_reports[phase]) self.config.hook.pytest_runtest_logreport(report=test_report) def pytest_report_header(self, config): changed_files = ",".join(self.testmon_data.source_tree.changed_files) if changed_files == '' or len(changed_files) > 100: changed_files = len(self.testmon_data.source_tree.changed_files) active_message = "testmon={}, changed files: {}, skipping collection of {} files".format( config.getoption('testmon'), changed_files, len(self.testmon_data.stable_files)) if self.testmon_data.variant: return active_message + ", run variant: {}".format( self.testmon_data.variant) else: return active_message + "." def pytest_ignore_collect(self, path, config): strpath = os.path.relpath(path.strpath, config.rootdir.strpath) if strpath in (self.f_to_ignore): self.collection_ignored.update(self.testmon_data.f_tests[strpath]) return True @pytest.mark.trylast def pytest_collection_modifyitems(self, session, config, items): self.testmon_data.collect_garbage(retain=self.collection_ignored.union( set([item.nodeid for item in items]))) for item in items: assert item.nodeid not in self.collection_ignored, ( item.nodeid, self.collection_ignored) for item in items: if self.test_should_run(item.nodeid): self.selected.append(item) else: self.deselected.add(item.nodeid) items[:] = self.selected session.config.hook.pytest_deselected( items=([self.FakeItemFromTestmon(session.config)] * len(self.collection_ignored.union(self.deselected)))) def pytest_runtestloop(self, session): ignored_deselected = self.collection_ignored.union(self.deselected) for nodeid in ignored_deselected: self.report_if_failed(nodeid) @pytest.mark.hookwrapper def pytest_runtest_protocol(self, item, nextitem): if self.config.getoption('testmon') == u'readonly': yield else: self.testmon.start() result = yield if result.excinfo and issubclass(result.excinfo[0], KeyboardInterrupt): self.testmon.stop() else: self.testmon.stop_and_save(self.testmon_data, item.config.rootdir.strpath, item.nodeid, self.reports[item.nodeid]) def pytest_runtest_logreport(self, report): assert report.when not in self.reports, \ "{} {} {}".format(report.nodeid, report.when, self.reports) self.reports[report.nodeid][report.when] = serialize_report(report) class FakeItemFromTestmon(object): def __init__(self, config): self.config = config def pytest_internalerror(self, excrepr, excinfo): self.testmon_save = False def pytest_keyboard_interrupt(self, excinfo): self.testmon_save = False def pytest_sessionfinish(self, session): if self.testmon_save: self.testmon_data.write_data() self.testmon.close()
class TestmonDeselect(object): def __init__(self, config, testmon_data): self.testmon_data = testmon_data self.testmon = Testmon(config.project_dirs, testmon_labels=testmon_options(config)) self.testmon_save = True self.config = config self.lastfailed = self.testmon_data.lastfailed def pytest_report_header(self, config): changed_files = ",".join([os.path.relpath(path, config.rootdir.strpath) for path in self.testmon_data.modules_cache]) if changed_files == '' or len(changed_files) > 100: changed_files = len(self.testmon_data.modules_cache) active_message = "testmon={}, changed files: {}, skipping collection of {} items".format( config.getoption('testmon'), changed_files, sum(self.testmon_data.unaffected_paths.values())) if self.testmon_data.variant: return active_message + ", run variant: {}".format(self.testmon_data.variant) else: return active_message + "." def pytest_collection_modifyitems(self, session, config, items): selected, deselected = [], [] self.testmon_data.collect_garbage(allnodeids=[item.nodeid for item in items]) for item in items: if item.nodeid in self.lastfailed or self.testmon_data.test_should_run(item.nodeid): selected.append(item) else: deselected.append(item) items[:] = selected if deselected: config.hook.pytest_deselected(items=deselected) @pytest.mark.hookwrapper def pytest_runtest_protocol(self, item, nextitem): if self.config.getoption('testmon') == u'readonly': yield self.testmon.start() result = yield # NOTE: pytest-watch also sends KeyboardInterrupt when changes are # detected. This should still save the collected data up until then. if result.excinfo and issubclass(result.excinfo[0], KeyboardInterrupt): self.testmon.stop() else: self.testmon.stop_and_save(self.testmon_data, item.config.rootdir.strpath, item.nodeid) def pytest_runtest_logreport(self, report): if report.failed and "xfail" not in report.keywords: if report.nodeid not in self.lastfailed: self.lastfailed.append(report.nodeid) elif not report.failed: if report.when == "call": try: if report.nodeid in self.lastfailed: self.lastfailed.remove(report.nodeid) except KeyError: pass class FakeItemFromTestmon(object): def __init__(self, config): self.config = config def pytest_ignore_collect(self, path, config): strpath = path.strpath if strpath in self.testmon_data.unaffected_paths: config.hook.pytest_deselected( items=([self.FakeItemFromTestmon(config)] * self.testmon_data.unaffected_paths[strpath])) return True def pytest_internalerror(self, excrepr, excinfo): self.testmon_save = False def pytest_sessionfinish(self, session): if self.testmon_save: self.testmon_data.write_data() self.testmon.close() def pytest_terminal_summary(self, terminalreporter, exitstatus=None): if (not self.testmon_save and terminalreporter.config.getvalue('verbose')): terminalreporter.line('testmon: not saving data')