Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cellmethod tolerance #5126

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
Convert existing tests to pytest.
  • Loading branch information
pp-mo committed Dec 21, 2022
commit 78ad58329c32e0010c77e10e069792ea51c63ba4
135 changes: 72 additions & 63 deletions lib/iris/tests/unit/fileformats/netcdf/test_parse_cell_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,39 @@
Unit tests for :func:`iris.fileformats.netcdf.parse_cell_methods`.

"""
import pytest

# import iris tests first so that some things can be initialised before
# importing anything else
import iris.tests as tests # isort:skip
from iris.coords import CellMethod
from iris.fileformats.netcdf import (
UnknownCellMethodWarning,
parse_cell_methods,
)

from unittest import mock

from iris.coords import CellMethod
from iris.fileformats.netcdf import parse_cell_methods
class TestParseCellMethods:
def _check_answers(self, test_strings, result):
"""
Compare a list of test strings against a single expected result.

Done this way so that any failures produce intelligible Pytest messages.
"""
expected_tests_and_results = [
(cell_method_str, result) for cell_method_str in test_strings
]
actual_tests_and_results = [
(cell_method_str, parse_cell_methods(cell_method_str))
for cell_method_str in test_strings
]
assert actual_tests_and_results == expected_tests_and_results

class Test(tests.IrisTest):
def test_simple(self):
# Some simple testcases which should all have the same result
cell_method_strings = [
"time: mean",
"time : mean",
]
expected = (CellMethod(method="mean", coords="time"),)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_with_interval(self):
cell_method_strings = [
Expand All @@ -37,9 +49,7 @@ def test_with_interval(self):
expected = (
CellMethod(method="variance", coords="time", intervals="1 hr"),
)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_multiple_axes(self):
cell_method_strings = [
Expand All @@ -51,9 +61,7 @@ def test_multiple_axes(self):
expected = (
CellMethod(method="standard_deviation", coords=["lat", "lon"]),
)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_multiple(self):
cell_method_strings = [
Expand All @@ -66,20 +74,26 @@ def test_multiple(self):
CellMethod(method="maximum", coords="time", intervals="1 hr"),
CellMethod(method="mean", coords="time", intervals="1 day"),
)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_comment(self):
cell_method_strings = [
"time: maximum (interval: 1 hr comment: first bit) "
"time: mean (interval: 1 day comment: second bit)",
"time : maximum (interval: 1 hr comment: first bit) "
"time: mean (interval: 1 day comment: second bit)",
"time: maximum (interval: 1 hr comment: first bit) "
"time : mean (interval: 1 day comment: second bit)",
"time : maximum (interval: 1 hr comment: first bit) "
"time : mean (interval: 1 day comment: second bit)",
(
"time: maximum (interval: 1 hr comment: first bit) "
"time: mean (interval: 1 day comment: second bit)"
),
(
"time : maximum (interval: 1 hr comment: first bit) "
"time: mean (interval: 1 day comment: second bit)"
),
(
"time: maximum (interval: 1 hr comment: first bit) "
"time : mean (interval: 1 day comment: second bit)"
),
(
"time : maximum (interval: 1 hr comment: first bit) "
"time : mean (interval: 1 day comment: second bit)"
),
]
expected = (
CellMethod(
Expand All @@ -95,9 +109,7 @@ def test_comment(self):
comments="second bit",
),
)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_comment_brackets(self):
cell_method_strings = [
Expand All @@ -112,35 +124,43 @@ def test_comment_brackets(self):
comments="18h(day-1)-18h",
),
)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_comment_bracket_mismatch_warning(self):
cell_method_strings = [
"time: minimum within days (comment: 18h day-1)-18h)",
"time : minimum within days (comment: 18h day-1)-18h)",
]
expected = (
CellMethod(
method="minimum within days",
coords="time",
intervals=None,
comments="18h day-1)-18h",
),
)
msg = (
"Cell methods may be incorrectly parsed due to mismatched brackets"
)
for cell_method_str in cell_method_strings:
with self.assertWarns(
UserWarning,
msg="Cell methods may be incorrectly parsed due to mismatched brackets",
):
_ = parse_cell_methods(cell_method_str)
with pytest.warns(UserWarning, match=msg):
self._check_answers(cell_method_strings, expected)

def test_badly_formatted_warning(self):
cell_method_strings = [
# "time: maximum (interval: 1 hr comment: first bit "
# "time: mean (interval: 1 day comment: second bit)",
"time: (interval: 1 hr comment: first bit) "
"time: mean (interval: 1 day comment: second bit)",
"time: maximum (interval: 1 hr comment: first bit) "
"time: (interval: 1 day comment: second bit)",
(
"time: (interval: 1 hr comment: first bit) "
"time: mean (interval: 1 day comment: second bit)"
),
(
"time: maximum (interval: 1 hr comment: first bit) "
"time: (interval: 1 day comment: second bit)"
),
]
for cell_method_str in cell_method_strings:
with self.assertWarns(
for cell_method_str in cell_method_strings[1:]:
with pytest.warns(
UserWarning,
msg=f"Failed to fully parse cell method string: {cell_method_str}",
match="Failed to fully parse cell method string: time: ",
):
_ = parse_cell_methods(cell_method_str)

Expand All @@ -152,9 +172,7 @@ def test_portions_of_cells(self):
expected = (
CellMethod(method="mean where sea_ice over sea", coords="area"),
)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_climatology(self):
cell_method_strings = [
Expand All @@ -167,9 +185,7 @@ def test_climatology(self):
CellMethod(method="minimum within days", coords="time"),
CellMethod(method="mean over days", coords="time"),
)
for cell_method_str in cell_method_strings:
res = parse_cell_methods(cell_method_str)
self.assertEqual(res, expected)
self._check_answers(cell_method_strings, expected)

def test_climatology_with_unknown_method(self):
cell_method_strings = [
Expand All @@ -182,15 +198,8 @@ def test_climatology_with_unknown_method(self):
CellMethod(method="min within days", coords="time"),
CellMethod(method="mean over days", coords="time"),
)
msg = "NetCDF variable contains unknown cell method 'min'"
for cell_method_str in cell_method_strings:
with mock.patch("warnings.warn") as warn:
with pytest.warns(UnknownCellMethodWarning, match=msg):
res = parse_cell_methods(cell_method_str)
self.assertIn(
"NetCDF variable contains unknown cell method 'min'",
warn.call_args[0][0],
)
self.assertEqual(res, expected)


if __name__ == "__main__":
tests.main()
assert res == expected