From 9f5e9bd2045cfd589c2c1d5e45b1f0479e9fe268 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 22 Jul 2025 11:53:17 -0700 Subject: [PATCH 1/5] added test file --- tests/cda/timeseries/timeseries_CDA_test.py | 114 ++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 tests/cda/timeseries/timeseries_CDA_test.py diff --git a/tests/cda/timeseries/timeseries_CDA_test.py b/tests/cda/timeseries/timeseries_CDA_test.py new file mode 100644 index 00000000..21366673 --- /dev/null +++ b/tests/cda/timeseries/timeseries_CDA_test.py @@ -0,0 +1,114 @@ +from datetime import datetime, timedelta, timezone + +import pandas as pd +import pytest + +import cwms.timeseries.timeseries as ts + +TEST_OFFICE = "SPK" +TEST_TS_ID = "pytest.Temperature.Inst.1Hour.0.Raw" +TEST_UNIT = "degF" +NOW = datetime.now(timezone.utc) +START_TIME = NOW - timedelta(hours=2) +END_TIME = NOW +TEST_DATA = pd.DataFrame( + { + "date-time": [ + START_TIME.isoformat(), + (START_TIME + timedelta(hours=1)).isoformat(), + ], + "value": [65.0, 66.5], + "quality-code": [0, 0], + } +) + +SECOND_TS_ID = "pytest.Temperature.Inst.1Hour.1.Raw" +SECOND_TEST_DATA = pd.DataFrame( + { + "date-time": [ + START_TIME.isoformat(), + (START_TIME + timedelta(hours=1)).isoformat(), + ], + "value": [72.1, 74.0], + "quality-code": [0, 0], + } +) + + +@pytest.fixture(autouse=True) +def init_session(request): + print("Initializing CWMS API session for timeseries operations test...") + + +def test_store_timeseries(): + json_data = ts.timeseries_df_to_json( + data=TEST_DATA, ts_id=TEST_TS_ID, units=TEST_UNIT, office_id=TEST_OFFICE + ) + ts.store_timeseries(json_data) + df = ts.get_timeseries(TEST_TS_ID, TEST_OFFICE, begin=START_TIME, end=END_TIME).df + assert not df.empty + + +# Unsure if correct +def test_update_timeseries_value(): + updated_data = TEST_DATA.copy() + updated_data.loc[1, "value"] = 67.2 + json_data = ts.timeseries_df_to_json( + data=updated_data, ts_id=TEST_TS_ID, units=TEST_UNIT, office_id=TEST_OFFICE + ) + ts.store_timeseries(json_data) + df = ts.get_timeseries(TEST_TS_ID, TEST_OFFICE, begin=START_TIME, end=END_TIME).df + assert 67.2 in df["value"].values + + +def test_delete_timeseries_data(): + json_data = ts.timeseries_df_to_json( + data=TEST_DATA, ts_id=TEST_TS_ID, units=TEST_UNIT, office_id=TEST_OFFICE + ) + ts.store_timeseries(json_data) + ts.delete_timeseries(TEST_TS_ID, TEST_OFFICE, START_TIME, END_TIME) + df = ts.get_timeseries(TEST_TS_ID, TEST_OFFICE, begin=START_TIME, end=END_TIME).df + assert df.empty + + +def test_get_timeseries(): + json_data = ts.timeseries_df_to_json( + data=TEST_DATA, ts_id=TEST_TS_ID, units=TEST_UNIT, office_id=TEST_OFFICE + ) + ts.store_timeseries(json_data) + df = ts.get_timeseries(TEST_TS_ID, TEST_OFFICE, begin=START_TIME, end=END_TIME).df + assert df.shape[0] == 2 + assert 65.0 in df["value"].values and 66.5 in df["value"].values + + +def test_store_multi_timeseries_df(): + multi_df = pd.concat( + [ + TEST_DATA.assign(ts_id=TEST_TS_ID, units=TEST_UNIT), + SECOND_TEST_DATA.assign(ts_id=SECOND_TS_ID, units=TEST_UNIT), + ], + ignore_index=True, + ) + ts.store_multi_timeseries_df(multi_df, office_id=TEST_OFFICE) + + df1 = ts.get_timeseries(TEST_TS_ID, TEST_OFFICE, begin=START_TIME, end=END_TIME).df + df2 = ts.get_timeseries( + SECOND_TS_ID, TEST_OFFICE, begin=START_TIME, end=END_TIME + ).df + + assert not df1.empty + assert not df2.empty + + +def test_get_multi_timeseries_df(): + combined_df = ts.get_multi_timeseries_df( + [TEST_TS_ID, SECOND_TS_ID], + office_id=TEST_OFFICE, + begin=START_TIME, + end=END_TIME, + melted=True, + ) + ts_ids = combined_df["ts_id"].unique().tolist() + assert TEST_TS_ID in ts_ids + assert SECOND_TS_ID in ts_ids + assert combined_df.shape[0] >= 4 From d340479a12fedba90a1e3d55464510f5531d7729 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 23 Jul 2025 12:29:38 -0700 Subject: [PATCH 2/5] Update timeseries_CDA_test.py --- tests/cda/timeseries/timeseries_CDA_test.py | 31 +++++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/tests/cda/timeseries/timeseries_CDA_test.py b/tests/cda/timeseries/timeseries_CDA_test.py index 21366673..97ca6554 100644 --- a/tests/cda/timeseries/timeseries_CDA_test.py +++ b/tests/cda/timeseries/timeseries_CDA_test.py @@ -3,10 +3,36 @@ import pandas as pd import pytest +import cwms +import cwms.api import cwms.timeseries.timeseries as ts + +# Setup and teardown fixture for test location +@pytest.fixture(scope="module", autouse=True) +def setup_data(): + loc_id = "pytest_loc" + location_data = { + "name": loc_id, + "latitude": 38.0, + "longitude": -121.0, + "public-name": "pytest location", + "long-name": "Pytest Location for Timeseries Testing", + "elevation": 10.0, + "unit": "m", + } + + # Store location before tests + cwms.store_location(location_data, office_id=TEST_OFFICE) + + yield + + # Delete location after tests + cwms.delete_location(loc_id, office_id=TEST_OFFICE) + + TEST_OFFICE = "SPK" -TEST_TS_ID = "pytest.Temperature.Inst.1Hour.0.Raw" +TEST_TS_ID = "pytest_loc.Temperature.Inst.1Hour.0.Raw" TEST_UNIT = "degF" NOW = datetime.now(timezone.utc) START_TIME = NOW - timedelta(hours=2) @@ -22,7 +48,7 @@ } ) -SECOND_TS_ID = "pytest.Temperature.Inst.1Hour.1.Raw" +SECOND_TS_ID = "pytest_loc.Temperature.Inst.1Hour.1.Raw" SECOND_TEST_DATA = pd.DataFrame( { "date-time": [ @@ -49,7 +75,6 @@ def test_store_timeseries(): assert not df.empty -# Unsure if correct def test_update_timeseries_value(): updated_data = TEST_DATA.copy() updated_data.loc[1, "value"] = 67.2 From b79d177c9758d297550562e6a99b39823195e038 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 23 Jul 2025 13:06:08 -0700 Subject: [PATCH 3/5] Update timeseries_CDA_test.py --- tests/cda/timeseries/timeseries_CDA_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cda/timeseries/timeseries_CDA_test.py b/tests/cda/timeseries/timeseries_CDA_test.py index 97ca6554..76bdabed 100644 --- a/tests/cda/timeseries/timeseries_CDA_test.py +++ b/tests/cda/timeseries/timeseries_CDA_test.py @@ -23,12 +23,12 @@ def setup_data(): } # Store location before tests - cwms.store_location(location_data, office_id=TEST_OFFICE) + cwms.store_location(location_data) yield # Delete location after tests - cwms.delete_location(loc_id, office_id=TEST_OFFICE) + cwms.delete_location(loc_id) TEST_OFFICE = "SPK" From 2a90a440900857921d7c4ea8e2015f4cda99e34c Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 5 Aug 2025 10:31:41 -0700 Subject: [PATCH 4/5] Update timeseries_CDA_test.py --- tests/cda/timeseries/timeseries_CDA_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cda/timeseries/timeseries_CDA_test.py b/tests/cda/timeseries/timeseries_CDA_test.py index 76bdabed..eeea1d50 100644 --- a/tests/cda/timeseries/timeseries_CDA_test.py +++ b/tests/cda/timeseries/timeseries_CDA_test.py @@ -12,6 +12,7 @@ @pytest.fixture(scope="module", autouse=True) def setup_data(): loc_id = "pytest_loc" + # fmt: off location_data = { "name": loc_id, "latitude": 38.0, @@ -19,8 +20,9 @@ def setup_data(): "public-name": "pytest location", "long-name": "Pytest Location for Timeseries Testing", "elevation": 10.0, - "unit": "m", + "unit": "m" } + # fmt: on # Store location before tests cwms.store_location(location_data) From 056a57454f5da310960941e68dd666c441e68e3f Mon Sep 17 00:00:00 2001 From: Eric Novotny Date: Wed, 6 Aug 2025 14:06:10 -0700 Subject: [PATCH 5/5] fix to locations loading in tests --- tests/cda/timeseries/timeseries_CDA_test.py | 71 ++++++++++++--------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/tests/cda/timeseries/timeseries_CDA_test.py b/tests/cda/timeseries/timeseries_CDA_test.py index eeea1d50..42e78d4b 100644 --- a/tests/cda/timeseries/timeseries_CDA_test.py +++ b/tests/cda/timeseries/timeseries_CDA_test.py @@ -4,38 +4,12 @@ import pytest import cwms -import cwms.api import cwms.timeseries.timeseries as ts - -# Setup and teardown fixture for test location -@pytest.fixture(scope="module", autouse=True) -def setup_data(): - loc_id = "pytest_loc" - # fmt: off - location_data = { - "name": loc_id, - "latitude": 38.0, - "longitude": -121.0, - "public-name": "pytest location", - "long-name": "Pytest Location for Timeseries Testing", - "elevation": 10.0, - "unit": "m" - } - # fmt: on - - # Store location before tests - cwms.store_location(location_data) - - yield - - # Delete location after tests - cwms.delete_location(loc_id) - - TEST_OFFICE = "SPK" -TEST_TS_ID = "pytest_loc.Temperature.Inst.1Hour.0.Raw" -TEST_UNIT = "degF" +TEST_LOCATION_ID = "pytest_loc" +TEST_TS_ID = f"{TEST_LOCATION_ID}.Flow.Inst.1Hour.0.Raw" +TEST_UNIT = "cfs" NOW = datetime.now(timezone.utc) START_TIME = NOW - timedelta(hours=2) END_TIME = NOW @@ -50,18 +24,53 @@ def setup_data(): } ) -SECOND_TS_ID = "pytest_loc.Temperature.Inst.1Hour.1.Raw" +SECOND_TS_ID = f"{TEST_LOCATION_ID}.Flow.Inst.1Day.0.Raw" SECOND_TEST_DATA = pd.DataFrame( { "date-time": [ START_TIME.isoformat(), - (START_TIME + timedelta(hours=1)).isoformat(), + (START_TIME + timedelta(days=1)).isoformat(), ], "value": [72.1, 74.0], "quality-code": [0, 0], } ) +# Setup and teardown fixture for test location + + +@pytest.fixture(scope="module", autouse=True) +def setup_data(): + TEST_LATITUDE = 45.1704758 + TEST_LONGITUDE = -92.8411439 + + location_data = { + "name": TEST_LOCATION_ID, + "office-id": TEST_OFFICE, + "latitude": TEST_LATITUDE, + "longitude": TEST_LONGITUDE, + "elevation": 250.0, + "horizontal-datum": "NAD83", + "vertical-datum": "NAVD88", + "location-type": "TESTING", + "public-name": "Test Location", + "long-name": "A pytest-generated location", + "timezone-name": "America/Los_Angeles", + "location-kind": "SITE", + "nation": "US", + } + # fmt: on + + # Store location before tests + cwms.store_location(location_data) + + yield + + # Delete location after tests + cwms.delete_location( + location_id=TEST_LOCATION_ID, office_id=TEST_OFFICE, cascade_delete=True + ) + @pytest.fixture(autouse=True) def init_session(request):