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

scripts: twister: Add TestCase status and reason printing #78345

Merged

Conversation

LukaszMrugala
Copy link
Collaborator

@LukaszMrugala LukaszMrugala commented Sep 12, 2024

When at verbosity 1, we print out the status of TestInstances. However, we omit the TestCases in that print-out. This makes it harder to notice changes at TestCase level, which require perusing the logs.

This PR adds TestCase status and reason printing at verbosity level 2. Reason printing is suppressed if the reason in None or empty.

Visual example:
image

@LukaszMrugala LukaszMrugala added Enhancement Changes/Updates/Additions to existing features RFC Request For Comments: want input from the community area: Twister Twister labels Sep 12, 2024
@LukaszMrugala LukaszMrugala marked this pull request as ready for review September 16, 2024 10:00
@nashif
Copy link
Member

nashif commented Sep 16, 2024

looks nice, but very busy, wonder if we should have this appear in verbosity level 2(-vv) instead of first (-v) and add a debug flag to replace level 2 now (-vv).

@LukaszMrugala
Copy link
Collaborator Author

Incorporated the suggestions. Waiting for the test results.

"verbosity.")
help="Call multiple times to increase verbosity.")

parser.add_argument(
Copy link
Member

Choose a reason for hiding this comment

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

This change should be a separate PR as it affects current output not only for TestCase statuses.

Also something is missing in this change, like this debug output:

if VERBOSE > 1:
# if we are using command line platform filter, no need to list every
# other platform as excluded, we know that already.
# Show only the discards that apply to the selected platforms on the
# command line
for i in tplan.instances.values():
if i.status == TwisterStatus.FILTER:
if options.platform and i.platform.name not in options.platform:
continue
logger.debug(
"{:<25} {:<50} {}SKIPPED{}: {}".format(
i.platform.name,
i.testsuite.name,
Fore.YELLOW,
Fore.RESET,
i.reason,
)
)

IMO multi -v command line options is more convenient way to set logging levels, whereas -d has so many different meanings including --debug as a special mode of program execution, not just extended log output.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think that at its core, coupling together debug level and verbosity while not committing to either one is hurting us in the long run.

We use both 'naked' verbosity checks and debug log levels while disallowing specifying them separately. That's not great.

We should either

  • fully ditch verbosity checks in the code and replace them with custom logging levels enabled by specific verbosity levels
  • add log level flag in the CLI to enable DEBUG level and still use verbosity to indicate how much information of any level one would like to have.

Given our current approach, the second option is closer to what we currently have. It should probably be in a separate PR.

Comment on lines +20 to +37
match(status):
case TwisterStatus.PASS:
color = Fore.GREEN
case TwisterStatus.SKIP | TwisterStatus.FILTER | TwisterStatus.BLOCK:
color = Fore.YELLOW
case TwisterStatus.FAIL | TwisterStatus.ERROR:
color = Fore.RED
case TwisterStatus.STARTED | TwisterStatus.NONE:
color = Fore.MAGENTA
case _:
color = Fore.RESET
return color
Copy link
Member

Choose a reason for hiding this comment

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

isn't dictionary lookup simpler for this purpose ?
just thinking of something like

return status2color[status] if status in status2color else Fore.RESET

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It would be less concise, as I wouldn't be able to use ORs (|) in the dictionary definition.

Copy link
Member

@golowanow golowanow Sep 17, 2024

Choose a reason for hiding this comment

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

It would be less concise, as I wouldn't be able to use ORs (|) in the dictionary definition.

hmm, less concise ? I think this is more pythonic way, and you can even have another palette (grayscale), set it off assigning None, etc.

status2color = { TwisterStatus.PASS: Fore.GREEN,
                 TwisterStatus.SKIP: Fore.YELLOW,
                 TwisterStatus.FILTER: Fore.YELLOW,
                 TwisterStatus.BLOCK: Fore.YELLOW,
                 TwisterStatus.FAIL: Fore.RED,
                 TwisterStatus.ERROR: Fore.RED,
                 TwisterStatus.STARTED: Fore.MAGENTA,
                 TwisterStatus.NONE: Fore.MAGENTA
}

besides, no problem, just imo.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe concise wasn't the right word - the Status-Colour relationship is a many-to-one relationship (many statuses can have the same colour), which is immediately apparent in match-case structure. Dictionary is an inherently one-to-one structure (one value for one key). This necessitates repeating colours (YELLOW three times, RED two, MAGENTA two) and it's a bit harder to get information of type "Which Statuses can be yellow?"

Copy link
Member

@golowanow golowanow Sep 17, 2024

Choose a reason for hiding this comment

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

and it's a bit harder to get information of type "Which Statuses can be yellow?"

yeah, in case of the match/case construct it is even harder: it needs to be executed for all statuses first to build status2color{} and filter it on values=='yellow'.

When at verbosity 1, we print out the status of TestInstances.
This makes it harder to notice changes at TestCase level,
which require perusing the logs.

This adds TestCase status and reason printing
if verbosity level is 2 or more.
Reason printing is suppressed if the reason is empty or None.

Signed-off-by: Lukasz Mrugala <[email protected]>
@nashif nashif merged commit 418b1e0 into zephyrproject-rtos:main Sep 17, 2024
29 checks passed
@@ -19,6 +21,21 @@ def _missing_(cls, value):
if value is None:
return TwisterStatus.NONE

@staticmethod
def get_color(status: TwisterStatus) -> str:
match(status):
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: If you use match keyword, than Twister requires Python 3.10. Therefore, using from __future__ import annotations does not have any sense (it enables some type annotations for lower versions of python)

Copy link
Collaborator

Choose a reason for hiding this comment

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

just mentioned that, because couple days ago @golowanow added PR to still have possibility to run Twister with Python 3.8: #77077
With match keyword it is not possible

Copy link
Member

Choose a reason for hiding this comment

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

I just ran into this on macOS:

❯ scripts/twister --help
ZEPHYR_BASE unset, using "/Users/johedber/src/zephyr/zephyr"
Traceback (most recent call last):
  File "/Users/johedber/src/zephyr/zephyr/scripts/twister", line 207, in <module>
    from twisterlib.twister_main import main
  File "/Users/johedber/src/zephyr/zephyr/scripts/pylib/twister/twisterlib/twister_main.py", line 16, in <module>
    from twisterlib.statuses import TwisterStatus
  File "/Users/johedber/src/zephyr/zephyr/scripts/pylib/twister/twisterlib/statuses.py", line 26
    match(status):
                  ^
SyntaxError: invalid syntax
❯ which python3
/usr/bin/python3
❯ python3 --version
Python 3.9.6

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

nit: If you use match keyword, than Twister requires Python 3.10. Therefore, using from __future__ import annotations does not have any sense (it enables some type annotations for lower versions of python)

You are right - I've used it to change TwisterStatus type hint into Self - it seems I didn't upstream it. My bad.

When it comes to Python<3.10 support - Zephyr does not claim to support it since 3.7.0 LTS (Python 3.10 is listed as minimum requirement), so I do not pay older versions special consideration.

Copy link
Member

@golowanow golowanow Sep 18, 2024

Choose a reason for hiding this comment

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

When it comes to Python<3.10 support - Zephyr does not claim to support it since 3.7.0

the problem is confusing user experience to get SyntaxError just for twister --help now.

#78671

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Twister Twister Enhancement Changes/Updates/Additions to existing features RFC Request For Comments: want input from the community
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants