From 7cf568cdf4b47355e884914d8160efab104d242a Mon Sep 17 00:00:00 2001 From: Ronnie Dutta <61982285+MetRonnie@users.noreply.github.com> Date: Thu, 3 Jun 2021 14:39:26 +0100 Subject: [PATCH] Refactor cycling_type unit test fixture --- tests/unit/conftest.py | 24 ++--- tests/unit/test_config.py | 162 ++++++++++++++++++-------------- tests/unit/test_task_trigger.py | 19 ++-- 3 files changed, 109 insertions(+), 96 deletions(-) diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index c029040cb52..22a58120fea 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -41,7 +41,7 @@ def tmp_run_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch): Args: reg: Workflow name. """ - def inner(reg: Optional[str] = None) -> Path: + def _tmp_run_dir(reg: Optional[str] = None) -> Path: cylc_run_dir = tmp_path / 'cylc-run' cylc_run_dir.mkdir(exist_ok=True) monkeypatch.setattr('cylc.flow.pathutil._CYLC_RUN_DIR', cylc_run_dir) @@ -52,32 +52,28 @@ def inner(reg: Optional[str] = None) -> Path: (run_dir / WorkflowFiles.Service.DIRNAME).mkdir(exist_ok=True) return run_dir return cylc_run_dir - return inner + return _tmp_run_dir @pytest.fixture -def cycling_type(monkeypatch: pytest.MonkeyPatch): - """Initialize the cycling type according to cycling mode. +def set_cycling_type(monkeypatch: pytest.MonkeyPatch): + """Initialize the Cylc cycling type. + Args: - mode: The cycling mode. + ctype: The cycling type (integer or iso8601). time_zone: If using ISO8601/datetime cycling type, you can specify a custom time zone to use. """ - def _cycling_type( - mode: str = 'integer', time_zone: Optional[str] = None - ) -> str: - if mode == 'integer': - ctype = INTEGER_CYCLING_TYPE - else: - ctype = ISO8601_CYCLING_TYPE + def _set_cycling_type( + ctype: str = INTEGER_CYCLING_TYPE, time_zone: Optional[str] = None + ) -> None: class _DefaultCycler: TYPE = ctype monkeypatch.setattr( 'cylc.flow.cycling.loader.DefaultCycler', _DefaultCycler) if ctype == ISO8601_CYCLING_TYPE: iso8601_init(time_zone=time_zone) - return ctype - return _cycling_type + return _set_cycling_type @pytest.fixture diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index afa707b584f..361a7a98ade 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -23,6 +23,7 @@ from cylc.flow import CYLC_LOG from cylc.flow.config import WorkflowConfig from cylc.flow.cycling import loader +from cylc.flow.cycling.loader import INTEGER_CYCLING_TYPE, ISO8601_CYCLING_TYPE from cylc.flow.exceptions import WorkflowConfigError, PointParsingError from cylc.flow.workflow_files import WorkflowFiles from cylc.flow.wallclock import get_utc_mode, set_utc_mode @@ -226,112 +227,124 @@ def test_family_inheritance_and_quotes( @pytest.mark.parametrize( - 'scheduling_cfg, expected_icp, expected_opt_icp, expected_err', + ('cycling_type', 'scheduling_cfg', 'expected_icp', 'expected_opt_icp', + 'expected_err'), [ - ( # Lack of icp + pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': None, 'initial cycle point constraints': [] }, None, None, - (WorkflowConfigError, "requires an initial cycle point") + (WorkflowConfigError, "requires an initial cycle point"), + id="Lack of icp" ), - ( # Default icp for integer cycling type + pytest.param( + INTEGER_CYCLING_TYPE, { - 'cycling mode': 'integer', 'initial cycle point': None, 'initial cycle point constraints': [] }, '1', None, - None + None, + id="Default icp for integer cycling type" ), - ( # non-integer ICP for integer cycling type + pytest.param( + INTEGER_CYCLING_TYPE, { - 'cycling mode': 'integer', 'initial cycle point': "now", 'initial cycle point constraints': [] }, None, None, - (PointParsingError, "invalid literal for int()") + (PointParsingError, "invalid literal for int()"), + id="Non-integer ICP for integer cycling type" ), - ( # more non-integer ICP for integer cycling type + pytest.param( + INTEGER_CYCLING_TYPE, { - 'cycling mode': 'integer', 'initial cycle point': "20500808T0000Z", 'initial cycle point constraints': [] }, None, None, - (PointParsingError, "invalid literal for int()") + (PointParsingError, "invalid literal for int()"), + id="More non-integer ICP for integer cycling type" ), - ( # non-ISO8601 ICP for ISO8601 cycling type + pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': "1", 'initial cycle point constraints': [] }, None, None, - (PointParsingError, "Invalid ISO 8601 date representation") + (PointParsingError, "Invalid ISO 8601 date representation"), + id="Non-ISO8601 ICP for ISO8601 cycling type" ), - ( # "now" + pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': 'now', 'initial cycle point constraints': [] }, '20050102T0615+0530', '20050102T0615+0530', - None + None, + id="ICP = now" ), - ( # Constraints + pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2013', 'initial cycle point constraints': ['T00', 'T12'] }, '20130101T0000+0530', None, - None + None, + id="Constraints" ), - ( # Violated constraints + pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2021-01-20', 'initial cycle point constraints': ['--01-19', '--01-21'] }, None, None, - (WorkflowConfigError, "does not meet the constraints") + (WorkflowConfigError, "does not meet the constraints"), + id="Violated constraints" ), ] ) def test_process_icp( - scheduling_cfg: Dict[str, Any], expected_icp: Optional[str], - expected_opt_icp: Optional[str], - expected_err: Optional[Tuple[Type[Exception], str]], - monkeypatch: Fixture, cycling_type: Fixture): + cycling_type: str, + scheduling_cfg: Dict[str, Any], + expected_icp: Optional[str], + expected_opt_icp: Optional[str], + expected_err: Optional[Tuple[Type[Exception], str]], + monkeypatch: pytest.MonkeyPatch, set_cycling_type: Fixture +) -> None: """Test WorkflowConfig.process_initial_cycle_point(). "now" is assumed to be 2005-01-02T06:15+0530 Params: + cycling_type: Workflow cycling type. scheduling_cfg: 'scheduling' section of workflow config. expected_icp: The expected icp value that gets set. expected_opt_icp: The expected value of options.icp that gets set (this gets stored in the workflow DB). expected_err: Exception class expected to be raised plus the message. """ - cycling_type(scheduling_cfg['cycling mode'], time_zone="+0530") - mocked_config = Mock() + set_cycling_type(cycling_type, time_zone="+0530") + mocked_config = Mock(cycling_type=cycling_type) mocked_config.cfg = { 'scheduling': scheduling_cfg } - mocked_config.cycling_type = cycling_type(scheduling_cfg['cycling mode'], time_zone="+0530") mocked_config.options.icp = None monkeypatch.setattr('cylc.flow.config.get_current_time_string', lambda: '20050102T0615+0530') @@ -358,8 +371,10 @@ def test_process_icp( ('now', '20050102T0615+0530'), (None, '18990501T0000+0530')] ) -def test_process_startcp(startcp: Optional[str], expected: str, - monkeypatch: Fixture, cycling_type: Fixture): +def test_process_startcp( + startcp: Optional[str], expected: str, + monkeypatch: pytest.MonkeyPatch, set_cycling_type: Fixture +) -> None: """Test WorkflowConfig.process_start_cycle_point(). An icp of 1899-05-01T00+0530 is assumed, and "now" is assumed to be @@ -369,7 +384,7 @@ def test_process_startcp(startcp: Optional[str], expected: str, startcp: The start cycle point given by cli option. expected: The expected startcp value that gets set. """ - cycling_type('', time_zone="+0530") + set_cycling_type(ISO8601_CYCLING_TYPE, time_zone="+0530") mocked_config = Mock(initial_point='18990501T0000+0530') mocked_config.options.startcp = startcp monkeypatch.setattr('cylc.flow.config.get_current_time_string', @@ -380,11 +395,11 @@ def test_process_startcp(startcp: Optional[str], expected: str, @pytest.mark.parametrize( - 'scheduling_cfg, options_fcp, expected_fcp, expected_err', + 'cycling_type, scheduling_cfg, options_fcp, expected_fcp, expected_err', [ pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2021', 'final cycle point': None, 'final cycle point constraints': [] @@ -395,8 +410,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="No fcp" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2016', 'final cycle point': '2021', 'final cycle point constraints': [] @@ -407,8 +422,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="fcp in cfg" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2016', 'final cycle point': '2021', 'final cycle point constraints': [] @@ -419,8 +434,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="Overriden by cli option" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2017-02-11', 'final cycle point': '+P4D', 'final cycle point constraints': [] @@ -431,8 +446,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="Relative fcp" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2017-02-11', 'final cycle point': '---04', 'final cycle point constraints': [] @@ -444,8 +459,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, # https://github.com/metomi/isodatetime/issues/80 ), pytest.param( + INTEGER_CYCLING_TYPE, { - 'cycling mode': 'integer', 'initial cycle point': '1', 'final cycle point': '4', 'final cycle point constraints': [] @@ -456,8 +471,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="Integer cycling" ), pytest.param( + INTEGER_CYCLING_TYPE, { - 'cycling mode': 'integer', 'initial cycle point': '1', 'final cycle point': '+P2', 'final cycle point constraints': [] @@ -468,8 +483,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="Relative fcp, integer cycling" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2013', 'final cycle point': '2009', 'final cycle point constraints': [] @@ -482,8 +497,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="fcp before icp" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2013', 'final cycle point': '-PT1S', 'final cycle point constraints': [] @@ -496,8 +511,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="Negative relative fcp" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2013', 'final cycle point': '2021', 'final cycle point constraints': ['T00', 'T12'] @@ -508,8 +523,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="Constraints" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2013', 'final cycle point': '2021-01-19', 'final cycle point constraints': ['--01-19', '--01-21'] @@ -520,8 +535,8 @@ def test_process_startcp(startcp: Optional[str], expected: str, id="Violated constraints" ), pytest.param( + ISO8601_CYCLING_TYPE, { - 'cycling mode': '', 'initial cycle point': '2013', 'final cycle point': '2021', 'final cycle point constraints': [] @@ -533,20 +548,25 @@ def test_process_startcp(startcp: Optional[str], expected: str, ), ] ) -def test_process_fcp(scheduling_cfg: dict, options_fcp: Optional[str], - expected_fcp: Optional[str], - expected_err: Optional[Tuple[Type[Exception], str]], - cycling_type: Fixture): +def test_process_fcp( + cycling_type: str, + scheduling_cfg: dict, + options_fcp: Optional[str], + expected_fcp: Optional[str], + expected_err: Optional[Tuple[Type[Exception], str]], + set_cycling_type: Fixture +) -> None: """Test WorkflowConfig.process_final_cycle_point(). Params: + cycling_type: Workflow cycling type. scheduling_cfg: 'scheduling' section of workflow config. options_fcp: The fcp set by cli option. expected_fcp: The expected fcp value that gets set. expected_err: Exception class expected to be raised plus the message. """ - cycling_type(scheduling_cfg['cycling mode'], time_zone='+0530') - mocked_config = Mock(cycling_type=scheduling_cfg['cycling mode']) + set_cycling_type(cycling_type, time_zone='+0530') + mocked_config = Mock(cycling_type=cycling_type) mocked_config.cfg = { 'scheduling': scheduling_cfg } @@ -800,30 +820,30 @@ def test_valid_rsync_includes_returns_correct_list(tmp_path): @pytest.mark.parametrize( - 'cycling_mode, runahead_limit, valid', + 'cycling_type, runahead_limit, valid', [ - ('integer', 'P14', True), - ('', 'P14', True), - ('', 'PT12H', True), - ('', 'P7D', True), - ('', 'P2W', True), - ('', '4', True), - - ('integer', 'PT12H', False), - ('integer', 'P7D', False), - ('integer', '4', False), - ('', '', False), - ('', 'asdf', False) + (INTEGER_CYCLING_TYPE, 'P14', True), + (ISO8601_CYCLING_TYPE, 'P14', True), + (ISO8601_CYCLING_TYPE, 'PT12H', True), + (ISO8601_CYCLING_TYPE, 'P7D', True), + (ISO8601_CYCLING_TYPE, 'P2W', True), + (ISO8601_CYCLING_TYPE, '4', True), + + (INTEGER_CYCLING_TYPE, 'PT12H', False), + (INTEGER_CYCLING_TYPE, 'P7D', False), + (INTEGER_CYCLING_TYPE, '4', False), + (ISO8601_CYCLING_TYPE, '', False), + (ISO8601_CYCLING_TYPE, 'asdf', False) ] ) def test_process_runahead_limit( - cycling_mode: str, runahead_limit: str, valid: bool, - cycling_type: Callable + cycling_type: str, runahead_limit: str, valid: bool, + set_cycling_type: Callable ) -> None: - mock_config = Mock(cycling_type=cycling_type(cycling_mode)) + set_cycling_type(cycling_type) + mock_config = Mock(cycling_type=cycling_type) mock_config.cfg = { 'scheduling': { - 'cycling mode': cycling_mode, 'runahead limit': runahead_limit } } diff --git a/tests/unit/test_task_trigger.py b/tests/unit/test_task_trigger.py index ea062626326..41c96823949 100644 --- a/tests/unit/test_task_trigger.py +++ b/tests/unit/test_task_trigger.py @@ -91,8 +91,8 @@ def test_check_exeption(): TaskTrigger.get_trigger_name("Foo:Elephant") -def test_get_parent_point(cycling_type): - cycling_type() +def test_get_parent_point(set_cycling_type): + set_cycling_type() one = get_point('1') two = get_point('2') @@ -112,8 +112,8 @@ def test_get_parent_point(cycling_type): assert trigger.get_parent_point(one) == two -def test_get_child_point(cycling_type): - cycling_type() +def test_get_child_point(set_cycling_type): + set_cycling_type() zero = get_point('0') one = get_point('1') @@ -143,8 +143,8 @@ def test_get_child_point(cycling_type): assert trigger.get_child_point(one, None) == two -def test_get_point(cycling_type): - cycling_type() +def test_get_point(set_cycling_type): + set_cycling_type() one = get_point('1') two = get_point('2') @@ -163,11 +163,8 @@ def test_get_point(cycling_type): assert trigger.get_point(one) == one -def test_str(cycling_type): - cycling_type() - - one = get_point('1') - two = get_point('2') +def test_str(set_cycling_type): + set_cycling_type() trigger = TaskTrigger('name', '1', 'output', offset_is_absolute=True) assert str(trigger) == 'name[1]:output'