Skip to content

Commit

Permalink
Merge pull request #38 from IMMM-SFA/feature/test-io
Browse files Browse the repository at this point in the history
adds unit tests for input/output methods; closes #37
  • Loading branch information
thurber authored May 6, 2021
2 parents 4af09fe + 22562b1 commit 8325dab
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 9 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/build_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ jobs:
pip install numpy-1.20.2+mkl-cp39-cp39-win_amd64.whl
curl -O https://download.lfd.uci.edu/pythonlibs/w4tscw6k/GDAL-3.2.2-cp39-cp39-win_amd64.whl
pip install GDAL-3.2.2-cp39-cp39-win_amd64.whl
curl -O https://download.lfd.uci.edu/pythonlibs/w4tscw6k/rasterio-1.2.1-cp39-cp39-win_amd64.whl
pip install rasterio-1.2.1-cp39-cp39-win_amd64.whl
curl -O https://download.lfd.uci.edu/pythonlibs/w4tscw6k/rasterio-1.2.3-cp39-cp39-win_amd64.whl
pip install rasterio-1.2.3-cp39-cp39-win_amd64.whl
pip install -r requirements.txt
python setup.py install
pip install numpy --upgrade
pip install python-benedict --upgrade
- name: Test and generate coverage report
run: |
Expand Down
3 changes: 2 additions & 1 deletion mosartwmpy/grid/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from mosartwmpy.config.parameters import Parameters
from mosartwmpy.reservoirs.grid import load_reservoirs


class Grid():
"""Class to store grid related values that are constant throughout a simulation."""

Expand Down Expand Up @@ -413,7 +414,7 @@ def to_files(self, path: str) -> None:
zip.write(filename, names[i])

@staticmethod
def from_files(path: str) -> 'Grid':
def from_files(path: Path) -> 'Grid':
"""Creates a Grid instance from columns in a dataframe.
Args:
Expand Down
5 changes: 5 additions & 0 deletions mosartwmpy/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from mosartwmpy.utilities.pretty_timer import pretty_timer
from mosartwmpy.utilities.inherit_docs import inherit_docs


@inherit_docs
class Model(Bmi):
"""The mosartwmpy basic model interface.
Expand Down Expand Up @@ -220,6 +221,10 @@ def update_until(self, time: float) -> None:

def finalize(self) -> None:
# simulation is over so free memory, write data, etc
for handler in logging.getLogger().handlers:
handler.close()
logging.getLogger().handlers.clear()
logging.shutdown()
return

def download_data(self, *args, **kwargs) -> None:
Expand Down
74 changes: 69 additions & 5 deletions mosartwmpy/tests/test_model.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,86 @@
import numpy as np
from pathlib import Path
import unittest

import pkg_resources

from mosartwmpy import Model
from mosartwmpy.grid.grid import Grid


class ModelTest(unittest.TestCase):
"""Test that the model initializes and runs with the default settings."""

def setUp(self):

# package data
GRID_FILE = pkg_resources.resource_filename('mosartwmpy', 'tests/grid.zip')
CONFIG_FILE = pkg_resources.resource_filename('mosartwmpy', 'tests/test_config.yaml')
RUNOFF_FILE = pkg_resources.resource_filename('mosartwmpy', 'tests/runoff_1981_01_01.nc')
DEMAND_FILE = pkg_resources.resource_filename('mosartwmpy', 'tests/demand_1981_01_01.nc')
RESERVOIRS_FILE = pkg_resources.resource_filename('mosartwmpy', 'tests/reservoirs.nc')

@classmethod
def setUpClass(self):
self.model = Model()
self.grid = Grid.from_files(Path('./mosartwmpy/tests/grid.zip'))
self.grid = Grid.from_files(self.GRID_FILE)
self.model.initialize(self.CONFIG_FILE, grid=self.grid)

# set paths for runoff data relative to package
self.model.config['runoff.path'] = self.RUNOFF_FILE
self.model.config['water_management.demand.path'] = self.DEMAND_FILE
self.model.config['water_management.reservoirs.path'] = self.RESERVOIRS_FILE

def test_can_initialize_and_run(self):
self.model.initialize(Path('./mosartwmpy/tests/test_config.yaml'), grid=self.grid)
@classmethod
def tearDownClass(self):
self.model.finalize()

def test_can_run(self):
self.model.update()
self.assertTrue(True, "model initializes and updates")

def test_input_io(self):
self.assertGreater(self.model.get_input_item_count(), 0, "model can count input")
input_vars = self.model.get_input_var_names()
self.assertGreater(len(input_vars), 0, "model can get input names")
self.assertIsInstance(self.model.get_var_units(input_vars[0]), str, "model can get units of input variable")
self.assertIsInstance(self.model.get_var_type(input_vars[0]), str, "model can get type of input variable")
self.assertGreater(self.model.get_var_itemsize(input_vars[0]), 0, "model can get item size of input variable")
self.assertGreater(self.model.get_var_nbytes(input_vars[0]), 0, "model can get nbytes of input variable")
single_index_value = np.full(1, -1234.56)
single_index_destination = np.empty(1)
single_index_position = np.full(1, 0)
self.model.set_value_at_indices(input_vars[0], single_index_position, single_index_value)
self.model.get_value_at_indices(input_vars[0], single_index_destination, single_index_position)
np.testing.assert_array_equal(single_index_destination, single_index_value, "model can get and set input at index")
full_value = np.full(self.model.get_grid_size(), -1234.56)
full_destination = np.empty_like(full_value)
pointer = self.model.get_value_ptr(input_vars[0])
self.model.set_value(input_vars[0], full_value)
self.model.get_value(input_vars[0], full_destination)
np.testing.assert_array_equal(full_destination, full_value, "model can get and set input")
np.testing.assert_array_equal(pointer, full_value, "model can get pointer for input variable")

def test_output_io(self):
self.assertGreater(self.model.get_output_item_count(), 0, "model can count output")
output_vars = self.model.get_output_var_names()
self.assertGreater(len(output_vars), 0, "model can get output names")
self.assertIsInstance(self.model.get_var_units(output_vars[0]), str, "model can get units of output variable")
self.assertIsInstance(self.model.get_var_type(output_vars[0]), str, "model can get type of output variable")
self.assertGreater(self.model.get_var_itemsize(output_vars[0]), 0, "model can get item size of output variable")
self.assertGreater(self.model.get_var_nbytes(output_vars[0]), 0, "model can get nbytes of output variable")
single_index_value = np.full(1, -1234.56)
single_index_destination = np.empty(1)
single_index_position = np.full(1, 0)
self.model.set_value_at_indices(output_vars[0], single_index_position, single_index_value)
self.model.get_value_at_indices(output_vars[0], single_index_destination, single_index_position)
np.testing.assert_array_equal(single_index_destination, single_index_value, "model can get and set output at index")
full_value = np.full(self.model.get_grid_size(), -1234.56)
full_destination = np.empty_like(full_value)
pointer = self.model.get_value_ptr(output_vars[0])
self.model.set_value(output_vars[0], full_value)
self.model.get_value(output_vars[0], full_destination)
np.testing.assert_array_equal(full_destination, full_value, "model can get and set output")
np.testing.assert_array_equal(pointer, full_value, "model can get pointer for output variable")


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pandas==1.1.4
pathvalidate==2.3.0
psutil==5.7.3
pyarrow==3.0.0
python-benedict==0.22.0
python-benedict==0.24.0
recommonmark==0.7.1
regex==2020.11.13
requests==2.25.1
Expand Down

0 comments on commit 8325dab

Please sign in to comment.