11import abc
22import datetime
3+ from typing import Any
34
45from pydantic import BaseModel
56
1011)
1112from contentctl .helper .utils import Utils
1213from contentctl .objects .enums import DetectionStatus
14+ from contentctl .objects .base_test_result import TestResultStatus
1315
1416
1517class DetectionTestingView (BaseModel , abc .ABC ):
@@ -74,18 +76,23 @@ def getSummaryObject(
7476 self ,
7577 test_result_fields : list [str ] = ["success" , "message" , "exception" , "status" , "duration" , "wait_duration" ],
7678 test_job_fields : list [str ] = ["resultCount" , "runDuration" ],
77- ) -> dict :
79+ ) -> dict [ str , dict [ str , Any ] | list [ dict [ str , Any ]] | str ] :
7880 """
7981 Iterates over detections, consolidating results into a single dict and aggregating metrics
8082 :param test_result_fields: fields to pull from the test result
8183 :param test_job_fields: fields to pull from the job content of the test result
8284 :returns: summary dict
8385 """
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 ]] = []
8689 total_pass = 0
8790 total_fail = 0
8891 total_skipped = 0
92+ total_production = 0
93+ total_experimental = 0
94+ total_deprecated = 0
95+ total_manual = 0
8996
9097 # Iterate the detections tested (anything in the output queue was tested)
9198 for detection in self .sync_obj .outputQueue :
@@ -95,46 +102,59 @@ def getSummaryObject(
95102 )
96103
97104 # Aggregate detection pass/fail metrics
98- if summary [ "success" ] is False :
105+ if detection . test_status == TestResultStatus . FAIL :
99106 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 )
100127 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 )
119129
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")
120148 # Aggregate summaries for the untested detections (anything still in the input queue was untested)
121149 total_untested = len (self .sync_obj .inputQueue )
122- untested_detections = []
150+ untested_detections : list [ dict [ str , Any ]] = []
123151 for detection in self .sync_obj .inputQueue :
124152 untested_detections .append (detection .get_summary ())
125153
126154 # Sort by detection name
127155 untested_detections .sort (key = lambda x : x ["name" ])
128156
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
138158 if (total_fail + len (untested_detections )) == 0 :
139159 overall_success = True
140160 else :
@@ -143,33 +163,39 @@ def getSummaryObject(
143163 # Compute total detections
144164 total_detections = total_fail + total_pass + total_untested + total_skipped
145165
166+ # Compute total detections actually tested (at least one test not skipped)
167+ total_tested_detections = total_fail + total_pass
146168
147169 # Compute the percentage of completion for testing, as well as the success rate
148170 percent_complete = Utils .getPercent (
149171 len (tested_detections ), len (untested_detections ), 1
150172 )
151173 success_rate = Utils .getPercent (
152- total_pass , total_detections - total_skipped , 1
174+ total_pass , total_tested_detections , 1
153175 )
154176
155- # TODO (#230): expand testing metrics reported
177+ # TODO (#230): expand testing metrics reported (and make nested)
156178 # Construct and return the larger results dict
157179 result_dict = {
158180 "summary" : {
181+ "mode" : self .config .getModeName (),
182+ "enable_integration_testing" : self .config .enable_integration_testing ,
159183 "success" : overall_success ,
160184 "total_detections" : total_detections ,
185+ "total_tested_detections" : total_tested_detections ,
161186 "total_pass" : total_pass ,
162187 "total_fail" : total_fail ,
163188 "total_skipped" : total_skipped ,
164189 "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 ,
166194 "success_rate" : success_rate ,
167195 },
168196 "tested_detections" : tested_detections ,
197+ "skipped_detections" : skipped_detections ,
169198 "untested_detections" : untested_detections ,
170199 "percent_complete" : percent_complete ,
171- "deprecated_detections" : deprecated_detections ,
172- "experimental_detections" : experimental_detections
173-
174200 }
175201 return result_dict
0 commit comments