Passed
Push — main ( 162760...d261f2 )
by Eran
01:41
created

test_networkx   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 352
Duplicated Lines 23.86 %

Importance

Changes 0
Metric Value
wmc 30
eloc 241
dl 84
loc 352
rs 10
c 0
b 0
f 0

20 Functions

Rating   Name   Duplication   Size   Complexity  
A test_populate_nodes_adds_new_node() 0 13 1
A test_populate_nodes_empty_generator() 0 12 1
A test_networkx_builder_repeating_edges() 0 21 2
A test_networkx_builder__map_graph_model() 0 14 1
A test_returns_graph_type_for_graph() 0 7 1
A test_networkx_builder_repeating_nodes() 0 19 2
A test_populate_nodes_handles_invalid_parent_node_id() 14 14 1
A test_populate_nodes_updates_existing_node() 0 14 1
A test_populate_nodes_universe_node_parent_handling() 14 14 1
A test_networkx_builder_simple_tuple() 0 17 2
A test_populate_nodes_callable_label_returns_non_string() 15 15 1
A test_populate_nodes_handles_empty_generator() 0 12 2
A test_populate_nodes_callable_label_assignment() 15 15 1
A test_populate_nodes_adds_edges_for_non_universe_parent() 13 13 1
A test_networkx_builder__graph_type() 0 22 4
A empty_graph_model() 0 5 1
A test_populate_nodes_adds_edge_for_non_universe_parent() 13 13 1
A test_populate_nodes_adds_new_nodes_with_attributes() 0 19 1
A builder_with_graph() 0 5 1
A test_networkx_builder__empty_model() 0 12 1

2 Methods

Rating   Name   Duplication   Size   Complexity  
A DummyNodeModel.__init__() 0 8 2
A DummyNode.__init__() 0 3 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
from collections import Counter
2
3
import networkx as nx
4
import pytest
5
6
import graphinate
7
import graphinate.builders
8
import graphinate.enums
9
from graphinate import GraphType
10
from graphinate.modeling import GraphModel, Multiplicity
11
from graphinate.typing import UniverseNode
12
13
graph_types = [
14
    (nx.Graph(), GraphType.Graph),
15
    (nx.DiGraph(), GraphType.DiGraph),
16
    (nx.MultiGraph(), GraphType.MultiGraph),
17
    (nx.MultiDiGraph(), GraphType.MultiDiGraph)
18
]
19
20
21
@pytest.mark.parametrize(('graph', 'expected_graph_type'), graph_types)
22
def test_returns_graph_type_for_graph(graph, expected_graph_type):
23
    # Act
24
    actual_graph_type = GraphType.of(graph)
25
26
    # Assert
27
    assert actual_graph_type == expected_graph_type
28
29
30
def test_networkx_builder__empty_model():
31
    # arrange
32
    name = ""
33
    graph_model = graphinate.model(name=name)
34
35
    # act
36
    builder = graphinate.builders.NetworkxBuilder(graph_model)
37
    graph = builder.build()
38
39
    # assert
40
    assert isinstance(graph, nx.Graph)
41
    assert graph.graph['name'] == name
42
43
44
@pytest.mark.parametrize('graph_type', list(graphinate.enums.GraphType))
45
def test_networkx_builder__graph_type(graph_type):
46
    # arrange
47
    name = str(graph_type)
48
    graph_model = graphinate.model(name=name)
49
50
    @graph_model.edge()
51
    def edge():
52
        for i in range(5):
53
            yield {'source': i, 'target': i + 1}
54
            if graph_type in (graphinate.enums.GraphType.DiGraph, graphinate.enums.GraphType.MultiDiGraph):
55
                yield {'source': i + 1, 'target': i}
56
            if graph_type in (graphinate.enums.GraphType.MultiGraph, graphinate.enums.GraphType.MultiDiGraph):
57
                yield {'source': i, 'target': i + 1}
58
59
    # act
60
    builder = graphinate.builders.NetworkxBuilder(graph_model, graph_type=graph_type)
61
    graph = builder.build()
62
63
    # assert
64
    assert isinstance(graph, nx.Graph)
65
    assert graph.graph['name'] == name
66
67
68
def test_networkx_builder_repeating_nodes():
69
    # arrange
70
    name = 'Repeating Nodes'
71
    graph_model = graphinate.GraphModel(name=name)
72
73
    @graph_model.node()
74
    def node():
75
        for i in range(5):
76
            yield i
77
            yield i
78
79
    # act
80
    builder = graphinate.builders.NetworkxBuilder(graph_model)
81
    graph: nx.Graph = builder.build()
82
83
    # assert
84
    assert isinstance(graph, nx.Graph)
85
    assert graph.graph['name'] == name
86
    assert all(graph.nodes[n]['magnitude'] == 2 for n in graph)
87
88
89
@pytest.mark.parametrize('weight', [1.0, 1.5])
90
def test_networkx_builder_repeating_edges(weight):
91
    # arrange
92
    name = 'Repeating Edges'
93
    graph_model = graphinate.GraphModel(name=name)
94
95
    @graph_model.edge(weight=weight)
96
    def edge():
97
        for i in range(5):
98
            e = {'source': i, 'target': i + 1}
99
            yield e
100
            yield e
101
102
    # act
103
    builder = graphinate.builders.NetworkxBuilder(graph_model)
104
    graph = builder.build()
105
106
    # assert
107
    assert isinstance(graph, nx.Graph)
108
    assert graph.graph['name'] == name
109
    assert all(m == weight * 2 for *_, m in graph.edges.data('weight'))
110
111
112
def test_networkx_builder_simple_tuple():
113
    # arrange
114
    name = 'Simple Tuple'
115
    graph_model = graphinate.GraphModel(name=name)
116
117
    @graph_model.edge()
118
    def edge():
119
        for i in range(5):
120
            yield {'source': (i,), 'target': (i + 1,)}
121
122
    # act
123
    builder = graphinate.builders.NetworkxBuilder(graph_model)
124
    graph = builder.build()
125
126
    # assert
127
    assert isinstance(graph, nx.Graph)
128
    assert graph.graph['name'] == name
129
130
131
@pytest.mark.parametrize('execution_number', range(5))
132
def test_networkx_builder__map_graph_model(execution_number, map_graph_model):
133
    # arrange
134
    country_count, city_count, graph_model = map_graph_model
135
    person_count = city_count
136
137
    # act
138
    builder = graphinate.builders.NetworkxBuilder(graph_model)
139
    graph = builder.build()
140
141
    # assert
142
    assert graph.order() == country_count + city_count + person_count
143
    assert graph.graph['node_types']['country'] == country_count
144
    assert graph.graph['node_types']['city'] == city_count
145
146
147
class DummyNode:
148
    def __init__(self, key, value):
149
        self.key = key
150
        self.value = value
151
152
153
class DummyNodeModel:
154
    def __init__(self, uniqueness=True, label=None, type_='dummy', multiplicity=Multiplicity.ALL,
155
                 parent_type=UniverseNode, generator=None):
156
        self.uniqueness = uniqueness
157
        self.label = label
158
        self.type = type_
159
        self.multiplicity = multiplicity
160
        self.parent_type = parent_type
161
        self.generator = generator or (lambda **kwargs: [])
162
163
164
@pytest.fixture
165
def empty_graph_model():
166
    model = GraphModel(name="test")
167
    model._node_models = {}
168
    return model
169
170
171
@pytest.fixture
172
def builder_with_graph(empty_graph_model):
173
    builder = graphinate.builders.NetworkxBuilder(empty_graph_model)
174
    builder._graph = nx.Graph(name="test", node_types=Counter(), edge_types=Counter())
175
    return builder
176
177
178
def test_populate_nodes_adds_new_nodes_with_attributes(builder_with_graph):
179
    node_type_absolute_id = ('parent', 'child')
180
    node = DummyNode(key='n1', value=42)
181
182
    def generator(**kwargs):
183
        yield node
184
185
    node_model = DummyNodeModel(generator=generator)
186
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
187
    builder_with_graph._populate_nodes(node_type_absolute_id)
188
    node_id = (node.key,)
189
    assert node_id in builder_with_graph._graph
190
    attrs = builder_with_graph._graph.nodes[node_id]
191
    assert attrs['label'] == node.key
192
    assert attrs['type'] == 'dummynode'
193
    assert attrs['value'] == [node.value]
194
    assert attrs['magnitude'] == 1
195
    assert attrs['lineage'] == [node.key]
196
    assert 'created' in attrs
197
198
199 View Code Duplication
def test_populate_nodes_adds_edges_for_non_universe_parent(builder_with_graph):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
200
    node_type_absolute_id = ('parent', 'child')
201
    node = DummyNode(key='n1', value=1)
202
203
    def generator(**kwargs):
204
        yield node
205
206
    node_model = DummyNodeModel(generator=generator, parent_type='not_universe')
207
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
208
    builder_with_graph._populate_nodes(node_type_absolute_id)
209
    parent_node_id = builder_with_graph._parent_node_id(node_type_absolute_id)
210
    node_id = (node.key,)
211
    assert (parent_node_id, node_id) in builder_with_graph._graph.edges
212
213
214
def test_populate_nodes_handles_empty_generator(builder_with_graph):
215
    node_type_absolute_id = ('parent', 'child')
216
217
    def generator(**kwargs):
218
        if False:
219
            yield
220
221
    node_model = DummyNodeModel(generator=generator)
222
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
223
    builder_with_graph._populate_nodes(node_type_absolute_id)
224
    assert len(builder_with_graph._graph.nodes) == 0
225
    assert len(builder_with_graph._graph.edges) == 0
226
227
228 View Code Duplication
def test_populate_nodes_callable_label_assignment(builder_with_graph):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
229
    node_type_absolute_id = ('parent', 'child')
230
    node = DummyNode(key='n1', value=7)
231
232
    def generator(**kwargs):
233
        yield node
234
235
    def label_fn(value):
236
        return f"label-{value}"
237
238
    node_model = DummyNodeModel(generator=generator, label=label_fn)
239
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
240
    builder_with_graph._populate_nodes(node_type_absolute_id)
241
    node_id = (node.key,)
242
    assert builder_with_graph._graph.nodes[node_id]['label'] == "label-7"
243
244
245 View Code Duplication
def test_populate_nodes_handles_invalid_parent_node_id(builder_with_graph):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
246
    node_type_absolute_id = ('parent', 'child')
247
    node = DummyNode(key='n1', value=1)
248
249
    def generator(**kwargs):
250
        yield node
251
252
    node_model = DummyNodeModel(generator=generator, parent_type=UniverseNode)
253
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
254
    builder_with_graph._populate_nodes(node_type_absolute_id)
255
    node_id = (node.key,)
256
    # Should not create any edge since parent_type is UniverseNode
257
    assert len(builder_with_graph._graph.edges) == 0
258
    assert node_id in builder_with_graph._graph
259
260
261
def test_populate_nodes_adds_new_node(builder_with_graph):
262
    node_type_absolute_id = ('parent', 'child')
263
    node = DummyNode(key='n2', value=99)
264
265
    def generator(**kwargs):
266
        yield node
267
268
    node_model = DummyNodeModel(generator=generator)
269
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
270
    builder_with_graph._populate_nodes(node_type_absolute_id)
271
    node_id = (node.key,)
272
    assert node_id in builder_with_graph._graph
273
    assert builder_with_graph._graph.nodes[node_id]['value'] == [99]
274
275
276
def test_populate_nodes_updates_existing_node(builder_with_graph):
277
    node_type_absolute_id = ('parent', 'child')
278
    node = DummyNode(key='n3', value=5)
279
280
    def generator(**kwargs):
281
        yield node
282
        yield node
283
284
    node_model = DummyNodeModel(generator=generator, multiplicity=Multiplicity.ALL)
285
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
286
    builder_with_graph._populate_nodes(node_type_absolute_id)
287
    node_id = (node.key,)
288
    assert builder_with_graph._graph.nodes[node_id]['value'] == [5, 5]
289
    assert builder_with_graph._graph.nodes[node_id]['magnitude'] == 2
290
291
292 View Code Duplication
def test_populate_nodes_adds_edge_for_non_universe_parent(builder_with_graph):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
293
    node_type_absolute_id = ('parent', 'child')
294
    node = DummyNode(key='n4', value=8)
295
296
    def generator(**kwargs):
297
        yield node
298
299
    node_model = DummyNodeModel(generator=generator, parent_type='not_universe')
300
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
301
    builder_with_graph._populate_nodes(node_type_absolute_id)
302
    parent_node_id = builder_with_graph._parent_node_id(node_type_absolute_id)
303
    node_id = (node.key,)
304
    assert (parent_node_id, node_id) in builder_with_graph._graph.edges
305
306
307 View Code Duplication
def test_populate_nodes_callable_label_returns_non_string(builder_with_graph):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
308
    node_type_absolute_id = ('parent', 'child')
309
    node = DummyNode(key='n5', value=123)
310
311
    def generator(**kwargs):
312
        yield node
313
314
    def label_fn(value):
315
        return 999  # Non-string label
316
317
    node_model = DummyNodeModel(generator=generator, label=label_fn)
318
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
319
    builder_with_graph._populate_nodes(node_type_absolute_id)
320
    node_id = (node.key,)
321
    assert builder_with_graph._graph.nodes[node_id]['label'] == 999
322
323
324
def test_populate_nodes_empty_generator(builder_with_graph):
325
    node_type_absolute_id = ('parent', 'child')
326
327
    def generator(**kwargs):
328
        """Dummy generator that yields nothing"""
329
        return  # NOSONAR
330
        yield  # NOSONAR
331
332
    node_model = DummyNodeModel(generator=generator)
333
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
334
    builder_with_graph._populate_nodes(node_type_absolute_id)
335
    assert len(builder_with_graph._graph.nodes) == 0
336
337
338 View Code Duplication
def test_populate_nodes_universe_node_parent_handling(builder_with_graph):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
339
    node_type_absolute_id = (UniverseNode, 'child')
340
    node = DummyNode(key='n6', value=55)
341
342
    def generator(**kwargs):
343
        yield node
344
345
    node_model = DummyNodeModel(generator=generator, parent_type=UniverseNode)
346
    builder_with_graph.model._node_models = {node_type_absolute_id: [node_model]}
347
    builder_with_graph._populate_nodes(node_type_absolute_id)
348
    node_id = (node.key,)
349
    # Lineage should be (node.key,) and no edge should be created
350
    assert builder_with_graph._graph.nodes[node_id]['lineage'] == [node.key]
351
    assert len(builder_with_graph._graph.edges) == 0
352