1
1
import abc
2
2
import datetime
3
+ from typing import Any
3
4
4
5
from pydantic import BaseModel
5
6
10
11
)
11
12
from contentctl .helper .utils import Utils
12
13
from contentctl .objects .enums import DetectionStatus
14
+ from contentctl .objects .base_test_result import TestResultStatus
13
15
14
16
15
17
class DetectionTestingView (BaseModel , abc .ABC ):
@@ -74,18 +76,23 @@ def getSummaryObject(
74
76
self ,
75
77
test_result_fields : list [str ] = ["success" , "message" , "exception" , "status" , "duration" , "wait_duration" ],
76
78
test_job_fields : list [str ] = ["resultCount" , "runDuration" ],
77
- ) -> dict :
79
+ ) -> dict [ str , dict [ str , Any ] | list [ dict [ str , Any ]] | str ] :
78
80
"""
79
81
Iterates over detections, consolidating results into a single dict and aggregating metrics
80
82
:param test_result_fields: fields to pull from the test result
81
83
:param test_job_fields: fields to pull from the job content of the test result
82
84
:returns: summary dict
83
85
"""
84
- # Init the list of tested detections, and some metrics aggregate counters
85
- tested_detections = []
86
+ # Init the list of tested and skipped detections, and some metrics aggregate counters
87
+ tested_detections : list [dict [str , Any ]] = []
88
+ skipped_detections : list [dict [str , Any ]] = []
86
89
total_pass = 0
87
90
total_fail = 0
88
91
total_skipped = 0
92
+ total_production = 0
93
+ total_experimental = 0
94
+ total_deprecated = 0
95
+ total_manual = 0
89
96
90
97
# Iterate the detections tested (anything in the output queue was tested)
91
98
for detection in self .sync_obj .outputQueue :
@@ -95,46 +102,59 @@ def getSummaryObject(
95
102
)
96
103
97
104
# Aggregate detection pass/fail metrics
98
- if summary [ "success" ] is False :
105
+ if detection . test_status == TestResultStatus . FAIL :
99
106
total_fail += 1
107
+ elif detection .test_status == TestResultStatus .PASS :
108
+ total_pass += 1
109
+ elif detection .test_status == TestResultStatus .SKIP :
110
+ total_skipped += 1
111
+
112
+ # Aggregate production status metrics
113
+ if detection .status == DetectionStatus .production .value : # type: ignore
114
+ total_production += 1
115
+ elif detection .status == DetectionStatus .experimental .value : # type: ignore
116
+ total_experimental += 1
117
+ elif detection .status == DetectionStatus .deprecated .value : # type: ignore
118
+ total_deprecated += 1
119
+
120
+ # Check if the detection is manual_test
121
+ if detection .tags .manual_test is not None :
122
+ total_manual += 1
123
+
124
+ # Append to our list (skipped or tested)
125
+ if detection .test_status == TestResultStatus .SKIP :
126
+ skipped_detections .append (summary )
100
127
else :
101
- #Test is marked as a success, but we need to determine if there were skipped unit tests
102
- #SKIPPED tests still show a success in this field, but we want to count them differently
103
- pass_increment = 1
104
- for test in summary .get ("tests" ):
105
- if test .get ("test_type" ) == "unit" and test .get ("status" ) == "skip" :
106
- total_skipped += 1
107
- #Test should not count as a pass, so do not increment the count
108
- pass_increment = 0
109
- break
110
- total_pass += pass_increment
111
-
112
-
113
- # Append to our list
114
- tested_detections .append (summary )
115
-
116
- # Sort s.t. all failures appear first (then by name)
117
- #Second short condition is a hack to get detections with unit skipped tests to appear above pass tests
118
- tested_detections .sort (key = lambda x : (x ["success" ], 0 if x .get ("tests" ,[{}])[0 ].get ("status" ,"status_missing" )== "skip" else 1 , x ["name" ]))
128
+ tested_detections .append (summary )
119
129
130
+ # Sort tested detections s.t. all failures appear first, then by name
131
+ tested_detections .sort (
132
+ key = lambda x : (
133
+ x ["success" ],
134
+ x ["name" ]
135
+ )
136
+ )
137
+
138
+ # Sort skipped detections s.t. detections w/ tests appear before those w/o, then by name
139
+ skipped_detections .sort (
140
+ key = lambda x : (
141
+ 0 if len (x ["tests" ]) > 0 else 1 ,
142
+ x ["name" ]
143
+ )
144
+ )
145
+
146
+ # TODO (#267): Align test reporting more closely w/ status enums (as it relates to
147
+ # "untested")
120
148
# Aggregate summaries for the untested detections (anything still in the input queue was untested)
121
149
total_untested = len (self .sync_obj .inputQueue )
122
- untested_detections = []
150
+ untested_detections : list [ dict [ str , Any ]] = []
123
151
for detection in self .sync_obj .inputQueue :
124
152
untested_detections .append (detection .get_summary ())
125
153
126
154
# Sort by detection name
127
155
untested_detections .sort (key = lambda x : x ["name" ])
128
156
129
- # Get lists of detections (name only) that were skipped due to their status (experimental or deprecated)
130
- experimental_detections = sorted ([
131
- detection .name for detection in self .sync_obj .skippedQueue if detection .status == DetectionStatus .experimental .value
132
- ])
133
- deprecated_detections = sorted ([
134
- detection .name for detection in self .sync_obj .skippedQueue if detection .status == DetectionStatus .deprecated .value
135
- ])
136
-
137
- # If any detection failed, the overall success is False
157
+ # If any detection failed, or if there are untested detections, the overall success is False
138
158
if (total_fail + len (untested_detections )) == 0 :
139
159
overall_success = True
140
160
else :
@@ -143,33 +163,39 @@ def getSummaryObject(
143
163
# Compute total detections
144
164
total_detections = total_fail + total_pass + total_untested + total_skipped
145
165
166
+ # Compute total detections actually tested (at least one test not skipped)
167
+ total_tested_detections = total_fail + total_pass
146
168
147
169
# Compute the percentage of completion for testing, as well as the success rate
148
170
percent_complete = Utils .getPercent (
149
171
len (tested_detections ), len (untested_detections ), 1
150
172
)
151
173
success_rate = Utils .getPercent (
152
- total_pass , total_detections - total_skipped , 1
174
+ total_pass , total_tested_detections , 1
153
175
)
154
176
155
- # TODO (#230): expand testing metrics reported
177
+ # TODO (#230): expand testing metrics reported (and make nested)
156
178
# Construct and return the larger results dict
157
179
result_dict = {
158
180
"summary" : {
181
+ "mode" : self .config .getModeName (),
182
+ "enable_integration_testing" : self .config .enable_integration_testing ,
159
183
"success" : overall_success ,
160
184
"total_detections" : total_detections ,
185
+ "total_tested_detections" : total_tested_detections ,
161
186
"total_pass" : total_pass ,
162
187
"total_fail" : total_fail ,
163
188
"total_skipped" : total_skipped ,
164
189
"total_untested" : total_untested ,
165
- "total_experimental_or_deprecated" : len (deprecated_detections + experimental_detections ),
190
+ "total_production" : total_production ,
191
+ "total_experimental" : total_experimental ,
192
+ "total_deprecated" : total_deprecated ,
193
+ "total_manual" : total_manual ,
166
194
"success_rate" : success_rate ,
167
195
},
168
196
"tested_detections" : tested_detections ,
197
+ "skipped_detections" : skipped_detections ,
169
198
"untested_detections" : untested_detections ,
170
199
"percent_complete" : percent_complete ,
171
- "deprecated_detections" : deprecated_detections ,
172
- "experimental_detections" : experimental_detections
173
-
174
200
}
175
201
return result_dict
0 commit comments