Mini Shell
"""Provides unit tests to verify that the connected components algorithm is functioning correctly."""
import unittest
from ..pygraph import UndirectedGraph, get_connected_components, get_connected_components_as_subgraphs, make_subgraph
from . import utility_functions
class ConnectedComponentsTest(unittest.TestCase):
def test_correct_connected_components(self):
"""Does the ''connected_components'' function return the proper component breakdown for an undirected graph?"""
# Build the test graph
graph = utility_functions.build_simple_test_graph()
# Known connected components
component_a = [1, 2, 4, 5]
component_b = [3]
component_c = [6, 7]
known_components = [component_a, component_b, component_c]
# Pull the calculated connected components
components = get_connected_components(graph)
# Verify that the known connected components are in the calculated connected components
# --There are 3 connected components in the test graph
self.assertEqual(3, len(components))
# --Verify each known component exists and has the correct number of nodes
found_components_count = 0
for kc in known_components:
found_known_component = False
for c in components:
# --Determine if the current component is a superset of known component (it might
# --have more nodes than the known component)
superset_match = True
for n in kc:
if n not in c:
# --This is not the correct component, go to the next one
superset_match = False
break
if superset_match:
# --Determine if the current component has precisely the same number of nodes
# --in it as the known component
found_known_component = (len(kc) == len(c))
if found_known_component:
found_components_count += 1
break
if not found_known_component:
# --We know the current component was not found in the connected components list,
# --fail with an error message
msg = 'Component {} not found in {}'.format(kc, components)
self.fail(msg)
# --This verifies that we found all three known components in the calculated components
# --Prior tests should stop things before we get this far if there are errors,
# --but it's a simple sanity check test
self.assertEqual(3, found_components_count)
def test_empty_connected_components(self):
"""Does the ''connected_components'' function return an empty list for an empty undirected graph?"""
graph = UndirectedGraph()
expected = []
calculated = get_connected_components(graph)
self.assertEqual(expected, calculated)
def test_empty_cc_as_subgraphs(self):
"""Does the ''get_connected_components_as_subgraphs'' function return an empty list
when given an empty graph?"""
graph = UndirectedGraph()
expected = []
calculated = get_connected_components_as_subgraphs(graph)
self.assertEqual(expected, calculated)
def test_cc_as_subgraphs(self):
"""Does the ''get_connected_components_as_subgraphs'' function return a list of the proper subgraphs?"""
graph = utility_functions.build_simple_test_graph()
component_a_nodes = [1, 2, 4, 5]
component_a_edges = [1, 2, 3]
component_b_nodes = [3]
component_b_edges = []
component_c_nodes = [6, 7]
component_c_edges = [4]
component_a = make_subgraph(graph, component_a_nodes, component_a_edges)
component_b = make_subgraph(graph, component_b_nodes, component_b_edges)
component_c = make_subgraph(graph, component_c_nodes, component_c_edges)
known_components = [component_a, component_b, component_c]
# Pull the calculated connected components
components = get_connected_components_as_subgraphs(graph)
# Verify that the known connected components are in the calculated connected components
# --There are 3 connected components in the test graph
self.assertEqual(3, len(components))
# --Verify each known component exists and has the correct number of nodes
found_components_count = 0
for kc in known_components:
found_known_component = False
for c in components:
# --Determine if the current component is a superset of known component (it might
# --have more nodes than the known component)
node_superset_match = True
edge_superset_match = True
for n in kc.get_all_node_ids():
if n not in c.get_all_node_ids():
# --This is not the correct component, go to the next one
node_superset_match = False
break
for e in kc.get_all_edge_ids():
if e not in c.get_all_edge_ids():
# --This is not the correct component, go to the next one
edge_superset_match = False
if node_superset_match and edge_superset_match:
# --Determine if the current component has precisely the same number
# --of nodes and edges as the known component
found_known_component = ((len(kc.get_all_node_ids()) == len(c.get_all_node_ids())) and (
len(kc.get_all_edge_ids()) == len(c.get_all_edge_ids())))
if found_known_component:
found_components_count += 1
break
if not found_known_component:
# --We know the current component was not found in the connected
# --components list, fail with an error message
component_string = '[{}]'.format(','.join(
['(Nodes: {}, Edges: {})'.format(c.get_all_node_ids(), c.get_all_edge_ids()) for c in components]))
msg = 'Component (Nodes: {}, Edges: {}) not found in {}'.format(kc.get_all_node_ids(),
kc.get_all_edge_ids(), component_string)
self.fail(msg)
# --This verifies that we found all three known components in the calculated components
# --Prior tests should stop things before we get this far if there are
# --errors, but it's a simple sanity check test
self.assertEqual(3, found_components_count)
Zerion Mini Shell 1.0