class MockModel: """Implement a mock model for testing.""" def __init__(self): """Initialize the mock, creating an empty node for tests.""" self.empty_node = DeploymentNode(name="Empty", environment="Live") self.empty_node.set_model(self) self.mock_element = MockElement("element") def __iadd__(self, node): """Simulate the model assigning IDs to new elements.""" if not node.id: node.id = "id" node.set_model(self) return self def get_element(self, id: str): """Simulate getting an element by ID.""" assert id == self.mock_element.id return self.mock_element def get_elements(self): """Simulate get_elements.""" return [] def add_relationship(self, **kwargs): """Simulate adding relationships.""" return Relationship(**kwargs)
def test_deployment_node_add_child_with_existing_parent( model_with_node: MockModel): """Check that adding a node with an existing parent fails.""" top_node = model_with_node.empty_node other_parent = DeploymentNode(name="OtherParent") with pytest.raises(ValueError, match="DeploymentNode .* already has parent."): top_node += DeploymentNode(name="child", parent=other_parent)
def test_deployment_node_uses_adds_relationship(model_with_node): """Test begin able to add a relationships between deployment nodes with using().""" node1 = model_with_node.empty_node node2 = DeploymentNode(name="node2") node2.set_model(model_with_node) rel = node1.uses(node2, "Replicates data to", technology="Some tech") assert rel.source is node1 assert rel.destination is node2 assert rel.description == "Replicates data to" assert rel.technology == "Some tech"
def test_model_add_lower_level_deployment_node(empty_model: Model): """Make sure child deployment nodes are not reflected in Model.deployent_nodes.""" node1 = empty_model.add_deployment_node(name="node1") node2 = DeploymentNode(name="node2", parent=node1) empty_model += node2 assert node2 not in empty_model.deployment_nodes assert node2 in empty_model.get_elements()
def add_deployment_node( self, deployment_node: Optional[DeploymentNode] = None, **kwargs ) -> DeploymentNode: """ Add a new deployment node to the model. Args: deployment_node (DeploymentNode, optional): Either provide a `DeploymentNode` instance or **kwargs: Provide keyword arguments for instantiating a `DeploymentNode` (recommended). Returns: DeploymentNode: Either the same or a new instance, depending on arguments. Raises: ValueError: When a deployment node with the same name already exists. See Also: DeploymentNode """ if deployment_node is None: deployment_node = DeploymentNode(**kwargs) if deployment_node.id in {d.id for d in self.deployment_nodes}: ValueError( f"A deployment node with the ID {deployment_node.id} already " f"exists in the model." ) self.deployment_nodes.add(deployment_node) self._add_element(deployment_node) return deployment_node
def test_deployment_node_add_with_iadd(model_with_node: MockModel): """Test adding things to a node using += rather than add_container.""" node = model_with_node.empty_node system = SoftwareSystem(name="system") model_with_node += system container = Container(name="container") system += container child_node = DeploymentNode(name="child", environment="Live") infra_node = InfrastructureNode(name="infra") node += child_node assert child_node in node.children assert child_node in node.child_elements node += system assert node.software_system_instances[0].software_system is system assert node.software_system_instances[0] in node.child_elements child_node += container assert child_node.container_instances[0].container is container assert child_node.container_instances[0] in child_node.child_elements child_node += infra_node assert infra_node in child_node.infrastructure_nodes assert child_node.infrastructure_nodes[0] in child_node.child_elements
def test_deployment_node_cant_add_child_in_different_environment( model_with_node): """Ensure that the environment of the child matches the parent.""" top_node = model_with_node.empty_node child = DeploymentNode(name="child", environment="Dev") with pytest.raises( ValueError, match= r"DeploymentNode .* cannot be in a different environment \(Dev\) from " + r"its parent \(Live\)\.", ): top_node += child
def test_deployment_node_serialization_of_recursive_nodes(model_with_node): """Check that nodes within nodes are handled with (de)serialisation.""" top_node = model_with_node.empty_node top_node.add_deployment_node(name="child") io = DeploymentNodeIO.from_orm(top_node) assert len(io.children) == 1 assert io.children[0].name == "child" new_top_node = DeploymentNode.hydrate(io, model_with_node) assert len(new_top_node.children) == 1 new_child = new_top_node.children[0] assert new_child.name == "child" assert new_child.parent is new_top_node
def test_deployment_node_serialising_infrastructure_nodes(model_with_node): """Test serialisation and deserialisation includes infrastructure nodes.""" node = model_with_node.empty_node node.add_infrastructure_node("infraNode") io = DeploymentNodeIO.from_orm(node) assert len(io.infrastructure_nodes) == 1 assert io.infrastructure_nodes[0].id == "id" assert io.infrastructure_nodes[0].name == "infraNode" node2 = DeploymentNode.hydrate(io, model_with_node) assert len(node2.infrastructure_nodes) == 1 infra_node = node2.infrastructure_nodes[0] assert infra_node.name == "infraNode" assert infra_node.parent is node2
def test_deployment_node_serialising_software_system(model_with_node): """Test serialisation and deserialisation includes container instances.""" node = model_with_node.empty_node system = model_with_node.mock_element node.add_software_system(system, replicate_relationships=False) io = DeploymentNodeIO.from_orm(node) assert len(io.software_system_instances) == 1 assert io.software_system_instances[0].id == "id" node2 = DeploymentNode.hydrate(io, model_with_node) assert len(node2.software_system_instances) == 1 instance = node2.software_system_instances[0] assert instance.instance_id == 1 assert instance.software_system is system assert instance.parent is node2
def test_deployment_node_serialising_container(model_with_node): """Test serialisation and deserialisation includes container instances.""" node = model_with_node.empty_node container = model_with_node.mock_element node.add_container(container, replicate_relationships=False) io = DeploymentNodeIO.from_orm(node) assert len(io.container_instances) == 1 assert io.container_instances[0].id == "id" node2 = DeploymentNode.hydrate(io, model_with_node) assert len(node2.container_instances) == 1 instance = node2.container_instances[0] assert instance.instance_id == 1 assert instance.container is container assert instance.model is model_with_node assert instance.parent is node2
def test_deployment_node_init(attributes): """Expect proper initialization from arguments.""" node = DeploymentNode(**attributes) for attr, expected in attributes.items(): assert getattr(node, attr) == expected
def __init__(self): """Initialize the mock, creating an empty node for tests.""" self.empty_node = DeploymentNode(name="Empty", environment="Live") self.empty_node.set_model(self) self.mock_element = MockElement("element")