Skip to content

Commit 002fcf4

Browse files
author
Tjaž Eržen
authored
Merge pull request #37 from Codeplain-ai/release/prepare-testing-script
Dedicated Environment-Preparation Script for Conformance Tests
2 parents ea8f6ff + 95ab14e commit 002fcf4

14 files changed

Lines changed: 94 additions & 36 deletions
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
unittests-script: ../../test_scripts/run_unittests_react.sh
21
conformance-tests-script: ../../test_scripts/run_conformance_tests_cypress.sh
32
verbose: true # verbose flag, defaults to false if not set
4-

plain2code_arguments.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ def create_parser():
175175
"1) First argument: path to a folder (e.g. 'build') containing generated source code, "
176176
"2) Second argument: path to a subfolder of the conformance tests folder (e.g. 'conformance_tests/subfoldername') containing test files.",
177177
)
178+
179+
parser.add_argument(
180+
"--prepare-environment-script",
181+
type=str,
182+
help="Path to a shell script that prepares the testing environment. The script should accept the build folder path as its first argument (default: 'build').",
183+
)
184+
178185
parser.add_argument(
179186
"--api",
180187
type=str,

render_machine/actions/fix_conformance_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any |
115115
response_files,
116116
style=console.OUTPUT_STYLE,
117117
)
118+
render_context.conformance_tests_running_context.should_prepare_testing_environment = True
118119
return self.IMPLEMENTATION_CODE_UPDATED, None
119120
else:
120121
return self.IMPLEMENTATION_CODE_NOT_UPDATED, None
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from typing import Any
2+
3+
import render_machine.render_utils as render_utils
4+
from plain2code_console import console
5+
from render_machine.actions.base_action import BaseAction
6+
from render_machine.render_context import RenderContext
7+
8+
9+
class PrepareTestingEnvironment(BaseAction):
10+
SUCCESSFUL_OUTCOME = "testing_environment_prepared"
11+
FAILED_OUTCOME = "testing_environment_preparation_failed"
12+
13+
def execute(self, render_context: RenderContext, _previous_action_payload: Any | None):
14+
if render_context.args.verbose:
15+
console.info(
16+
f"[b]Running testing environment preparation script {render_context.args.prepare_environment_script} for build folder {render_context.args.build_folder}.[/b]"
17+
)
18+
exit_code, _ = render_utils.execute_script(
19+
render_context.args.prepare_environment_script,
20+
[render_context.args.build_folder],
21+
render_context.args.verbose,
22+
"Testing Environment Preparation",
23+
)
24+
25+
render_context.conformance_tests_running_context.should_prepare_testing_environment = False
26+
27+
if exit_code == 0:
28+
return self.SUCCESSFUL_OUTCOME, None
29+
else:
30+
return self.FAILED_OUTCOME, None

render_machine/actions/run_conformance_tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any |
2424
console.info(
2525
f"\n[b]Running conformance tests script {render_context.args.conformance_tests_script} for {conformance_tests_folder_name} (functional requirement {render_context.conformance_tests_running_context.current_testing_frid}).[/b]"
2626
)
27-
exit_code, conformance_tests_issue = render_utils.execute_test_script(
27+
exit_code, conformance_tests_issue = render_utils.execute_script(
2828
render_context.args.conformance_tests_script,
2929
[render_context.args.build_folder, conformance_tests_folder_name],
3030
render_context.args.verbose,
31-
"conformance",
31+
"Conformance Tests",
3232
)
3333

3434
if exit_code == 0:

render_machine/actions/run_unit_tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any |
1818
console.info(
1919
f"[b]Running unit tests script {render_context.args.unittests_script}.[/b] (attempt: {render_context.unit_tests_running_context.fix_attempts + 1})"
2020
)
21-
exit_code, unittests_issue = render_utils.execute_test_script(
21+
exit_code, unittests_issue = render_utils.execute_script(
2222
render_context.args.unittests_script,
2323
[render_context.args.build_folder],
2424
render_context.args.verbose,
25-
"unit",
25+
"Unit Tests",
2626
)
2727

2828
if exit_code == 0:

render_machine/render_context.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ def start_refactoring_code(self):
175175
)
176176
self.machine.dispatch(triggers.PROCEED_FRID_PROCESSING)
177177

178+
def start_testing_environment_preparation(self):
179+
if (
180+
self.args.prepare_environment_script is None
181+
or not self.conformance_tests_running_context.should_prepare_testing_environment
182+
):
183+
self.machine.dispatch(triggers.MARK_TESTING_ENVIRONMENT_PREPARED)
184+
178185
def start_conformance_tests_processing(self):
179186
console.info("\n[b]Implementing conformance tests...[/b]\n")
180187
conformance_tests_json = self.conformance_tests_utils.get_conformance_tests_json()
@@ -185,6 +192,7 @@ def start_conformance_tests_processing(self):
185192
fix_attempts=0,
186193
conformance_tests_json=conformance_tests_json,
187194
conformance_tests_render_attempts=0,
195+
should_prepare_testing_environment=True,
188196
)
189197

190198
def finish_conformance_tests_processing(self):

render_machine/render_types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ class ConformanceTestsRunningContext:
3333
# - current_testing_frid == frid noqa: E800
3434
# - conformance_test_phase_index == 0 (conformance tests phase)
3535
current_testing_frid_high_level_implementation_plan: Optional[str] = None
36+
should_prepare_testing_environment: bool = False

render_machine/render_utils.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import plain_spec
88
from plain2code_console import console
99

10-
TEST_SCRIPT_EXECUTION_TIMEOUT = 120
10+
SCRIPT_EXECUTION_TIMEOUT = 120
1111
TIMEOUT_ERROR_EXIT_CODE = 124
1212

1313

@@ -40,53 +40,53 @@ def print_inputs(render_context, existing_files_content, message):
4040
)
4141

4242

43-
def execute_test_script(test_script, scripts_args, verbose, test_type):
43+
def execute_script(script, scripts_args, verbose, script_type):
4444
try:
4545
start_time = time.time()
4646
result = subprocess.run(
47-
[file_utils.add_current_path_if_no_path(test_script)] + scripts_args,
47+
[file_utils.add_current_path_if_no_path(script)] + scripts_args,
4848
stdout=subprocess.PIPE,
4949
stderr=subprocess.STDOUT,
5050
text=True,
51-
timeout=TEST_SCRIPT_EXECUTION_TIMEOUT,
51+
timeout=SCRIPT_EXECUTION_TIMEOUT,
5252
)
5353
elapsed_time = time.time() - start_time
54-
# Log the info about the tests
54+
# Log the info about the script execution
5555
if verbose:
56-
with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".test_output") as temp_file:
57-
temp_file.write("\n═════════════════════════ Test Script Output ═════════════════════════\n")
56+
with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".script_output") as temp_file:
57+
temp_file.write(f"\n═════════════════════════ {script_type} Script Output ═════════════════════════\n")
5858
temp_file.write(result.stdout)
5959
temp_file.write("\n══════════════════════════════════════════════════════════════════════\n")
6060
temp_file_path = temp_file.name
6161
if result.returncode != 0:
62-
temp_file.write(f"Test script {test_script} failed with exit code {result.returncode}.\n")
62+
temp_file.write(f"{script_type} script {script} failed with exit code {result.returncode}.\n")
6363
else:
64-
temp_file.write(f"Test script {test_script} successfully passed.\n")
65-
temp_file.write(f"Test execution time: {elapsed_time:.2f} seconds.\n")
64+
temp_file.write(f"{script_type} script {script} successfully passed.\n")
65+
temp_file.write(f"{script_type} script execution time: {elapsed_time:.2f} seconds.\n")
6666

67-
console.info(f"[b]Test output stored in: {temp_file_path}[/b]")
67+
console.info(f"[b]{script_type} script output stored in: {temp_file_path}[/b]")
6868

6969
if result.returncode != 0:
7070
console.info(
71-
f"[b]The {test_type} tests have failed. Initiating the patching mode to automatically correct the discrepancies.[/b]\n"
71+
f"[b]The {script_type} script has failed. Initiating the patching mode to automatically correct the discrepancies.[/b]\n"
7272
)
7373
else:
74-
console.info(f"[b]All {test_type} tests passed successfully.[/b]\n")
74+
console.info(f"[b]All {script_type} script passed successfully.[/b]\n")
7575

7676
return result.returncode, result.stdout
7777
except subprocess.TimeoutExpired as e:
7878
# Store timeout output in a temporary file
7979
if verbose:
80-
with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".test_timeout") as temp_file:
81-
temp_file.write(f"Test script {test_script} timed out after {TEST_SCRIPT_EXECUTION_TIMEOUT} seconds.")
80+
with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".script_timeout") as temp_file:
81+
temp_file.write(f"{script_type} script {script} timed out after {SCRIPT_EXECUTION_TIMEOUT} seconds.")
8282
if e.stdout:
8383
decoded_output = e.stdout.decode("utf-8") if isinstance(e.stdout, bytes) else e.stdout
84-
temp_file.write(f"Test script partial output before the timeout:\n{decoded_output}")
84+
temp_file.write(f"{script_type} script partial output before the timeout:\n{decoded_output}")
8585
else:
86-
temp_file.write("Test script did not produce any output before the timeout.")
86+
temp_file.write(f"{script_type} script did not produce any output before the timeout.")
8787
temp_file_path = temp_file.name
8888
console.warning(
89-
f"The {test_type} test timed out after {TEST_SCRIPT_EXECUTION_TIMEOUT} seconds. Test output stored in: {temp_file_path}\n"
89+
f"The {script_type} script timed out after {SCRIPT_EXECUTION_TIMEOUT} seconds. {script_type} script output stored in: {temp_file_path}\n"
9090
)
9191

92-
return TIMEOUT_ERROR_EXIT_CODE, f"Tests did not finish in {TEST_SCRIPT_EXECUTION_TIMEOUT} seconds."
92+
return TIMEOUT_ERROR_EXIT_CODE, f"{script_type} script did not finish in {SCRIPT_EXECUTION_TIMEOUT} seconds."

render_machine/state_machine_config.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from render_machine.actions.fix_conformance_test import FixConformanceTest
1919
from render_machine.actions.fix_unit_tests import FixUnitTests
2020
from render_machine.actions.prepare_repositories import PrepareRepositories
21+
from render_machine.actions.prepare_testing_environment import PrepareTestingEnvironment
2122
from render_machine.actions.refactor_code import RefactorCode
2223
from render_machine.actions.render_conformance_tests import RenderConformanceTests
2324
from render_machine.actions.render_functional_requirement import RenderFunctionalRequirement
@@ -88,7 +89,8 @@ def get_action_map(self) -> Dict[str, Any]:
8889
git_utils.REFACTORED_CODE_COMMIT_MESSAGE
8990
),
9091
f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTING_INITIALISED.value}": RenderConformanceTests(),
91-
f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_READY.value}": RunConformanceTests(),
92+
f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_GENERATED.value}": PrepareTestingEnvironment(),
93+
f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}": RunConformanceTests(),
9294
f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_FAILED.value}": FixConformanceTest(),
9395
f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.POSTPROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTS_READY_FOR_SUMMARY.value}": SummarizeConformanceTests(),
9496
f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.POSTPROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTS_READY_FOR_COMMIT.value}": CommitConformanceTestsChanges(
@@ -120,6 +122,8 @@ def get_action_result_triggers_map(self) -> Dict[str, str]:
120122
CommitImplementationCodeChanges.SUCCESSFUL_OUTCOME: triggers.PROCEED_FRID_PROCESSING,
121123
CreateDist.SUCCESSFUL_OUTCOME: triggers.FINISH_RENDER,
122124
RenderConformanceTests.SUCCESSFUL_OUTCOME: triggers.MARK_CONFORMANCE_TESTS_READY,
125+
PrepareTestingEnvironment.SUCCESSFUL_OUTCOME: triggers.MARK_TESTING_ENVIRONMENT_PREPARED,
126+
PrepareTestingEnvironment.FAILED_OUTCOME: triggers.HANDLE_ERROR,
123127
RunConformanceTests.SUCCESSFUL_OUTCOME: triggers.MOVE_TO_NEXT_CONFORMANCE_TEST,
124128
RunConformanceTests.FAILED_OUTCOME: triggers.MARK_CONFORMANCE_TESTS_FAILED,
125129
RunConformanceTests.UNRECOVERABLE_ERROR_OUTCOME: triggers.HANDLE_ERROR,
@@ -177,7 +181,11 @@ def get_processing_conformance_tests_states(self, render_context: RenderContext)
177181
"name": States.CONFORMANCE_TESTING_INITIALISED.value,
178182
"on_enter": "start_conformance_tests_for_frid",
179183
},
180-
States.CONFORMANCE_TEST_READY.value,
184+
{
185+
"name": States.CONFORMANCE_TEST_GENERATED.value,
186+
"on_enter": "start_testing_environment_preparation",
187+
},
188+
States.CONFORMANCE_TEST_ENV_PREPARED.value,
181189
{
182190
"name": States.CONFORMANCE_TEST_FAILED.value,
183191
"on_enter": "start_fixing_conformance_tests",
@@ -345,10 +353,15 @@ def get_transitions(self) -> List[Dict[str, str]]:
345353
{
346354
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTING_INITIALISED.value}",
347355
"trigger": triggers.MARK_CONFORMANCE_TESTS_READY,
348-
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_READY.value}",
356+
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_GENERATED.value}",
357+
},
358+
{
359+
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_GENERATED.value}",
360+
"trigger": triggers.MARK_TESTING_ENVIRONMENT_PREPARED,
361+
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}",
349362
},
350363
{
351-
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_READY.value}",
364+
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}",
352365
"trigger": triggers.MARK_CONFORMANCE_TESTS_FAILED,
353366
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_FAILED.value}",
354367
},
@@ -358,14 +371,14 @@ def get_transitions(self) -> List[Dict[str, str]]:
358371
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTING_INITIALISED.value}",
359372
},
360373
{
361-
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_READY.value}",
374+
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}",
362375
"trigger": triggers.MOVE_TO_NEXT_CONFORMANCE_TEST,
363376
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTING_INITIALISED.value}",
364377
},
365378
{
366379
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_FAILED.value}",
367380
"trigger": triggers.MARK_CONFORMANCE_TESTS_READY,
368-
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_READY.value}",
381+
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}",
369382
},
370383
{
371384
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_FAILED.value}",
@@ -375,7 +388,7 @@ def get_transitions(self) -> List[Dict[str, str]]:
375388
{
376389
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.PROCESSING_UNIT_TESTS.value}_{States.UNIT_TESTS_READY.value}",
377390
"trigger": triggers.MARK_UNIT_TESTS_PASSED,
378-
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_READY.value}",
391+
"dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_GENERATED.value}",
379392
},
380393
{
381394
"source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.PROCESSING_UNIT_TESTS.value}_{States.UNIT_TESTS_READY.value}",

0 commit comments

Comments
 (0)