Skip to content

Commit

Permalink
Merge pull request #145 from hrcorval/release_4.0.3
Browse files Browse the repository at this point in the history
Release 4.0.3
  • Loading branch information
hrcorval authored Sep 23, 2024
2 parents 6e61382 + a48d4ae commit 801f6b1
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 118 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ eggs/
.eggs/
.idea
.pypirc
.cursorrules
.vscode
lib/
lib64/
parts/
Expand Down
16 changes: 16 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
Version History
===============================================================================

Version: 4.0.4
-------------------------------------------------------------------------------
ENHANCEMENTS:

* Added the 'worker_id' context.config.userdata parameter to allow users to identify which worker is executing every feature or scenario when running tests in parallel. `PR #121 <https://github.com/hrcorval/behavex/pull/121>`_
* Adding the --parallel-delay argument, to enable setting a staggered execution when running tests in parallel. `Issue #142 <https://github.com/hrcorval/behavex/issues/142>`_

FIXES:

* Standardized XML report generation for parallel and single-process runs. `Issue #144 <https://github.com/hrcorval/behavex/issues/144>`_

CONTRIBUTIONS:

* Contributions from `JackHerRrer <https://github.com/JackHerRrer>`__, by providing the implementation to include the 'worker_id' context.config.userdata parameter (Thanks JackHerRrer!!)


Version: 4.0.2
-------------------------------------------------------------------------------
ENHANCEMENTS:
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ Examples:
When the parallel-scheme is set by **feature**, all tests within each feature will be run sequentially.

### Identifying each parallel process

BehaveX populates the Behave contexts with the `worker_id` user-specific data. This variable contains the id of the current behave process.

E.g If BehaveX is started with `--parallel-processes 2`, the first instance of behave will receive `worker_id=0`, and the second instance will receive `worker_id=1`.

This variable can be accessed within the python tests using `context.config.userdata['worker_id']`

## Test execution reports
### HTML report
This is a friendly test execution report that contains information related to test scenarios, execution status, execution evidence and metrics. A filters bar is also provided to filter scenarios by name, tag or status.
Expand Down
5 changes: 5 additions & 0 deletions behavex/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ def parse_arguments(args):
help="Specifies whether parallel execution should be performed at the scenario or feature level.",
required=False,
)
parser.add_argument(
'--parallel-delay',
type=int,
default=0,
help='Delay in milliseconds before starting each parallel process')
parser.add_argument(
'-ip',
'--include-paths',
Expand Down
10 changes: 5 additions & 5 deletions behavex/outputs/jinja/xml.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@
{%- macro print_scenario(scenario) -%}
{%- set scenario_tags = scenario|get_scenario_tags-%}
{%- set is_muted = ('MUTE' in scenario_tags and scenario.status == 'failed')-%}
{%- set scenario_crashed = True if (scenario.status == 'failed' and not scenario.error_background and not scenario.error_step) else False -%}
{%- set errors_step = 0-%}
{%- for step in scenario.steps -%}
{%- set errors_step = errors_step + (0 if step.error_message else 1) -%}
{%- endfor -%}
<testcase time="{{ scenario.duration }}" name={{scenario.name|normalize|CIXC|quoteattr|safe}} status="{{ scenario.status if not is_muted else 'skipped'}}"
classname={{scenario.feature.name|normalize|CIXC|quoteattr|safe }}>
{%- set steps_with_exception = scenario.steps|get_list_exception_steps(scenario._background_steps) -%}
{%- set scenario_crashed = True if (scenario.status == 'failed' and steps_with_exception|length == 0) else False -%}
{%- if scenario_crashed and not is_muted -%}
<failure type=Exception message={{scenario.error_msg|get_error_message|CIXC|quoteattr|safe }}>
<![CDATA[ {{ scenario.error_msg }} ]]>
</failure>
<failure type=Exception message={{scenario.error_msg|get_error_message|CIXC|quoteattr|safe }}>
<![CDATA[ {{ scenario.error_msg }} ]]>
</failure>
{%- elif steps_with_exception and not is_muted -%}
{%- for step in steps_with_exception -%}
<failure type={{ step.exception.__class__.__name__ |normalize|CIXC|quoteattr|safe}} message={{step.exception.message|get_error_message|CIXC|quoteattr|safe }}>
<failure type={{ step.exception.__class__.__name__ |normalize|CIXC|quoteattr|safe}} message={{ step.exception|string|get_error_message|CIXC|quoteattr|safe}}>
<![CDATA[ Failing step: {{step|print_step|safe}} Location:{{step.filename|normalize|safe}}
{{step|get_lines_exception|safe}}
]]>
Expand Down
14 changes: 7 additions & 7 deletions behavex/outputs/jinja/xml_json.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{{'\n'}}
{%- endfor -%}
{%- endif -%}
{{ 16*' ' ~ step|print_step_json ~ '\n'}}
{{ 16*' ' ~ step|print_step_json|safe ~ '\n'}}
{%- endmacro -%}
{%- macro print_scenario(scenario) -%}
{%- set scenario_tags = scenario|get_scenario_tags-%}
Expand All @@ -30,13 +30,13 @@
classname={{scenario.feature|normalize|CIXC|quoteattr|safe }} >
{% set step_with_exception = scenario.error_step %}
{%- if scenario_crashed and not is_muted -%}
<failure type=Exception message={{scenario.error_msg|get_error_message|CIXC|quoteattr|safe }}>
<![CDATA[ {{ scenario.error_msg }} ]]>
</failure>
<failure type="Exception" message={{scenario.error_msg|get_error_message|CIXC|quoteattr|safe }}>
<![CDATA[ {{ scenario.error_msg }} ]]>
</failure>
{%- elif step_with_exception and not is_muted -%}
<failure message={{step_with_exception.error_msg|get_error_message|CIXC|quoteattr|safe }} type="AssertionError">
<![CDATA[ Failing step: {{step_with_exception|print_step_json|safe}} Location:{{step_with_exception.index}}
{{step_with_exception|safe}}
<failure type="AssertionError" message={{step_with_exception.error_msg|get_error_message|CIXC|quoteattr|safe }}>
<![CDATA[ Failing step: {{step_with_exception|print_step_json|safe}} Location:{{feature["filename"]}}
{{step_with_exception|get_lines_exception|safe}}
]]>
</failure>
{%- endif -%}
Expand Down
10 changes: 7 additions & 3 deletions behavex/outputs/jinja_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,11 @@ def _print_step_json(step):


def get_lines_exception(step):
if step.exception:
if type(step) is dict:
return u'\n'.join(
[16 * u' ' + line for line in step['error_lines']]
).strip()
elif step.exception:
return u'\n'.join(
[16 * u' ' + line for line in traceback.format_tb(step.exc_traceback)]
).strip()
Expand Down Expand Up @@ -192,8 +196,8 @@ def _get_path_log(scenario):
return path_logs


def _quoteattr(string):
return "''" if not string else quoteattr(string)
def _quoteattr(string_to_quote):
return "''" if not string_to_quote else quoteattr(string_to_quote)


def _print_tag_xml(tags):
Expand Down
25 changes: 12 additions & 13 deletions behavex/outputs/report_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,23 +335,22 @@ def create_log_path(name, execution_retry=False):
return path


def get_error_message(message_error):
if not message_error:
def get_error_message(error_message):
if not error_message:
return u''
if isinstance(message_error, Exception):
if hasattr(message_error, 'message'):
if isinstance(error_message, Exception):
if hasattr(error_message, 'message'):
# noinspection PyBroadException
try:
message_error = traceback.format_tb(message_error.message)
error_message = traceback.format_tb(error_message.message)
except BaseException:
message_error = repr(message_error.message)
if hasattr(message_error, 'exc_traceback'):
message_error = traceback.format_tb(message_error.exc_traceback)
elif not isinstance(message_error, str):
message_error = repr(message_error)
return u'\n'.join(
[16 * u' ' + line for line in text(message_error).split('\n')]
).strip()
error_message = repr(error_message.message)
if hasattr(error_message, 'exc_traceback'):
error_message = traceback.format_tb(error_message.exc_traceback)
elif not isinstance(error_message, str):
error_message = repr(error_message)
formatted_error = u'\n'.join([16 * u' ' + line for line in text(error_message).split('\n')]).strip()
return formatted_error


def text(value, encoding=None, errors=None):
Expand Down
Loading

0 comments on commit 801f6b1

Please sign in to comment.