@@ -31,10 +31,8 @@ def configure(config: Config) -> None:
3131 raise Exception (
3232 "gherkin-terminal-reporter is not compatible with any other terminal reporter."
3333 "You can use only one terminal reporter."
34- "Currently '{0}' is used."
35- "Please decide to use one by deactivating {0} or gherkin-terminal-reporter." .format (
36- current_reporter .__class__
37- )
34+ f" Currently '{ current_reporter .__class__ } ' is used."
35+ f" Please decide to use one by deactivating { current_reporter .__class__ } or gherkin-terminal-reporter."
3836 )
3937 gherkin_reporter = GherkinTerminalReporter (config )
4038 config .pluginmanager .unregister (current_reporter )
@@ -49,72 +47,96 @@ def __init__(self, config: Config) -> None:
4947 self .current_rule : str | None = None
5048
5149 def pytest_runtest_logreport (self , report : TestReport ) -> None :
52- rep = report
53- res = self .config .hook .pytest_report_teststatus (report = rep , config = self .config )
54- cat , letter , word = res
50+ result = self .config .hook .pytest_report_teststatus (report = report , config = self .config )
51+ result_category , result_letter , result_word = result
5552
56- if not letter and not word :
57- # probably passed setup/teardown
53+ if not result_letter and not result_word :
5854 return None
5955
60- if isinstance (word , tuple ):
61- word , word_markup = word
62- elif rep .passed :
63- word_markup = {"green" : True }
64- elif rep .failed :
65- word_markup = {"red" : True }
66- elif rep .skipped :
67- word_markup = {"yellow" : True }
68- feature_markup = {"blue" : True }
69- scenario_markup = word_markup
70- rule_markup = {"purple" : True }
71-
7256 try :
7357 scenario = test_report_context_registry [report ].scenario
7458 except KeyError :
7559 scenario = None
7660
7761 if self .verbosity <= 0 or scenario is None :
78- return super ().pytest_runtest_logreport (rep )
62+ return super ().pytest_runtest_logreport (report )
7963
80- rule = scenario .get ("rule" )
81- indent = " " if rule else ""
64+ report_renderer = ReportRenderer (self , report , scenario , result_word )
8265
8366 if self .verbosity == 1 :
84- self .ensure_newline ()
85- self ._tw .write (f"{ scenario ['feature' ]['keyword' ]} : " , ** feature_markup )
86- self ._tw .write (scenario ["feature" ]["name" ], ** feature_markup )
87- self ._tw .write ("\n " )
88-
89- if rule and rule ["name" ] != self .current_rule :
90- self ._tw .write (f" { rule ['keyword' ]} : " , ** rule_markup )
91- self ._tw .write (rule ["name" ], ** rule_markup )
92- self ._tw .write ("\n " )
93- self .current_rule = rule ["name" ]
94-
95- self ._tw .write (f"{ indent } { scenario ['keyword' ]} : " , ** scenario_markup )
96- self ._tw .write (scenario ["name" ], ** scenario_markup )
97- self ._tw .write (" " )
98- self ._tw .write (word , ** word_markup )
99- self ._tw .write ("\n " )
67+ report_renderer .write_scenario_summary ()
10068 elif self .verbosity > 1 :
101- self .ensure_newline ()
102- self ._tw .write (f"{ scenario ['feature' ]['keyword' ]} : " , ** feature_markup )
103- self ._tw .write (scenario ["feature" ]["name" ], ** feature_markup )
104- self ._tw .write ("\n " )
105-
106- if rule and rule ["name" ] != self .current_rule :
107- self ._tw .write (f" { rule ['keyword' ]} : " , ** rule_markup )
108- self ._tw .write (rule ["name" ], ** rule_markup )
109- self ._tw .write ("\n " )
110- self .current_rule = rule ["name" ]
111-
112- self ._tw .write (f"{ indent } { scenario ['keyword' ]} : " , ** scenario_markup )
113- self ._tw .write (scenario ["name" ], ** scenario_markup )
114- self ._tw .write ("\n " )
115- for step in scenario ["steps" ]:
116- self ._tw .write (f"{ indent } { step ['keyword' ]} { step ['name' ]} \n " , ** scenario_markup )
117- self ._tw .write (f"{ indent } { word } " , ** word_markup )
118- self ._tw .write ("\n \n " )
119-
120- self .stats .setdefault (cat , []).append (rep )
69+ report_renderer .write_detailed_scenario_with_steps ()
70+
71+ self .stats .setdefault (result_category , []).append (report )
72+
73+
74+ class ReportRenderer :
75+ def __init__ (
76+ self , reporter : GherkinTerminalReporter , report : TestReport , scenario : dict , result_outcome : str
77+ ) -> None :
78+ self .reporter = reporter
79+ self .report = report
80+ self .scenario = scenario
81+ self .rule = scenario .get ("rule" )
82+ if isinstance (result_outcome , tuple ):
83+ self .result_outcome , self .feature_markup = result_outcome
84+ else :
85+ self .result_outcome = result_outcome
86+ self .feature_markup = {"blue" : True }
87+ self .rule_markup = {"purple" : True }
88+ self .tw = self .reporter ._tw
89+ self .current_indentation_index = 0
90+
91+ def get_outcome_markup (self ) -> dict :
92+ if self .report .passed :
93+ return {"green" : True }
94+ elif self .report .failed :
95+ return {"red" : True }
96+ elif self .report .skipped :
97+ return {"yellow" : True }
98+
99+ def write_scenario_summary (self , has_steps : bool = False ) -> None :
100+ """Write the feature and scenario header to the terminal."""
101+ self .tw .write ("\n " )
102+ self .tw .write (f"{ self .scenario ['feature' ]['keyword' ]} : " , ** self .feature_markup )
103+ self .tw .write (self .scenario ["feature" ]["name" ], ** self .feature_markup )
104+ self .tw .write ("\n " )
105+
106+ if self .rule and self .rule ["name" ] != self .reporter .current_rule :
107+ self .current_indentation_index = 1
108+ self .tw .write (
109+ f"{ self ._get_indent (self .current_indentation_index )} { self .rule ['keyword' ]} : " , ** self .rule_markup
110+ )
111+ self .tw .write (self .rule ["name" ], ** self .rule_markup )
112+ self .tw .write ("\n " )
113+ self .reporter .current_rule = self .rule ["name" ]
114+
115+ self .current_indentation_index += 1
116+ self .tw .write (
117+ f"{ self ._get_indent (self .current_indentation_index )} { self .scenario ['keyword' ]} : " ,
118+ ** self .get_outcome_markup (),
119+ )
120+ self .tw .write (self .scenario ["name" ], ** self .get_outcome_markup ())
121+ if not has_steps :
122+ self .tw .write (" " , ** self .get_outcome_markup ())
123+ self .tw .write (self .result_outcome , ** self .get_outcome_markup ())
124+ self .tw .write ("\n " )
125+
126+ def write_detailed_scenario_with_steps (self ) -> None :
127+ """Write the full details of the scenario including the steps."""
128+ self .write_scenario_summary (has_steps = True )
129+
130+ for step in self .scenario ["steps" ]:
131+ self .current_indentation_index += 1
132+ self .tw .write (
133+ f"{ self ._get_indent (self .current_indentation_index )} { step ['keyword' ]} { step ['name' ]} \n " ,
134+ ** self .get_outcome_markup (),
135+ )
136+
137+ self .tw .write (f"{ self ._get_indent (2 )} { self .result_outcome } " , ** self .get_outcome_markup ())
138+ self .tw .write ("\n \n " )
139+
140+ @staticmethod
141+ def _get_indent (level : int ) -> str :
142+ return " " * level
0 commit comments