Skip to content

Commit cdec5aa

Browse files
Add tests for experiment result
1 parent 6493d48 commit cdec5aa

File tree

3 files changed

+152
-5
lines changed

3 files changed

+152
-5
lines changed

lib/ramble/ramble/test/end_to_end/experiment_hashes.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,17 @@ def test_experiment_hashes(mutable_config, mutable_mock_workspace_path, workspac
6161
with open(experiment_inventory) as f:
6262
data = sjson.load(f)
6363

64-
assert "application_definition" in data
65-
assert data["application_definition"] != ""
66-
assert data["application_definition"] is not None
64+
assert "object_definitions" in data
65+
assert data["object_definitions"] is not None
66+
assert data["object_definitions"] != []
67+
68+
found_app = False
69+
for definition in data["object_definitions"]:
70+
if definition["type"] == "applications":
71+
found_app = True
72+
assert definition["digest"] != ""
73+
assert definition["digest"] is not None
74+
assert found_app
6775

6876
# Test Attributes
6977
expected_attrs = {"variables", "modifiers", "env_vars", "internals", "chained_experiments"}

lib/ramble/ramble/test/experiment_result.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,25 @@
88

99
"""Tests on the ExperimentResult class"""
1010

11+
import pytest
12+
1113
from ramble.experiment_result import ExperimentResult
1214

1315

14-
def test_to_dict(mutable_mock_apps_repo):
16+
@pytest.fixture
17+
def mock_workspace():
18+
class MockWorkspace:
19+
def __init__(self):
20+
self.path = "/mock/workspace/path"
21+
self.name = "mock_workspace"
22+
23+
def get_path(self):
24+
return self.path
25+
26+
return MockWorkspace()
27+
28+
29+
def test_to_dict(mutable_mock_apps_repo, mock_workspace):
1530
basic_app_inst = mutable_mock_apps_repo.get("basic")
1631
basic_app_inst.set_variables_and_variants(
1732
{"workload_name": "test_wl", "experiment_status": "placeholder", "test_var": "my_var"},
@@ -20,7 +35,7 @@ def test_to_dict(mutable_mock_apps_repo):
2035
)
2136
basic_app_inst.set_status("UNKNOWN")
2237
exp_res = ExperimentResult(basic_app_inst)
23-
exp_res.finalize()
38+
exp_res.finalize(mock_workspace)
2439
res_dict = exp_res.to_dict()
2540

2641
assert "name" in res_dict
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Copyright 2022-2025 The Ramble Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
# option. This file may not be copied, modified, or distributed
7+
# except according to those terms.
8+
9+
"""
10+
Tests for the experiment_result module.
11+
"""
12+
13+
import os
14+
import time
15+
16+
import pytest
17+
18+
from ramble.experiment_result import ExperimentResult
19+
from ramble.util.file_util import get_newest_experiment_file
20+
21+
# pylint: disable=protected-access
22+
23+
24+
@pytest.fixture
25+
def experiment_result(tmpdir):
26+
"""Fixture for an ExperimentResult object."""
27+
app_inst = mock_app_inst(tmpdir)
28+
result = ExperimentResult(app_inst)
29+
result.name = "test_experiment"
30+
result.status = "SUCCESS"
31+
result.raw_variables = {"VAR1": "VALUE1"}
32+
result.variables = {"VAR1": "VALUE1"}
33+
result.variants = ["variant1", "variant2"]
34+
result.object_definitions = [{"name": "test_object", "type": "APPLICATION"}]
35+
return result
36+
37+
38+
def mock_app_inst(tmpdir):
39+
"""Creates a mock application instance."""
40+
41+
class MockExpander:
42+
"""Mock expander class."""
43+
44+
def __init__(self):
45+
self.experiment_run_dir = str(tmpdir)
46+
47+
class MockAppInst:
48+
"""Mock application instance class."""
49+
50+
def __init__(self):
51+
self.expander = MockExpander()
52+
53+
def object_inventory(self, workspace): # pylint: disable=unused-argument
54+
"""Returns a mock object inventory."""
55+
return [{"name": "test_object", "type": "APPLICATION"}]
56+
57+
return MockAppInst()
58+
59+
60+
def test_write_read_cache(experiment_result, tmpdir):
61+
"""Test writing and reading the experiment result cache."""
62+
app_inst = mock_app_inst(tmpdir)
63+
experiment_result.write_cache(app_inst)
64+
65+
new_result = ExperimentResult(app_inst)
66+
assert new_result.read_cache(None, app_inst)
67+
68+
assert new_result.name == experiment_result.name
69+
assert new_result.status == experiment_result.status
70+
assert new_result.raw_variables == experiment_result.raw_variables
71+
assert new_result.variables == experiment_result.variables
72+
assert new_result.variants == experiment_result.variants
73+
assert new_result.object_definitions == experiment_result.object_definitions
74+
75+
76+
def test_get_newest_experiment_file(tmpdir):
77+
"""Test the get_newest_experiment_file function."""
78+
# Create some files with different modification times
79+
file1 = tmpdir.join("file1.txt")
80+
file1.write("content")
81+
time.sleep(0.1)
82+
file2 = tmpdir.join("file2.txt")
83+
file2.write("content")
84+
time.sleep(0.1)
85+
subdir = tmpdir.mkdir("subdir")
86+
file3 = subdir.join("file3.txt")
87+
file3.write("content")
88+
89+
newest_file, timestamp = get_newest_experiment_file(str(tmpdir))
90+
assert newest_file == str(file3)
91+
assert timestamp == os.path.getmtime(str(file3))
92+
93+
94+
def test_read_cache_stale(experiment_result, tmpdir):
95+
"""Test that read_cache returns False if the cache is stale."""
96+
app_inst = mock_app_inst(tmpdir)
97+
experiment_result.write_cache(app_inst)
98+
99+
# Make a file that is newer than the cache
100+
time.sleep(0.1)
101+
new_file = tmpdir.join("new_file.txt")
102+
new_file.write("content")
103+
104+
new_result = ExperimentResult(app_inst)
105+
assert not new_result.read_cache(None, app_inst)
106+
107+
108+
def test_read_cache_object_inventory_changed(experiment_result, tmpdir):
109+
"""
110+
Test that read_cache returns False if the object inventory has changed.
111+
"""
112+
app_inst = mock_app_inst(tmpdir)
113+
experiment_result.write_cache(app_inst)
114+
115+
class MockAppInstNewInventory(type(app_inst)):
116+
"""Mock application instance with a different object inventory."""
117+
118+
def object_inventory(self, workspace): # pylint: disable=unused-argument
119+
"""Returns a different mock object inventory."""
120+
return [{"name": "new_object", "type": "APPLICATION"}]
121+
122+
new_app_inst = MockAppInstNewInventory()
123+
new_result = ExperimentResult(new_app_inst)
124+
assert not new_result.read_cache(None, new_app_inst)

0 commit comments

Comments
 (0)