Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/skip remaining tests being executed #1029

Merged
merged 18 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions doc/en/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,17 @@ Command line
--trace-tests-output
Specify output file for tests impacted by change in Testplan pattern format (see --trace-tests). Will be ignored if --trace-tests is not specified. Default to standard output.
--xfail-tests Read a list of known to fail testcases from a JSON file with each entry looks like: {"<Multitest>:<TestSuite>:<testcase>": {"reason": <value>, "strict": <value>} }

--runtime-data PATH Historical runtime data which will be used for Multitest auto-part and weight-based Task smart-scheduling with entries looks like:

{
"<Multitest>": {
"execution_time": 199.99,
"setup_time": 39.99,
},
......
}
--skip-remaining {cases-on-failed,cases-on-error,suites-on-failed,suites-on-error,tests-on-failed,tests-on-error}
Skip the remaining Testcases/Testsuites/Multitests being executed when a Testcase has failed or raised exception.
Filtering:
--patterns Test filter, supports glob notation & multiple arguments.

Expand Down Expand Up @@ -427,7 +437,7 @@ Command line
--report-tags-all <tag_name_1> --report-tags-all <tag_name 2>

--report-tags-all <tag_name_1> <tag_category_1>=<tag_name_2>
--file-log-level {exporter_info,test_info,driver_info,critical,error,warning,info,debug,none}
--file-log-level {USER_INFO,CRITICAL,ERROR,WARNING,INFO,DEBUG,NONE}

Specify log level for file logs. Set to None to disable file logging.

Expand Down
3 changes: 3 additions & 0 deletions doc/newsfragments/2540_new.skip_remaining.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added a new command line argument ``--skip-remaining``, a new argument ``skip_strategy`` to MultiTest, allowing certain test execution being skipped for a better user experience.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allow early return of test execution and skip remaining Testcases/Testsuites/Multitests being executed when a Testcase has failed or raised exception.


Argument ``uid`` of :py:meth:`Testplan.add_resource <testplan.base.Testplan.add_resource>` should match the uid of the ``resource`` argument.
4 changes: 2 additions & 2 deletions testplan/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,10 @@ def __init__(
)

# By default, a LocalRunner is added to store and execute the tests.
self._runnable.add_resource(LocalRunner(), uid="local_runner")
self._runnable.add_resource(LocalRunner())

# Stores independent environments.
self._runnable.add_resource(Environments(), uid="environments")
self._runnable.add_resource(Environments())

@property
def parser(self):
Expand Down
2 changes: 1 addition & 1 deletion testplan/common/entity/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def _record_resource_exception(self, message, resource, msg_store):
fetch_msg = "\n".join(resource.fetch_error_log())

msg = message.format(
resource=str(resource),
resource=resource,
traceback_exc=traceback.format_exc(),
fetch_msg=fetch_msg,
)
Expand Down
8 changes: 4 additions & 4 deletions testplan/common/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ def log_test_status(
):
"""Shortcut to log a pass/fail status for a test."""
if status.normalised() == Status.PASSED:
pass_label = Color.green(status.value.title())
pass_label = Color.green(status.name.title())
elif status <= Status.FAILED:
pass_label = Color.red(status.value.title())
pass_label = Color.red(status.name.title())
elif status.normalised() == Status.UNSTABLE:
pass_label = Color.yellow(status.value.title())
pass_label = Color.yellow(status.name.title())
else: # unknown
pass_label = status.value.title()
pass_label = status.name.title()

indent_str = indent * " "
msg = self._TEST_STATUS_FORMAT
Expand Down
17 changes: 15 additions & 2 deletions testplan/common/utils/selector.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# decouple represetation from evaluation
# typevar always of kind *, type hint won't work much here
"""
inspired by recursion schemes from the functional programming world, to de-
couple represetation (of operators) from evaluation (of them on different
types)

see https://blog.sumtypeofway.com/posts/introduction-to-recursion-schemes.html

unlike statically-typed languages, python doesn't need a representation for
a possibly infinite recursively type, thus we omit a "fixed-point" type here

typevar in current python always of kind *, type hint won't work much here
"""

from dataclasses import dataclass
from typing import Any, Callable, Generic, Set, TypeVar
Expand All @@ -18,6 +28,7 @@ def map(self, f: Callable[[T], U]) -> Self:

@dataclass
class And2(Generic[T]):
# logic and accepting 2 operands
lterm: T
rterm: T

Expand All @@ -27,6 +38,7 @@ def map(self, f):

@dataclass
class Or2(Generic[T]):
# logic or accepting 2 operands
lterm: T
rterm: T

Expand Down Expand Up @@ -62,6 +74,7 @@ def map(self, _):


def cata(f: Callable, rep: Expr):
# i.e. catamorphism
# cata :: (f t -> t) -> f (f (f ...)) -> t
return f(rep.map(lambda x: cata(f, x)))

Expand Down
3 changes: 2 additions & 1 deletion testplan/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ class Environments(Resource):
:py:class:`~testplan.common.entity.base.Resource` options.
"""

def __init__(self, **options):
def __init__(self, uid="environments", **options):
super(Environments, self).__init__(**options)
self._envs = {}
self._uid = uid

@property
def envs(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def get_header(self, source, depth, row_idx):
header,
"",
"",
(Status.PASSED if passed else Status.FAILED).value.title(),
(Status.PASSED if passed else Status.FAILED).name.title(),
],
style=default_assertion_style(passed=passed, depth=depth),
start=row_idx,
Expand Down Expand Up @@ -522,7 +522,7 @@ def get_detail(self, source, depth, row_idx):
"",
(
Status.PASSED if passed else Status.FAILED
).value.title(),
).name.title(),
],
style=styles,
start=row_idx + counter,
Expand Down
4 changes: 2 additions & 2 deletions testplan/exporters/testing/pdf/renderers/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ def format_status(report_status: Status) -> str:
erroneous tests will be displayed as failed.
"""
if report_status in (Status.FAILED, Status.ERROR):
return Status.FAILED.value.title()
return report_status.value.title()
return Status.FAILED.name.title()
return report_status.name.title()


@registry.bind(TestReport)
Expand Down
16 changes: 11 additions & 5 deletions testplan/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,21 @@ def generate_parser(self) -> HelpParser:
}""",
)

general_group.add_argument(
"-r",
"--resource-monitor",
dest="resource_monitor",
default=self._default_options["resource_monitor"],
action="store_true",
help="Enables resource monitor",
)

general_group.add_argument(
"--skip-remaining",
metavar="OPTION",
choices=common.SkipStrategy.all_options(),
dest="skip_strategy",
help="When a Testcase has failed or error has occurred, skip the "
"remaining of Testcases in the same Testsuite/Multitest/Testplan (or "
"anything with equal level) being executed. Valid values: "
+ str(common.SkipStrategy.all_options()),
help="Skip the remaining Testcases/Testsuites/Multitests being "
"executed when a Testcase has failed or raised exception.",
)

filter_group = parser.add_argument_group("Filtering")
Expand Down
Loading
Loading