Skip to content

Commit 2a67e62

Browse files
author
Alan Christie
committed
feat: Validator now has better tag-level validation
1 parent 87a9e3f commit 2a67e62

7 files changed

+376
-17
lines changed

tests/test_decoder.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,21 @@
3030
_SIMPLE_PYTHON_MOLPROPS_WORKFLOW: Dict[str, Any] = yaml.safe_load(workflow_file)
3131
assert _SIMPLE_PYTHON_MOLPROPS_WORKFLOW
3232

33+
_DUPLICATE_WORKFLOW_VARIABLE_NAMES_WORKFLOW_FILE: str = os.path.join(
34+
os.path.dirname(__file__),
35+
"workflow-definitions",
36+
"duplicate-workflow-variable-names.yaml",
37+
)
38+
with open(
39+
_DUPLICATE_WORKFLOW_VARIABLE_NAMES_WORKFLOW_FILE, "r", encoding="utf8"
40+
) as workflow_file:
41+
_DUPLICATE_WORKFLOW_VARIABLE_NAMES_WORKFLOW: Dict[str, Any] = yaml.safe_load(
42+
workflow_file
43+
)
44+
assert _DUPLICATE_WORKFLOW_VARIABLE_NAMES_WORKFLOW
45+
3346

34-
def test_validate_minimal():
47+
def test_validate_schema_for_minimal():
3548
# Arrange
3649

3750
# Act
@@ -41,7 +54,7 @@ def test_validate_minimal():
4154
assert error is None
4255

4356

44-
def test_validate_minimal_get_step_names():
57+
def test_minimal_get_step_names():
4558
# Arrange
4659

4760
# Act
@@ -51,7 +64,7 @@ def test_validate_minimal_get_step_names():
5164
assert names == ["step-1"]
5265

5366

54-
def test_validate_without_name():
67+
def test_workflow_without_name():
5568
# Arrange
5669
workflow = _MINIMAL_WORKFLOW.copy()
5770
_ = workflow.pop("name", None)
@@ -63,7 +76,7 @@ def test_validate_without_name():
6376
assert error == "'name' is a required property"
6477

6578

66-
def test_validate_name_with_spaces():
79+
def test_workflow_name_with_spaces():
6780
# Arrange
6881
workflow = _MINIMAL_WORKFLOW.copy()
6982
workflow["name"] = "workflow with spaces"
@@ -77,7 +90,7 @@ def test_validate_name_with_spaces():
7790
)
7891

7992

80-
def test_validate_shortcut_example_1():
93+
def test_validate_schema_for_shortcut_example_1():
8194
# Arrange
8295

8396
# Act
@@ -87,7 +100,7 @@ def test_validate_shortcut_example_1():
87100
assert error is None
88101

89102

90-
def test_validate_python_simple_molprops():
103+
def test_validate_schema_for_python_simple_molprops():
91104
# Arrange
92105

93106
# Act
@@ -97,15 +110,16 @@ def test_validate_python_simple_molprops():
97110
assert error is None
98111

99112

100-
def test_get_workflow_variables():
113+
def test_get_workflow_variables_for_smiple_python_molprops():
101114
# Arrange
102115

103116
# Act
104117
wf_variables = decoder.get_variable_names(_SIMPLE_PYTHON_MOLPROPS_WORKFLOW)
105118

106119
# Assert
107-
assert len(wf_variables) == 1
120+
assert len(wf_variables) == 2
108121
assert "candidateMolecules" in wf_variables
122+
assert "clusteredMolecules" in wf_variables
109123

110124

111125
def test_get_workflow_description():
@@ -138,3 +152,15 @@ def test_get_workflow_steps():
138152
assert len(steps) == 2
139153
assert steps[0]["name"] == "step1"
140154
assert steps[1]["name"] == "step2"
155+
156+
157+
def test_get_workflow_variables_for_duplicate_variables():
158+
# Arrange
159+
160+
# Act
161+
names = decoder.get_variable_names(_DUPLICATE_WORKFLOW_VARIABLE_NAMES_WORKFLOW)
162+
163+
# Assert
164+
assert len(names) == 2
165+
assert names[0] == "x"
166+
assert names[1] == "x"

tests/test_workflow_validator_for_create_level.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_validate_example_smiles_to_file():
6464
assert error.error_msg is None
6565

6666

67-
def test_validate_example_tow_step_nop():
67+
def test_validate_example_two_step_nop():
6868
# Arrange
6969
workflow_file: str = os.path.join(
7070
os.path.dirname(__file__), "workflow-definitions", "example-two-step-nop.yaml"

tests/test_workflow_validator_for_run_level.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ def test_validate_example_nop_file():
2929
assert error.error_msg is None
3030

3131

32+
def test_validate_duplicate_step_names():
33+
# Arrange
34+
workflow_file: str = os.path.join(
35+
os.path.dirname(__file__), "workflow-definitions", "duplicate-step-names.yaml"
36+
)
37+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
38+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
39+
assert workflow
40+
41+
# Act
42+
error = WorkflowValidator.validate(
43+
level=ValidationLevel.RUN,
44+
workflow_definition=workflow,
45+
)
46+
47+
# Assert
48+
assert error.error_num == 2
49+
assert error.error_msg == ["Duplicate step names found: step-1"]
50+
51+
3252
def test_validate_example_smiles_to_file():
3353
# Arrange
3454
workflow_file: str = os.path.join(
@@ -49,7 +69,7 @@ def test_validate_example_smiles_to_file():
4969
assert error.error_msg is None
5070

5171

52-
def test_validate_example_tow_step_nop():
72+
def test_validate_example_two_step_nop():
5373
# Arrange
5474
workflow_file: str = os.path.join(
5575
os.path.dirname(__file__), "workflow-definitions", "example-two-step-nop.yaml"
@@ -87,3 +107,47 @@ def test_validate_shortcut_example_1():
87107
# Assert
88108
assert error.error_num == 0
89109
assert error.error_msg is None
110+
111+
112+
def test_validate_simple_python_molprops():
113+
# Arrange
114+
workflow_file: str = os.path.join(
115+
os.path.dirname(__file__), "workflow-definitions", "simple-python-molprops.yaml"
116+
)
117+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
118+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
119+
assert workflow
120+
variables = {"candidateMolecules": "input.sdf", "clusteredMolecules": "output.sdf"}
121+
122+
# Act
123+
error = WorkflowValidator.validate(
124+
level=ValidationLevel.RUN,
125+
workflow_definition=workflow,
126+
variables=variables,
127+
)
128+
129+
# Assert
130+
assert error.error_num == 0
131+
assert error.error_msg is None
132+
133+
134+
def test_validate_duplicate_workflow_variable_names():
135+
# Arrange
136+
workflow_file: str = os.path.join(
137+
os.path.dirname(__file__),
138+
"workflow-definitions",
139+
"duplicate-workflow-variable-names.yaml",
140+
)
141+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
142+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
143+
assert workflow
144+
145+
# Act
146+
error = WorkflowValidator.validate(
147+
level=ValidationLevel.TAG,
148+
workflow_definition=workflow,
149+
)
150+
151+
# Assert
152+
assert error.error_num == 3
153+
assert error.error_msg == ["Duplicate workflow variable names found: x"]
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import os
2+
from typing import Any
3+
4+
import pytest
5+
import yaml
6+
7+
pytestmark = pytest.mark.unit
8+
9+
from workflow.workflow_validator import ValidationLevel, WorkflowValidator
10+
11+
12+
def test_validate_example_nop_file():
13+
# Arrange
14+
workflow_file: str = os.path.join(
15+
os.path.dirname(__file__), "workflow-definitions", "example-nop-fail.yaml"
16+
)
17+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
18+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
19+
assert workflow
20+
21+
# Act
22+
error = WorkflowValidator.validate(
23+
level=ValidationLevel.TAG,
24+
workflow_definition=workflow,
25+
)
26+
27+
# Assert
28+
assert error.error_num == 0
29+
assert error.error_msg is None
30+
31+
32+
def test_validate_duplicate_step_names():
33+
# Arrange
34+
workflow_file: str = os.path.join(
35+
os.path.dirname(__file__), "workflow-definitions", "duplicate-step-names.yaml"
36+
)
37+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
38+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
39+
assert workflow
40+
41+
# Act
42+
error = WorkflowValidator.validate(
43+
level=ValidationLevel.TAG,
44+
workflow_definition=workflow,
45+
)
46+
47+
# Assert
48+
assert error.error_num == 2
49+
assert error.error_msg == ["Duplicate step names found: step-1"]
50+
51+
52+
def test_validate_example_smiles_to_file():
53+
# Arrange
54+
workflow_file: str = os.path.join(
55+
os.path.dirname(__file__), "workflow-definitions", "example-smiles-to-file.yaml"
56+
)
57+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
58+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
59+
assert workflow
60+
61+
# Act
62+
error = WorkflowValidator.validate(
63+
level=ValidationLevel.TAG,
64+
workflow_definition=workflow,
65+
)
66+
67+
# Assert
68+
assert error.error_num == 0
69+
assert error.error_msg is None
70+
71+
72+
def test_validate_example_two_step_nop():
73+
# Arrange
74+
workflow_file: str = os.path.join(
75+
os.path.dirname(__file__), "workflow-definitions", "example-two-step-nop.yaml"
76+
)
77+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
78+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
79+
assert workflow
80+
81+
# Act
82+
error = WorkflowValidator.validate(
83+
level=ValidationLevel.TAG,
84+
workflow_definition=workflow,
85+
)
86+
87+
# Assert
88+
assert error.error_num == 0
89+
assert error.error_msg is None
90+
91+
92+
def test_validate_shortcut_example_1():
93+
# Arrange
94+
workflow_file: str = os.path.join(
95+
os.path.dirname(__file__), "workflow-definitions", "shortcut-example-1.yaml"
96+
)
97+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
98+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
99+
assert workflow
100+
101+
# Act
102+
error = WorkflowValidator.validate(
103+
level=ValidationLevel.TAG,
104+
workflow_definition=workflow,
105+
)
106+
107+
# Assert
108+
assert error.error_num == 0
109+
assert error.error_msg is None
110+
111+
112+
def test_validate_simple_python_molprops():
113+
# Arrange
114+
workflow_file: str = os.path.join(
115+
os.path.dirname(__file__), "workflow-definitions", "simple-python-molprops.yaml"
116+
)
117+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
118+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
119+
assert workflow
120+
121+
# Act
122+
error = WorkflowValidator.validate(
123+
level=ValidationLevel.TAG,
124+
workflow_definition=workflow,
125+
)
126+
127+
# Assert
128+
assert error.error_num == 0
129+
assert error.error_msg is None
130+
131+
132+
def test_validate_duplicate_workflow_variable_names():
133+
# Arrange
134+
workflow_file: str = os.path.join(
135+
os.path.dirname(__file__),
136+
"workflow-definitions",
137+
"duplicate-workflow-variable-names.yaml",
138+
)
139+
with open(workflow_file, "r", encoding="utf8") as workflow_file:
140+
workflow: dict[str, Any] = yaml.load(workflow_file, Loader=yaml.FullLoader)
141+
assert workflow
142+
143+
# Act
144+
error = WorkflowValidator.validate(
145+
level=ValidationLevel.TAG,
146+
workflow_definition=workflow,
147+
)
148+
149+
# Assert
150+
assert error.error_num == 3
151+
assert error.error_msg == ["Duplicate workflow variable names found: x"]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
kind: DataManagerWorkflow
3+
kind-version: "2024.1"
4+
name: duplicate-step-names
5+
steps:
6+
- name: step-1
7+
specification: >-
8+
{}
9+
- name: step-1
10+
specification: >-
11+
{}

0 commit comments

Comments
 (0)