def coverage(project, logger, reactor): em = reactor.execution_manager # type: ExecutionManager source_path = nc( project.expand_path(project.get_property("coverage_source_path"))) module_names = discover_modules(source_path) module_file_suffixes = discover_module_files(source_path) module_exceptions = as_list(project.get_property("coverage_exceptions")) module_names, module_files, omit_patterns = _filter_covered_modules( logger, module_names, module_file_suffixes, module_exceptions, source_path) for idx, module_name in enumerate(module_names): logger.debug("Module %r (file %r) coverage to be verified", module_name, module_files[idx]) coverage_config = dict( data_file=project.expand_path("$dir_target", "%s.coverage" % project.name), data_suffix=False, cover_pylib=False, config_file=False, branch=True, debug=as_list(project.get_property("coverage_debug")), context=project.name) project.set_property("__coverage_config", coverage_config) patch_coverage() from coverage import coverage as coverage_factory cov = coverage_factory(**coverage_config) cov.erase() cov.save() for covered_task in project.get_property( "__covered_tasks"): # type: CoveredTask if em.is_task_in_current_execution_plan(covered_task.name): task_cov = run_coverage(project, logger, reactor, covered_task, source_path, module_names, module_files, omit_patterns) cov._data.update(task_cov._data) cov.save() failure = _build_coverage_report(project, logger, "%s coverage" % project.name, project.name, "", cov, source_path, module_names, module_files) if failure: raise failure
def do_coverage(project, logger, reactor, execution_prefix, execution_name, target_task, shortest_plan): """ This function MUST ALWAYS execute in a fork. The sys.modules will be manipulated extensively to stage the tests properly, which may affect execute down the line. It's best to simple let this method exit and the fork die rather than to try to recover. """ source_tree_path = project.get_property("dir_source_main_python") reset_modules = project.get_property("%s_reset_modules" % execution_prefix) allow_non_imported_modules = project.get_property( "%s_allow_non_imported_modules" % execution_prefix) module_names = _discover_modules_to_cover(project) for module_name in module_names: logger.debug("Module '%s' coverage to be verified", module_name) if reset_modules and not is_windows(): _delete_non_essential_modules() __import__("pybuilder.plugins.python") # Reimport self # Starting fresh from coverage import coverage as coverage_factory coverage = coverage_factory(cover_pylib=False, branch=True, source=[source_tree_path]) patch_multiprocessing(coverage.config) try: try: _start_coverage(project, coverage) if shortest_plan: reactor.execute_task_shortest_plan(target_task) else: reactor.execute_task(target_task) finally: _stop_coverage(project, coverage) finally: reverse_patch_multiprocessing() module_exceptions = project.get_property("%s_exceptions" % execution_prefix) modules, non_imported_modules = _list_all_covered_modules( logger, module_names, module_exceptions, allow_non_imported_modules) failure = _build_coverage_report(project, logger, execution_name, execution_prefix, coverage, modules) if non_imported_modules and not allow_non_imported_modules: raise BuildFailedException( "Some modules have not been imported and have no coverage") if failure: raise failure
def start(self, pipe): # type: (RemoteObjectPipe) -> None from .._coverage_util import patch_coverage patch_coverage() from coverage import coverage as coverage_factory coverage = coverage_factory(*self.cov_args, **self.cov_kwargs) self.coverage = coverage coverage.start()
def do_coverage(project, logger, reactor, execution_prefix, execution_name, target_task, shortest_plan): """ This function MUST ALWAYS execute in a fork. The sys.modules will be manipulated extensively to stage the tests properly, which may affect execute down the line. It's best to simple let this method exit and the fork die rather than to try to recover. """ source_tree_path = project.get_property("dir_source_main_python") reset_modules = project.get_property("%s_reset_modules" % execution_prefix) allow_non_imported_modules = project.get_property("%s_allow_non_imported_modules" % execution_prefix) module_names = _discover_modules_to_cover(project) for module_name in module_names: logger.debug("Module '%s' coverage to be verified", module_name) if reset_modules and not is_windows(): _delete_non_essential_modules() __import__("pybuilder.plugins.python") # Reimport self # Starting fresh from coverage import coverage as coverage_factory coverage = coverage_factory(cover_pylib=False, branch=True, source=[source_tree_path]) patch_multiprocessing(coverage.config) try: try: _start_coverage(project, coverage) if shortest_plan: reactor.execute_task_shortest_plan(target_task) else: reactor.execute_task(target_task) finally: _stop_coverage(project, coverage) finally: reverse_patch_multiprocessing() module_exceptions = project.get_property("%s_exceptions" % execution_prefix) modules, non_imported_modules = _list_all_covered_modules(logger, module_names, module_exceptions, allow_non_imported_modules) failure = _build_coverage_report(project, logger, execution_name, execution_prefix, coverage, modules) if non_imported_modules and not allow_non_imported_modules: raise BuildFailedException("Some modules have not been imported and have no coverage") if failure: raise failure
# Make sure we can actually load coverage CoverageImporter(config["cov_parent_dir"]).install() sys.path.append(main_file_dir) from _coverage_util import save_normalized_coverage, patch_coverage del sys.path[-1] # Patch coverage patch_coverage() from coverage import coverage as coverage_factory from coverage.execfile import PyRunner coverage = coverage_factory(*(config.get("cov_args", ())), **(config.get("cov_kwargs", {}))) source_path = config["cov_source_path"] omit_patterns = config["cov_omit_patterns"] args = sys.argv module = False if args and args[0] == "-m": module = True args = args[1:] runner = PyRunner(args, as_module=module) runner.prepare() coverage.start() try: runner.run()
def do_coverage(project, logger, reactor, execution_prefix, execution_name, target_task, shortest_plan): from coverage import coverage as coverage_factory source_tree_path = project.get_property("dir_source_main_python") coverage = coverage_factory(cover_pylib=False, source=[source_tree_path]) _start_coverage(coverage) project.set_property('__running_coverage', True) # tell other plugins that we are not really unit testing right now if shortest_plan: reactor.execute_task_shortest_plan(target_task) else: reactor.execute_task(target_task) project.set_property('__running_coverage', False) _stop_coverage(coverage, project, logger, execution_prefix) coverage_too_low = False threshold = project.get_property("%s_threshold_warn" % execution_prefix) exceptions = project.get_property("%s_exceptions" % execution_prefix) report = { "module_names": [] } sum_lines = 0 sum_lines_not_covered = 0 module_names = _discover_modules_to_cover(project) modules = [] for module_name in module_names: try: module = sys.modules[module_name] except KeyError: logger.warn("Module not imported: {0}. No coverage information available.".format(module_name)) continue modules.append(module) module_report_data = build_module_report(coverage, module) should_ignore_module = module_name in exceptions if not should_ignore_module: sum_lines += module_report_data[0] sum_lines_not_covered += module_report_data[2] module_report = { "module": module_name, "coverage": module_report_data[4], "sum_lines": module_report_data[0], "lines": module_report_data[1], "sum_lines_not_covered": module_report_data[2], "lines_not_covered": module_report_data[3], } report["module_names"].append(module_report) if module_report_data[4] < threshold: msg = "Test coverage below %2d%% for %s: %2d%%" % (threshold, module_name, module_report_data[4]) if not should_ignore_module: logger.warn(msg) coverage_too_low = True else: logger.info(msg) if sum_lines == 0: overall_coverage = 0 else: overall_coverage = (sum_lines - sum_lines_not_covered) * 100 / sum_lines report["overall_coverage"] = overall_coverage if overall_coverage < threshold: logger.warn("Overall %s is below %2d%%: %2d%%", execution_name, threshold, overall_coverage) coverage_too_low = True else: logger.info("Overall %s is %2d%%", execution_name, overall_coverage) project.write_report("%s.json" % execution_prefix, render_report(report)) _write_summary_report(coverage, project, modules, execution_prefix) if coverage_too_low and project.get_property("%s_break_build" % execution_prefix): raise BuildFailedException("Test coverage for at least one module is below %d%%", threshold)
def run_coverage(project, logger, reactor, covered_task, source_path, module_names, module_files, omit_patterns): config_prefix = covered_task.config_prefix logger.info("Collecting coverage information for %r", str(covered_task)) if project.get_property("%scoverage_fork" % config_prefix) is not None: logger.warn( "%scoverage_fork is deprecated, coverage always runs in a spawned process", config_prefix) if project.get_property("%scoverage_reload_modules" % config_prefix) is not None: logger.warn( "%scoverage_reload_modules is deprecated - modules are no longer reloaded", config_prefix) if project.get_property("%scoverage_reset_modules" % config_prefix) is not None: logger.warn( "%scoverage_reset_modules is deprecated - modules are no longer reset", config_prefix) if project.get_property("%scoverage_allow_non_imported_modules" % config_prefix) is not None: logger.warn( "%scoverage_allow_non_imported_modules- modules are no longer imported", config_prefix) if project.get_property("%scoverage_branch_threshold_warn" % config_prefix) == 0: logger.warn( "%scoverage_branch_threshold_warn is 0 and branch coverage will not be checked", config_prefix) if project.get_property("%scoverage_branch_partial_threshold_warn" % config_prefix) == 0: logger.warn( "%scoverage_branch_partial_threshold_warn is 0 and partial branch coverage will not be checked", config_prefix) coverage_config = dict( data_file=project.expand_path("$dir_target", "%s.coverage" % covered_task.filename), data_suffix=True, cover_pylib=False, config_file=False, branch=True, context=str(covered_task), debug=as_list( project.get_property("%scoverage_debug" % config_prefix, project.get_property("coverage_debug"))), concurrency=project.get_property( "%scoverage_concurrency" % config_prefix, project.get_property("coverage_concurrency"))) from coverage import coverage as coverage_factory cov = coverage_factory(**coverage_config) cov.erase() cov_tool = CoverageTool(source_path, omit_patterns, **coverage_config) em = reactor.execution_manager reactor.add_tool(cov_tool) try: coverage_env_name = project.get_property("%scoverage_python_env" % config_prefix) if coverage_env_name: current_python_env = reactor.python_env_registry[coverage_env_name] reactor.python_env_registry.push_override( coverage_env_name, _override_python_env_for_coverage(current_python_env, coverage_config, source_path, omit_patterns)) try: em.execute_task(covered_task.task, logger=logger, project=project, reactor=reactor, _executable=covered_task.executable) finally: if coverage_env_name: reactor.python_env_registry.pop_override(coverage_env_name) finally: reactor.remove_tool(cov_tool) cov.combine() cov.save() failure = _build_coverage_report(project, logger, covered_task.coverage_name, covered_task.filename, config_prefix, cov, source_path, module_names, module_files) if failure: raise failure return cov
def do_coverage(project, logger, reactor): from coverage import coverage as coverage_factory source_tree_path = project.get_property("dir_source_main_python") coverage = coverage_factory(cover_pylib=False, source=[source_tree_path]) start_coverage(coverage) project.set_property( '__running_coverage', True ) # tell other plugins that we are not really unit testing right now reactor.execute_task("run_unit_tests") project.set_property('__running_coverage', False) stop_coverage(coverage, project, logger) coverage_too_low = False threshold = project.get_property("coverage_threshold_warn") exceptions = project.get_property("coverage_exceptions") report = {"module_names": []} sum_lines = 0 sum_lines_not_covered = 0 module_names = discover_modules_to_cover(project) modules = [] for module_name in module_names: try: module = sys.modules[module_name] except KeyError: logger.warn( "Module not imported: {0}. No coverage information available.". format(module_name)) continue modules.append(module) module_report_data = build_module_report(coverage, module) should_ignore_module = module_name in exceptions if not should_ignore_module: sum_lines += module_report_data[0] sum_lines_not_covered += module_report_data[2] module_report = { "module": module_name, "coverage": module_report_data[4], "sum_lines": module_report_data[0], "lines": module_report_data[1], "sum_lines_not_covered": module_report_data[2], "lines_not_covered": module_report_data[3], } report["module_names"].append(module_report) if module_report_data[4] < threshold: msg = "Test coverage below %2d%% for %s: %2d%%" % ( threshold, module_name, module_report_data[4]) if not should_ignore_module: logger.warn(msg) coverage_too_low = True else: logger.info(msg) if sum_lines == 0: overall_coverage = 0 else: overall_coverage = (sum_lines - sum_lines_not_covered) * 100 / sum_lines report["overall_coverage"] = overall_coverage if overall_coverage < threshold: logger.warn("Overall coverage is below %2d%%: %2d%%", threshold, overall_coverage) coverage_too_low = True else: logger.info("Overall coverage is %2d%%", overall_coverage) project.write_report("coverage.json", render_report(report)) write_summary_report(coverage, project, modules) if coverage_too_low and project.get_property("coverage_break_build"): raise BuildFailedException( "Test coverage for at least one module is below %d%%", threshold)
def do_coverage(project, logger, reactor, execution_prefix, execution_name, target_task, shortest_plan): """ This function MUST ALWAYS execute in a fork. The sys.modules will be manipulated extensively to stage the tests properly, which may affect execute down the line. It's best to simple let this method exit and the fork die rather than to try to recover. """ source_tree_path = project.get_property("dir_source_main_python") module_names = _discover_modules_to_cover(project) for module_name in module_names: logger.debug("Module '%s' coverage to be verified", module_name) _delete_non_essential_modules() __import__("pybuilder.plugins.python") # Reimport self # Starting fresh from coverage import coverage as coverage_factory coverage = coverage_factory(cover_pylib=False, branch=True, source=[source_tree_path]) try: project.set_property('__running_coverage', True) # tell other plugins that we are not really unit testing right now _start_coverage(coverage) if shortest_plan: reactor.execute_task_shortest_plan(target_task) else: reactor.execute_task(target_task) finally: _stop_coverage(coverage) project.set_property('__running_coverage', False) coverage_too_low = False threshold = project.get_property("%s_threshold_warn" % execution_prefix) exceptions = project.get_property("%s_exceptions" % execution_prefix) report = { "module_names": [] } sum_lines = 0 sum_lines_not_covered = 0 modules = [] for module_name in module_names: try: module = sys.modules[module_name] except KeyError: logger.warn("Module '%s' was not imported by the covered tests", module_name) try: module = __import__(module_name) except SyntaxError as e: logger.warn("Coverage for module '%s' cannot be established - syntax error: %s", module_name, e) continue if module not in modules: modules.append(module) module_report_data = build_module_report(coverage, module) should_ignore_module = module_name in exceptions if not should_ignore_module: sum_lines += module_report_data[0] sum_lines_not_covered += module_report_data[2] module_report = { "module": module_name, "coverage": module_report_data[4], "sum_lines": module_report_data[0], "lines": module_report_data[1], "sum_lines_not_covered": module_report_data[2], "lines_not_covered": module_report_data[3], } logger.debug("Module coverage report: %s", module_report) report["module_names"].append(module_report) if module_report_data[4] < threshold: msg = "Test coverage below %2d%% for %s: %2d%%" % (threshold, module_name, module_report_data[4]) if not should_ignore_module: logger.warn(msg) coverage_too_low = True else: logger.info(msg) if sum_lines == 0: overall_coverage = 0 else: overall_coverage = (sum_lines - sum_lines_not_covered) * 100 / sum_lines report["overall_coverage"] = overall_coverage if overall_coverage < threshold: logger.warn("Overall %s is below %2d%%: %2d%%", execution_name, threshold, overall_coverage) coverage_too_low = True else: logger.info("Overall %s is %2d%%", execution_name, overall_coverage) project.write_report("%s.json" % execution_prefix, render_report(report)) _write_summary_report(coverage, project, modules, execution_prefix, execution_name) if coverage_too_low and project.get_property("%s_break_build" % execution_prefix): raise BuildFailedException("Test coverage for at least one module is below %d%%", threshold)
def do_coverage(project, logger, reactor, execution_prefix, execution_name, target_task, shortest_plan): """ This function MUST ALWAYS execute in a fork. The sys.modules will be manipulated extensively to stage the tests properly, which may affect execute down the line. It's best to simple let this method exit and the fork die rather than to try to recover. """ source_tree_path = project.get_property("dir_source_main_python") module_names = _discover_modules_to_cover(project) for module_name in module_names: logger.debug("Module '%s' coverage to be verified", module_name) _delete_non_essential_modules() __import__("pybuilder.plugins.python") # Reimport self # Starting fresh from coverage import coverage as coverage_factory coverage = coverage_factory(cover_pylib=False, branch=True, source=[source_tree_path]) try: project.set_property( '__running_coverage', True ) # tell other plugins that we are not really unit testing right now _start_coverage(coverage) if shortest_plan: reactor.execute_task_shortest_plan(target_task) else: reactor.execute_task(target_task) finally: _stop_coverage(coverage) project.set_property('__running_coverage', False) coverage_too_low = False threshold = project.get_property("%s_threshold_warn" % execution_prefix) exceptions = project.get_property("%s_exceptions" % execution_prefix) report = {"module_names": []} sum_lines = 0 sum_lines_not_covered = 0 modules = [] for module_name in module_names: try: module = sys.modules[module_name] except KeyError: logger.warn("Module '%s' was not imported by the covered tests", module_name) try: module = __import__(module_name) except SyntaxError as e: logger.warn( "Coverage for module '%s' cannot be established - syntax error: %s", module_name, e) continue if module not in modules: modules.append(module) module_report_data = build_module_report(coverage, module) should_ignore_module = module_name in exceptions if not should_ignore_module: sum_lines += module_report_data[0] sum_lines_not_covered += module_report_data[2] module_report = { "module": module_name, "coverage": module_report_data[4], "sum_lines": module_report_data[0], "lines": module_report_data[1], "sum_lines_not_covered": module_report_data[2], "lines_not_covered": module_report_data[3], } logger.debug("Module coverage report: %s", module_report) report["module_names"].append(module_report) if module_report_data[4] < threshold: msg = "Test coverage below %2d%% for %s: %2d%%" % ( threshold, module_name, module_report_data[4]) if not should_ignore_module: logger.warn(msg) coverage_too_low = True else: logger.info(msg) if sum_lines == 0: overall_coverage = 0 else: overall_coverage = (sum_lines - sum_lines_not_covered) * 100 / sum_lines report["overall_coverage"] = overall_coverage if overall_coverage < threshold: logger.warn("Overall %s is below %2d%%: %2d%%", execution_name, threshold, overall_coverage) coverage_too_low = True else: logger.info("Overall %s is %2d%%", execution_name, overall_coverage) project.write_report("%s.json" % execution_prefix, render_report(report)) _write_summary_report(coverage, project, modules, execution_prefix, execution_name) if coverage_too_low and project.get_property( "%s_break_build" % execution_prefix): raise BuildFailedException( "Test coverage for at least one module is below %d%%", threshold)