refactor: new lightweight test runner
This commit is contained in:
parent
5c6b2b5bec
commit
fcaf173923
1 changed files with 134 additions and 104 deletions
|
|
@ -32,129 +32,153 @@ def main(
|
|||
debug: bool = False,
|
||||
debug_exceptions: tuple[Exception] | None = None,
|
||||
selected_categories: list[str] | None = None,
|
||||
light: bool = False,
|
||||
) -> None:
|
||||
"""Main function to run tests"""
|
||||
import logging
|
||||
if light:
|
||||
from frappe.testing import TestConfig
|
||||
from frappe.testing.environment import _disable_scheduler_if_needed
|
||||
|
||||
from frappe.testing import (
|
||||
TestConfig,
|
||||
TestRunner,
|
||||
discover_all_tests,
|
||||
discover_doctype_tests,
|
||||
discover_module_tests,
|
||||
)
|
||||
from frappe.testing.environment import _cleanup_after_tests, _initialize_test_environment
|
||||
from frappe.tests.utils.generators import _clear_test_log
|
||||
|
||||
_clear_test_log()
|
||||
|
||||
if debug and not debug_exceptions:
|
||||
debug_exceptions = (Exception,)
|
||||
|
||||
testing_module_logger = logging.getLogger("frappe.testing")
|
||||
testing_module_logger.setLevel(logging.DEBUG if verbose else logging.INFO)
|
||||
start_time = time.time()
|
||||
|
||||
# Check for mutually exclusive arguments
|
||||
exclusive_args = [doctype, doctype_list_path, module_def, module]
|
||||
if sum(arg is not None for arg in exclusive_args) > 1:
|
||||
raise click.UsageError(
|
||||
"Error: The following arguments are mutually exclusive: "
|
||||
"doctype, doctype_list_path, module_def, and module. "
|
||||
"Please specify only one of these."
|
||||
test_config = TestConfig(
|
||||
profile=profile,
|
||||
failfast=failfast,
|
||||
tests=tests,
|
||||
case=case,
|
||||
pdb_on_exceptions=debug_exceptions,
|
||||
selected_categories=selected_categories or [],
|
||||
skip_before_tests=skip_before_tests,
|
||||
)
|
||||
# init environment
|
||||
frappe.init(site)
|
||||
if not frappe.db:
|
||||
frappe.connect()
|
||||
|
||||
# Prepare debug log message
|
||||
debug_params = []
|
||||
for param_name in [
|
||||
"site",
|
||||
"app",
|
||||
"module",
|
||||
"doctype",
|
||||
"module_def",
|
||||
"verbose",
|
||||
"tests",
|
||||
"force",
|
||||
"profile",
|
||||
"junit_xml_output",
|
||||
"doctype_list_path",
|
||||
"failfast",
|
||||
"case",
|
||||
"skip_before_tests",
|
||||
"debug_exceptions",
|
||||
"debug",
|
||||
"selected_categories",
|
||||
]:
|
||||
param_value = locals()[param_name]
|
||||
if param_value is not None:
|
||||
debug_params.append(f"{param_name}={param_value}")
|
||||
# require db access
|
||||
_disable_scheduler_if_needed()
|
||||
frappe.clear_cache()
|
||||
|
||||
if debug_params:
|
||||
click.secho(f"Starting test run with parameters: {', '.join(debug_params)}", fg="cyan", bold=True)
|
||||
testing_module_logger.info(f"started with: {', '.join(debug_params)}")
|
||||
else:
|
||||
click.secho("Starting test run with no specific parameters", fg="cyan", bold=True)
|
||||
testing_module_logger.info("started with no specific parameters")
|
||||
for handler in testing_module_logger.handlers:
|
||||
if file := getattr(handler, "baseFilename", None):
|
||||
click.secho(
|
||||
f"View detailed logs{' (using --verbose)' if not verbose else ''}: {click.style(file, bold=True)}"
|
||||
import logging
|
||||
|
||||
from frappe.testing import (
|
||||
TestConfig,
|
||||
TestRunner,
|
||||
discover_all_tests,
|
||||
discover_doctype_tests,
|
||||
discover_module_tests,
|
||||
)
|
||||
from frappe.testing.environment import _cleanup_after_tests, _initialize_test_environment
|
||||
from frappe.tests.utils.generators import _clear_test_log
|
||||
|
||||
_clear_test_log()
|
||||
|
||||
if debug and not debug_exceptions:
|
||||
debug_exceptions = (Exception,)
|
||||
|
||||
testing_module_logger = logging.getLogger("frappe.testing")
|
||||
testing_module_logger.setLevel(logging.DEBUG if verbose else logging.INFO)
|
||||
start_time = time.time()
|
||||
|
||||
# Check for mutually exclusive arguments
|
||||
exclusive_args = [doctype, doctype_list_path, module_def, module]
|
||||
if sum(arg is not None for arg in exclusive_args) > 1:
|
||||
raise click.UsageError(
|
||||
"Error: The following arguments are mutually exclusive: "
|
||||
"doctype, doctype_list_path, module_def, and module. "
|
||||
"Please specify only one of these."
|
||||
)
|
||||
|
||||
test_config = TestConfig(
|
||||
profile=profile,
|
||||
failfast=failfast,
|
||||
tests=tests,
|
||||
case=case,
|
||||
pdb_on_exceptions=debug_exceptions,
|
||||
selected_categories=selected_categories or [],
|
||||
skip_before_tests=skip_before_tests,
|
||||
)
|
||||
# Prepare debug log message
|
||||
debug_params = []
|
||||
for param_name in [
|
||||
"site",
|
||||
"app",
|
||||
"module",
|
||||
"doctype",
|
||||
"module_def",
|
||||
"verbose",
|
||||
"tests",
|
||||
"force",
|
||||
"profile",
|
||||
"junit_xml_output",
|
||||
"doctype_list_path",
|
||||
"failfast",
|
||||
"case",
|
||||
"skip_before_tests",
|
||||
"debug_exceptions",
|
||||
"debug",
|
||||
"selected_categories",
|
||||
]:
|
||||
param_value = locals()[param_name]
|
||||
if param_value is not None:
|
||||
debug_params.append(f"{param_name}={param_value}")
|
||||
|
||||
_initialize_test_environment(site, test_config)
|
||||
if debug_params:
|
||||
click.secho(f"Starting test run with parameters: {', '.join(debug_params)}", fg="cyan", bold=True)
|
||||
testing_module_logger.info(f"started with: {', '.join(debug_params)}")
|
||||
else:
|
||||
click.secho("Starting test run with no specific parameters", fg="cyan", bold=True)
|
||||
testing_module_logger.info("started with no specific parameters")
|
||||
for handler in testing_module_logger.handlers:
|
||||
if file := getattr(handler, "baseFilename", None):
|
||||
click.secho(
|
||||
f"View detailed logs{' (using --verbose)' if not verbose else ''}: {click.style(file, bold=True)}"
|
||||
)
|
||||
|
||||
xml_output_file = _setup_xml_output(junit_xml_output)
|
||||
|
||||
try:
|
||||
# Create TestRunner instance
|
||||
runner = TestRunner(
|
||||
verbosity=2 if testing_module_logger.getEffectiveLevel() < logging.INFO else 1,
|
||||
tb_locals=testing_module_logger.getEffectiveLevel() <= logging.INFO,
|
||||
cfg=test_config,
|
||||
buffer=not debug, # unfortunate as it messes up stdout/stderr output order
|
||||
test_config = TestConfig(
|
||||
profile=profile,
|
||||
failfast=failfast,
|
||||
tests=tests,
|
||||
case=case,
|
||||
pdb_on_exceptions=debug_exceptions,
|
||||
selected_categories=selected_categories or [],
|
||||
skip_before_tests=skip_before_tests,
|
||||
)
|
||||
|
||||
if doctype or doctype_list_path:
|
||||
doctype = _load_doctype_list(doctype_list_path) if doctype_list_path else doctype
|
||||
discover_doctype_tests(doctype, runner, app, force)
|
||||
elif module_def:
|
||||
_run_module_def_tests(app, module_def, runner, force)
|
||||
elif module:
|
||||
discover_module_tests(module, runner, app)
|
||||
else:
|
||||
apps = [app] if app else frappe.get_installed_apps()
|
||||
discover_all_tests(apps, runner)
|
||||
_initialize_test_environment(site, test_config)
|
||||
|
||||
results = []
|
||||
for app, category, suite in runner.iterRun():
|
||||
click.secho(
|
||||
f"\nRunning {suite.countTestCases()} {category} tests for {app}", fg="cyan", bold=True
|
||||
xml_output_file = _setup_xml_output(junit_xml_output)
|
||||
|
||||
try:
|
||||
# Create TestRunner instance
|
||||
runner = TestRunner(
|
||||
verbosity=2 if testing_module_logger.getEffectiveLevel() < logging.INFO else 1,
|
||||
tb_locals=testing_module_logger.getEffectiveLevel() <= logging.INFO,
|
||||
cfg=test_config,
|
||||
buffer=not debug, # unfortunate as it messes up stdout/stderr output order
|
||||
)
|
||||
results.append([app, category, runner.run(suite)])
|
||||
|
||||
success = all(r.wasSuccessful() for _, _, r in results)
|
||||
if not success:
|
||||
sys.exit(1)
|
||||
if doctype or doctype_list_path:
|
||||
doctype = _load_doctype_list(doctype_list_path) if doctype_list_path else doctype
|
||||
discover_doctype_tests(doctype, runner, app, force)
|
||||
elif module_def:
|
||||
_run_module_def_tests(app, module_def, runner, force)
|
||||
elif module:
|
||||
discover_module_tests(module, runner, app)
|
||||
else:
|
||||
apps = [app] if app else frappe.get_installed_apps()
|
||||
discover_all_tests(apps, runner)
|
||||
|
||||
return results
|
||||
results = []
|
||||
for app, category, suite in runner.iterRun():
|
||||
click.secho(
|
||||
f"\nRunning {suite.countTestCases()} {category} tests for {app}", fg="cyan", bold=True
|
||||
)
|
||||
results.append([app, category, runner.run(suite)])
|
||||
|
||||
finally:
|
||||
_cleanup_after_tests()
|
||||
if xml_output_file:
|
||||
xml_output_file.close()
|
||||
success = all(r.wasSuccessful() for _, _, r in results)
|
||||
if not success:
|
||||
sys.exit(1)
|
||||
|
||||
end_time = time.time()
|
||||
testing_module_logger.debug(f"Total test run time: {end_time - start_time:.3f} seconds")
|
||||
return results
|
||||
|
||||
finally:
|
||||
_cleanup_after_tests()
|
||||
if xml_output_file:
|
||||
xml_output_file.close()
|
||||
|
||||
end_time = time.time()
|
||||
testing_module_logger.debug(f"Total test run time: {end_time - start_time:.3f} seconds")
|
||||
|
||||
|
||||
def _setup_xml_output(junit_xml_output):
|
||||
|
|
@ -246,6 +270,7 @@ def _get_doctypes_for_module_def(app, module_def):
|
|||
default="all",
|
||||
help="Select test category to run",
|
||||
)
|
||||
@click.option("--light", is_flag=True, default=False)
|
||||
@pass_context
|
||||
def run_tests(
|
||||
context: CliCtxObj,
|
||||
|
|
@ -263,6 +288,7 @@ def run_tests(
|
|||
failfast=False,
|
||||
case=None,
|
||||
test_category="all",
|
||||
light=False,
|
||||
debug=False,
|
||||
):
|
||||
"""Run python unit-tests"""
|
||||
|
|
@ -290,6 +316,9 @@ def run_tests(
|
|||
click.secho("Simply remove the flag.", fg="green")
|
||||
return
|
||||
|
||||
if light:
|
||||
click.secho("Light test runner selected")
|
||||
|
||||
main(
|
||||
site,
|
||||
app,
|
||||
|
|
@ -307,6 +336,7 @@ def run_tests(
|
|||
skip_before_tests=skip_before_tests,
|
||||
debug=debug,
|
||||
selected_categories=[] if test_category == "all" else test_category,
|
||||
light=light,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue