Skip to content

Commit a2809ea

Browse files
Add unit tests (#150)
* Add unit tests * remove python version * more fixes * Restrict python version * Update pipeline.yml * feat: Add unit tests for shared.py to achieve 100% coverage (#151) Adds a comprehensive test suite for the `python_workflow_definition/shared.py` module, increasing test coverage to 100%. The new tests cover all functions in the module, including: - `get_kwargs` - `get_source_handles` - `convert_nodes_list_to_dict` - `update_node_names` - `set_result_node` - `remove_result` In addition to happy path scenarios, the tests also cover edge cases such as empty list inputs and error conditions, ensuring the robustness of the module. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent 1660b50 commit a2809ea

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

.github/workflows/pipeline.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,38 @@ jobs:
159159
jupyter-book build . --path-output public
160160
mv public/_build/html public_html
161161
touch public_html/.nojekyll
162+
163+
unittest_matrix:
164+
runs-on: ${{ matrix.operating-system }}
165+
strategy:
166+
matrix:
167+
include:
168+
- operating-system: macos-latest
169+
python-version: '3.12'
170+
171+
- operating-system: ubuntu-latest
172+
python-version: '3.12'
173+
174+
- operating-system: ubuntu-latest
175+
python-version: '3.11'
176+
177+
steps:
178+
- uses: actions/checkout@v4
179+
- name: Setup environment
180+
shell: bash -l {0}
181+
run: |
182+
echo -e "channels:\n - conda-forge\n" > .condarc
183+
sed '/- python/d' binder/environment.yml > environment.yml
184+
- name: Setup Mambaforge
185+
uses: conda-incubator/setup-miniconda@v3
186+
with:
187+
python-version: ${{ matrix.python-version }}
188+
miniforge-version: latest
189+
condarc-file: .condarc
190+
environment-file: environment.yml
191+
- name: Test
192+
shell: bash -l {0}
193+
timeout-minutes: 30
194+
run: |
195+
pip install . --no-deps --no-build-isolation
196+
python -m unittest discover tests

tests/test_shared.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import unittest
2+
from python_workflow_definition.shared import (
3+
get_dict,
4+
get_list,
5+
get_kwargs,
6+
get_source_handles,
7+
convert_nodes_list_to_dict,
8+
update_node_names,
9+
set_result_node,
10+
remove_result,
11+
EDGES_LABEL,
12+
NODES_LABEL,
13+
SOURCE_LABEL,
14+
SOURCE_PORT_LABEL,
15+
TARGET_LABEL,
16+
TARGET_PORT_LABEL,
17+
)
18+
19+
20+
class TestShared(unittest.TestCase):
21+
def test_get_dict(self):
22+
self.assertEqual({"a": 1, "b": 2, "c": 3}, get_dict(a=1, b=2, c=3))
23+
24+
def test_get_list(self):
25+
self.assertEqual([1, 2, 3], get_list(a=1, b=2, c=3))
26+
27+
def test_get_kwargs(self):
28+
lst = [
29+
{
30+
TARGET_PORT_LABEL: "a",
31+
SOURCE_LABEL: "s1",
32+
SOURCE_PORT_LABEL: "sp1",
33+
},
34+
{
35+
TARGET_PORT_LABEL: "b",
36+
SOURCE_LABEL: "s2",
37+
SOURCE_PORT_LABEL: "sp2",
38+
},
39+
]
40+
self.assertEqual(
41+
{
42+
"a": {SOURCE_LABEL: "s1", SOURCE_PORT_LABEL: "sp1"},
43+
"b": {SOURCE_LABEL: "s2", SOURCE_PORT_LABEL: "sp2"},
44+
},
45+
get_kwargs(lst),
46+
)
47+
48+
def test_get_kwargs_empty(self):
49+
self.assertEqual({}, get_kwargs([]))
50+
51+
def test_get_source_handles(self):
52+
edges_lst = [
53+
{SOURCE_LABEL: "s1", SOURCE_PORT_LABEL: "sp1"},
54+
{SOURCE_LABEL: "s1", SOURCE_PORT_LABEL: "sp2"},
55+
{SOURCE_LABEL: "s2", SOURCE_PORT_LABEL: "sp3"},
56+
]
57+
self.assertEqual(
58+
{"s1": ["sp1", "sp2"], "s2": ["sp3"]}, get_source_handles(edges_lst)
59+
)
60+
61+
def test_get_source_handles_no_port(self):
62+
edges_lst = [
63+
{SOURCE_LABEL: "s1", SOURCE_PORT_LABEL: None},
64+
{SOURCE_LABEL: "s1", SOURCE_PORT_LABEL: None},
65+
]
66+
self.assertEqual({"s1": [0, 1]}, get_source_handles(edges_lst))
67+
68+
def test_get_source_handles_empty(self):
69+
self.assertEqual({}, get_source_handles([]))
70+
71+
def test_convert_nodes_list_to_dict(self):
72+
nodes_list = [
73+
{"id": 1, "name": "n1"},
74+
{"id": 2, "value": "v2"},
75+
{"id": 0, "name": "n0"},
76+
]
77+
self.assertEqual(
78+
{"0": "n0", "1": "n1", "2": "v2"},
79+
convert_nodes_list_to_dict(nodes_list),
80+
)
81+
82+
def test_convert_nodes_list_to_dict_empty(self):
83+
self.assertEqual({}, convert_nodes_list_to_dict([]))
84+
85+
def test_update_node_names(self):
86+
workflow_dict = {
87+
NODES_LABEL: [
88+
{"id": 0, "type": "input", "name": ""},
89+
{"id": 1, "type": "input", "name": ""},
90+
{"id": 2, "type": "input", "name": ""},
91+
{"id": 3, "type": "other", "name": ""},
92+
],
93+
EDGES_LABEL: [
94+
{SOURCE_LABEL: 0, TARGET_PORT_LABEL: "a"},
95+
{SOURCE_LABEL: 1, TARGET_PORT_LABEL: "b"},
96+
{SOURCE_LABEL: 2, TARGET_PORT_LABEL: "a"},
97+
],
98+
}
99+
update_node_names(workflow_dict)
100+
self.assertEqual("a_0", workflow_dict[NODES_LABEL][0]["name"])
101+
self.assertEqual("b", workflow_dict[NODES_LABEL][1]["name"])
102+
self.assertEqual("a_1", workflow_dict[NODES_LABEL][2]["name"])
103+
104+
def test_set_result_node(self):
105+
workflow_dict = {
106+
NODES_LABEL: [{"id": 0, "type": "input"}],
107+
EDGES_LABEL: [],
108+
}
109+
set_result_node(workflow_dict)
110+
self.assertEqual(2, len(workflow_dict[NODES_LABEL]))
111+
self.assertEqual("output", workflow_dict[NODES_LABEL][1]["type"])
112+
self.assertEqual(1, len(workflow_dict[EDGES_LABEL]))
113+
114+
def test_set_result_node_already_exists(self):
115+
workflow_dict = {
116+
NODES_LABEL: [
117+
{"id": 0, "type": "input"},
118+
{"id": 1, "type": "output"},
119+
],
120+
EDGES_LABEL: [{SOURCE_LABEL: 0, TARGET_LABEL: 1}],
121+
}
122+
set_result_node(workflow_dict)
123+
self.assertEqual(3, len(workflow_dict[NODES_LABEL]))
124+
self.assertEqual("output", workflow_dict[NODES_LABEL][2]["type"])
125+
self.assertEqual(2, len(workflow_dict[EDGES_LABEL]))
126+
127+
def test_set_result_node_no_end_node(self):
128+
workflow_dict = {
129+
NODES_LABEL: [{"id": 0}, {"id": 1}],
130+
EDGES_LABEL: [
131+
{SOURCE_LABEL: 0, TARGET_LABEL: 1},
132+
{SOURCE_LABEL: 1, TARGET_LABEL: 0},
133+
],
134+
}
135+
with self.assertRaises(IndexError):
136+
set_result_node(workflow_dict)
137+
138+
def test_remove_result(self):
139+
workflow_dict = {
140+
NODES_LABEL: [
141+
{"id": 0, "type": "input"},
142+
{"id": 1, "type": "output"},
143+
],
144+
EDGES_LABEL: [{SOURCE_LABEL: 0, TARGET_LABEL: 1}],
145+
}
146+
new_workflow = remove_result(workflow_dict)
147+
self.assertEqual(1, len(new_workflow[NODES_LABEL]))
148+
self.assertEqual(0, len(new_workflow[EDGES_LABEL]))
149+
150+
def test_remove_result_no_output(self):
151+
workflow_dict = {
152+
NODES_LABEL: [{"id": 0, "type": "input"}],
153+
EDGES_LABEL: [],
154+
}
155+
with self.assertRaises(IndexError):
156+
remove_result(workflow_dict)

0 commit comments

Comments
 (0)