Skip to content

Commit e90a313

Browse files
author
Alan Christie
committed
fix: Better testing of validation (job must be present)
1 parent b61baa7 commit e90a313

7 files changed

+100
-14
lines changed

tests/test_decoder.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from typing import Any, Dict
2+
from typing import Any
33

44
import pytest
55
import yaml
@@ -13,21 +13,21 @@
1313
os.path.dirname(__file__), "workflow-definitions", "minimal.yaml"
1414
)
1515
with open(_MINIMAL_WORKFLOW_FILE, "r", encoding="utf8") as workflow_file:
16-
_MINIMAL_WORKFLOW: Dict[str, Any] = yaml.safe_load(workflow_file)
16+
_MINIMAL_WORKFLOW: dict[str, Any] = yaml.safe_load(workflow_file)
1717
assert _MINIMAL_WORKFLOW
1818

1919
_SHORTCUT_EXAMPLE_1_WORKFLOW_FILE: str = os.path.join(
2020
os.path.dirname(__file__), "workflow-definitions", "shortcut-example-1.yaml"
2121
)
2222
with open(_SHORTCUT_EXAMPLE_1_WORKFLOW_FILE, "r", encoding="utf8") as workflow_file:
23-
_SHORTCUT_EXAMPLE_1_WORKFLOW: Dict[str, Any] = yaml.safe_load(workflow_file)
23+
_SHORTCUT_EXAMPLE_1_WORKFLOW: dict[str, Any] = yaml.safe_load(workflow_file)
2424
assert _SHORTCUT_EXAMPLE_1_WORKFLOW
2525

2626
_SIMPLE_PYTHON_MOLPROPS_WORKFLOW_FILE: str = os.path.join(
2727
os.path.dirname(__file__), "workflow-definitions", "simple-python-molprops.yaml"
2828
)
2929
with open(_SIMPLE_PYTHON_MOLPROPS_WORKFLOW_FILE, "r", encoding="utf8") as workflow_file:
30-
_SIMPLE_PYTHON_MOLPROPS_WORKFLOW: Dict[str, Any] = yaml.safe_load(workflow_file)
30+
_SIMPLE_PYTHON_MOLPROPS_WORKFLOW: dict[str, Any] = yaml.safe_load(workflow_file)
3131
assert _SIMPLE_PYTHON_MOLPROPS_WORKFLOW
3232

3333
_SIMPLE_PYTHON_MOLPROPS_WITH_OPTIONS_WORKFLOW_FILE: str = os.path.join(
@@ -38,7 +38,7 @@
3838
with open(
3939
_SIMPLE_PYTHON_MOLPROPS_WITH_OPTIONS_WORKFLOW_FILE, "r", encoding="utf8"
4040
) as workflow_file:
41-
_SIMPLE_PYTHON_MOLPROPS_WITH_OPTIONS_WORKFLOW: Dict[str, Any] = yaml.safe_load(
41+
_SIMPLE_PYTHON_MOLPROPS_WITH_OPTIONS_WORKFLOW: dict[str, Any] = yaml.safe_load(
4242
workflow_file
4343
)
4444
assert _SIMPLE_PYTHON_MOLPROPS_WITH_OPTIONS_WORKFLOW
@@ -49,7 +49,7 @@
4949
"simple-python-parallel.yaml",
5050
)
5151
with open(_SIMPLE_PYTHON_PARALLEL_FILE, "r", encoding="utf8") as workflow_file:
52-
_SIMPLE_PYTHON_PARALLEL_WORKFLOW: Dict[str, Any] = yaml.safe_load(workflow_file)
52+
_SIMPLE_PYTHON_PARALLEL_WORKFLOW: dict[str, Any] = yaml.safe_load(workflow_file)
5353
assert _SIMPLE_PYTHON_PARALLEL_WORKFLOW
5454

5555
_STEP_SPECIFICATION_VARIABLE_NAMES_WORKFLOW_FILE: str = os.path.join(
@@ -60,7 +60,7 @@
6060
with open(
6161
_STEP_SPECIFICATION_VARIABLE_NAMES_WORKFLOW_FILE, "r", encoding="utf8"
6262
) as workflow_file:
63-
_STEP_SPECIFICATION_VARIABLE_NAMES_WORKFLOW: Dict[str, Any] = yaml.safe_load(
63+
_STEP_SPECIFICATION_VARIABLE_NAMES_WORKFLOW: dict[str, Any] = yaml.safe_load(
6464
workflow_file
6565
)
6666
assert _STEP_SPECIFICATION_VARIABLE_NAMES_WORKFLOW

tests/test_workflow_validator_for_create_level.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
from tests.wapi_adapter import UnitTestWorkflowAPIAdapter
1111
from workflow.workflow_validator import ValidationLevel, WorkflowValidator
1212

13+
_NO_SUCH_JOB_WORKFLOW_FILE: str = os.path.join(
14+
os.path.dirname(__file__), "workflow-definitions", "no-such-job.yaml"
15+
)
16+
with open(_NO_SUCH_JOB_WORKFLOW_FILE, "r", encoding="utf8") as workflow_file:
17+
_NO_SUCH_JOB_WORKFLOW: dict[str, Any] = yaml.safe_load(workflow_file)
18+
assert _NO_SUCH_JOB_WORKFLOW
19+
1320

1421
@pytest.fixture
1522
def wapi():
@@ -33,6 +40,22 @@ def test_validate_minimal(wapi):
3340
assert error.error_msg is None
3441

3542

43+
def test_validate_no_such_job(wapi):
44+
# Arrange
45+
wapi_adapter = wapi
46+
47+
# Act
48+
error = WorkflowValidator.validate(
49+
level=ValidationLevel.CREATE,
50+
workflow_definition=_NO_SUCH_JOB_WORKFLOW,
51+
wapi_adapter=wapi_adapter,
52+
)
53+
54+
# Assert
55+
assert error.error_num == 0
56+
assert error.error_msg is None
57+
58+
3659
def test_validate_example_nop_file(wapi):
3760
# Arrange
3861
wapi_adapter = wapi

tests/test_workflow_validator_for_run_level.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,39 @@
99
from tests.wapi_adapter import UnitTestWorkflowAPIAdapter
1010
from workflow.workflow_validator import ValidationLevel, WorkflowValidator
1111

12+
_NO_SUCH_JOB_WORKFLOW_FILE: str = os.path.join(
13+
os.path.dirname(__file__), "workflow-definitions", "no-such-job.yaml"
14+
)
15+
with open(_NO_SUCH_JOB_WORKFLOW_FILE, "r", encoding="utf8") as workflow_file:
16+
_NO_SUCH_JOB_WORKFLOW: dict[str, Any] = yaml.safe_load(workflow_file)
17+
assert _NO_SUCH_JOB_WORKFLOW
18+
1219

1320
@pytest.fixture
1421
def wapi():
1522
wapi_adapter = UnitTestWorkflowAPIAdapter()
1623
yield wapi_adapter
1724

1825

26+
def test_validate_no_such_job(wapi):
27+
# Arrange
28+
wapi_adapter = wapi
29+
30+
# Act
31+
error = WorkflowValidator.validate(
32+
level=ValidationLevel.RUN,
33+
workflow_definition=_NO_SUCH_JOB_WORKFLOW,
34+
wapi_adapter=wapi_adapter,
35+
)
36+
37+
# Assert
38+
assert error.error_num != 0
39+
assert error.error_msg != None
40+
assert len(error.error_msg) == 1
41+
assert error.error_msg[0].startswith("Step ")
42+
assert error.error_msg[0].endswith(" is not present")
43+
44+
1945
def test_validate_example_nop_file(wapi):
2046
# Arrange
2147
wapi_adapter = wapi

tests/test_workflow_validator_for_tag_level.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,36 @@
99
from tests.wapi_adapter import UnitTestWorkflowAPIAdapter
1010
from workflow.workflow_validator import ValidationLevel, WorkflowValidator
1111

12+
_NO_SUCH_JOB_WORKFLOW_FILE: str = os.path.join(
13+
os.path.dirname(__file__), "workflow-definitions", "no-such-job.yaml"
14+
)
15+
with open(_NO_SUCH_JOB_WORKFLOW_FILE, "r", encoding="utf8") as workflow_file:
16+
_NO_SUCH_JOB_WORKFLOW: dict[str, Any] = yaml.safe_load(workflow_file)
17+
assert _NO_SUCH_JOB_WORKFLOW
18+
1219

1320
@pytest.fixture
1421
def wapi():
1522
wapi_adapter = UnitTestWorkflowAPIAdapter()
1623
yield wapi_adapter
1724

1825

26+
def test_validate_no_such_job(wapi):
27+
# Arrange
28+
wapi_adapter = wapi
29+
30+
# Act
31+
error = WorkflowValidator.validate(
32+
level=ValidationLevel.TAG,
33+
workflow_definition=_NO_SUCH_JOB_WORKFLOW,
34+
wapi_adapter=wapi_adapter,
35+
)
36+
37+
# Assert
38+
assert error.error_num == 0
39+
assert error.error_msg is None
40+
41+
1942
def test_validate_example_nop_file(wapi):
2043
# Arrange
2144
wapi_adapter = wapi

tests/wapi_adapter.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,10 @@ def get_instance(self, *, instance_id: str) -> tuple[dict[str, Any], int]:
280280
def get_job(
281281
self, *, collection: str, job: str, version: str
282282
) -> tuple[dict[str, Any], int]:
283-
assert collection == _JOB_DEFINITIONS["collection"]
284-
assert job in _JOB_DEFINITIONS["jobs"]
283+
if collection != _JOB_DEFINITIONS["collection"]:
284+
return {}, 0
285+
if job not in _JOB_DEFINITIONS["jobs"]:
286+
return {}, 0
285287
assert version
286288

287289
jd = _JOB_DEFINITIONS["jobs"][job]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
kind: DataManagerWorkflow
3+
kind-version: "2025.2"
4+
name: workflow-minimal
5+
6+
steps:
7+
8+
- name: step-1
9+
specification:
10+
collection: a
11+
job: no-such-job
12+
version: "1.0.0"

workflow/workflow_validator.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ def _validate_run_level(
171171
)
172172

173173
# All of the jobs must be known to the DM
174+
errors: list[str] = []
174175
for step_name in get_step_names(workflow_definition):
175176
step_spec = get_step_specification(workflow_definition, step_name)
176177
j_collection: str = step_spec["collection"]
@@ -182,11 +183,10 @@ def _validate_run_level(
182183
version=j_version,
183184
)
184185
if not job:
185-
return ValidationResult(
186-
error_num=9,
187-
error_msg=[
188-
f"Step {step_name} Job ({j_collection}|{j_job}|{j_version}) is not present"
189-
],
186+
errors.append(
187+
f"Step {step_name} Job ({j_collection}|{j_job}|{j_version}) is not present"
190188
)
189+
if errors:
190+
return ValidationResult(error_num=9, error_msg=errors)
191191

192192
return _VALIDATION_SUCCESS

0 commit comments

Comments
 (0)