Skip to content

Commit fb31313

Browse files
committed
Allow for running Alfalfa integration tests on non-local deployment
1 parent 0797a71 commit fb31313

File tree

9 files changed

+166
-175
lines changed

9 files changed

+166
-175
lines changed

tests/api/conftest.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88

99
@pytest.fixture
10-
def base_url():
11-
return 'http://localhost/api/v2'
10+
def base_url(alfalfa_host: str):
11+
return f'{alfalfa_host}/api/v2'
1212

1313

1414
@pytest.fixture
15-
def alfalfa_client():
16-
return AlfalfaClient()
15+
def alfalfa_client(alfalfa_host: str):
16+
return AlfalfaClient(host=alfalfa_host)
1717

1818

1919
@pytest.fixture

tests/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,15 @@ def mock_dispatcher(tmp_path: Path):
3434
work_dir.mkdir()
3535
dispatcher = MockDispatcher(work_dir)
3636
yield dispatcher
37+
38+
39+
def pytest_addoption(parser):
40+
parser.addoption("--host", action="store", default="http://localhost")
41+
42+
43+
@pytest.fixture
44+
def alfalfa_host(pytestconfig: pytest.Config):
45+
alfalfa_host = pytestconfig.getoption("host")
46+
if isinstance(alfalfa_host, str):
47+
alfalfa_host.rstrip('/')
48+
return alfalfa_host

tests/integration/conftest.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Consider factoring this out of the test file
22
import os
3-
import shutil
4-
import tempfile
53
from pathlib import Path
64

75
import pytest
@@ -28,8 +26,8 @@ def pytest_generate_tests(metafunc):
2826

2927

3028
@pytest.fixture
31-
def alfalfa():
32-
client = AlfalfaClient(host="http://localhost")
29+
def alfalfa(alfalfa_host: str):
30+
client = AlfalfaClient(host=alfalfa_host)
3331
yield client
3432

3533

@@ -43,14 +41,6 @@ def ref_id(model_path: Path, alfalfa: AlfalfaClient):
4341
alfalfa.stop()
4442

4543

46-
def create_zip(model_dir):
47-
zip_file_fd, zip_file_path = tempfile.mkstemp(suffix='.zip')
48-
zip_file_path = Path(zip_file_path)
49-
shutil.make_archive(zip_file_path.parent / zip_file_path.stem, "zip", model_dir)
50-
51-
return zip_file_path
52-
53-
5444
def prepare_model(model_path):
5545
model_path = Path(__file__).parents[0] / 'models' / model_path
5646
return str(model_path)

tests/integration/test_broken_models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66

77

88
@pytest.mark.integration
9-
def test_broken_models(broken_model_path):
10-
alfalfa = AlfalfaClient(host='http://localhost')
9+
def test_broken_models(broken_model_path, alfalfa: AlfalfaClient):
1110
with pytest.raises(AlfalfaException):
1211
run_id = alfalfa.submit(str(broken_model_path))
1312
alfalfa.start(
Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import datetime
2-
from unittest import TestCase
32

43
import pytest
54
from alfalfa_client.alfalfa_client import AlfalfaClient
@@ -9,52 +8,50 @@
98

109

1110
@pytest.mark.integration
12-
class TestRefrigCaseOSW(TestCase):
13-
14-
def test_invalid_start_conditions(self):
15-
zip_file_path = prepare_model('refrig_case_osw')
16-
alfalfa = AlfalfaClient(host='http://localhost')
17-
model_id = alfalfa.submit(zip_file_path)
18-
with pytest.raises(AlfalfaException):
19-
alfalfa.start(
20-
model_id,
21-
external_clock=False,
22-
start_datetime=datetime.datetime(2019, 1, 2, 0, 0, 0),
23-
end_datetime=datetime.datetime(2019, 1, 1, 0, 0, 0),
24-
timescale=5
25-
)
26-
27-
def test_basic_io(self):
28-
zip_file_path = prepare_model('refrig_case_osw')
29-
alfalfa = AlfalfaClient(host='http://localhost')
30-
model_id = alfalfa.submit(zip_file_path)
31-
32-
alfalfa.wait(model_id, "ready")
11+
def test_invalid_start_conditions(alfalfa: AlfalfaClient):
12+
zip_file_path = prepare_model('refrig_case_osw')
13+
model_id = alfalfa.submit(zip_file_path)
14+
with pytest.raises(AlfalfaException):
3315
alfalfa.start(
3416
model_id,
35-
external_clock=True,
36-
start_datetime=datetime.datetime(2019, 1, 2, 0, 2, 0),
37-
end_datetime=datetime.datetime(2019, 1, 3, 0, 0, 0)
17+
external_clock=False,
18+
start_datetime=datetime.datetime(2019, 1, 2, 0, 0, 0),
19+
end_datetime=datetime.datetime(2019, 1, 1, 0, 0, 0),
20+
timescale=5
3821
)
3922

40-
alfalfa.wait(model_id, "running")
4123

42-
inputs = alfalfa.get_inputs(model_id)
43-
assert "Test_Point_1" in inputs, "Test_Point_1 is in input points"
44-
inputs = {}
45-
inputs["Test_Point_1"] = 12
24+
@pytest.mark.integration
25+
def test_basic_io(alfalfa: AlfalfaClient):
26+
zip_file_path = prepare_model('refrig_case_osw')
27+
model_id = alfalfa.submit(zip_file_path)
28+
29+
alfalfa.wait(model_id, "ready")
30+
alfalfa.start(
31+
model_id,
32+
external_clock=True,
33+
start_datetime=datetime.datetime(2019, 1, 2, 0, 2, 0),
34+
end_datetime=datetime.datetime(2019, 1, 3, 0, 0, 0)
35+
)
36+
37+
alfalfa.wait(model_id, "running")
38+
39+
inputs = alfalfa.get_inputs(model_id)
40+
assert "Test_Point_1" in inputs, "Test_Point_1 is in input points"
41+
inputs = {}
42+
inputs["Test_Point_1"] = 12
4643

47-
alfalfa.set_inputs(model_id, inputs)
44+
alfalfa.set_inputs(model_id, inputs)
4845

49-
outputs = alfalfa.get_outputs(model_id)
50-
assert "Test_Point_1" in outputs.keys(), "Echo point for Test_Point_1 is not in outputs"
46+
outputs = alfalfa.get_outputs(model_id)
47+
assert "Test_Point_1" in outputs.keys(), "Echo point for Test_Point_1 is not in outputs"
5148

52-
# -- Advance a single time step
53-
alfalfa.advance([model_id])
49+
# -- Advance a single time step
50+
alfalfa.advance([model_id])
5451

55-
outputs = alfalfa.get_outputs(model_id)
56-
assert outputs["Test_Point_1"] == pytest.approx(12), "Test_Point_1 value has not been processed by the model"
52+
outputs = alfalfa.get_outputs(model_id)
53+
assert outputs["Test_Point_1"] == pytest.approx(12), "Test_Point_1 value has not been processed by the model"
5754

58-
# Shut down
59-
alfalfa.stop(model_id)
60-
alfalfa.wait(model_id, "complete")
55+
# Shut down
56+
alfalfa.stop(model_id)
57+
alfalfa.wait(model_id, "complete")

tests/integration/test_schedule_override.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77

88

99
@pytest.mark.integration
10-
def test_schedule_point_generation():
11-
alfalfa = AlfalfaClient('http://localhost')
10+
def test_schedule_point_generation(alfalfa: AlfalfaClient):
1211
site_id = alfalfa.submit(prepare_model('schedule_model'))
1312

1413
inputs = alfalfa.get_inputs(site_id)
@@ -27,8 +26,7 @@ def test_schedule_point_generation():
2726

2827

2928
@pytest.mark.integration
30-
def test_schedule_override():
31-
alfalfa = AlfalfaClient('http://localhost')
29+
def test_schedule_override(alfalfa: AlfalfaClient):
3230
site_id = alfalfa.submit(prepare_model('schedule_model'))
3331

3432
alfalfa.start(
Lines changed: 85 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from datetime import datetime, timedelta
2-
from unittest import TestCase
32

43
import pytest
54
from alfalfa_client.alfalfa_client import AlfalfaClient
@@ -19,87 +18,89 @@
1918
##################################################################################################
2019

2120

21+
@pytest.fixture
22+
def simple_thermostat_run_id(alfalfa: AlfalfaClient):
23+
fmu_path = prepare_model('simple_thermostat.fmu')
24+
run_id = alfalfa.submit(fmu_path)
25+
26+
alfalfa.wait(run_id, "ready")
27+
28+
yield run_id
29+
30+
alfalfa.stop(run_id)
31+
alfalfa.wait(run_id, "complete")
32+
33+
2234
@pytest.mark.integration
23-
class TestSimpleThermostat(TestCase):
24-
25-
def setUp(self):
26-
self.alfalfa = AlfalfaClient(host='http://localhost')
27-
fmu_path = prepare_model('simple_thermostat.fmu')
28-
self.model_id = self.alfalfa.submit(fmu_path)
29-
30-
self.alfalfa.wait(self.model_id, "ready")
31-
32-
self.current_datetime = datetime(2019, 1, 1)
33-
34-
self.alfalfa.start(
35-
self.model_id,
36-
external_clock=True,
37-
start_datetime=self.current_datetime,
38-
end_datetime=datetime(2019, 1, 1, 0, 5),
39-
timescale=5
40-
)
41-
self.alfalfa.wait(self.model_id, "running")
42-
43-
def test_io_with_external_clock(self):
44-
# Simulation is running, but time should still be at 0
45-
model_time = self.alfalfa.get_sim_time(self.model_id)
46-
assert self.current_datetime == model_time
47-
48-
# If outputs are requested before the simulation is advanced,
49-
# there will be an error.
50-
# See issue https://github.com/NREL/alfalfa/issues/119
51-
self.current_datetime += timedelta(minutes=1)
52-
self.alfalfa.advance([self.model_id])
53-
model_time = self.alfalfa.get_sim_time(self.model_id)
54-
assert self.current_datetime == model_time
55-
56-
# Having not set any inputs the fmu will be at the initial state.
57-
# The control signal output "rea" is at 0.0
58-
outputs = self.alfalfa.get_outputs(self.model_id)
59-
rea = outputs.get("rea")
60-
assert rea == pytest.approx(0.0)
61-
62-
# Attempt to override the measured temp (ie zone temperature),
63-
# and the setpoint, such that zone temperature is over setpoint.
64-
self.alfalfa.set_inputs(self.model_id, {"oveWriMeasuredTemp_u": 303.15, "oveWriSetPoint_u": 294.15})
65-
66-
# Advance time, outputs will not be updated until advance happens.
67-
# Should this limitation be considered a bug?
68-
# Note that boptest advance and set input apis are combined,
69-
# so that there is no method to set inputs without advancing
70-
self.current_datetime += timedelta(minutes=1)
71-
self.alfalfa.advance([self.model_id])
72-
model_time = self.alfalfa.get_sim_time(self.model_id)
73-
assert self.current_datetime == model_time
74-
75-
# When temperature is over setpoint controller returns 0.0
76-
outputs = self.alfalfa.get_outputs(self.model_id)
77-
rea = outputs.get("rea")
78-
assert rea == pytest.approx(0.0)
79-
80-
# Now override the measured (zone) temperature such that it is below setpoint
81-
self.alfalfa.set_inputs(self.model_id, {"oveWriMeasuredTemp_u": 283.15, "oveWriSetPoint_u": 294.15})
82-
83-
self.current_datetime += timedelta(minutes=1)
84-
self.alfalfa.advance([self.model_id])
85-
model_time = self.alfalfa.get_sim_time(self.model_id)
86-
assert self.current_datetime == model_time
87-
88-
# When temperature is below setpoint controller returns 1.0
89-
outputs = self.alfalfa.get_outputs(self.model_id)
90-
rea = outputs.get("rea")
91-
assert rea == pytest.approx(1.0)
92-
93-
# Test the control signal override
94-
self.alfalfa.set_inputs(self.model_id, {"oveWriActuatorSignal_u": 0.0})
95-
self.current_datetime += timedelta(minutes=1)
96-
self.alfalfa.advance([self.model_id])
97-
model_time = self.alfalfa.get_sim_time(self.model_id)
98-
assert self.current_datetime == model_time
99-
outputs = self.alfalfa.get_outputs(self.model_id)
100-
rea = outputs.get("rea")
101-
assert rea == pytest.approx(0.0)
102-
103-
def tearDown(self):
104-
self.alfalfa.stop(self.model_id)
105-
self.alfalfa.wait(self.model_id, "complete")
35+
def test_io_with_external_clock(alfalfa: AlfalfaClient, simple_thermostat_run_id):
36+
run_id = simple_thermostat_run_id
37+
38+
current_datetime = datetime(2019, 1, 1)
39+
40+
alfalfa.start(
41+
run_id,
42+
external_clock=True,
43+
start_datetime=current_datetime,
44+
end_datetime=datetime(2019, 1, 1, 0, 5),
45+
timescale=5
46+
)
47+
alfalfa.wait(run_id, "running")
48+
49+
# Simulation is running, but time should still be at 0
50+
model_time = alfalfa.get_sim_time(run_id)
51+
assert current_datetime == model_time
52+
53+
# If outputs are requested before the simulation is advanced,
54+
# there will be an error.
55+
# See issue https://github.com/NREL/alfalfa/issues/119
56+
current_datetime += timedelta(minutes=1)
57+
alfalfa.advance([run_id])
58+
model_time = alfalfa.get_sim_time(run_id)
59+
assert current_datetime == model_time
60+
61+
# Having not set any inputs the fmu will be at the initial state.
62+
# The control signal output "rea" is at 0.0
63+
outputs = alfalfa.get_outputs(run_id)
64+
rea = outputs.get("rea")
65+
assert rea == pytest.approx(0.0)
66+
67+
# Attempt to override the measured temp (ie zone temperature),
68+
# and the setpoint, such that zone temperature is over setpoint.
69+
alfalfa.set_inputs(run_id, {"oveWriMeasuredTemp_u": 303.15, "oveWriSetPoint_u": 294.15})
70+
71+
# Advance time, outputs will not be updated until advance happens.
72+
# Should this limitation be considered a bug?
73+
# Note that boptest advance and set input apis are combined,
74+
# so that there is no method to set inputs without advancing
75+
current_datetime += timedelta(minutes=1)
76+
alfalfa.advance([run_id])
77+
model_time = alfalfa.get_sim_time(run_id)
78+
assert current_datetime == model_time
79+
80+
# When temperature is over setpoint controller returns 0.0
81+
outputs = alfalfa.get_outputs(run_id)
82+
rea = outputs.get("rea")
83+
assert rea == pytest.approx(0.0)
84+
85+
# Now override the measured (zone) temperature such that it is below setpoint
86+
alfalfa.set_inputs(run_id, {"oveWriMeasuredTemp_u": 283.15, "oveWriSetPoint_u": 294.15})
87+
88+
current_datetime += timedelta(minutes=1)
89+
alfalfa.advance([run_id])
90+
model_time = alfalfa.get_sim_time(run_id)
91+
assert current_datetime == model_time
92+
93+
# When temperature is below setpoint controller returns 1.0
94+
outputs = alfalfa.get_outputs(run_id)
95+
rea = outputs.get("rea")
96+
assert rea == pytest.approx(1.0)
97+
98+
# Test the control signal override
99+
alfalfa.set_inputs(run_id, {"oveWriActuatorSignal_u": 0.0})
100+
current_datetime += timedelta(minutes=1)
101+
alfalfa.advance([run_id])
102+
model_time = alfalfa.get_sim_time(run_id)
103+
assert current_datetime == model_time
104+
outputs = alfalfa.get_outputs(run_id)
105+
rea = outputs.get("rea")
106+
assert rea == pytest.approx(0.0)

0 commit comments

Comments
 (0)