Skip to content

Commit

Permalink
feature #2253 tests for config_validate, mock logger in conftest
Browse files Browse the repository at this point in the history
  • Loading branch information
John-Sharples committed Aug 23, 2023
1 parent 6a46c0a commit 06872a3
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 4 deletions.
20 changes: 20 additions & 0 deletions internal/tests/pytests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest
import getpass
import shutil
from unittest import mock
from pathlib import Path
from netCDF4 import Dataset

Expand Down Expand Up @@ -80,12 +81,30 @@ def metplus_config(request):
the failed tests. To use this fixture, add metplus_config to the test
function arguments and set a variable called config to metplus_config, e.g.
config = metplus_config.
This fixture also replaces config.logger with a MagicMock object. This
allows tests to assert the logger was called with a specific message.
e.g.
def test_example(metplus_config):
config = metplus_config
some_function(config)
config.logger.info.assert_called_once_with("Info message")
config.logger.error.assert_not_called()
See documentation for unittest.mock for full functionality.
"""
script_dir = os.path.dirname(__file__)
args = [os.path.join(script_dir, "minimum_pytest.conf")]
config = config_metplus.setup(args)

# Set mock logger
old_logger = config.logger
config.logger = mock.MagicMock()

yield config

config.logger = old_logger
# don't remove output base if test fails
if request.node.rep_call.failed:
return
Expand Down Expand Up @@ -115,6 +134,7 @@ def read_configs(extra_configs):

return read_configs


@pytest.fixture(scope="module")
def make_dummy_nc():
return make_nc
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
////////////////////////////////////////////////////////////////////////////////
// Fake config for testing config_validate.py
//
censor_thresh = [];
censor_val = [];
cat_thresh = [ NA ];
cnt_thresh = [ NA ];

//
// Forecast and observation fields to be verified
//
fcst = {
${METPLUS_FCST_FILE_TYPE}
${METPLUS_FCST_FIELD}
}

obs = {
${METPLUS_OBS_FILE_TYPE}
${METPLUS_OBS_FIELD}
}
////////////////////////////////////////////////////////////////////////////////
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/usr/bin/env python3

import pytest

from unittest import mock
import pprint
import os
from datetime import datetime

from metplus.util.config_validate import *
from metplus.util import config_validate as cv


@pytest.mark.parametrize(
Expand Down Expand Up @@ -51,7 +51,7 @@
@pytest.mark.util
def test_is_var_item_valid(metplus_config, item_list, extension, is_valid):
conf = metplus_config
assert is_var_item_valid(item_list, '1', extension, conf)[0] == is_valid
assert cv.is_var_item_valid(item_list, '1', extension, conf)[0] == is_valid


@pytest.mark.parametrize(
Expand Down Expand Up @@ -97,4 +97,94 @@ def test_is_var_item_valid_levels(metplus_config, item_list, configs_to_set, is_
for key, value in configs_to_set.items():
conf.set('config', key, value)

assert is_var_item_valid(item_list, '1', 'LEVELS', conf)[0] == is_valid
assert cv.is_var_item_valid(item_list, '1', 'LEVELS', conf)[0] == is_valid



@pytest.mark.parametrize(
'deprecated_list, expected',
[
([], (True, [])),
(['METPLUS_FCST_FILE_TYPE'], (False, [])),
(['SOME_OTHER_CONFIG_ITEM'], (True, [])),
]
)
@pytest.mark.util
def test_check_for_deprecated_met_config(metplus_config, deprecated_list, expected):
script_dir = os.path.dirname(__file__)
met_config = os.path.join(script_dir, 'met_config_validate.conf')

metplus_config.set('config', 'TEST_CONFIG_FILE', met_config)

with mock.patch.object(cv, 'DEPRECATED_MET_LIST', deprecated_list):
actual = cv.check_for_deprecated_met_config(metplus_config)
assert actual == expected


@pytest.mark.util
def test_check_for_deprecated_config_simple(metplus_config):
actual = cv.check_for_deprecated_config(metplus_config)
assert actual == (True, [])
metplus_config.logger.error.assert_not_called


@pytest.mark.parametrize(
'dep_item,deprecated_dict, expected, err_msgs',
[
(
"TEST_DEPRECATED",
{
'upgrade': 'ensemble',
'alt': 'ice cream',
'copy': True
},
(False, ["sed -i 's|^TEST_DEPRECATED|ice cream|g' dir/config1.conf", "sed -i 's|{TEST_DEPRECATED}|{ice cream}|g' dir/config1.conf"]),
['DEPRECATED CONFIG ITEMS WERE FOUND. PLEASE FOLLOW THE INSTRUCTIONS TO UPDATE THE CONFIG FILES',
'TEST_DEPRECATED should be replaced with ice cream'],
),
(
"TEST_DEPRECATED_<n>",
{
'upgrade': 'ensemble',
'alt': 'nth degree',
'copy': False
},
(False, []),
['DEPRECATED CONFIG ITEMS WERE FOUND. PLEASE FOLLOW THE INSTRUCTIONS TO UPDATE THE CONFIG FILES'],
),
(
"TEST_DEPRECATED_NO_ALT",
{},
(False, []),
['DEPRECATED CONFIG ITEMS WERE FOUND. PLEASE FOLLOW THE INSTRUCTIONS TO UPDATE THE CONFIG FILES',
'TEST_DEPRECATED_NO_ALT should be removed'],
),
(
"TEST_DEPRECATED_NO_dict",
[],
(True, []),
[],
),
]
)
@pytest.mark.util
def test_check_for_deprecated_config(metplus_config,
dep_item,
deprecated_dict,
expected,
err_msgs):

depr_dict = {dep_item: deprecated_dict}
config = metplus_config
config.set('config', dep_item.replace('<n>','2'), 'old value')
config.set('config', 'CONFIG_INPUT', 'dir/config1.conf')

with mock.patch.object(cv, 'DEPRECATED_DICT', depr_dict):
actual = cv.check_for_deprecated_config(metplus_config)
assert actual == expected

if err_msgs:
for msg in err_msgs:
config.logger.error.assert_any_call(msg)
else:
config.logger.error.assert_not_called
19 changes: 19 additions & 0 deletions internal/tests/pytests/util/constants/test_constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import pytest
from metplus.util.constants import DEPRECATED_DICT

@pytest.mark.util
def test_deprecated_dict():
"""
Test that the structure of DEPRECATED_DICT is as expected.
If not config_validate may give unexpected answers, and
will not necessarily raise an error.
"""
allowed_keys = {'alt','copy','upgrade'}
allowed_upgrade_values = {'ensemble'}

for _, v in DEPRECATED_DICT.items():
assert isinstance(v, dict)
assert set(v.keys()).issubset(allowed_keys)

if 'upgrade' in v.keys():
assert v['upgrade'] in allowed_upgrade_values

0 comments on commit 06872a3

Please sign in to comment.