Skip to content

Commit

Permalink
feat(pytest): add an assert_error plugin method
Browse files Browse the repository at this point in the history
Fixes #162
  • Loading branch information
lengau committed Sep 13, 2024
1 parent 9dfc386 commit 0f842af
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 5 deletions.
18 changes: 15 additions & 3 deletions craft_cli/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
import pathlib
import re
import tempfile
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, cast
from unittest.mock import call

import pytest

from craft_cli import messages, printer
from craft_cli import errors, messages, printer

if TYPE_CHECKING:
from unittest.mock import _Call
Expand Down Expand Up @@ -163,6 +163,18 @@ def assert_messages(self, texts):
"""
self.assert_interactions([call("message", text) for text in texts])

def assert_error(self, error: errors.CraftError) -> errors.CraftError:
"""Check that the 'error' method was called with the given error."""
# Error should be the last thing called, so start at the end.
errors_called = []
for stored_call in reversed(self.interactions):
if stored_call.args[0] != "error":
continue
errors_called.append(stored_call.args[1])
if stored_call.args[1] == error:
return cast(errors.CraftError, stored_call.args[1])
raise AssertionError(f"Error not emitted: {error!r}", errors_called[::-1])

def assert_interactions(self, expected_call_list):
"""Check that the expected call list happen at some point between all stored calls.
Expand Down Expand Up @@ -205,7 +217,7 @@ def advance(self, *a, **k):
def emitter(monkeypatch):
"""Provide a helper to test everything that was shown using the Emitter."""
recording_emitter = RecordingEmitter()
for method_name in ("message", "progress", "verbose", "debug", "trace"):
for method_name in ("message", "progress", "verbose", "debug", "trace", "error"):
monkeypatch.setattr(
messages.emit,
method_name,
Expand Down
40 changes: 38 additions & 2 deletions tests/test_pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

"""Test the fixtures provided by Craft CLI."""

import copy
from unittest.mock import call

import pytest

from craft_cli import messages, printer
from craft_cli import messages, printer, errors


# -- tests for the `init_emitter` auto-fixture

Expand Down Expand Up @@ -183,6 +184,41 @@ def test_emitter_messages(emitter):
)


@pytest.mark.parametrize(
"error",
[
errors.CraftError("Basic error"),
errors.CraftError("Detailed", details="Very detailed"),
errors.CraftError("Resolved", resolution="640x480"),
errors.CraftError("Documented", docs_url="https://docs.ubuntu.com"),
errors.CraftError("Detailed Resolved", details="Extra fine", resolution="3840x2160"),
],
)
def test_emitter_error_success(emitter, error):
"""Verify that the checking the emitter for the correct error succeeds."""
error_copy = copy.deepcopy(error) # Ensure we're not just checking identity.
messages.emit.error(error)
assert emitter.assert_error(error_copy) is error


@pytest.mark.parametrize(
("error", "assert_error"),
[
(errors.CraftError("Basic"), errors.CraftError("Very basic")),
(
errors.CraftError("Detailed", details="Case sensitive"),
errors.CraftError("Detailed", details="case Sensitive"),
),
],
)
def test_emitter_error_failure(emitter, error, assert_error):
"""Verify that checking the emitter for the wrong error fails."""
messages.emit.error(error)
with pytest.raises(AssertionError, match="Error not emitted:") as exc_info:
emitter.assert_error(assert_error)
assert exc_info.value.args[1] == [error]


def test_emitter_interactions_positive_complete(emitter):
"""All interactions can be verified, complete."""
messages.emit.progress("foo")
Expand Down

0 comments on commit 0f842af

Please sign in to comment.