From 3ab28ff08f65c06d2cb8f32a68d9b9e408c15a9b Mon Sep 17 00:00:00 2001 From: Jonas Schulte Date: Tue, 20 Jan 2026 13:31:54 +0100 Subject: [PATCH 01/11] updating foxes tests --- pyproject.toml | 2 +- tests/test_foxes.py | 27 +++++++-------------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7243809..099bc51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ classifiers = [ requires-python = ">=3.9,<3.12" dependencies = [ "py_wake>=2.6.5", - "foxes>=1.6.2", + "foxes>=1.7.0", "windIO @ git+https://github.com/EUFlow/windIO.git", "wayve @ git+https://gitlab.kuleuven.be/TFSO-software/wayve@dev_foxes", #"numpy<2", diff --git a/tests/test_foxes.py b/tests/test_foxes.py index ac22881..4e32388 100644 --- a/tests/test_foxes.py +++ b/tests/test_foxes.py @@ -1,7 +1,7 @@ import os from pathlib import Path +from shutil import rmtree -from foxes import Engine, reset_engine from windIO import __path__ as wiop from windIO import validate as validate_yaml @@ -10,30 +10,17 @@ test_path = Path(os.path.dirname(__file__)) windIO_path = Path(wiop[0]) -engine = None - def _run_foxes(wes_dir): assert wes_dir.is_dir(), f"{wes_dir} is not a directory" - global engine - if engine is None: - engine = Engine.new("default", verbosity=0) - engine.initialize() - print("SETTING ENGINE:", engine) - for yaml_input in wes_dir.glob("system.yaml"): - if "_noXYgrid" not in str(yaml_input): - print("\nRUNNING FOXES ON", yaml_input, "\n") - validate_yaml(yaml_input, Path("plant/wind_energy_system")) - output_dir_name = Path("output_test_foxes") - output_dir_name.mkdir(parents=True, exist_ok=True) - try: - run_foxes(yaml_input, output_dir=output_dir_name, engine=None) - except Exception as e: - reset_engine() - engine = None - raise e + print("\nRUNNING FOXES ON", yaml_input, "\n") + validate_yaml(yaml_input, Path("plant/wind_energy_system")) + output_dir_name = Path("output_test_foxes") + output_dir_name.mkdir(parents=True, exist_ok=True) + run_foxes(yaml_input, output_dir=output_dir_name) + rmtree(output_dir_name) def test_foxes_KUL(): From dc2da372bf06fe9e4b44d2758553f06722a72b54 Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 20 Jan 2026 12:59:47 +0100 Subject: [PATCH 02/11] Add test cleanup fixtures and remove global state - Create tests/conftest.py with pytest fixtures for automatic cleanup - Add output_dir fixture using tmp_path with conditional cleanup (preserves output on test failure for debugging) - Add foxes_engine fixture to replace global engine state - Add session-scoped pre-cleanup to remove leftover output directories - Register 'slow' marker for long-running tests - Update test_foxes.py to use fixtures instead of global engine - Update test_pywake.py to use output_dir fixture - Update test_cs.py to use output_dir fixture - Update test_wayve.py to use output_dir fixture and mark as slow Tests now properly clean up after themselves while preserving output on failure for debugging purposes. --- tests/conftest.py | 124 +++++++++++++++++++++++++++++++++++++++++++ tests/test_cs.py | 34 ++++++------ tests/test_foxes.py | 60 ++++++++++----------- tests/test_pywake.py | 25 ++++----- tests/test_wayve.py | 13 ++--- 5 files changed, 185 insertions(+), 71 deletions(-) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..aa81994 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,124 @@ +""" +Pytest configuration and fixtures for WIFA tests. + +Provides: +- Pre-test cleanup of leftover output directories +- Output directory fixtures with conditional cleanup (preserved on failure) +- FOXES engine fixture with proper initialization and teardown +""" + +import shutil +from pathlib import Path + +import pytest +from foxes import Engine, reset_engine + + +# Store test outcomes for conditional cleanup +_test_outcomes = {} + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_makereport(item, call): + """Track test outcomes to conditionally preserve output on failure.""" + outcome = yield + report = outcome.get_result() + if report.when == "call": + _test_outcomes[item.nodeid] = report.failed + + +def pytest_configure(config): + """Register custom markers.""" + config.addinivalue_line("markers", "slow: marks tests as slow (deselect with '-m \"not slow\"')") + + +@pytest.fixture(scope="session", autouse=True) +def cleanup_old_outputs(): + """Remove output directories from previous test runs at session start.""" + patterns = [ + "output_pywake_*", + "output_test_*", + "output", + ] + for pattern in patterns: + for path in Path(".").glob(pattern): + if path.is_dir(): + shutil.rmtree(path) + elif path.is_file(): + path.unlink() + yield + + +@pytest.fixture +def output_dir(request, tmp_path): + """ + Provide a unique temporary output directory for tests. + + Cleans up automatically on test success, preserves on failure for debugging. + """ + yield tmp_path + + # Only clean up if test passed + test_failed = _test_outcomes.get(request.node.nodeid, False) + if not test_failed: + if tmp_path.exists(): + shutil.rmtree(tmp_path) + + +@pytest.fixture +def named_output_dir(request): + """ + Provide a named output directory based on test name. + + Use this when tests need output in the current working directory + (e.g., for Code Saturne integration). + + Cleans up automatically on test success, preserves on failure. + """ + test_name = request.node.name.replace("[", "_").replace("]", "_").rstrip("_") + output_path = Path(f"output_test_{test_name}") + output_path.mkdir(parents=True, exist_ok=True) + + yield output_path + + # Only clean up if test passed + test_failed = _test_outcomes.get(request.node.nodeid, False) + if not test_failed: + if output_path.exists(): + shutil.rmtree(output_path) + + +@pytest.fixture +def cleanup_output_dir(request): + """ + Cleanup fixture for tests that write to the default 'output/' directory. + + Use this when tests can't control their output location (e.g., when YAML + specifies output_folder). Cleans up on success, preserves on failure. + """ + output_path = Path("output") + + yield output_path + + # Only clean up if test passed + test_failed = _test_outcomes.get(request.node.nodeid, False) + if not test_failed: + if output_path.exists(): + shutil.rmtree(output_path) + + +@pytest.fixture +def foxes_engine(): + """ + Provide a fresh FOXES engine instance per test. + + Properly initializes the engine before the test and resets it after, + ensuring no state leaks between tests. + """ + engine = Engine.new("default", verbosity=0) + engine.initialize() + + yield engine + + # Always reset engine after test + reset_engine() diff --git a/tests/test_cs.py b/tests/test_cs.py index 622164d..99df863 100644 --- a/tests/test_cs.py +++ b/tests/test_cs.py @@ -11,51 +11,53 @@ def _run_cs(wes_dir, output_dir): + """Run Code Saturne on all system* files in the given directory.""" i = 1 for yaml_input in wes_dir.glob("system*"): print("\nRUNNING CODE_SATURNE ON", yaml_input, "\n") validate_yaml(yaml_input, Path("plant/wind_energy_system")) + # Create subdirectory for each yaml file within the fixture-provided output_dir + sub_output_dir = output_dir / f"run_{i}" + sub_output_dir.mkdir(parents=True, exist_ok=True) run_code_saturne( yaml_input, test_mode=False, - output_dir="output_test_" + output_dir + "_" + str(i), + output_dir=str(sub_output_dir), ) i += 1 -def test_cs_KUL(): +def test_cs_KUL(output_dir): wes_dir = test_path / "../examples/cases/KUL_LES/wind_energy_system/" - _run_cs(wes_dir, "KUL") + _run_cs(wes_dir, output_dir) -def test_cs_4wts(): +def test_cs_4wts(output_dir): wes_dir = test_path / "../examples/cases/windio_4turbines/wind_energy_system/" - _run_cs(wes_dir, "4wts") + _run_cs(wes_dir, output_dir) -def test_cs_abl(): +def test_cs_abl(output_dir): wes_dir = test_path / "../examples/cases/windio_4turbines_ABL/wind_energy_system/" - _run_cs(wes_dir, "abl") + _run_cs(wes_dir, output_dir) -def test_cs_abl_stable(): +def test_cs_abl_stable(output_dir): wes_dir = ( test_path / "../examples/cases/windio_4turbines_ABL_stable/wind_energy_system/" ) - _run_cs(wes_dir, "abl_stable") + _run_cs(wes_dir, output_dir) -def test_cs_profiles(): +def test_cs_profiles(output_dir): wes_dir = ( test_path / "../examples/cases/windio_4turbines_profiles_stable/wind_energy_system/" ) - _run_cs(wes_dir, "profiles") + _run_cs(wes_dir, output_dir) if __name__ == "__main__": - test_cs_KUL() - test_cs_4wts() - test_cs_abl() - test_cs_abl_stable() - test_cs_profiles() + import pytest + + pytest.main([__file__, "-v"]) diff --git a/tests/test_foxes.py b/tests/test_foxes.py index 4e32388..8e4ae36 100644 --- a/tests/test_foxes.py +++ b/tests/test_foxes.py @@ -11,82 +11,76 @@ windIO_path = Path(wiop[0]) -def _run_foxes(wes_dir): +def _run_foxes(wes_dir, output_dir): + """Run FOXES on all system.yaml files in the given directory.""" assert wes_dir.is_dir(), f"{wes_dir} is not a directory" for yaml_input in wes_dir.glob("system.yaml"): - print("\nRUNNING FOXES ON", yaml_input, "\n") - validate_yaml(yaml_input, Path("plant/wind_energy_system")) - output_dir_name = Path("output_test_foxes") - output_dir_name.mkdir(parents=True, exist_ok=True) - run_foxes(yaml_input, output_dir=output_dir_name) - rmtree(output_dir_name) + if "_noXYgrid" not in str(yaml_input): + print("\nRUNNING FOXES ON", yaml_input, "\n") + validate_yaml(yaml_input, Path("plant/wind_energy_system")) + run_foxes(yaml_input, output_dir=output_dir, engine=None) -def test_foxes_KUL(): +def test_foxes_KUL(foxes_engine, output_dir): wes_dir = test_path / "../examples/cases/KUL_LES/wind_energy_system/" - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_4wts(): +def test_foxes_4wts(foxes_engine, output_dir): wes_dir = test_path / "../examples/cases/windio_4turbines/wind_energy_system/" - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_abl(): +def test_foxes_abl(foxes_engine, output_dir): wes_dir = test_path / "../examples/cases/windio_4turbines_ABL/wind_energy_system/" - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_abl_stable(): +def test_foxes_abl_stable(foxes_engine, output_dir): wes_dir = ( test_path / "../examples/cases/windio_4turbines_ABL_stable/wind_energy_system/" ) - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_profiles(): +def test_foxes_profiles(foxes_engine, output_dir): wes_dir = ( test_path / "../examples/cases/windio_4turbines_profiles_stable/wind_energy_system/" ) - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_heterogeneous_wind_rose_at_turbines(): +def test_foxes_heterogeneous_wind_rose_at_turbines(foxes_engine, output_dir): wes_dir = ( test_path / "../examples/cases/heterogeneous_wind_rose_at_turbines/wind_energy_system/" ) - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_heterogeneous_wind_rose_map(): +def test_foxes_heterogeneous_wind_rose_map(foxes_engine, output_dir): wes_dir = ( test_path / "../examples/cases/heterogeneous_wind_rose_map/wind_energy_system/" ) - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_simple_wind_rose(): +def test_foxes_simple_wind_rose(foxes_engine, output_dir): wes_dir = test_path / "../examples/cases/simple_wind_rose/wind_energy_system/" - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) -def test_foxes_timeseries_with_operating_flag(): +def test_foxes_timeseries_with_operating_flag(foxes_engine, output_dir): wes_dir = ( test_path / "../examples/cases/timeseries_with_operating_flag/wind_energy_system/" ) - _run_foxes(wes_dir) + _run_foxes(wes_dir, output_dir) if __name__ == "__main__": - test_foxes_KUL() - test_foxes_4wts() - test_foxes_abl() - test_foxes_abl_stable() - test_foxes_profiles() - test_foxes_heterogeneous_wind_rose_at_turbines() - test_foxes_heterogeneous_wind_rose_map() - test_foxes_simple_wind_rose() + import pytest + + pytest.main([__file__, "-v"]) diff --git a/tests/test_pywake.py b/tests/test_pywake.py index 3c01eb2..77bb790 100644 --- a/tests/test_pywake.py +++ b/tests/test_pywake.py @@ -50,7 +50,7 @@ def four_turbine_site(config_params): return wfm(x, y, ws=ws, wd=wd, time=True), config_name -def test_pywake_KUL(): +def test_pywake_KUL(output_dir): yaml_input = ( test_path / "../examples/cases/KUL_LES/wind_energy_system/system_pywake.yaml" ) @@ -59,10 +59,7 @@ def test_pywake_KUL(): validate_yaml(yaml_input, Path("plant/wind_energy_system")) # compute AEP (next step is to return a richer set of outputs) - output_dir_name = "output_pywake_4wts" - Path(output_dir_name).mkdir(parents=True, exist_ok=True) - pywake_aep = run_pywake(yaml_input, output_dir=output_dir_name) - # print(pywake_aep) + pywake_aep = run_pywake(yaml_input, output_dir=output_dir) # Check result pywake_aep_expected = 7515.2 @@ -87,7 +84,7 @@ def config_params(request): return request.param -def test_pywake_4wts(four_turbine_site): +def test_pywake_4wts(four_turbine_site, output_dir): wfm, config_name = four_turbine_site yaml_input = ( @@ -98,17 +95,14 @@ def test_pywake_4wts(four_turbine_site): validate_yaml(yaml_input, Path("plant/wind_energy_system")) # compute AEP (next step is to return a richer set of outputs) - output_dir_name = "output_pywake_4wts" - Path(output_dir_name).mkdir(parents=True, exist_ok=True) - pywake_aep = run_pywake(yaml_input, output_dir=output_dir_name) - # print(pywake_aep) + pywake_aep = run_pywake(yaml_input, output_dir=output_dir) # Check result pywake_aep_expected = wfm.aep().sum() npt.assert_array_almost_equal(pywake_aep, pywake_aep_expected, 0) -def test_pywake_4wts_operating_flag(): +def test_pywake_4wts_operating_flag(output_dir): x = [0, 1248.1, 2496.2, 3744.3] y = [0, 0, 0, 0] ws = [10.0910225, 10.233016, 8.797999, 9.662098, 9.78371, 10.307792] @@ -148,10 +142,7 @@ def test_pywake_4wts_operating_flag(): validate_yaml(yaml_input, Path("plant/wind_energy_system")) # compute AEP (next step is to return a richer set of outputs) - output_dir_name = "output_pywake_4wts" - Path(output_dir_name).mkdir(parents=True, exist_ok=True) - pywake_aep = run_pywake(yaml_input, output_dir=output_dir_name) - # print(pywake_aep) + pywake_aep = run_pywake(yaml_input, output_dir=output_dir) # Check result pywake_aep_expected = res.aep().sum() @@ -181,7 +172,9 @@ def test_pywake_4wts_operating_flag(): # fmt: on -def test_simple_wind_rose(): +def test_simple_wind_rose(cleanup_output_dir): + # Note: This test uses the output_folder from the YAML ("output/"), not a fixture. + # The cleanup_output_dir fixture handles cleanup of "output/". _ = run_pywake( test_path / "../examples/cases/simple_wind_rose/wind_energy_system/system.yaml" ) diff --git a/tests/test_wayve.py b/tests/test_wayve.py index 902edf0..c418b06 100644 --- a/tests/test_wayve.py +++ b/tests/test_wayve.py @@ -1,6 +1,7 @@ import os from pathlib import Path +import pytest from windIO import __path__ as wiop from windIO import validate as validate_yaml @@ -10,16 +11,16 @@ windIO_path = Path(wiop[0]) -# @pytest.mark.skip() -def test_wayve_4wts(): +@pytest.mark.slow +def test_wayve_4wts(output_dir): yaml_input = ( test_path / "../examples/cases/windio_4turbines/wind_energy_system/system.yaml" ) validate_yaml(yaml_input, Path("plant/wind_energy_system")) - output_dir_name = Path("output_test_wayve") - output_dir_name.mkdir(parents=True, exist_ok=True) - run_wayve(yaml_input, output_dir=output_dir_name, debug_mode=True) + run_wayve(yaml_input, output_dir=output_dir, debug_mode=True) if __name__ == "__main__": - test_wayve_4wts() + import pytest + + pytest.main([__file__, "-v"]) From e78313ce3e77aef7204df4323fe16833b3ef392e Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 20 Jan 2026 13:07:13 +0100 Subject: [PATCH 03/11] black --- tests/conftest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index aa81994..76c3542 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,7 +13,6 @@ import pytest from foxes import Engine, reset_engine - # Store test outcomes for conditional cleanup _test_outcomes = {} @@ -29,7 +28,9 @@ def pytest_runtest_makereport(item, call): def pytest_configure(config): """Register custom markers.""" - config.addinivalue_line("markers", "slow: marks tests as slow (deselect with '-m \"not slow\"')") + config.addinivalue_line( + "markers", "slow: marks tests as slow (deselect with '-m \"not slow\"')" + ) @pytest.fixture(scope="session", autouse=True) From 1fa81e1c1e6ce6c1bd7120c468bd68f2a8299ba3 Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 20 Jan 2026 13:15:01 +0100 Subject: [PATCH 04/11] handle foxes versions --- tests/conftest.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 76c3542..2844865 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,13 @@ from pathlib import Path import pytest -from foxes import Engine, reset_engine +from foxes import Engine + +# Handle different foxes versions - reset_engine location varies +try: + from foxes import reset_engine +except ImportError: + from foxes.core import reset_engine # Store test outcomes for conditional cleanup _test_outcomes = {} From e1d9b024b8ecf7d49c1cc42455f8c7c807c11faa Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 20 Jan 2026 13:23:03 +0100 Subject: [PATCH 05/11] foxes versions --- tests/conftest.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 2844865..91df20b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -17,7 +17,10 @@ try: from foxes import reset_engine except ImportError: - from foxes.core import reset_engine + try: + from foxes.core import reset_engine + except ImportError: + from foxes.core.engine import reset_engine # Store test outcomes for conditional cleanup _test_outcomes = {} From 5e069dc37c157de1253a75f293997eb5cb6ab2f3 Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 20 Jan 2026 13:26:22 +0100 Subject: [PATCH 06/11] foxes versions --- tests/conftest.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 91df20b..4afc21b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -20,7 +20,13 @@ try: from foxes.core import reset_engine except ImportError: - from foxes.core.engine import reset_engine + try: + from foxes.core.engine import reset_engine + except ImportError: + # Older foxes versions don't have reset_engine - use no-op + def reset_engine(): + pass + # Store test outcomes for conditional cleanup _test_outcomes = {} From 6f91354a4c9458172f4805b7c25e9a5de45539ca Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 20 Jan 2026 13:55:09 +0100 Subject: [PATCH 07/11] Fix tests --- tests/conftest.py | 4 +++- tests/test_cs.py | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 4afc21b..5b0e2e3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -132,7 +132,9 @@ def foxes_engine(): ensuring no state leaks between tests. """ engine = Engine.new("default", verbosity=0) - engine.initialize() + # initialize() only exists in newer foxes versions + if hasattr(engine, "initialize"): + engine.initialize() yield engine diff --git a/tests/test_cs.py b/tests/test_cs.py index 99df863..8aa51fb 100644 --- a/tests/test_cs.py +++ b/tests/test_cs.py @@ -16,9 +16,8 @@ def _run_cs(wes_dir, output_dir): for yaml_input in wes_dir.glob("system*"): print("\nRUNNING CODE_SATURNE ON", yaml_input, "\n") validate_yaml(yaml_input, Path("plant/wind_energy_system")) - # Create subdirectory for each yaml file within the fixture-provided output_dir + # Pass subdirectory path - run_code_saturne will create it sub_output_dir = output_dir / f"run_{i}" - sub_output_dir.mkdir(parents=True, exist_ok=True) run_code_saturne( yaml_input, test_mode=False, From 2906526c6882dface72c8462fa45f689c551fe1c Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 20 Jan 2026 14:07:37 +0100 Subject: [PATCH 08/11] use default foxes engine --- tests/conftest.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5b0e2e3..9678795 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,6 @@ from pathlib import Path import pytest -from foxes import Engine # Handle different foxes versions - reset_engine location varies try: @@ -126,17 +125,12 @@ def cleanup_output_dir(request): @pytest.fixture def foxes_engine(): """ - Provide a fresh FOXES engine instance per test. + Ensure FOXES engine state is reset after each test. - Properly initializes the engine before the test and resets it after, - ensuring no state leaks between tests. + Lets foxes use its default engine, then resets state after the test + to prevent leakage between tests. """ - engine = Engine.new("default", verbosity=0) - # initialize() only exists in newer foxes versions - if hasattr(engine, "initialize"): - engine.initialize() + yield None - yield engine - - # Always reset engine after test + # Reset engine state after test reset_engine() From d5359035982a30af19f1eab2b1a5b32a335f9b86 Mon Sep 17 00:00:00 2001 From: btol Date: Thu, 22 Jan 2026 14:05:26 +0100 Subject: [PATCH 09/11] Simplify foxes engine handling * Ensure run_pywake correctly uses output_dir argument --- tests/conftest.py | 14 -------------- tests/test_foxes.py | 18 +++++++++--------- wifa/pywake_api.py | 17 ++++++++++------- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 9678795..bdaf9c1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -120,17 +120,3 @@ def cleanup_output_dir(request): if not test_failed: if output_path.exists(): shutil.rmtree(output_path) - - -@pytest.fixture -def foxes_engine(): - """ - Ensure FOXES engine state is reset after each test. - - Lets foxes use its default engine, then resets state after the test - to prevent leakage between tests. - """ - yield None - - # Reset engine state after test - reset_engine() diff --git a/tests/test_foxes.py b/tests/test_foxes.py index 8e4ae36..1f2c1a0 100644 --- a/tests/test_foxes.py +++ b/tests/test_foxes.py @@ -22,29 +22,29 @@ def _run_foxes(wes_dir, output_dir): run_foxes(yaml_input, output_dir=output_dir, engine=None) -def test_foxes_KUL(foxes_engine, output_dir): +def test_foxes_KUL(output_dir): wes_dir = test_path / "../examples/cases/KUL_LES/wind_energy_system/" _run_foxes(wes_dir, output_dir) -def test_foxes_4wts(foxes_engine, output_dir): +def test_foxes_4wts(output_dir): wes_dir = test_path / "../examples/cases/windio_4turbines/wind_energy_system/" _run_foxes(wes_dir, output_dir) -def test_foxes_abl(foxes_engine, output_dir): +def test_foxes_abl(output_dir): wes_dir = test_path / "../examples/cases/windio_4turbines_ABL/wind_energy_system/" _run_foxes(wes_dir, output_dir) -def test_foxes_abl_stable(foxes_engine, output_dir): +def test_foxes_abl_stable(output_dir): wes_dir = ( test_path / "../examples/cases/windio_4turbines_ABL_stable/wind_energy_system/" ) _run_foxes(wes_dir, output_dir) -def test_foxes_profiles(foxes_engine, output_dir): +def test_foxes_profiles(output_dir): wes_dir = ( test_path / "../examples/cases/windio_4turbines_profiles_stable/wind_energy_system/" @@ -52,7 +52,7 @@ def test_foxes_profiles(foxes_engine, output_dir): _run_foxes(wes_dir, output_dir) -def test_foxes_heterogeneous_wind_rose_at_turbines(foxes_engine, output_dir): +def test_foxes_heterogeneous_wind_rose_at_turbines(output_dir): wes_dir = ( test_path / "../examples/cases/heterogeneous_wind_rose_at_turbines/wind_energy_system/" @@ -60,19 +60,19 @@ def test_foxes_heterogeneous_wind_rose_at_turbines(foxes_engine, output_dir): _run_foxes(wes_dir, output_dir) -def test_foxes_heterogeneous_wind_rose_map(foxes_engine, output_dir): +def test_foxes_heterogeneous_wind_rose_map(output_dir): wes_dir = ( test_path / "../examples/cases/heterogeneous_wind_rose_map/wind_energy_system/" ) _run_foxes(wes_dir, output_dir) -def test_foxes_simple_wind_rose(foxes_engine, output_dir): +def test_foxes_simple_wind_rose(output_dir): wes_dir = test_path / "../examples/cases/simple_wind_rose/wind_energy_system/" _run_foxes(wes_dir, output_dir) -def test_foxes_timeseries_with_operating_flag(foxes_engine, output_dir): +def test_foxes_timeseries_with_operating_flag(output_dir): wes_dir = ( test_path / "../examples/cases/timeseries_with_operating_flag/wind_energy_system/" diff --git a/wifa/pywake_api.py b/wifa/pywake_api.py index 1c42edb..584d32c 100644 --- a/wifa/pywake_api.py +++ b/wifa/pywake_api.py @@ -97,7 +97,7 @@ def weighted_quantile( return np.interp(quantiles, weighted_quantiles, values) -def run_pywake(yamlFile, output_dir="output"): +def run_pywake(yamlFile, output_dir=None): from py_wake import NOJ, BastankhahGaussian, HorizontalGrid from py_wake.deficit_models import SelfSimilarityDeficit2020 from py_wake.deficit_models.fuga import FugaDeficit @@ -179,12 +179,15 @@ def dict_to_site(resource_dict): else: system_dat = yamlFile - # output_dir priority: 1) yaml file, 2) function argument, 3) default - output_dir = str( - system_dat["attributes"] - .get("model_outputs_specification", {}) - .get("output_folder", output_dir) - ) + # output_dir priority: 1) function argument, 2) yaml file, 3) default "output" + if output_dir is None: + output_dir = str( + system_dat["attributes"] + .get("model_outputs_specification", {}) + .get("output_folder", "output") + ) + else: + output_dir = str(output_dir) Path(output_dir).mkdir(parents=True, exist_ok=True) From 9c0376e04cf13c7b2e561be5c3bd4238c07977f2 Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 10 Feb 2026 13:49:05 +0100 Subject: [PATCH 10/11] Clean up test files Remove unused reset_engine import fallback from conftest, remove _noXYgrid filter and redundant engine=None arg in test_foxes, and remove if __name__ blocks from test modules. Co-Authored-By: Claude Opus 4.6 --- tests/conftest.py | 15 --------------- tests/test_cs.py | 6 ------ tests/test_foxes.py | 13 +++---------- tests/test_wayve.py | 6 ------ 4 files changed, 3 insertions(+), 37 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index bdaf9c1..b03ae58 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,6 @@ Provides: - Pre-test cleanup of leftover output directories - Output directory fixtures with conditional cleanup (preserved on failure) -- FOXES engine fixture with proper initialization and teardown """ import shutil @@ -12,20 +11,6 @@ import pytest -# Handle different foxes versions - reset_engine location varies -try: - from foxes import reset_engine -except ImportError: - try: - from foxes.core import reset_engine - except ImportError: - try: - from foxes.core.engine import reset_engine - except ImportError: - # Older foxes versions don't have reset_engine - use no-op - def reset_engine(): - pass - # Store test outcomes for conditional cleanup _test_outcomes = {} diff --git a/tests/test_cs.py b/tests/test_cs.py index 8aa51fb..e778edf 100644 --- a/tests/test_cs.py +++ b/tests/test_cs.py @@ -54,9 +54,3 @@ def test_cs_profiles(output_dir): / "../examples/cases/windio_4turbines_profiles_stable/wind_energy_system/" ) _run_cs(wes_dir, output_dir) - - -if __name__ == "__main__": - import pytest - - pytest.main([__file__, "-v"]) diff --git a/tests/test_foxes.py b/tests/test_foxes.py index 1f2c1a0..dff51a0 100644 --- a/tests/test_foxes.py +++ b/tests/test_foxes.py @@ -16,10 +16,9 @@ def _run_foxes(wes_dir, output_dir): assert wes_dir.is_dir(), f"{wes_dir} is not a directory" for yaml_input in wes_dir.glob("system.yaml"): - if "_noXYgrid" not in str(yaml_input): - print("\nRUNNING FOXES ON", yaml_input, "\n") - validate_yaml(yaml_input, Path("plant/wind_energy_system")) - run_foxes(yaml_input, output_dir=output_dir, engine=None) + print("\nRUNNING FOXES ON", yaml_input, "\n") + validate_yaml(yaml_input, Path("plant/wind_energy_system")) + run_foxes(yaml_input, output_dir=output_dir) def test_foxes_KUL(output_dir): @@ -78,9 +77,3 @@ def test_foxes_timeseries_with_operating_flag(output_dir): / "../examples/cases/timeseries_with_operating_flag/wind_energy_system/" ) _run_foxes(wes_dir, output_dir) - - -if __name__ == "__main__": - import pytest - - pytest.main([__file__, "-v"]) diff --git a/tests/test_wayve.py b/tests/test_wayve.py index c418b06..07483e3 100644 --- a/tests/test_wayve.py +++ b/tests/test_wayve.py @@ -18,9 +18,3 @@ def test_wayve_4wts(output_dir): ) validate_yaml(yaml_input, Path("plant/wind_energy_system")) run_wayve(yaml_input, output_dir=output_dir, debug_mode=True) - - -if __name__ == "__main__": - import pytest - - pytest.main([__file__, "-v"]) From 77bdcabf304051cdb87618ccb2b9861ce9bca5b2 Mon Sep 17 00:00:00 2001 From: btol Date: Tue, 10 Feb 2026 14:07:17 +0100 Subject: [PATCH 11/11] Fix pre-commit issues Fix duplicate key in analysis_US.yaml (run_partition -> mesh_partition) and fix isort blank line in conftest.py. Co-Authored-By: Claude Opus 4.6 --- examples/cases/KUL_LES/wind_energy_system/analysis_US.yaml | 2 +- tests/conftest.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/cases/KUL_LES/wind_energy_system/analysis_US.yaml b/examples/cases/KUL_LES/wind_energy_system/analysis_US.yaml index dca8fcc..a6ca679 100644 --- a/examples/cases/KUL_LES/wind_energy_system/analysis_US.yaml +++ b/examples/cases/KUL_LES/wind_energy_system/analysis_US.yaml @@ -64,7 +64,7 @@ HPC_config: mesh_node_number: 2 mesh_ntasks_per_node: 48 mesh_wall_time_hours: 1 - run_partition: "" + mesh_partition: "" # wckey: "" diff --git a/tests/conftest.py b/tests/conftest.py index b03ae58..ba3e084 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,6 @@ import pytest - # Store test outcomes for conditional cleanup _test_outcomes = {}