1919import datetime
2020from rtps_test_utilities import log_message
2121import test_suite
22+ from enum import Enum
23+
24+ class TestStatus (Enum ):
25+ PASSED = 1
26+ FAILED = 2
27+ UNSUPPORTED = 3
2228
2329class XlxsReportArgumentParser :
2430 """Class that parse the arguments of the application."""
@@ -90,23 +96,27 @@ def get_product_name(product:str) -> str:
9096
9197class JunitAggregatedData :
9298 """
93- Class that contains the JUnit aggregated data as a tuple of 2 integers
94- [tests_passed, total_tests]. This identifies one cell in the summary
95- table that shows the product and the amount of tests passed and total.
99+ Class that contains the JUnit aggregated data as a tuple of 3 integers
100+ [tests_passed, total_tests, tests_unsupported]. This identifies one cell in
101+ the summary table that shows the product and the amount of tests passed,
102+ total and unsupported.
96103 """
97- data : tuple [int ,int ] # [tests_passed, total_tests]
104+ data : tuple [int ,int , int ] # [tests_passed, total_tests, tests_unsupported ]
98105
99- def __init__ (self , passed_tests : int , total_tests : int ) -> None :
100- self .data = [passed_tests , total_tests ]
106+ def __init__ (self , passed_tests : int , total_tests : int , unsupported_tests : int ) -> None :
107+ self .data = [passed_tests , total_tests , unsupported_tests ]
101108
102109 def get_passed_tests (self ):
103110 return self .data [0 ]
104111
105112 def get_total_tests (self ):
106113 return self .data [1 ]
107114
115+ def get_unsupported_tests (self ):
116+ return self .data [2 ]
117+
108118 def __str__ (self ) -> str :
109- return f'({ self .data [0 ]} , { self .data [1 ]} )'
119+ return f'({ self .data [0 ]} , { self .data [1 ]} , { self . data [ 2 ] } )'
110120
111121class JunitTestCaseAggregatedData :
112122 """
@@ -115,22 +125,21 @@ class JunitTestCaseAggregatedData:
115125 Publisher or Subscriber) and with all other products (as Subscribers or
116126 Publishers, the opposite).
117127 This tuple is composed by 2 strings that identifies the other product
118- (Publisher or Subscriber), the test name and whether the test was
119- successful or not.
128+ (Publisher or Subscriber), the test name and the status of the test.
120129 """
121- # [publisher or subscriber name, test_name, passed_tests ]
122- data : tuple [str ,str ,bool ] = None
130+ # [publisher or subscriber name, test_name, status ]
131+ data : tuple [str ,str ,TestStatus ] = None
123132
124- def __init__ (self , product : str , test_name : str , passed : bool ) -> None :
125- self .data = (product , test_name , passed )
133+ def __init__ (self , product : str , test_name : str , status : TestStatus ) -> None :
134+ self .data = (product , test_name , status )
126135
127136 def get_product_name (self ):
128137 return self .data [0 ]
129138
130139 def get_test_name (self ):
131140 return self .data [1 ]
132141
133- def get_passed (self ):
142+ def get_status (self ):
134143 return self .data [2 ]
135144
136145 def __str__ (self ) -> str :
@@ -185,6 +194,7 @@ def update_value_aggregated_data_dict(self,
185194 updated_data = JunitAggregatedData (
186195 dictionary [key ].get_passed_tests () + value .get_passed_tests (),
187196 dictionary [key ].get_total_tests () + value .get_total_tests (),
197+ dictionary [key ].get_unsupported_tests () + value .get_unsupported_tests ()
188198 )
189199 dictionary [key ] = updated_data
190200 else :
@@ -221,47 +231,30 @@ def get_info(self, input: pathlib.Path = None):
221231 publisher_name = ProductUtils .get_product_name (product_names .group (1 ))
222232 subscriber_name = ProductUtils .get_product_name (product_names .group (2 ))
223233
224- # get the value of the passed_tests and total_tests as a
225- # JunitAggregatedData
226- element = JunitAggregatedData (
227- suite .tests - suite .failures - suite .skipped - suite .errors ,
228- suite .tests
229- )
230-
231- # update the information of the product in the summary_dict with
232- # the information of the publisher and the subscriber
233- self .update_value_aggregated_data_dict (
234- self .summary_dict , publisher_name , element )
235- # do not add duplicated data if the publisher and subscriber names
236- # are the same
237- if publisher_name != subscriber_name :
238- self .update_value_aggregated_data_dict (
239- self .summary_dict , subscriber_name , element )
240-
241- # Get table with the summary of the test passed/total_tests for
242- # every product as publisher and as subscriber
243- product_dict_key = (publisher_name , subscriber_name )
244- product_test_data = JunitAggregatedData (
245- suite .tests - suite .failures - suite .skipped - suite .errors ,
246- suite .tests )
247- self .update_value_aggregated_data_dict (
248- self .product_summary_dict ,
249- product_dict_key ,
250- product_test_data )
251-
252234 # for each test case in the test suite, fill out the dictionaries
253235 # that contains information about the product as publisher and
254236 # subscriber
237+ unsupported_tests_count = 0
255238 for case in list (iter (suite )):
239+ this_test_unsupported = False
256240 test_name = re .search (r'((?:Test_)[\S]+_\d+)' , case .name ).group (1 )
257241
242+ # count number of unsupported tests for the summary
243+ # result array is not empty and the message contains 'UNSUPPORTED_FEATURE'
244+ if case .result and len (case .result ) > 0 \
245+ and 'UNSUPPORTED_FEATURE' in case .result [0 ].message .upper ():
246+ unsupported_tests_count += 1
247+ this_test_unsupported = True
248+
258249 # update the value of the publisher_name as publisher with
259250 # all products as subscribers.
260- # the tuple is (subscriber_name, test_name, is_passed )
251+ # the tuple is (subscriber_name, test_name, status )
261252 publisher_test_result = JunitTestCaseAggregatedData (
262253 product = subscriber_name ,
263254 test_name = test_name ,
264- passed = case .is_passed
255+ status = TestStatus .PASSED if case .is_passed
256+ else TestStatus .FAILED if not this_test_unsupported
257+ else TestStatus .UNSUPPORTED
265258 )
266259
267260 # add the resulting tuple to the publisher dictionary, the key
@@ -275,11 +268,13 @@ def get_info(self, input: pathlib.Path = None):
275268
276269 # update the value of the subscriber_name as subscriber with
277270 # all products as publishers.
278- # the tuple is (publisher_name, test_name, is_passed )
271+ # the tuple is (publisher_name, test_name, status )
279272 subscriber_test_result = JunitTestCaseAggregatedData (
280273 product = publisher_name ,
281274 test_name = test_name ,
282- passed = case .is_passed
275+ status = TestStatus .PASSED if case .is_passed
276+ else TestStatus .FAILED if not this_test_unsupported
277+ else TestStatus .UNSUPPORTED
283278 )
284279
285280 # add the resulting tuple to the subscriber dictionary, the key
@@ -291,6 +286,37 @@ def get_info(self, input: pathlib.Path = None):
291286 product_dict = self .subscriber_product_dict
292287 )
293288
289+ # get the value of the passed_tests, total_tests and
290+ # unsupported_tests as a JunitAggregatedData
291+ element = JunitAggregatedData (
292+ suite .tests - suite .failures - suite .skipped - suite .errors ,
293+ suite .tests ,
294+ unsupported_tests_count
295+ )
296+
297+ # update the information of the product in the summary_dict with
298+ # the information of the publisher and the subscriber
299+ self .update_value_aggregated_data_dict (
300+ self .summary_dict , publisher_name , element )
301+ # do not add duplicated data if the publisher and subscriber names
302+ # are the same
303+ if publisher_name != subscriber_name :
304+ self .update_value_aggregated_data_dict (
305+ self .summary_dict , subscriber_name , element )
306+
307+ # Get table with the summary of the test
308+ # passed/total_tests/unsupported_tests for every product as
309+ # publisher and as subscriber
310+ product_dict_key = (publisher_name , subscriber_name )
311+ product_test_data = JunitAggregatedData (
312+ suite .tests - suite .failures - suite .skipped - suite .errors ,
313+ suite .tests ,
314+ unsupported_tests_count )
315+ self .update_value_aggregated_data_dict (
316+ self .product_summary_dict ,
317+ product_dict_key ,
318+ product_test_data )
319+
294320class ColorUtils :
295321 """Set specific colors"""
296322 GREEN = '#4EB168'
@@ -437,17 +463,20 @@ def get_format_color(self, index: int, num_elements: int):
437463 else : # ratio == 1
438464 return self .__formats ['result_green' ]
439465
440- def get_format_color_bool (self , passed : bool ):
466+ def get_format_color_bool (self , status : TestStatus ):
441467 """
442- Get the corresponding color format depending on 'passed '.
443- Green if passed is True , Red otherwise
468+ Get the corresponding color format depending on 'status '.
469+ Green if status is PASSED , Red if FAILED, Yellow if UNSUPPORTED
444470 """
445- if passed :
471+ if status == TestStatus . PASSED :
446472 # Return GREEN
447- return self .get_format_color (1 ,1 )
473+ return self .__formats ['result_green' ]
474+ elif status == TestStatus .FAILED :
475+ # Return RED
476+ return self .__formats ['result_red' ]
448477 else :
449- # Return FALSE
450- return self .get_format_color ( 0 , 1 )
478+ # Return YELLOW
479+ return self .__formats [ 'result_yellow' ]
451480
452481 def add_static_data_test (self ,
453482 worksheet : xlsxwriter .Workbook .worksheet_class ,
@@ -607,7 +636,7 @@ def add_product_table(self,
607636 'Test' ,
608637 self .__formats ['bold_w_border' ])
609638
610- # This column dictionary will keep the colum for the subscriber product
639+ # This column dictionary will keep the column for the subscriber product
611640 column_dict = {}
612641 row_dict = {}
613642 # for all elements (test results), add the corresponding value to the
@@ -649,12 +678,14 @@ def add_product_table(self,
649678 self .__formats ['bold_w_border' ])
650679
651680 # set OK or ERROR if the test passed or not
652- str_result = 'OK' if element .get_passed () else 'ERROR'
681+ str_result = 'OK' if element .get_status () == TestStatus .PASSED \
682+ else 'ERROR' if element .get_status () == TestStatus .FAILED \
683+ else 'UNSUPPORTED'
653684 worksheet .write (
654685 process_row ,
655686 process_column ,
656687 str_result ,
657- self .get_format_color_bool (element .get_passed ()))
688+ self .get_format_color_bool (element .get_status ()))
658689 return (current_row , current_column )
659690
660691 def add_data_summary_worksheet (self ,
@@ -677,32 +708,59 @@ def add_data_summary_worksheet(self,
677708 worksheet .write (
678709 current_row , current_column + 2 ,
679710 'Test Passed' , self .__formats ['bold_w_border' ])
711+ worksheet .write (
712+ current_row , current_column + 3 ,
713+ 'Unsupported Test' , self .__formats ['bold_w_border' ])
714+ worksheet .write (
715+ current_row , current_column + 4 ,
716+ 'Supported Test Passed' , self .__formats ['bold_w_border' ])
680717
681718 current_row += 1
682719
683720 # Create table with the total passed_tests/total_tests per product
684721 for product_name , value in self .__data .summary_dict .items ():
722+ # company name
685723 worksheet .write (
686724 current_row , current_column ,
687725 ProductUtils .get_company_name (product_name ),
688726 self .__formats ['bold_w_border' ])
727+ # product name
689728 worksheet .write (
690729 current_row , current_column + 1 ,
691730 product_name ,
692731 self .__formats ['bold_w_border' ])
732+ # test passed
693733 worksheet .write (
694734 current_row , current_column + 2 ,
695735 str (value .get_passed_tests ()) + ' / ' +
696- str (value .get_total_tests ()),
736+ str (value .get_total_tests ()),
697737 self .get_format_color (value .get_passed_tests (),
698738 value .get_total_tests ()))
739+ # unsupported tests
740+ worksheet .write (
741+ current_row , current_column + 3 ,
742+ str (value .get_unsupported_tests ()) + ' / ' +
743+ str (value .get_total_tests ()),
744+ self .__formats ['result_yellow' ] if value .get_unsupported_tests () > 0
745+ else self .__formats ['result_green' ])
746+ # supported tests passed
747+ worksheet .write (
748+ current_row , current_column + 4 ,
749+ str (value .get_passed_tests ()) + ' / ' +
750+ str (value .get_total_tests () - value .get_unsupported_tests ()),
751+ self .get_format_color (value .get_passed_tests (),
752+ value .get_total_tests () - value .get_unsupported_tests ()))
699753 current_row += 1
700754
701755 # Add 2 rows of gap for the next table
702756 current_row += 2
703757 worksheet .write (
704758 current_row , current_column ,
705- 'Publisher/Subscriber' , self .__formats ['bold_w_border' ])
759+ 'Test Result: passed / total / unsupported' , self .__formats ['bold_w_border' ])
760+ current_row += 1
761+ worksheet .write (
762+ current_row , current_column ,
763+ 'Publisher (row)/Subscriber (column)' , self .__formats ['bold_w_border' ])
706764
707765 # create a dictionary to store the row/column of the product name
708766 # for example, row_dict['Connext DDS 6.1.2'] = 30 means that the
@@ -747,7 +805,8 @@ def add_data_summary_worksheet(self,
747805
748806 worksheet .write (process_row , process_column ,
749807 str (value .get_passed_tests ()) + ' / ' +
750- str (value .get_total_tests ()),
808+ str (value .get_total_tests ()) + ' / ' +
809+ str (value .get_unsupported_tests ()),
751810 self .get_format_color (value .get_passed_tests (), value .get_total_tests ()))
752811
753812 def add_static_data_summary_worksheet (self ,
0 commit comments