6
6
import math
7
7
import os
8
8
import time
9
- from typing import TYPE_CHECKING , Any , Literal , TypedDict
9
+ from typing import TYPE_CHECKING , Literal , TypedDict
10
10
11
11
from typing_extensions import NotRequired
12
12
13
- from .reporting import test_report_context_registry
13
+ from .reporting import FeatureDict , ScenarioReportDict , StepReportDict , test_report_context_registry
14
14
15
15
if TYPE_CHECKING :
16
16
from _pytest .config import Config
19
19
from _pytest .terminal import TerminalReporter
20
20
21
21
22
+ class ResultElementDict (TypedDict ):
23
+ status : Literal ["passed" , "failed" , "skipped" ]
24
+ duration : int # in nanoseconds
25
+ error_message : NotRequired [str ]
26
+
27
+
28
+ class TagElementDict (TypedDict ):
29
+ name : str
30
+ line : int
31
+
32
+
33
+ class MatchElementDict (TypedDict ):
34
+ location : str
35
+
36
+
37
+ class StepElementDict (TypedDict ):
38
+ keyword : str
39
+ name : str
40
+ line : int
41
+ match : MatchElementDict
42
+ result : ResultElementDict
43
+
44
+
45
+ class ScenarioElementDict (TypedDict ):
46
+ keyword : str
47
+ id : str
48
+ name : str
49
+ line : int
50
+ description : str
51
+ tags : list [TagElementDict ]
52
+ type : Literal ["scenario" ]
53
+ steps : list [StepElementDict ]
54
+
55
+
56
+ class FeatureElementDict (TypedDict ):
57
+ keyword : str
58
+ uri : str
59
+ name : str
60
+ id : str
61
+ line : int
62
+ description : str
63
+ language : str
64
+ tags : list [TagElementDict ]
65
+ elements : list [ScenarioElementDict ]
66
+
67
+
68
+ class FeaturesDict (TypedDict ):
69
+ features : dict [str , FeatureElementDict ]
70
+
71
+
22
72
def add_options (parser : Parser ) -> None :
23
73
"""Add pytest-bdd options."""
24
74
group = parser .getgroup ("bdd" , "Cucumber JSON" )
@@ -48,21 +98,15 @@ def unconfigure(config: Config) -> None:
48
98
config .pluginmanager .unregister (xml )
49
99
50
100
51
- class Result (TypedDict ):
52
- status : Literal ["passed" , "failed" , "skipped" ]
53
- duration : int # in nanoseconds
54
- error_message : NotRequired [str ]
55
-
56
-
57
101
class LogBDDCucumberJSON :
58
102
"""Logging plugin for cucumber like json output."""
59
103
60
104
def __init__ (self , logfile : str ) -> None :
61
105
logfile = os .path .expanduser (os .path .expandvars (logfile ))
62
106
self .logfile = os .path .normpath (os .path .abspath (logfile ))
63
- self .features : dict [str , dict ] = {}
107
+ self .features : dict [str , FeatureElementDict ] = {}
64
108
65
- def _get_result (self , step : dict [ str , Any ], report : TestReport , error_message : bool = False ) -> Result :
109
+ def _get_result (self , step : StepReportDict , report : TestReport , error_message : bool = False ) -> ResultElementDict :
66
110
"""Get scenario test run result.
67
111
68
112
:param step: `Step` step we get result for
@@ -80,12 +124,12 @@ def _get_result(self, step: dict[str, Any], report: TestReport, error_message: b
80
124
status = "skipped"
81
125
else :
82
126
raise ValueError (f"Unknown test outcome { report .outcome } " )
83
- res : Result = {"status" : status , "duration" : int (math .floor ((10 ** 9 ) * step ["duration" ]))} # nanosec
127
+ res : ResultElementDict = {"status" : status , "duration" : int (math .floor ((10 ** 9 ) * step ["duration" ]))} # nanosec
84
128
if res_message is not None :
85
129
res ["error_message" ] = res_message
86
130
return res
87
131
88
- def _serialize_tags (self , item : dict [ str , Any ] ) -> list [dict [ str , Any ] ]:
132
+ def _serialize_tags (self , item : FeatureDict | ScenarioReportDict ) -> list [TagElementDict ]:
89
133
"""Serialize item's tags.
90
134
91
135
:param item: json-serialized `Scenario` or `Feature`.
@@ -110,7 +154,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None:
110
154
# skip if there isn't a result or scenario has no steps
111
155
return
112
156
113
- def stepmap (step : dict [ str , Any ] ) -> dict [ str , Any ] :
157
+ def stepmap (step : StepReportDict ) -> StepElementDict :
114
158
error_message = False
115
159
if step ["failed" ] and not scenario .setdefault ("failed" , False ):
116
160
scenario ["failed" ] = True
0 commit comments