@@ -36,7 +36,66 @@ def check_dependencies_after(self):
3636 assert new_requirements_txt == self .expected_requirements
3737
3838
39- class BaseRemediationIntegrationTest :
39+ class BaseIntegrationTestMixin :
40+ def _assert_sonar_fields (self , result ):
41+ del result
42+
43+ def _assert_codetf_output (self , codetf_schema ):
44+ with open (self .output_path , "r" , encoding = "utf-8" ) as f :
45+ codetf = json .load (f )
46+
47+ jsonschema .validate (codetf , codetf_schema )
48+
49+ assert sorted (codetf .keys ()) == ["results" , "run" ]
50+ run = codetf ["run" ]
51+ self ._assert_run_fields (run , self .output_path )
52+ results = codetf ["results" ]
53+ # CodeTf2 spec requires relative paths
54+ self ._assert_results_fields (results , self .code_filename )
55+
56+ def write_original_code (self ):
57+ with open (self .code_path , "w" , encoding = "utf-8" ) as f :
58+ f .write (self .original_code )
59+
60+ def _assert_results_fields (self , results , output_path ):
61+ assert len (results ) == 1
62+ result = results [0 ]
63+ assert result ["codemod" ] == self .codemod_instance .id
64+ assert result ["references" ] == [
65+ ref .model_dump (exclude_none = True )
66+ for ref in self .codemod_instance .references
67+ ]
68+
69+ assert ("detectionTool" in result ) == bool (self .sonar_issues_json )
70+ assert ("detectionTool" in result ) == bool (self .sonar_hotspots_json )
71+
72+ # TODO: if/when we add description for each url
73+ for reference in result ["references" ][
74+ # Last references for Sonar has a different description
75+ : (
76+ - len (self .codemod .requested_rules )
77+ if self .sonar_issues_json or self .sonar_hotspots_json
78+ else None
79+ )
80+ ]:
81+ assert reference ["url" ] == reference ["description" ]
82+
83+ self ._assert_sonar_fields (result )
84+
85+ def _assert_command_line (self , run , output_path ):
86+ pass
87+
88+ def _assert_run_fields (self , run , output_path ):
89+ self ._assert_command_line (run , output_path )
90+ assert run ["vendor" ] == "pixee"
91+ assert run ["tool" ] == "codemodder-python"
92+ assert run ["version" ] == __version__
93+ assert run ["elapsed" ] != ""
94+ assert run ["directory" ] == os .path .abspath (self .code_dir )
95+ assert run ["sarifs" ] == []
96+
97+
98+ class BaseRemediationIntegrationTest (BaseIntegrationTestMixin ):
4099 codemod = NotImplementedError
41100 original_code = NotImplementedError
42101 expected_diff_per_change = NotImplementedError
@@ -77,11 +136,7 @@ def setup_class(cls):
77136 with open (cls .code_path , "r" , encoding = "utf-8" ) as f : # type: ignore
78137 cls .original_code = f .read ()
79138
80- def _assert_run_fields (self , run , output_path ):
81- assert run ["vendor" ] == "pixee"
82- assert run ["tool" ] == "codemodder-python"
83- assert run ["version" ] == __version__
84- assert run ["elapsed" ] != ""
139+ def _assert_command_line (self , run , output_path ):
85140 assert run [
86141 "commandLine"
87142 ] == f'codemodder { self .code_dir } --output { output_path } --codemod-include={ self .codemod_instance .id } --path-include={ self .code_filename } --path-exclude=""' + (
@@ -93,35 +148,10 @@ def _assert_run_fields(self, run, output_path):
93148 if self .sonar_hotspots_json
94149 else ""
95150 )
96- assert run ["directory" ] == os .path .abspath (self .code_dir )
97- assert run ["sarifs" ] == []
98151
99152 def _assert_results_fields (self , results , output_path ):
100- assert len ( results ) == 1
153+ super (). _assert_results_fields ( results , output_path )
101154 result = results [0 ]
102- assert result ["codemod" ] == self .codemod_instance .id
103- assert result ["references" ] == [
104- ref .model_dump (exclude_none = True )
105- for ref in self .codemod_instance .references
106- ]
107-
108- assert ("detectionTool" in result ) == bool (self .sonar_issues_json )
109- assert ("detectionTool" in result ) == bool (self .sonar_hotspots_json )
110-
111- # TODO: if/when we add description for each url
112- for reference in result ["references" ][
113- # Last references for Sonar has a different description
114- : (
115- - len (self .codemod .requested_rules )
116- if self .sonar_issues_json or self .sonar_hotspots_json
117- else None
118- )
119- ]:
120- assert reference ["url" ] == reference ["description" ]
121-
122- self ._assert_sonar_fields (result )
123-
124- # There should be a changeset for every expected change
125155 assert len (result ["changeset" ]) == self .num_changes
126156 # gather all the change files and test against the expected number
127157 assert len ({c ["path" ] for c in result ["changeset" ]}) == self .num_changed_files
@@ -143,26 +173,6 @@ def _assert_results_fields(self, results, output_path):
143173 self .change_description
144174 }
145175
146- def _assert_sonar_fields (self , result ):
147- del result
148-
149- def _assert_codetf_output (self , codetf_schema ):
150- with open (self .output_path , "r" , encoding = "utf-8" ) as f :
151- codetf = json .load (f )
152-
153- jsonschema .validate (codetf , codetf_schema )
154-
155- assert sorted (codetf .keys ()) == ["results" , "run" ]
156- run = codetf ["run" ]
157- self ._assert_run_fields (run , self .output_path )
158- results = codetf ["results" ]
159- # CodeTf2 spec requires relative paths
160- self ._assert_results_fields (results , self .code_filename )
161-
162- def write_original_code (self ):
163- with open (self .code_path , "w" , encoding = "utf-8" ) as f :
164- f .write (self .original_code )
165-
166176 def test_codetf_output (self , codetf_schema ):
167177 """
168178 Tests correct codetf output.
@@ -296,7 +306,7 @@ def _check_code_after(self, patched_codes):
296306 )
297307
298308
299- class BaseIntegrationTest (DependencyTestMixin ):
309+ class BaseIntegrationTest (BaseIntegrationTestMixin , DependencyTestMixin ):
300310 codemod = NotImplementedError
301311 original_code = NotImplementedError
302312 replacement_lines = NotImplementedError
@@ -352,11 +362,7 @@ def teardown_class(cls):
352362 if cls .requirements_file_name :
353363 pathlib .Path (cls .dependency_path ).unlink (missing_ok = True )
354364
355- def _assert_run_fields (self , run , output_path ):
356- assert run ["vendor" ] == "pixee"
357- assert run ["tool" ] == "codemodder-python"
358- assert run ["version" ] == __version__
359- assert run ["elapsed" ] != ""
365+ def _assert_command_line (self , run , output_path ):
360366 assert run [
361367 "commandLine"
362368 ] == f'codemodder_hardening { self .code_dir } --output { output_path } --codemod-include={ self .codemod_instance .id } --path-include={ self .code_filename } --path-exclude=""' + (
@@ -368,34 +374,11 @@ def _assert_run_fields(self, run, output_path):
368374 if self .sonar_hotspots_json
369375 else ""
370376 )
371- assert run ["directory" ] == os .path .abspath (self .code_dir )
372- assert run ["sarifs" ] == []
373377
374378 def _assert_results_fields (self , results , output_path ):
375- assert len (results ) == 1
376- result = results [0 ]
377- assert result ["codemod" ] == self .codemod_instance .id
378- assert result ["references" ] == [
379- ref .model_dump (exclude_none = True )
380- for ref in self .codemod_instance .references
381- ]
382-
383- assert ("detectionTool" in result ) == bool (self .sonar_issues_json )
384- assert ("detectionTool" in result ) == bool (self .sonar_hotspots_json )
385-
386- # TODO: if/when we add description for each url
387- for reference in result ["references" ][
388- # Last references for Sonar has a different description
389- : (
390- - len (self .codemod .requested_rules )
391- if self .sonar_issues_json or self .sonar_hotspots_json
392- else None
393- )
394- ]:
395- assert reference ["url" ] == reference ["description" ]
396-
397- self ._assert_sonar_fields (result )
379+ super ()._assert_results_fields (results , output_path )
398380
381+ result = results [0 ]
399382 assert len (result ["changeset" ]) == self .num_changed_files
400383
401384 # A codemod may change multiple files. For now we will
@@ -411,22 +394,6 @@ def _assert_results_fields(self, results, output_path):
411394 assert line_change ["lineNumber" ] == int (self .expected_line_change )
412395 assert line_change ["description" ] == self .change_description
413396
414- def _assert_sonar_fields (self , result ):
415- del result
416-
417- def _assert_codetf_output (self , codetf_schema ):
418- with open (self .output_path , "r" , encoding = "utf-8" ) as f :
419- codetf = json .load (f )
420-
421- jsonschema .validate (codetf , codetf_schema )
422-
423- assert sorted (codetf .keys ()) == ["results" , "run" ]
424- run = codetf ["run" ]
425- self ._assert_run_fields (run , self .output_path )
426- results = codetf ["results" ]
427- # CodeTf2 spec requires relative paths
428- self ._assert_results_fields (results , self .code_filename )
429-
430397 def check_code_after (self ) -> ModuleType :
431398 with open (self .code_path , "r" , encoding = "utf-8" ) as f : # type: ignore
432399 new_code = f .read ()
@@ -435,10 +402,6 @@ def check_code_after(self) -> ModuleType:
435402 path = self .code_path , allowed_exceptions = self .allowed_exceptions # type: ignore
436403 )
437404
438- def write_original_code (self ):
439- with open (self .code_path , "w" , encoding = "utf-8" ) as f :
440- f .write (self .original_code )
441-
442405 def test_file_rewritten (self , codetf_schema ):
443406 """
444407 Tests that file is re-written correctly with new code and correct codetf output.
0 commit comments