Skip to content

Commit

Permalink
Add unit tests, set coverage target to 95
Browse files Browse the repository at this point in the history
  • Loading branch information
Thanhphan1147 committed Jan 20, 2024
1 parent 8a093fe commit a218747
Show file tree
Hide file tree
Showing 5 changed files with 356 additions and 22 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ skips = ["*/*test.py", "*/test_*.py", "*tests/*.py"]
branch = true

[tool.coverage.report]
# fail_under = 99
fail_under = 95
show_missing = true

[tool.pytest.ini_options]
Expand Down
137 changes: 137 additions & 0 deletions tests/unit/test_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Copyright 2024 Canonical Ltd.
# See LICENSE file for licensing details.
#
# Learn more about testing at: https://juju.is/docs/sdk/testing

# pylint: disable=protected-access
"""Test for agent relations."""

import secrets
from unittest.mock import MagicMock, PropertyMock

import ops.testing
import pytest
from charms.operator_libs_linux.v1 import systemd

import service
from charm import JenkinsAgentCharm

agent_relation_data = {"url": "http://example.com", "jenkins-agent-0_secret": secrets.token_hex(4)}


def test_agent_relation_joined(harness: ops.testing.Harness):
"""
arrange: patched State.from_charm that raises an InvalidState Error.
act: when the JenkinsAgentCharm is initialized.
assert: The agent falls into BlockedStatus.
"""
harness.begin()
relation_id = harness.add_relation("agent", "jenkins-k8s", unit_data=agent_relation_data)
charm: JenkinsAgentCharm = harness.charm
assert (
harness.get_relation_data(relation_id, app_or_unit="jenkins-agent/0")
== charm.state.agent_meta.as_dict()
)


def test_agent_relation_changed_service_restart(
harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch
):
"""
arrange: patched State.from_charm that raises an InvalidState Error.
act: when the JenkinsAgentCharm is initialized.
assert: The agent falls into BlockedStatus.
"""
_ = harness.add_relation("agent", "jenkins-k8s", unit_data=agent_relation_data)
harness.begin()
charm: JenkinsAgentCharm = harness.charm
assert charm.state.agent_relation_credentials
assert (
charm.state.agent_relation_credentials.secret
== agent_relation_data["jenkins-agent-0_secret"]
)
assert charm.state.agent_relation_credentials.address == agent_relation_data["url"]

monkeypatch.setattr(charm.jenkins_agent_service, "restart", MagicMock())
charm.agent_observer._on_agent_relation_changed(MagicMock())
assert charm.unit.status.name == ops.ActiveStatus.name


def test_agent_relation_changed_service_restart_error(
harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch
):
"""
arrange: patched State.from_charm that raises an InvalidState Error.
act: when the JenkinsAgentCharm is initialized.
assert: The agent falls into BlockedStatus.
"""
_ = harness.add_relation("agent", "jenkins-k8s", unit_data=agent_relation_data)
harness.begin()
charm: JenkinsAgentCharm = harness.charm
assert charm.state.agent_relation_credentials
assert (
charm.state.agent_relation_credentials.secret
== agent_relation_data["jenkins-agent-0_secret"]
)
assert charm.state.agent_relation_credentials.address == agent_relation_data["url"]

monkeypatch.setattr(
charm.jenkins_agent_service, "restart", MagicMock(side_effect=service.ServiceRestartError)
)
with pytest.raises(RuntimeError, match="Error restarting the agent service."):
charm.agent_observer._on_agent_relation_changed(MagicMock())


def test_agent_relation_changed_service_already_active(
harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch
):
"""
arrange: patched State.from_charm that raises an InvalidState Error.
act: when the JenkinsAgentCharm is initialized.
assert: The agent falls into BlockedStatus.
"""
service_restart_mock = MagicMock()
service_is_active_mock = PropertyMock(return_value=True)
monkeypatch.setattr(service.JenkinsAgentService, "restart", service_restart_mock)
monkeypatch.setattr(service.JenkinsAgentService, "is_active", service_is_active_mock)

_ = harness.add_relation("agent", "jenkins-k8s", unit_data=agent_relation_data)
harness.begin()
charm: JenkinsAgentCharm = harness.charm
charm.agent_observer._on_agent_relation_changed(MagicMock())
assert service_is_active_mock.call_count == 1
assert service_restart_mock.call_count == 0


def test_agent_relation_departed_service_stop_error(
harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch
):
"""
arrange: patched State.from_charm that raises an InvalidState Error.
act: when the JenkinsAgentCharm is initialized.
assert: The agent falls into BlockedStatus.
"""
monkeypatch.setattr(systemd, "service_stop", MagicMock(side_effect=systemd.SystemdError))

relation_id = harness.add_relation("agent", "jenkins-k8s", unit_data=agent_relation_data)
harness.begin()
harness.remove_relation(relation_id=relation_id)
charm: JenkinsAgentCharm = harness.charm
assert charm.unit.status.name == ops.BlockedStatus.name
assert charm.unit.status.message == "Error stopping the agent service"


def test_agent_relation_departed(harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch):
"""
arrange: patched State.from_charm that raises an InvalidState Error.
act: when the JenkinsAgentCharm is initialized.
assert: The agent falls into BlockedStatus.
"""
monkeypatch.setattr(systemd, "service_stop", MagicMock())

relation_id = harness.add_relation("agent", "jenkins-k8s", unit_data=agent_relation_data)
harness.begin()
harness.remove_relation(relation_id=relation_id)
charm: JenkinsAgentCharm = harness.charm
assert charm.unit.status.name == ops.BlockedStatus.name
assert charm.unit.status.message == "Waiting for config/relation."
93 changes: 72 additions & 21 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,6 @@
from charm import JenkinsAgentCharm


def raise_exception(exception: Exception):
"""Raise exception function for monkeypatching.
Args:
exception: The exception to raise.
Raises:
exception: .
"""
raise exception


def test___init___invalid_state(harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch):
"""
arrange: patched State.from_charm that raises an InvalidState Error.
Expand All @@ -43,9 +31,9 @@ def test___init___invalid_state(harness: ops.testing.Harness, monkeypatch: pytes

harness.begin()

jenkins_charm: JenkinsAgentCharm = harness.charm
assert jenkins_charm.unit.status.name == ops.BlockedStatus.name
assert jenkins_charm.unit.status.message == "Invalid executor message"
charm: JenkinsAgentCharm = harness.charm
assert charm.unit.status.name == ops.BlockedStatus.name
assert charm.unit.status.message == "Invalid executor message"


def test__on_upgrade_charm(harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch):
Expand All @@ -58,12 +46,12 @@ def test__on_upgrade_charm(harness: ops.testing.Harness, monkeypatch: pytest.Mon
monkeypatch.setattr(service.JenkinsAgentService, "restart", MagicMock())
harness.begin()

jenkins_charm: JenkinsAgentCharm = harness.charm
charm: JenkinsAgentCharm = harness.charm
upgrade_charm_event = MagicMock(spec=ops.UpgradeCharmEvent)
jenkins_charm._on_upgrade_charm(upgrade_charm_event)
charm._on_upgrade_charm(upgrade_charm_event)

assert jenkins_charm.unit.status.message == "Waiting for relation."
assert jenkins_charm.unit.status.name == ops.BlockedStatus.name
assert charm.unit.status.message == "Waiting for relation."
assert charm.unit.status.name == ops.BlockedStatus.name


def test__on_config_changed(harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch):
Expand All @@ -77,8 +65,71 @@ def test__on_config_changed(harness: ops.testing.Harness, monkeypatch: pytest.Mo
get_relation_mock = MagicMock()
monkeypatch.setattr(ops.Model, "get_relation", get_relation_mock)

jenkins_charm: JenkinsAgentCharm = harness.charm
jenkins_charm._on_config_changed(config_changed_event)
charm: JenkinsAgentCharm = harness.charm
charm._on_config_changed(config_changed_event)

agent_relation = get_relation_mock.return_value
assert agent_relation.data[harness._unit_name].update.call_count == 1


def test_restart_agent_service(harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch):
"""
arrange: given a charm with patched relation.
act: when _on_config_changed is called.
assert: The charm correctly updates the relation databag.
"""
get_relation_mock = MagicMock()
monkeypatch.setattr(ops.Model, "get_relation", get_relation_mock)
get_credentials_mock = MagicMock()
restart_mock = MagicMock()
monkeypatch.setattr(service.JenkinsAgentService, "restart", restart_mock)

harness.begin()

charm: JenkinsAgentCharm = harness.charm
monkeypatch.setattr(charm.state, "agent_relation_credentials", get_credentials_mock)
charm.restart_agent_service()

assert restart_mock.call_count == 1
assert charm.unit.status.name == ops.ActiveStatus.name


def test_restart_agent_service_incomplete_relation_data(
harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch
):
"""
arrange: given a charm with patched relation.
act: when _on_config_changed is called.
assert: The charm correctly updates the relation databag.
"""
get_relation_mock = MagicMock()
monkeypatch.setattr(ops.Model, "get_relation", get_relation_mock)
harness.begin()

charm: JenkinsAgentCharm = harness.charm
monkeypatch.setattr(charm.state, "agent_relation_credentials", None)
charm.restart_agent_service()

assert charm.unit.status.name == ops.WaitingStatus.name


def test_restart_agent_service_service_restart_error(
harness: ops.testing.Harness, monkeypatch: pytest.MonkeyPatch
):
"""
arrange: given a charm with patched relation.
act: when _on_config_changed is called.
assert: The charm correctly updates the relation databag.
"""
get_relation_mock = MagicMock()
monkeypatch.setattr(ops.Model, "get_relation", get_relation_mock)
get_credentials_mock = MagicMock()
restart_mock = MagicMock(side_effect=service.ServiceRestartError)
monkeypatch.setattr(service.JenkinsAgentService, "restart", restart_mock)

harness.begin()

charm: JenkinsAgentCharm = harness.charm
monkeypatch.setattr(charm.state, "agent_relation_credentials", get_credentials_mock)
with pytest.raises(RuntimeError, match="Error restarting the agent service"):
charm.restart_agent_service()
Loading

0 comments on commit a218747

Please sign in to comment.