Skip to content

Commit ed89170

Browse files
bpkrothpre-commit-ci[bot]motus
authored
Refactor some test fixtures for better reuse so we can test loading Scheduler config examples (#981)
# Pull Request ## Title Refactor some test fixtures for better reuse so we can test loading Scheduler config examples ______________________________________________________________________ ## Description - Moves temporary file based sqlite Storage fixture to a reusable location. - Move Optimizer fixtures to reusable location following Storage fixtures pattern. - Uses both in setting up TrialRunner fixtures for testing Scheduler config examples. - Also be sure to load all test configs too. ______________________________________________________________________ ## Type of Change - 🔄 Refactor - 🧪 Tests ______________________________________________________________________ ## Testing - Introduces new CI test for Scheduler configs that follows the usual pattern for other objects (Storage, Optimizer, Environments, Services, etc.) ______________________________________________________________________ ## Additional Notes (optional) - Split out from #980, #973 ______________________________________________________________________ --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sergiy Matusevych <sergiym@microsoft.com>
1 parent 069452b commit ed89170

File tree

13 files changed

+458
-238
lines changed

13 files changed

+458
-238
lines changed

mlos_bench/mlos_bench/tests/config/environments/test_load_environment_config_examples.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from mlos_bench.environments.base_environment import Environment
1212
from mlos_bench.environments.composite_env import CompositeEnv
1313
from mlos_bench.services.config_persistence import ConfigPersistenceService
14-
from mlos_bench.tests.config import locate_config_examples
14+
from mlos_bench.tests.config import BUILTIN_TEST_CONFIG_PATH, locate_config_examples
1515
from mlos_bench.tunables.tunable_groups import TunableGroups
1616

1717
_LOG = logging.getLogger(__name__)
@@ -39,6 +39,14 @@ def filter_configs(configs_to_filter: list[str]) -> list[str]:
3939
)
4040
assert configs
4141

42+
test_configs = locate_config_examples(
43+
BUILTIN_TEST_CONFIG_PATH,
44+
CONFIG_TYPE,
45+
filter_configs,
46+
)
47+
assert test_configs
48+
configs.extend(test_configs)
49+
4250

4351
@pytest.mark.parametrize("config_path", configs)
4452
def test_load_environment_config_examples(

mlos_bench/mlos_bench/tests/config/experiments/experiment_test_config.jsonc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
"resourceGroup": "mlos-autotuning-test-rg",
1616
"location": "eastus",
1717
"vmName": "vmTestName",
18+
"ssh_username": "testuser",
19+
"ssh_priv_key_path": "/home/testuser/.ssh/id_rsa",
20+
"ssh_hostname": "${vmName}",
21+
"ssh_port": 22,
1822
"tunable_params_map": {
1923
"linux-runtime": ["linux-scheduler", "linux-swap"],
2024
"linux-boot": ["linux-kernel-boot"],

mlos_bench/mlos_bench/tests/config/optimizers/test_load_optimizer_config_examples.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from mlos_bench.config.schemas import ConfigSchema
1111
from mlos_bench.optimizers.base_optimizer import Optimizer
1212
from mlos_bench.services.config_persistence import ConfigPersistenceService
13-
from mlos_bench.tests.config import locate_config_examples
13+
from mlos_bench.tests.config import BUILTIN_TEST_CONFIG_PATH, locate_config_examples
1414
from mlos_bench.tunables.tunable_groups import TunableGroups
1515
from mlos_bench.util import get_class_from_name
1616

@@ -34,6 +34,14 @@ def filter_configs(configs_to_filter: list[str]) -> list[str]:
3434
)
3535
assert configs
3636

37+
test_configs = locate_config_examples(
38+
BUILTIN_TEST_CONFIG_PATH,
39+
CONFIG_TYPE,
40+
filter_configs,
41+
)
42+
# assert test_configs
43+
configs.extend(test_configs)
44+
3745

3846
@pytest.mark.parametrize("config_path", configs)
3947
def test_load_optimizer_config_examples(
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
#
5+
"""Unit tests for the mlos_bench Scheduler configs."""
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
#
5+
"""
6+
Pytest fixtures for Scheduler config tests.
7+
8+
Provides fixtures for creating multiple TrialRunner instances using the mock environment
9+
config.
10+
"""
11+
12+
from importlib.resources import files
13+
14+
import pytest
15+
16+
from mlos_bench.schedulers.trial_runner import TrialRunner
17+
from mlos_bench.services.config_persistence import ConfigPersistenceService
18+
from mlos_bench.util import path_join
19+
20+
# pylint: disable=redefined-outer-name
21+
22+
TRIAL_RUNNERS_COUNT = 4
23+
24+
25+
@pytest.fixture
26+
def mock_env_config_path() -> str:
27+
"""
28+
Returns the absolute path to the mock environment configuration file.
29+
30+
This file is used to create TrialRunner instances for testing.
31+
"""
32+
# Use the files() routine to locate the file relative to this directory
33+
return path_join(
34+
str(files("mlos_bench.config").joinpath("environments", "mock", "mock_env.jsonc")),
35+
abs_path=True,
36+
)
37+
38+
39+
@pytest.fixture
40+
def trial_runners(
41+
config_loader_service: ConfigPersistenceService,
42+
mock_env_config_path: str,
43+
) -> list[TrialRunner]:
44+
"""
45+
Fixture that returns a list of TrialRunner instances using the mock environment
46+
config.
47+
48+
Returns
49+
-------
50+
list[TrialRunner]
51+
List of TrialRunner instances created from the mock environment config.
52+
"""
53+
return TrialRunner.create_from_json(
54+
config_loader=config_loader_service,
55+
env_json=mock_env_config_path,
56+
num_trial_runners=TRIAL_RUNNERS_COUNT,
57+
)
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
#
5+
"""Tests for loading scheduler config examples."""
6+
import logging
7+
8+
import pytest
9+
10+
import mlos_bench.tests.optimizers.fixtures
11+
import mlos_bench.tests.storage.sql.fixtures
12+
from mlos_bench.config.schemas.config_schemas import ConfigSchema
13+
from mlos_bench.optimizers.mock_optimizer import MockOptimizer
14+
from mlos_bench.schedulers.base_scheduler import Scheduler
15+
from mlos_bench.schedulers.trial_runner import TrialRunner
16+
from mlos_bench.services.config_persistence import ConfigPersistenceService
17+
from mlos_bench.storage.sql.storage import SqlStorage
18+
from mlos_bench.tests.config import BUILTIN_TEST_CONFIG_PATH, locate_config_examples
19+
from mlos_bench.util import get_class_from_name
20+
21+
mock_opt = mlos_bench.tests.optimizers.fixtures.mock_opt
22+
storage = mlos_bench.tests.storage.sql.fixtures.storage
23+
24+
25+
_LOG = logging.getLogger(__name__)
26+
_LOG.setLevel(logging.DEBUG)
27+
28+
# pylint: disable=redefined-outer-name
29+
30+
# Get the set of configs to test.
31+
CONFIG_TYPE = "schedulers"
32+
33+
34+
def filter_configs(configs_to_filter: list[str]) -> list[str]:
35+
"""If necessary, filter out json files that aren't for the module we're testing."""
36+
return configs_to_filter
37+
38+
39+
configs = locate_config_examples(
40+
ConfigPersistenceService.BUILTIN_CONFIG_PATH,
41+
CONFIG_TYPE,
42+
filter_configs,
43+
)
44+
assert configs
45+
46+
test_configs = locate_config_examples(
47+
BUILTIN_TEST_CONFIG_PATH,
48+
CONFIG_TYPE,
49+
filter_configs,
50+
)
51+
# assert test_configs
52+
configs.extend(test_configs)
53+
54+
55+
@pytest.mark.parametrize("config_path", configs)
56+
def test_load_scheduler_config_examples(
57+
config_loader_service: ConfigPersistenceService,
58+
config_path: str,
59+
mock_env_config_path: str,
60+
trial_runners: list[TrialRunner],
61+
storage: SqlStorage,
62+
mock_opt: MockOptimizer,
63+
) -> None:
64+
"""Tests loading a config example."""
65+
# pylint: disable=too-many-arguments,too-many-positional-arguments
66+
config = config_loader_service.load_config(config_path, ConfigSchema.SCHEDULER)
67+
assert isinstance(config, dict)
68+
cls = get_class_from_name(config["class"])
69+
assert issubclass(cls, Scheduler)
70+
global_config = {
71+
# Required configs generally provided by the Launcher.
72+
"experiment_id": f"test_experiment_{__name__}",
73+
"trial_id": 1,
74+
}
75+
# Make an instance of the class based on the config.
76+
scheduler_inst = config_loader_service.build_scheduler(
77+
config=config,
78+
global_config=global_config,
79+
trial_runners=trial_runners,
80+
optimizer=mock_opt,
81+
storage=storage,
82+
root_env_config=mock_env_config_path,
83+
)
84+
assert scheduler_inst is not None
85+
assert isinstance(scheduler_inst, cls)

mlos_bench/mlos_bench/tests/config/services/test_load_service_config_examples.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from mlos_bench.config.schemas.config_schemas import ConfigSchema
1111
from mlos_bench.services.base_service import Service
1212
from mlos_bench.services.config_persistence import ConfigPersistenceService
13-
from mlos_bench.tests.config import locate_config_examples
13+
from mlos_bench.tests.config import BUILTIN_TEST_CONFIG_PATH, locate_config_examples
1414

1515
_LOG = logging.getLogger(__name__)
1616
_LOG.setLevel(logging.DEBUG)
@@ -40,6 +40,14 @@ def predicate(config_path: str) -> bool:
4040
)
4141
assert configs
4242

43+
test_configs = locate_config_examples(
44+
BUILTIN_TEST_CONFIG_PATH,
45+
CONFIG_TYPE,
46+
filter_configs,
47+
)
48+
assert test_configs
49+
configs.extend(test_configs)
50+
4351

4452
@pytest.mark.parametrize("config_path", configs)
4553
def test_load_service_config_examples(

mlos_bench/mlos_bench/tests/config/storage/test_load_storage_config_examples.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from mlos_bench.config.schemas.config_schemas import ConfigSchema
1111
from mlos_bench.services.config_persistence import ConfigPersistenceService
1212
from mlos_bench.storage.base_storage import Storage
13-
from mlos_bench.tests.config import locate_config_examples
13+
from mlos_bench.tests.config import BUILTIN_TEST_CONFIG_PATH, locate_config_examples
1414
from mlos_bench.util import get_class_from_name
1515

1616
_LOG = logging.getLogger(__name__)
@@ -33,6 +33,14 @@ def filter_configs(configs_to_filter: list[str]) -> list[str]:
3333
)
3434
assert configs
3535

36+
test_configs = locate_config_examples(
37+
BUILTIN_TEST_CONFIG_PATH,
38+
CONFIG_TYPE,
39+
filter_configs,
40+
)
41+
# assert test_configs
42+
configs.extend(test_configs)
43+
3644

3745
@pytest.mark.parametrize("config_path", configs)
3846
def test_load_storage_config_examples(

0 commit comments

Comments
 (0)