From 7c1c8a1b3081dc71809887a12e94120afcbf4107 Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Tue, 21 Apr 2026 16:49:11 +0200 Subject: [PATCH 1/9] Implementing current FRID first test execution order --- render_machine/actions/fix_conformance_test.py | 1 + render_machine/render_context.py | 8 ++++++++ render_machine/render_types.py | 1 + render_machine/state_machine_config.py | 8 +++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/render_machine/actions/fix_conformance_test.py b/render_machine/actions/fix_conformance_test.py index eee87979..20cae71d 100644 --- a/render_machine/actions/fix_conformance_test.py +++ b/render_machine/actions/fix_conformance_test.py @@ -151,6 +151,7 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any | style=console.OUTPUT_STYLE, ) render_context.conformance_tests_running_context.should_prepare_testing_environment = True + render_context.conformance_tests_running_context.implementation_code_was_updated = True return self.IMPLEMENTATION_CODE_UPDATED, None else: return self.IMPLEMENTATION_CODE_NOT_UPDATED, None diff --git a/render_machine/render_context.py b/render_machine/render_context.py index 6698636f..8785377a 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -278,6 +278,7 @@ def get_next_conformance_tests_running_context(self): def start_unittests_processing_in_conformance_tests(self): self.start_unittests_processing() + self.conformance_tests_running_context.implementation_code_was_updated = False self.conformance_tests_running_context = self.get_first_conformance_tests_running_context() def finish_unittests_processing(self): @@ -365,7 +366,14 @@ def start_conformance_tests_processing(self): def finish_conformance_tests_processing(self): self.conformance_tests_running_context = None + def implementation_code_was_updated_in_conformance_tests(self) -> bool: + return self.conformance_tests_running_context.implementation_code_was_updated + def start_conformance_tests_for_frid(self): + if self.conformance_tests_running_context.implementation_code_was_updated: + self.conformance_tests_running_context.implementation_code_was_updated = False + self.conformance_tests_running_context.current_testing_frid = None + if self.conformance_tests_running_context.regenerating_conformance_tests: if self.verbose: console.info( diff --git a/render_machine/render_types.py b/render_machine/render_types.py index d0d7a4fc..f2c9c47e 100644 --- a/render_machine/render_types.py +++ b/render_machine/render_types.py @@ -51,6 +51,7 @@ def __init__( # - current_testing_frid == frid noqa: E800 # - conformance_test_phase_index == 0 (conformance tests phase) self.regenerating_conformance_tests: bool = False + self.implementation_code_was_updated: bool = False self.current_testing_frid_high_level_implementation_plan: Optional[str] = None self.previous_conformance_tests_issue_old: Optional[str] = None self.previous_conformance_tests_issue_frid: Optional[str] = None diff --git a/render_machine/state_machine_config.py b/render_machine/state_machine_config.py index e0e9a0e2..e9a3af9c 100644 --- a/render_machine/state_machine_config.py +++ b/render_machine/state_machine_config.py @@ -130,7 +130,7 @@ def get_action_result_triggers_map(self) -> Dict[str, str]: RunConformanceTests.FAILED_OUTCOME: triggers.MARK_CONFORMANCE_TESTS_FAILED, RunConformanceTests.UNRECOVERABLE_ERROR_OUTCOME: triggers.HANDLE_ERROR, FixConformanceTest.IMPLEMENTATION_CODE_NOT_UPDATED: triggers.MARK_CONFORMANCE_TESTS_READY, - FixConformanceTest.IMPLEMENTATION_CODE_UPDATED: triggers.MARK_UNIT_TESTS_READY, + FixConformanceTest.IMPLEMENTATION_CODE_UPDATED: triggers.MARK_CONFORMANCE_TESTS_READY, CommitConformanceTestsChanges.SUCCESSFUL_OUTCOME_IMPLEMENTATION_UPDATED: triggers.MARK_NEXT_CONFORMANCE_TESTS_POSTPROCESSING_STEP, CommitConformanceTestsChanges.SUCCESSFUL_OUTCOME_IMPLEMENTATION_NOT_UPDATED: triggers.PROCEED_FRID_PROCESSING, SummarizeConformanceTests.SUCCESSFUL_OUTCOME: triggers.MARK_NEXT_CONFORMANCE_TESTS_POSTPROCESSING_STEP, @@ -397,6 +397,12 @@ def get_transitions(self) -> List[Dict[str, Any]]: "trigger": triggers.MARK_REGENERATION_OF_CONFORMANCE_TESTS, "dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTING_INITIALISED.value}", }, + { + "source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}", + "trigger": triggers.MOVE_TO_NEXT_CONFORMANCE_TEST, + "dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.PROCESSING_UNIT_TESTS.value}", + "conditions": ["should_run_unit_tests", "implementation_code_was_updated_in_conformance_tests"], + }, { "source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}", "trigger": triggers.MOVE_TO_NEXT_CONFORMANCE_TEST, From 49d2c1c13610c66b54c9c70efae5f5f6ef252c0a Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Thu, 23 Apr 2026 10:53:33 +0200 Subject: [PATCH 2/9] Not repeating the last er --- render_machine/render_context.py | 68 +++++++++++++++++++++----------- render_machine/render_types.py | 1 + 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/render_machine/render_context.py b/render_machine/render_context.py index 8785377a..e1685747 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -279,6 +279,7 @@ def get_next_conformance_tests_running_context(self): def start_unittests_processing_in_conformance_tests(self): self.start_unittests_processing() self.conformance_tests_running_context.implementation_code_was_updated = False + self.conformance_tests_running_context.regression_run_started = True self.conformance_tests_running_context = self.get_first_conformance_tests_running_context() def finish_unittests_processing(self): @@ -352,10 +353,13 @@ def start_testing_environment_preparation(self): def start_conformance_tests_processing(self): console.info("Implementing conformance tests...") + current_frid_specifications, _ = plain_spec.get_specifications_for_frid( + self.plain_source_tree, self.frid_context.frid + ) self.conformance_tests_running_context = ConformanceTestsRunningContext( current_testing_module_name=self.module_name, - current_testing_frid=None, - current_testing_frid_specifications=None, + current_testing_frid=self.frid_context.frid, + current_testing_frid_specifications=current_frid_specifications, conformance_test_phase_index=0, fix_attempts=0, conformance_tests_json=self.conformance_tests.get_conformance_tests_json(self.module_name), @@ -370,10 +374,6 @@ def implementation_code_was_updated_in_conformance_tests(self) -> bool: return self.conformance_tests_running_context.implementation_code_was_updated def start_conformance_tests_for_frid(self): - if self.conformance_tests_running_context.implementation_code_was_updated: - self.conformance_tests_running_context.implementation_code_was_updated = False - self.conformance_tests_running_context.current_testing_frid = None - if self.conformance_tests_running_context.regenerating_conformance_tests: if self.verbose: console.info( @@ -390,36 +390,60 @@ def start_conformance_tests_for_frid(self): self.conformance_tests_running_context.fix_attempts = 0 self.conformance_tests_running_context.regenerating_conformance_tests = False else: - # This block is now only executed for the main (last) module. This means that no conformance tests - # postprocessing is taking place. Maybe it should? - if ( - self.conformance_tests_running_context.current_testing_module_name == self.module_name + if self.conformance_tests_running_context.implementation_code_was_updated: + self.conformance_tests_running_context.implementation_code_was_updated = False + self.conformance_tests_running_context.regression_run_started = True + self.conformance_tests_running_context.current_testing_frid = None + + # This block handles phase-based rendering for the current FRID being implemented. + # Only runs before regression starts — during regression the current FRID is treated + # as an existing test like any other. + elif ( + not self.conformance_tests_running_context.regression_run_started + and self.conformance_tests_running_context.current_testing_module_name == self.module_name and self.conformance_tests_running_context.current_testing_frid == self.frid_context.frid ): + if not self.conformance_tests_running_context.current_conformance_tests_exist(): + # No entry yet — RenderConformanceTests will create it on this action cycle + return + if not self.frid_context.specifications.get( plain_spec.ACCEPTANCE_TESTS ) or self.conformance_tests_running_context.conformance_test_phase_index == len( self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS] ): - self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED) + # All phases done — start regression run over earlier FRIDs + self.conformance_tests_running_context.regression_run_started = True + self.conformance_tests_running_context.current_testing_frid = None + # fall through to get_first below + else: + if self.conformance_tests_running_context.conformance_test_phase_index == 0: + self.conformance_tests_running_context.current_testing_frid_high_level_implementation_plan = None + + self.conformance_tests_running_context.conformance_test_phase_index += 1 + current_acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][ + : self.conformance_tests_running_context.conformance_test_phase_index + ] + self.conformance_tests_running_context.get_conformance_tests_json( + self.conformance_tests_running_context.current_testing_module_name + )[self.frid_context.frid][plain_spec.ACCEPTANCE_TESTS] = current_acceptance_tests return - if self.conformance_tests_running_context.conformance_test_phase_index == 0: - self.conformance_tests_running_context.current_testing_frid_high_level_implementation_plan = None - - self.conformance_tests_running_context.conformance_test_phase_index += 1 - current_acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][ - : self.conformance_tests_running_context.conformance_test_phase_index - ] - self.conformance_tests_running_context.get_conformance_tests_json( - self.conformance_tests_running_context.current_testing_module_name - )[self.frid_context.frid][plain_spec.ACCEPTANCE_TESTS] = current_acceptance_tests - return if self.conformance_tests_running_context.current_testing_frid is None: self.conformance_tests_running_context = self.get_first_conformance_tests_running_context() else: self.conformance_tests_running_context = self.get_next_conformance_tests_running_context() + # Detect regression completion: we've reached the current FRID (don't re-run it) + if self.conformance_tests_running_context.regression_run_started: + current = self.conformance_tests_running_context.current_testing_frid + if self.conformance_tests_running_context.current_testing_module_name == self.module_name and ( + current is None or current == self.frid_context.frid + ): + self.conformance_tests_running_context.current_testing_frid = self.frid_context.frid + self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED) + return + if self.conformance_tests_running_context.current_testing_module_name == self.module_name: self.conformance_tests_running_context.current_testing_frid_specifications, _ = ( plain_spec.get_specifications_for_frid( diff --git a/render_machine/render_types.py b/render_machine/render_types.py index f2c9c47e..c7420fcd 100644 --- a/render_machine/render_types.py +++ b/render_machine/render_types.py @@ -52,6 +52,7 @@ def __init__( # - conformance_test_phase_index == 0 (conformance tests phase) self.regenerating_conformance_tests: bool = False self.implementation_code_was_updated: bool = False + self.regression_run_started: bool = False self.current_testing_frid_high_level_implementation_plan: Optional[str] = None self.previous_conformance_tests_issue_old: Optional[str] = None self.previous_conformance_tests_issue_frid: Optional[str] = None From 8f272c1ef6ce65e43ddd7a4a99408b547798b344 Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Tue, 5 May 2026 10:27:34 +0200 Subject: [PATCH 3/9] format --- render_machine/render_context.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/render_machine/render_context.py b/render_machine/render_context.py index e1685747..fcf007d0 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -418,7 +418,9 @@ def start_conformance_tests_for_frid(self): # fall through to get_first below else: if self.conformance_tests_running_context.conformance_test_phase_index == 0: - self.conformance_tests_running_context.current_testing_frid_high_level_implementation_plan = None + self.conformance_tests_running_context.current_testing_frid_high_level_implementation_plan = ( + None + ) self.conformance_tests_running_context.conformance_test_phase_index += 1 current_acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][ From 2efbfb1ac6be66ba8ad2687ea31855ed6ee7c6b0 Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Wed, 6 May 2026 09:24:09 +0200 Subject: [PATCH 4/9] Refactor and made sure that prepare_env gets run --- render_machine/render_context.py | 6 ------ render_machine/state_machine_config.py | 8 +------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/render_machine/render_context.py b/render_machine/render_context.py index fcf007d0..4dd83c1a 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -278,9 +278,6 @@ def get_next_conformance_tests_running_context(self): def start_unittests_processing_in_conformance_tests(self): self.start_unittests_processing() - self.conformance_tests_running_context.implementation_code_was_updated = False - self.conformance_tests_running_context.regression_run_started = True - self.conformance_tests_running_context = self.get_first_conformance_tests_running_context() def finish_unittests_processing(self): existing_files = file_utils.list_all_text_files(self.build_folder) @@ -370,9 +367,6 @@ def start_conformance_tests_processing(self): def finish_conformance_tests_processing(self): self.conformance_tests_running_context = None - def implementation_code_was_updated_in_conformance_tests(self) -> bool: - return self.conformance_tests_running_context.implementation_code_was_updated - def start_conformance_tests_for_frid(self): if self.conformance_tests_running_context.regenerating_conformance_tests: if self.verbose: diff --git a/render_machine/state_machine_config.py b/render_machine/state_machine_config.py index e9a3af9c..e0e9a0e2 100644 --- a/render_machine/state_machine_config.py +++ b/render_machine/state_machine_config.py @@ -130,7 +130,7 @@ def get_action_result_triggers_map(self) -> Dict[str, str]: RunConformanceTests.FAILED_OUTCOME: triggers.MARK_CONFORMANCE_TESTS_FAILED, RunConformanceTests.UNRECOVERABLE_ERROR_OUTCOME: triggers.HANDLE_ERROR, FixConformanceTest.IMPLEMENTATION_CODE_NOT_UPDATED: triggers.MARK_CONFORMANCE_TESTS_READY, - FixConformanceTest.IMPLEMENTATION_CODE_UPDATED: triggers.MARK_CONFORMANCE_TESTS_READY, + FixConformanceTest.IMPLEMENTATION_CODE_UPDATED: triggers.MARK_UNIT_TESTS_READY, CommitConformanceTestsChanges.SUCCESSFUL_OUTCOME_IMPLEMENTATION_UPDATED: triggers.MARK_NEXT_CONFORMANCE_TESTS_POSTPROCESSING_STEP, CommitConformanceTestsChanges.SUCCESSFUL_OUTCOME_IMPLEMENTATION_NOT_UPDATED: triggers.PROCEED_FRID_PROCESSING, SummarizeConformanceTests.SUCCESSFUL_OUTCOME: triggers.MARK_NEXT_CONFORMANCE_TESTS_POSTPROCESSING_STEP, @@ -397,12 +397,6 @@ def get_transitions(self) -> List[Dict[str, Any]]: "trigger": triggers.MARK_REGENERATION_OF_CONFORMANCE_TESTS, "dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TESTING_INITIALISED.value}", }, - { - "source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}", - "trigger": triggers.MOVE_TO_NEXT_CONFORMANCE_TEST, - "dest": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.PROCESSING_UNIT_TESTS.value}", - "conditions": ["should_run_unit_tests", "implementation_code_was_updated_in_conformance_tests"], - }, { "source": f"{States.IMPLEMENTING_FRID.value}_{States.PROCESSING_CONFORMANCE_TESTS.value}_{States.CONFORMANCE_TEST_ENV_PREPARED.value}", "trigger": triggers.MOVE_TO_NEXT_CONFORMANCE_TEST, From 98ff8320117590e33a5465c9f82bb0d6f8b3af89 Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Mon, 11 May 2026 16:08:56 +0200 Subject: [PATCH 5/9] Refactored the start_conformance_tests_for_frid and code related to conformance test fixing logic. --- .../actions/fix_conformance_test.py | 8 +- .../actions/render_conformance_tests.py | 47 ++- render_machine/render_context.py | 303 +++++++++++++----- render_machine/render_types.py | 62 +++- 4 files changed, 316 insertions(+), 104 deletions(-) diff --git a/render_machine/actions/fix_conformance_test.py b/render_machine/actions/fix_conformance_test.py index 20cae71d..ae3ddbe2 100644 --- a/render_machine/actions/fix_conformance_test.py +++ b/render_machine/actions/fix_conformance_test.py @@ -9,6 +9,7 @@ from render_machine.actions.base_action import BaseAction from render_machine.implementation_code_helpers import ImplementationCodeHelpers from render_machine.render_context import RenderContext +from render_machine.render_types import TestExecutionPhase class FixConformanceTest(BaseAction): @@ -151,7 +152,12 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any | style=console.OUTPUT_STYLE, ) render_context.conformance_tests_running_context.should_prepare_testing_environment = True - render_context.conformance_tests_running_context.implementation_code_was_updated = True + + # Record which test triggered the change and transition to retry phase + ctx = render_context.conformance_tests_running_context + ctx.test_that_triggered_code_change = (ctx.current_testing_module_name, ctx.current_testing_frid) + ctx.execution_phase = TestExecutionPhase.RETRYING_AFTER_CODE_CHANGE + return self.IMPLEMENTATION_CODE_UPDATED, None else: return self.IMPLEMENTATION_CODE_NOT_UPDATED, None diff --git a/render_machine/actions/render_conformance_tests.py b/render_machine/actions/render_conformance_tests.py index 8ea9c457..6453cb02 100644 --- a/render_machine/actions/render_conformance_tests.py +++ b/render_machine/actions/render_conformance_tests.py @@ -8,6 +8,7 @@ from render_machine.actions.base_action import BaseAction from render_machine.implementation_code_helpers import ImplementationCodeHelpers from render_machine.render_context import RenderContext +from render_machine.render_types import AcceptanceTestPhase, TestExecutionPhase class RenderConformanceTests(BaseAction): @@ -20,19 +21,38 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | return self._render_acceptance_test(render_context) def _should_render_conformance_tests(self, render_context: RenderContext) -> bool: - return render_context.conformance_tests_running_context.conformance_test_phase_index == 0 + """Check if we should render full conformance tests (first time) vs just acceptance tests (incremental).""" - def _render_conformance_tests(self, render_context: RenderContext): - if render_context.verbose: - console.info("Implementing test requirements:") - console.print_list( - render_context.conformance_tests_running_context.current_testing_frid_specifications[ - plain_spec.TEST_REQUIREMENTS - ], - style=console.INFO_STYLE, - ) + ctx = render_context.conformance_tests_running_context + + # If we're in regression phase, tests already exist - don't render anything new + if ctx.execution_phase == TestExecutionPhase.RUNNING_REGRESSION: + return True # Return True to skip rendering (conformance tests already exist) + + # Render full conformance tests when: + # 1. NOT_STARTED: First render, before acceptance tests begin + if ctx.acceptance_test_phase == AcceptanceTestPhase.NOT_STARTED: + return True + # 2. NOT_APPLICABLE: No acceptance tests defined, always use full conformance test path + if ctx.acceptance_test_phase == AcceptanceTestPhase.NOT_APPLICABLE: + # Return True so _render_conformance_tests() is called, which will skip if tests already exist + return True + + # 3. All other cases (IN_PROGRESS, COMPLETED): Render acceptance tests incrementally + return False + + def _render_conformance_tests(self, render_context: RenderContext): + # Check if tests already exist (e.g., during regression) - if so, skip rendering if not render_context.conformance_tests_running_context.current_conformance_tests_exist(): + if render_context.verbose: + console.info("Implementing test requirements:") + console.print_list( + render_context.conformance_tests_running_context.current_testing_frid_specifications[ + plain_spec.TEST_REQUIREMENTS + ], + style=console.INFO_STYLE, + ) fr_subfolder_name = render_context.codeplain_api.generate_folder_name_from_functional_requirement( frid=render_context.conformance_tests_running_context.current_testing_frid, module_name=render_context.conformance_tests_running_context.current_testing_module_name, @@ -128,6 +148,10 @@ def _render_conformance_tests(self, render_context: RenderContext): return self.SUCCESSFUL_OUTCOME, None def _render_acceptance_test(self, render_context: RenderContext): + if plain_spec.ACCEPTANCE_TESTS not in render_context.frid_context.specifications: + # If there are no acceptance tests defined, continue. + return self.SUCCESSFUL_OUTCOME, None + _, existing_files_content = ImplementationCodeHelpers.fetch_existing_files(render_context.build_folder) _, memory_files_content = MemoryManager.fetch_memory_files(render_context.memory_manager.memory_folder) ( @@ -140,8 +164,9 @@ def _render_acceptance_test(self, render_context: RenderContext): render_context.conformance_tests_running_context.get_current_conformance_test_folder_name(), ) + # Get the current acceptance test being rendered (completed count is 1-based) acceptance_test = render_context.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][ - render_context.conformance_tests_running_context.conformance_test_phase_index - 1 + render_context.conformance_tests_running_context.acceptance_tests_completed - 1 ] if render_context.verbose: diff --git a/render_machine/render_context.py b/render_machine/render_context.py index 4dd83c1a..5c3ca7dc 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -14,9 +14,11 @@ from render_machine import triggers from render_machine.conformance_tests import CONFORMANCE_TESTS_DEFINITION_FILE_NAME, ConformanceTests from render_machine.render_types import ( + AcceptanceTestPhase, ConformanceTestsRunningContext, FridContext, ScriptExecutionHistory, + TestExecutionPhase, UnitTestsRunningContext, ) @@ -357,104 +359,243 @@ def start_conformance_tests_processing(self): current_testing_module_name=self.module_name, current_testing_frid=self.frid_context.frid, current_testing_frid_specifications=current_frid_specifications, - conformance_test_phase_index=0, fix_attempts=0, conformance_tests_json=self.conformance_tests.get_conformance_tests_json(self.module_name), conformance_tests_render_attempts=0, should_prepare_testing_environment=True, + frid_being_implemented=self.frid_context.frid, ) def finish_conformance_tests_processing(self): self.conformance_tests_running_context = None - def start_conformance_tests_for_frid(self): - if self.conformance_tests_running_context.regenerating_conformance_tests: - if self.verbose: - console.info( - f"Recreating conformance tests for functionality {self.conformance_tests_running_context.current_testing_frid}." - ) + # ========== Helper Methods for Conformance Test Execution ========== + + def _should_run_current_frid_tests(self) -> bool: + """Check if we should run/continue testing the current FRID.""" + ctx = self.conformance_tests_running_context + return ( + ctx.execution_phase == TestExecutionPhase.TESTING_CURRENT_FRID + and ctx.current_testing_module_name == self.module_name + and ctx.current_testing_frid == ctx.frid_being_implemented + ) - existing_conformance_tests_folder = self.conformance_tests_running_context.get_conformance_tests_json( - self.conformance_tests_running_context.current_testing_module_name - ).pop(self.conformance_tests_running_context.current_testing_frid) + def _has_more_acceptance_test_phases(self) -> bool: + """Check if there are more acceptance test phases to run.""" + ctx = self.conformance_tests_running_context - file_utils.delete_folder(existing_conformance_tests_folder["folder_name"]) + if ctx.acceptance_test_phase == AcceptanceTestPhase.NOT_APPLICABLE: + return False + if ctx.acceptance_test_phase == AcceptanceTestPhase.COMPLETED: + return False - self.conformance_tests_running_context.conformance_tests_render_attempts += 1 - self.conformance_tests_running_context.fix_attempts = 0 - self.conformance_tests_running_context.regenerating_conformance_tests = False + acceptance_tests = self.frid_context.specifications.get(plain_spec.ACCEPTANCE_TESTS, []) + return ctx.acceptance_tests_completed < len(acceptance_tests) + + def _start_regression_phase(self): + """Transition to regression testing phase.""" + ctx = self.conformance_tests_running_context + ctx.execution_phase = TestExecutionPhase.RUNNING_REGRESSION + ctx.current_testing_frid = None # Will be set by get_first_conformance_tests_running_context + + def _get_next_test_to_run(self): + """Determine which test to run next based on current phase.""" + ctx = self.conformance_tests_running_context + + if ctx.current_testing_frid is None: + return self.get_first_conformance_tests_running_context() else: - if self.conformance_tests_running_context.implementation_code_was_updated: - self.conformance_tests_running_context.implementation_code_was_updated = False - self.conformance_tests_running_context.regression_run_started = True - self.conformance_tests_running_context.current_testing_frid = None - - # This block handles phase-based rendering for the current FRID being implemented. - # Only runs before regression starts — during regression the current FRID is treated - # as an existing test like any other. - elif ( - not self.conformance_tests_running_context.regression_run_started - and self.conformance_tests_running_context.current_testing_module_name == self.module_name - and self.conformance_tests_running_context.current_testing_frid == self.frid_context.frid - ): - if not self.conformance_tests_running_context.current_conformance_tests_exist(): - # No entry yet — RenderConformanceTests will create it on this action cycle - return + return self.get_next_conformance_tests_running_context() + + def _has_reached_implementation_frid(self) -> bool: + """Check if regression has reached the FRID being implemented.""" + ctx = self.conformance_tests_running_context + return ( + ctx.execution_phase == TestExecutionPhase.RUNNING_REGRESSION + and ctx.current_testing_module_name == self.module_name + and (ctx.current_testing_frid is None or ctx.current_testing_frid == ctx.frid_being_implemented) + ) - if not self.frid_context.specifications.get( - plain_spec.ACCEPTANCE_TESTS - ) or self.conformance_tests_running_context.conformance_test_phase_index == len( - self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS] - ): - # All phases done — start regression run over earlier FRIDs - self.conformance_tests_running_context.regression_run_started = True - self.conformance_tests_running_context.current_testing_frid = None - # fall through to get_first below - else: - if self.conformance_tests_running_context.conformance_test_phase_index == 0: - self.conformance_tests_running_context.current_testing_frid_high_level_implementation_plan = ( - None - ) - - self.conformance_tests_running_context.conformance_test_phase_index += 1 - current_acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][ - : self.conformance_tests_running_context.conformance_test_phase_index - ] - self.conformance_tests_running_context.get_conformance_tests_json( - self.conformance_tests_running_context.current_testing_module_name - )[self.frid_context.frid][plain_spec.ACCEPTANCE_TESTS] = current_acceptance_tests - return - - if self.conformance_tests_running_context.current_testing_frid is None: - self.conformance_tests_running_context = self.get_first_conformance_tests_running_context() + def _setup_test_specifications(self): + """Load specifications for the current test.""" + ctx = self.conformance_tests_running_context + + if ctx.current_testing_module_name == self.module_name: + ctx.current_testing_frid_specifications, _ = plain_spec.get_specifications_for_frid( + self.plain_source_tree, ctx.current_testing_frid + ) + else: + ctx.current_testing_frid_specifications = ctx.get_conformance_tests_json(ctx.current_testing_module_name)[ + ctx.current_testing_frid + ]["functional_requirement"] + + # ========== Phase Handlers ========== + + def _handle_test_regeneration(self): + """Handle regeneration of conformance tests after too many failures.""" + ctx = self.conformance_tests_running_context + + if self.verbose: + console.info(f"Recreating conformance tests for functionality {ctx.current_testing_frid}.") + + existing_folder = ctx.get_conformance_tests_json(ctx.current_testing_module_name).pop(ctx.current_testing_frid) + file_utils.delete_folder(existing_folder["folder_name"]) + + ctx.conformance_tests_render_attempts += 1 + ctx.fix_attempts = 0 + ctx.regenerating_conformance_tests = False + + def _handle_retry_after_code_change(self): + """Re-run the test that failed and triggered a code change.""" + ctx = self.conformance_tests_running_context + + # The test that failed is still in current_testing_frid - just re-run it + self._setup_test_specifications() + + if ctx.current_conformance_tests_exist(): + self.machine.dispatch(triggers.MARK_CONFORMANCE_TESTS_READY) + + def _on_conformance_test_passed_after_retry(self): + """Called when a test passes after being retried due to code changes.""" + ctx = self.conformance_tests_running_context + + if ctx.execution_phase == TestExecutionPhase.RETRYING_AFTER_CODE_CHANGE: + # Test passed after code change - restart regression from the beginning + ctx.test_that_triggered_code_change = None + self._start_regression_phase() + + def _handle_current_frid_testing(self): + """Handle incremental testing of the current FRID being implemented.""" + ctx = self.conformance_tests_running_context + + # Initialize acceptance test phase on first run (before checking if tests exist) + # This prevents duplicate test runs by ensuring the phase is set immediately + if ctx.acceptance_test_phase == AcceptanceTestPhase.NOT_STARTED: + acceptance_tests = self.frid_context.specifications.get(plain_spec.ACCEPTANCE_TESTS) + if not acceptance_tests: + ctx.acceptance_test_phase = AcceptanceTestPhase.NOT_APPLICABLE + # Increment counter immediately to signal "we're starting the test process" + # This prevents re-running the test after it's rendered + ctx.acceptance_tests_completed = 1 else: - self.conformance_tests_running_context = self.get_next_conformance_tests_running_context() - - # Detect regression completion: we've reached the current FRID (don't re-run it) - if self.conformance_tests_running_context.regression_run_started: - current = self.conformance_tests_running_context.current_testing_frid - if self.conformance_tests_running_context.current_testing_module_name == self.module_name and ( - current is None or current == self.frid_context.frid - ): - self.conformance_tests_running_context.current_testing_frid = self.frid_context.frid - self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED) - return - - if self.conformance_tests_running_context.current_testing_module_name == self.module_name: - self.conformance_tests_running_context.current_testing_frid_specifications, _ = ( - plain_spec.get_specifications_for_frid( - self.plain_source_tree, self.conformance_tests_running_context.current_testing_frid - ) - ) + ctx.acceptance_test_phase = AcceptanceTestPhase.IN_PROGRESS + + # Wait for tests to be rendered + if not ctx.current_conformance_tests_exist(): + return + + # Handle case: No acceptance tests + if ctx.acceptance_test_phase == AcceptanceTestPhase.NOT_APPLICABLE: + if ctx.acceptance_tests_completed == 1: + # Test has run once - move to regression + ctx.acceptance_test_phase = AcceptanceTestPhase.COMPLETED + self._start_regression_phase() + self._handle_regression_testing() + return else: - self.conformance_tests_running_context.current_testing_frid_specifications = ( - self.conformance_tests_running_context.get_conformance_tests_json( - self.conformance_tests_running_context.current_testing_module_name - )[self.conformance_tests_running_context.current_testing_frid]["functional_requirement"] - ) + # This shouldn't happen since we set completed=1 during initialization + raise RuntimeError(f"Unexpected state: acceptance_tests_completed={ctx.acceptance_tests_completed}") + + # Handle case: Has acceptance tests + if ctx.acceptance_test_phase == AcceptanceTestPhase.IN_PROGRESS: + if self._has_more_acceptance_test_phases(): + # Run next phase + if ctx.acceptance_tests_completed == 0: + ctx.current_testing_frid_high_level_implementation_plan = None + + ctx.acceptance_tests_completed += 1 + acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][ + : ctx.acceptance_tests_completed + ] + ctx.get_conformance_tests_json(ctx.current_testing_module_name)[self.frid_context.frid][ + plain_spec.ACCEPTANCE_TESTS + ] = acceptance_tests + return + else: + # All phases done - move to regression + ctx.acceptance_test_phase = AcceptanceTestPhase.COMPLETED + self._start_regression_phase() + self._handle_regression_testing() + return + + # Should not reach here + raise RuntimeError(f"Unexpected acceptance test phase: {ctx.acceptance_test_phase}") + + def _handle_regression_testing(self): + """Handle regression testing of all earlier FRIDs.""" + + ctx = self.conformance_tests_running_context + + # Get next test to run + self.conformance_tests_running_context = self._get_next_test_to_run() + + # Check if we've reached the implementation FRID + if self._has_reached_implementation_frid(): + ctx.execution_phase = TestExecutionPhase.COMPLETED + ctx.current_testing_frid = ctx.frid_being_implemented + self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED) + return + + # Set up specs and run test + self._setup_test_specifications() - if self.conformance_tests_running_context.current_conformance_tests_exist(): - self.machine.dispatch(triggers.MARK_CONFORMANCE_TESTS_READY) + if ctx.current_conformance_tests_exist(): + self.machine.dispatch(triggers.MARK_CONFORMANCE_TESTS_READY) + + # ========== Main Conformance Test Orchestration ========== + + def start_conformance_tests_for_frid(self): + """ + Orchestrate conformance test execution. + + Flow: + 1. Handle test regeneration (if needed) + 2. Handle test passed after retry (transition to regression) + 3. Handle code changes (retry failed test) + 4. Handle current FRID testing (incremental phases) + 5. Handle regression testing (all earlier FRIDs) + 6. Detect completion + """ + + ctx = self.conformance_tests_running_context + + # ========== STEP 1: Handle Test Regeneration ========== + if ctx.regenerating_conformance_tests: + self._handle_test_regeneration() + return + + # ========== STEP 2: Test Passed After Retry - Transition to Regression ========== + # This happens when MOVE_TO_NEXT_CONFORMANCE_TEST is triggered after a retry succeeds + if ( + ctx.execution_phase == TestExecutionPhase.RETRYING_AFTER_CODE_CHANGE + and ctx.test_that_triggered_code_change is not None + ): + # The test that had code changes has now passed + self._on_conformance_test_passed_after_retry() + # Fall through to handle regression + + # ========== STEP 3: Handle Code Changes (Retry) ========== + if ctx.execution_phase == TestExecutionPhase.RETRYING_AFTER_CODE_CHANGE: + self._handle_retry_after_code_change() + return + + # ========== STEP 3: Handle Current FRID Testing ========== + if self._should_run_current_frid_tests(): + self._handle_current_frid_testing() + return + + # ========== STEP 4: Handle Regression Testing ========== + if ctx.execution_phase == TestExecutionPhase.RUNNING_REGRESSION: + self._handle_regression_testing() + return + + # ========== STEP 5: Completion ========== + if ctx.execution_phase == TestExecutionPhase.COMPLETED: + self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED) + return + + # Should never reach here + raise RuntimeError(f"Unexpected execution phase: {ctx.execution_phase}") def start_fixing_conformance_tests(self): self.conformance_tests_running_context.fix_attempts += 1 diff --git a/render_machine/render_types.py b/render_machine/render_types.py index c7420fcd..1aef5c02 100644 --- a/render_machine/render_types.py +++ b/render_machine/render_types.py @@ -1,9 +1,42 @@ from dataclasses import dataclass, field +from enum import Enum, auto from typing import Any, Optional import plain_spec +class TestExecutionPhase(Enum): + """Explicit phases of conformance test execution.""" + + # Initial testing of current FRID + TESTING_CURRENT_FRID = auto() + + # Running regression tests on earlier FRIDs + RUNNING_REGRESSION = auto() + + # Re-running a specific test that failed after code change + RETRYING_AFTER_CODE_CHANGE = auto() + + # All tests passed + COMPLETED = auto() + + +class AcceptanceTestPhase(Enum): + """Phases for incremental acceptance test execution.""" + + # No acceptance tests have been run yet + NOT_STARTED = auto() + + # Currently running acceptance tests incrementally + IN_PROGRESS = auto() + + # All acceptance tests completed + COMPLETED = auto() + + # No acceptance tests defined for this FRID + NOT_APPLICABLE = auto() + + @dataclass class FridContext: frid: str @@ -30,11 +63,11 @@ def __init__( conformance_tests_json: dict, conformance_tests_render_attempts: int, current_testing_frid_specifications: Optional[dict[str, list]], - conformance_test_phase_index: int, should_prepare_testing_environment: bool, conflicting_requirement_count: int = 0, conflicting_module_name: Optional[str] = None, conflicting_frid: Optional[str] = None, + frid_being_implemented: Optional[str] = None, ): self.current_testing_module_name = current_testing_module_name self.current_testing_frid = current_testing_frid @@ -42,17 +75,19 @@ def __init__( self._conformance_tests_json = {current_testing_module_name: conformance_tests_json} self.conformance_tests_render_attempts = conformance_tests_render_attempts self.current_testing_frid_specifications = current_testing_frid_specifications - self.conformance_test_phase_index = conformance_test_phase_index self.should_prepare_testing_environment = should_prepare_testing_environment self.conflicting_requirement_count = conflicting_requirement_count self.conflicting_module_name = conflicting_module_name self.conflicting_frid = conflicting_frid - # will be propagated only when: - # - current_testing_frid == frid noqa: E800 - # - conformance_test_phase_index == 0 (conformance tests phase) + + self.execution_phase: TestExecutionPhase = TestExecutionPhase.TESTING_CURRENT_FRID + self.acceptance_test_phase: AcceptanceTestPhase = AcceptanceTestPhase.NOT_STARTED + self.acceptance_tests_completed: int = 0 + self.frid_being_implemented: Optional[str] = frid_being_implemented + self.test_that_triggered_code_change: Optional[tuple[str, str]] = None + self.regenerating_conformance_tests: bool = False - self.implementation_code_was_updated: bool = False - self.regression_run_started: bool = False + self.current_testing_frid_high_level_implementation_plan: Optional[str] = None self.previous_conformance_tests_issue_old: Optional[str] = None self.previous_conformance_tests_issue_frid: Optional[str] = None @@ -91,9 +126,12 @@ def get_current_acceptance_tests(self) -> Optional[list[str]]: def get_current_acceptance_test(self) -> Optional[str]: """Get the current acceptance test text (raw, unformatted).""" - return self.current_testing_frid_specifications[plain_spec.ACCEPTANCE_TESTS][ - self.conformance_test_phase_index - 1 - ] + if plain_spec.ACCEPTANCE_TESTS not in self.current_testing_frid_specifications: + return None + acceptance_tests = self.current_testing_frid_specifications[plain_spec.ACCEPTANCE_TESTS] + if not acceptance_tests or self.acceptance_tests_completed == 0: + return None + return acceptance_tests[self.acceptance_tests_completed - 1] def set_conformance_tests_summary(self, summary: list[dict]): self.get_conformance_tests_json(self.current_testing_module_name)[self.current_testing_frid][ @@ -105,7 +143,9 @@ def get_context_summary(self) -> dict: "current_testing_module_name": self.current_testing_module_name, "current_testing_frid": self.current_testing_frid, "fix_attempts": self.fix_attempts, - "conformance_test_phase_index": self.conformance_test_phase_index, + "execution_phase": self.execution_phase.name, + "acceptance_test_phase": self.acceptance_test_phase.name, + "acceptance_tests_completed": self.acceptance_tests_completed, } From 575e45ec7a4af07b5ca3694cd99778e44ac3a109 Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Mon, 11 May 2026 16:12:21 +0200 Subject: [PATCH 6/9] Removed legacy flags --- tui/state_handlers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tui/state_handlers.py b/tui/state_handlers.py index 8b3aa43d..12b0791f 100644 --- a/tui/state_handlers.py +++ b/tui/state_handlers.py @@ -4,6 +4,7 @@ from typing import Optional from plain2code_events import RenderContextSnapshot +from render_machine.render_types import AcceptanceTestPhase from render_machine.states import States from . import components as tui_components @@ -194,7 +195,9 @@ def handle(self, segments: list[str], snapshot: RenderContextSnapshot, previous_ if segments[2] != States.POSTPROCESSING_CONFORMANCE_TESTS.value: if segments[2] == States.CONFORMANCE_TESTING_INITIALISED.value: - if snapshot.conformance_tests_running_context.conformance_test_phase_index == 0: + phase = snapshot.conformance_tests_running_context.acceptance_test_phase + # Rendering full conformance tests (if there are no acceptance tests available or haven't been started yet) + if phase == AcceptanceTestPhase.NOT_STARTED or phase == AcceptanceTestPhase.NOT_APPLICABLE: rendering_text = f"Rendering conformance tests for functionality {snapshot.conformance_tests_running_context.current_testing_frid}" update_progress_item_substates( self.tui, From 97efcd4c3162efa8f1677cf6ae0a2c8a0b02c92a Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Tue, 12 May 2026 07:59:30 +0200 Subject: [PATCH 7/9] Fixed acceptance tests --- render_machine/render_context.py | 14 +++++++------- tui/state_handlers.py | 8 +++++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/render_machine/render_context.py b/render_machine/render_context.py index 5c3ca7dc..9b48d631 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -468,8 +468,12 @@ def _handle_current_frid_testing(self): """Handle incremental testing of the current FRID being implemented.""" ctx = self.conformance_tests_running_context - # Initialize acceptance test phase on first run (before checking if tests exist) - # This prevents duplicate test runs by ensuring the phase is set immediately + # Wait for tests to be rendered + if not ctx.current_conformance_tests_exist(): + return + + # Initialize acceptance test phase AFTER tests exist and pass + # This ensures full conformance tests run first before acceptance tests if ctx.acceptance_test_phase == AcceptanceTestPhase.NOT_STARTED: acceptance_tests = self.frid_context.specifications.get(plain_spec.ACCEPTANCE_TESTS) if not acceptance_tests: @@ -480,10 +484,6 @@ def _handle_current_frid_testing(self): else: ctx.acceptance_test_phase = AcceptanceTestPhase.IN_PROGRESS - # Wait for tests to be rendered - if not ctx.current_conformance_tests_exist(): - return - # Handle case: No acceptance tests if ctx.acceptance_test_phase == AcceptanceTestPhase.NOT_APPLICABLE: if ctx.acceptance_tests_completed == 1: @@ -507,7 +507,7 @@ def _handle_current_frid_testing(self): acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][ : ctx.acceptance_tests_completed ] - ctx.get_conformance_tests_json(ctx.current_testing_module_name)[self.frid_context.frid][ + ctx.get_conformance_tests_json(ctx.current_testing_module_name)[ctx.current_testing_frid][ plain_spec.ACCEPTANCE_TESTS ] = acceptance_tests return diff --git a/tui/state_handlers.py b/tui/state_handlers.py index 12b0791f..7f74c137 100644 --- a/tui/state_handlers.py +++ b/tui/state_handlers.py @@ -20,15 +20,17 @@ ) -def format_acceptance_test_text(raw_text: str) -> str: +def format_acceptance_test_text(raw_text: str | None) -> str: """Format acceptance test text for display by removing list prefix if present. Args: - raw_text: The raw acceptance test text from specifications + raw_text: The raw acceptance test text from specifications (can be None during state transitions) Returns: - Formatted text with "- " prefix removed if present + Formatted text with "- " prefix removed if present, or empty string if None """ + if raw_text is None: + return "" if raw_text.startswith("- "): return raw_text[2:] return raw_text From cd8d22c09b3c5a5167b5ce5978f4566160c0979d Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Tue, 12 May 2026 09:12:26 +0200 Subject: [PATCH 8/9] Rerunning final test if regression run has failed tests --- render_machine/render_context.py | 28 ++++++++++++++++++++-------- render_machine/render_types.py | 1 + 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/render_machine/render_context.py b/render_machine/render_context.py index 9b48d631..2acd6f3f 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -395,6 +395,11 @@ def _has_more_acceptance_test_phases(self) -> bool: def _start_regression_phase(self): """Transition to regression testing phase.""" ctx = self.conformance_tests_running_context + + # Only reset code_changed flag if starting fresh regression (not restarting after fix) + if ctx.execution_phase != TestExecutionPhase.RETRYING_AFTER_CODE_CHANGE: + ctx.code_changed_during_regression = False + ctx.execution_phase = TestExecutionPhase.RUNNING_REGRESSION ctx.current_testing_frid = None # Will be set by get_first_conformance_tests_running_context @@ -460,7 +465,8 @@ def _on_conformance_test_passed_after_retry(self): ctx = self.conformance_tests_running_context if ctx.execution_phase == TestExecutionPhase.RETRYING_AFTER_CODE_CHANGE: - # Test passed after code change - restart regression from the beginning + # Test passed after code change - mark that code changed and restart regression + ctx.code_changed_during_regression = True ctx.test_that_triggered_code_change = None self._start_regression_phase() @@ -529,17 +535,23 @@ def _handle_regression_testing(self): # Get next test to run self.conformance_tests_running_context = self._get_next_test_to_run() - # Check if we've reached the implementation FRID - if self._has_reached_implementation_frid(): - ctx.execution_phase = TestExecutionPhase.COMPLETED - ctx.current_testing_frid = ctx.frid_being_implemented - self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED) - return - # Set up specs and run test self._setup_test_specifications() if ctx.current_conformance_tests_exist(): + # Check if this is the implementation FRID (last test to run) + if self._has_reached_implementation_frid(): + # Reached implementation FRID - only re-run it if code changed during regression + if ctx.code_changed_during_regression: + # Code changed - run the implementation FRID again to verify no regression + # After it passes, mark as completed on next iteration + ctx.execution_phase = TestExecutionPhase.COMPLETED + else: + # No code changes - skip re-running implementation FRID, mark as completed immediately + ctx.execution_phase = TestExecutionPhase.COMPLETED + self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED) + return + self.machine.dispatch(triggers.MARK_CONFORMANCE_TESTS_READY) # ========== Main Conformance Test Orchestration ========== diff --git a/render_machine/render_types.py b/render_machine/render_types.py index 1aef5c02..a8bbd478 100644 --- a/render_machine/render_types.py +++ b/render_machine/render_types.py @@ -85,6 +85,7 @@ def __init__( self.acceptance_tests_completed: int = 0 self.frid_being_implemented: Optional[str] = frid_being_implemented self.test_that_triggered_code_change: Optional[tuple[str, str]] = None + self.code_changed_during_regression: bool = False self.regenerating_conformance_tests: bool = False From f4ff8b6dab36c83d357b23ca42fc56fcbf98a4ad Mon Sep 17 00:00:00 2001 From: VitjanZ Date: Tue, 12 May 2026 11:45:40 +0200 Subject: [PATCH 9/9] Fixed context order in handle_regression_testing --- render_machine/render_context.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/render_machine/render_context.py b/render_machine/render_context.py index 2acd6f3f..7229fb7f 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -530,11 +530,12 @@ def _handle_current_frid_testing(self): def _handle_regression_testing(self): """Handle regression testing of all earlier FRIDs.""" - ctx = self.conformance_tests_running_context - # Get next test to run self.conformance_tests_running_context = self._get_next_test_to_run() + # Get reference to the updated context + ctx = self.conformance_tests_running_context + # Set up specs and run test self._setup_test_specifications()