@@ -89,7 +89,7 @@ def patch_scenario_with_accuracy(context, scenario, data_key_suffix, accuracy=0.
8989 """
9090 def scenario_run_with_accuracy (context , scenario_run , scenario , * args , ** kwargs ):
9191 # Execute the scenario multiple times and count passed executions
92- passed_executions = 0
92+ passed_executions = skipped_executions = 0
9393 # Copy scenario steps to avoid modifications in each execution, especially when using behave variables
9494 # transformation, like map_param and replace_param methods
9595 orig_steps = deepcopy (scenario .steps )
@@ -99,30 +99,64 @@ def scenario_run_with_accuracy(context, scenario_run, scenario, *args, **kwargs)
9999 # Restore original steps before each execution
100100 scenario .steps = deepcopy (orig_steps )
101101 if not scenario_run (* args , ** kwargs ):
102- passed_executions += 1
103- status = "PASSED"
102+ if scenario .status == Status .skipped :
103+ skipped_executions += 1
104+ status = "SKIPPED"
105+ else :
106+ passed_executions += 1
107+ status = "PASSED"
104108 else :
105109 status = "FAILED"
106110 print (f"ACCURACY SCENARIO { status } : execution { execution + 1 } /{ executions } " )
107111 context .logger .info (f"Accuracy scenario execution { status } ({ execution + 1 } /{ executions } )" )
108112
109- # Calculate scenario accuracy
110- scenario_accuracy = passed_executions / executions
111- has_passed = scenario_accuracy >= accuracy
112- final_status = 'PASSED' if has_passed else 'FAILED'
113- print (f"\n ACCURACY SCENARIO { final_status } : { executions } executions,"
114- f" accuracy { scenario_accuracy } >= { accuracy } " )
115- final_message = (f"Accuracy scenario { final_status } after { executions } executions with"
116- f" accuracy { scenario_accuracy } >= { accuracy } " )
117-
118- # Set final scenario status
119- if has_passed :
120- context .logger .info (final_message )
121- scenario .set_status (Status .passed )
113+
114+ if executions == skipped_executions :
115+ run_response = False # Run method returns true only when failed
116+ context .logger .info ("All accuracy scenario executions are skipped" )
122117 else :
123- context .logger .error (final_message )
124- scenario .set_status (Status .failed )
125- return not has_passed # Run method returns true when failed
118+ # Calculate scenario accuracy
119+ scenario_accuracy = passed_executions / (executions - skipped_executions )
120+ has_passed = scenario_accuracy >= accuracy
121+ run_response = not has_passed # Run method returns true only when failed
122+ final_status = 'PASSED' if has_passed else 'FAILED'
123+ print (f"\n ACCURACY SCENARIO { final_status } : { executions } executions,"
124+ f" accuracy { scenario_accuracy } >= { accuracy } " )
125+ final_message = (f"Accuracy scenario { final_status } after { executions } executions with"
126+ f" accuracy { scenario_accuracy } >= { accuracy } "
127+ f" ({ passed_executions } passed, { skipped_executions } skipped,"
128+ f" { executions - passed_executions - skipped_executions } failed)" )
129+
130+ # Set final scenario status
131+ if has_passed :
132+ context .logger .info (final_message )
133+ scenario .set_status (Status .passed )
134+ else :
135+ context .logger .error (final_message )
136+ scenario .set_status (Status .failed )
137+ scenario .exception = AssertionError (final_message )
138+
139+ # Clean accuracy execution data from context
140+ context .storage .pop ("accuracy_execution_data" , None )
141+ context .storage .pop ("accuracy_execution_index" , None )
142+
143+ # Execute Allure after_scenario hook if Allure is being used
144+ if hasattr (context , 'allure' ):
145+ if scenario .status == Status .passed :
146+ # Change failed steps to avoid marking scenario as failed in Allure when accuracy is met
147+ for step in scenario .all_steps :
148+ if step .status == Status .failed :
149+ step .set_status (Status .passed )
150+ step .exception = None
151+ elif scenario .status == Status .failed :
152+ latest_step = list (scenario .all_steps )[- 1 ]
153+ latest_step .set_status (Status .failed )
154+ latest_step .exception = AssertionError (final_message )
155+ context .allure .listener .behave_config = context
156+ context .allure .listener .behave_config .show_skipped = True
157+ context .allure .after_scenario (context , scenario )
158+
159+ return run_response
126160
127161 scenario_run = scenario .run
128162 scenario .run = functools .partial (scenario_run_with_accuracy , context , scenario_run , scenario )
0 commit comments