Skip to content

Commit

Permalink
Allow for running Alfalfa integration tests on non-local deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
TShapinsky committed Jul 1, 2024
1 parent 0797a71 commit fb31313
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 175 deletions.
8 changes: 4 additions & 4 deletions tests/api/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@


@pytest.fixture
def base_url():
return 'http://localhost/api/v2'
def base_url(alfalfa_host: str):
return f'{alfalfa_host}/api/v2'


@pytest.fixture
def alfalfa_client():
return AlfalfaClient()
def alfalfa_client(alfalfa_host: str):
return AlfalfaClient(host=alfalfa_host)


@pytest.fixture
Expand Down
12 changes: 12 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ def mock_dispatcher(tmp_path: Path):
work_dir.mkdir()
dispatcher = MockDispatcher(work_dir)
yield dispatcher


def pytest_addoption(parser):
parser.addoption("--host", action="store", default="http://localhost")


@pytest.fixture
def alfalfa_host(pytestconfig: pytest.Config):
alfalfa_host = pytestconfig.getoption("host")
if isinstance(alfalfa_host, str):
alfalfa_host.rstrip('/')
return alfalfa_host
14 changes: 2 additions & 12 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Consider factoring this out of the test file
import os
import shutil
import tempfile
from pathlib import Path

import pytest
Expand All @@ -28,8 +26,8 @@ def pytest_generate_tests(metafunc):


@pytest.fixture
def alfalfa():
client = AlfalfaClient(host="http://localhost")
def alfalfa(alfalfa_host: str):
client = AlfalfaClient(host=alfalfa_host)
yield client


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


def create_zip(model_dir):
zip_file_fd, zip_file_path = tempfile.mkstemp(suffix='.zip')
zip_file_path = Path(zip_file_path)
shutil.make_archive(zip_file_path.parent / zip_file_path.stem, "zip", model_dir)

return zip_file_path


def prepare_model(model_path):
model_path = Path(__file__).parents[0] / 'models' / model_path
return str(model_path)
3 changes: 1 addition & 2 deletions tests/integration/test_broken_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@


@pytest.mark.integration
def test_broken_models(broken_model_path):
alfalfa = AlfalfaClient(host='http://localhost')
def test_broken_models(broken_model_path, alfalfa: AlfalfaClient):
with pytest.raises(AlfalfaException):
run_id = alfalfa.submit(str(broken_model_path))
alfalfa.start(
Expand Down
77 changes: 37 additions & 40 deletions tests/integration/test_refrig_case_osw.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import datetime
from unittest import TestCase

import pytest
from alfalfa_client.alfalfa_client import AlfalfaClient
Expand All @@ -9,52 +8,50 @@


@pytest.mark.integration
class TestRefrigCaseOSW(TestCase):

def test_invalid_start_conditions(self):
zip_file_path = prepare_model('refrig_case_osw')
alfalfa = AlfalfaClient(host='http://localhost')
model_id = alfalfa.submit(zip_file_path)
with pytest.raises(AlfalfaException):
alfalfa.start(
model_id,
external_clock=False,
start_datetime=datetime.datetime(2019, 1, 2, 0, 0, 0),
end_datetime=datetime.datetime(2019, 1, 1, 0, 0, 0),
timescale=5
)

def test_basic_io(self):
zip_file_path = prepare_model('refrig_case_osw')
alfalfa = AlfalfaClient(host='http://localhost')
model_id = alfalfa.submit(zip_file_path)

alfalfa.wait(model_id, "ready")
def test_invalid_start_conditions(alfalfa: AlfalfaClient):
zip_file_path = prepare_model('refrig_case_osw')
model_id = alfalfa.submit(zip_file_path)
with pytest.raises(AlfalfaException):
alfalfa.start(
model_id,
external_clock=True,
start_datetime=datetime.datetime(2019, 1, 2, 0, 2, 0),
end_datetime=datetime.datetime(2019, 1, 3, 0, 0, 0)
external_clock=False,
start_datetime=datetime.datetime(2019, 1, 2, 0, 0, 0),
end_datetime=datetime.datetime(2019, 1, 1, 0, 0, 0),
timescale=5
)

alfalfa.wait(model_id, "running")

inputs = alfalfa.get_inputs(model_id)
assert "Test_Point_1" in inputs, "Test_Point_1 is in input points"
inputs = {}
inputs["Test_Point_1"] = 12
@pytest.mark.integration
def test_basic_io(alfalfa: AlfalfaClient):
zip_file_path = prepare_model('refrig_case_osw')
model_id = alfalfa.submit(zip_file_path)

alfalfa.wait(model_id, "ready")
alfalfa.start(
model_id,
external_clock=True,
start_datetime=datetime.datetime(2019, 1, 2, 0, 2, 0),
end_datetime=datetime.datetime(2019, 1, 3, 0, 0, 0)
)

alfalfa.wait(model_id, "running")

inputs = alfalfa.get_inputs(model_id)
assert "Test_Point_1" in inputs, "Test_Point_1 is in input points"
inputs = {}
inputs["Test_Point_1"] = 12

alfalfa.set_inputs(model_id, inputs)
alfalfa.set_inputs(model_id, inputs)

outputs = alfalfa.get_outputs(model_id)
assert "Test_Point_1" in outputs.keys(), "Echo point for Test_Point_1 is not in outputs"
outputs = alfalfa.get_outputs(model_id)
assert "Test_Point_1" in outputs.keys(), "Echo point for Test_Point_1 is not in outputs"

# -- Advance a single time step
alfalfa.advance([model_id])
# -- Advance a single time step
alfalfa.advance([model_id])

outputs = alfalfa.get_outputs(model_id)
assert outputs["Test_Point_1"] == pytest.approx(12), "Test_Point_1 value has not been processed by the model"
outputs = alfalfa.get_outputs(model_id)
assert outputs["Test_Point_1"] == pytest.approx(12), "Test_Point_1 value has not been processed by the model"

# Shut down
alfalfa.stop(model_id)
alfalfa.wait(model_id, "complete")
# Shut down
alfalfa.stop(model_id)
alfalfa.wait(model_id, "complete")
6 changes: 2 additions & 4 deletions tests/integration/test_schedule_override.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@


@pytest.mark.integration
def test_schedule_point_generation():
alfalfa = AlfalfaClient('http://localhost')
def test_schedule_point_generation(alfalfa: AlfalfaClient):
site_id = alfalfa.submit(prepare_model('schedule_model'))

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


@pytest.mark.integration
def test_schedule_override():
alfalfa = AlfalfaClient('http://localhost')
def test_schedule_override(alfalfa: AlfalfaClient):
site_id = alfalfa.submit(prepare_model('schedule_model'))

alfalfa.start(
Expand Down
169 changes: 85 additions & 84 deletions tests/integration/test_simple_thermostat_fmu.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from datetime import datetime, timedelta
from unittest import TestCase

import pytest
from alfalfa_client.alfalfa_client import AlfalfaClient
Expand All @@ -19,87 +18,89 @@
##################################################################################################


@pytest.fixture
def simple_thermostat_run_id(alfalfa: AlfalfaClient):
fmu_path = prepare_model('simple_thermostat.fmu')
run_id = alfalfa.submit(fmu_path)

alfalfa.wait(run_id, "ready")

yield run_id

alfalfa.stop(run_id)
alfalfa.wait(run_id, "complete")


@pytest.mark.integration
class TestSimpleThermostat(TestCase):

def setUp(self):
self.alfalfa = AlfalfaClient(host='http://localhost')
fmu_path = prepare_model('simple_thermostat.fmu')
self.model_id = self.alfalfa.submit(fmu_path)

self.alfalfa.wait(self.model_id, "ready")

self.current_datetime = datetime(2019, 1, 1)

self.alfalfa.start(
self.model_id,
external_clock=True,
start_datetime=self.current_datetime,
end_datetime=datetime(2019, 1, 1, 0, 5),
timescale=5
)
self.alfalfa.wait(self.model_id, "running")

def test_io_with_external_clock(self):
# Simulation is running, but time should still be at 0
model_time = self.alfalfa.get_sim_time(self.model_id)
assert self.current_datetime == model_time

# If outputs are requested before the simulation is advanced,
# there will be an error.
# See issue https://github.com/NREL/alfalfa/issues/119
self.current_datetime += timedelta(minutes=1)
self.alfalfa.advance([self.model_id])
model_time = self.alfalfa.get_sim_time(self.model_id)
assert self.current_datetime == model_time

# Having not set any inputs the fmu will be at the initial state.
# The control signal output "rea" is at 0.0
outputs = self.alfalfa.get_outputs(self.model_id)
rea = outputs.get("rea")
assert rea == pytest.approx(0.0)

# Attempt to override the measured temp (ie zone temperature),
# and the setpoint, such that zone temperature is over setpoint.
self.alfalfa.set_inputs(self.model_id, {"oveWriMeasuredTemp_u": 303.15, "oveWriSetPoint_u": 294.15})

# Advance time, outputs will not be updated until advance happens.
# Should this limitation be considered a bug?
# Note that boptest advance and set input apis are combined,
# so that there is no method to set inputs without advancing
self.current_datetime += timedelta(minutes=1)
self.alfalfa.advance([self.model_id])
model_time = self.alfalfa.get_sim_time(self.model_id)
assert self.current_datetime == model_time

# When temperature is over setpoint controller returns 0.0
outputs = self.alfalfa.get_outputs(self.model_id)
rea = outputs.get("rea")
assert rea == pytest.approx(0.0)

# Now override the measured (zone) temperature such that it is below setpoint
self.alfalfa.set_inputs(self.model_id, {"oveWriMeasuredTemp_u": 283.15, "oveWriSetPoint_u": 294.15})

self.current_datetime += timedelta(minutes=1)
self.alfalfa.advance([self.model_id])
model_time = self.alfalfa.get_sim_time(self.model_id)
assert self.current_datetime == model_time

# When temperature is below setpoint controller returns 1.0
outputs = self.alfalfa.get_outputs(self.model_id)
rea = outputs.get("rea")
assert rea == pytest.approx(1.0)

# Test the control signal override
self.alfalfa.set_inputs(self.model_id, {"oveWriActuatorSignal_u": 0.0})
self.current_datetime += timedelta(minutes=1)
self.alfalfa.advance([self.model_id])
model_time = self.alfalfa.get_sim_time(self.model_id)
assert self.current_datetime == model_time
outputs = self.alfalfa.get_outputs(self.model_id)
rea = outputs.get("rea")
assert rea == pytest.approx(0.0)

def tearDown(self):
self.alfalfa.stop(self.model_id)
self.alfalfa.wait(self.model_id, "complete")
def test_io_with_external_clock(alfalfa: AlfalfaClient, simple_thermostat_run_id):
run_id = simple_thermostat_run_id

current_datetime = datetime(2019, 1, 1)

alfalfa.start(
run_id,
external_clock=True,
start_datetime=current_datetime,
end_datetime=datetime(2019, 1, 1, 0, 5),
timescale=5
)
alfalfa.wait(run_id, "running")

# Simulation is running, but time should still be at 0
model_time = alfalfa.get_sim_time(run_id)
assert current_datetime == model_time

# If outputs are requested before the simulation is advanced,
# there will be an error.
# See issue https://github.com/NREL/alfalfa/issues/119
current_datetime += timedelta(minutes=1)
alfalfa.advance([run_id])
model_time = alfalfa.get_sim_time(run_id)
assert current_datetime == model_time

# Having not set any inputs the fmu will be at the initial state.
# The control signal output "rea" is at 0.0
outputs = alfalfa.get_outputs(run_id)
rea = outputs.get("rea")
assert rea == pytest.approx(0.0)

# Attempt to override the measured temp (ie zone temperature),
# and the setpoint, such that zone temperature is over setpoint.
alfalfa.set_inputs(run_id, {"oveWriMeasuredTemp_u": 303.15, "oveWriSetPoint_u": 294.15})

# Advance time, outputs will not be updated until advance happens.
# Should this limitation be considered a bug?
# Note that boptest advance and set input apis are combined,
# so that there is no method to set inputs without advancing
current_datetime += timedelta(minutes=1)
alfalfa.advance([run_id])
model_time = alfalfa.get_sim_time(run_id)
assert current_datetime == model_time

# When temperature is over setpoint controller returns 0.0
outputs = alfalfa.get_outputs(run_id)
rea = outputs.get("rea")
assert rea == pytest.approx(0.0)

# Now override the measured (zone) temperature such that it is below setpoint
alfalfa.set_inputs(run_id, {"oveWriMeasuredTemp_u": 283.15, "oveWriSetPoint_u": 294.15})

current_datetime += timedelta(minutes=1)
alfalfa.advance([run_id])
model_time = alfalfa.get_sim_time(run_id)
assert current_datetime == model_time

# When temperature is below setpoint controller returns 1.0
outputs = alfalfa.get_outputs(run_id)
rea = outputs.get("rea")
assert rea == pytest.approx(1.0)

# Test the control signal override
alfalfa.set_inputs(run_id, {"oveWriActuatorSignal_u": 0.0})
current_datetime += timedelta(minutes=1)
alfalfa.advance([run_id])
model_time = alfalfa.get_sim_time(run_id)
assert current_datetime == model_time
outputs = alfalfa.get_outputs(run_id)
rea = outputs.get("rea")
assert rea == pytest.approx(0.0)
Loading

0 comments on commit fb31313

Please sign in to comment.