launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #27801
[Merge] ~jugmac00/lpcraft:easier-testing-for-argparse-applications into lpcraft:main
Jürgen Gmach has proposed merging ~jugmac00/lpcraft:easier-testing-for-argparse-applications into lpcraft:main.
Commit message:
Enable easier testing for argparse applications
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~jugmac00/lpcraft/+git/lpcraft/+merge/412567
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~jugmac00/lpcraft:easier-testing-for-argparse-applications into lpcraft:main.
diff --git a/lpcraft/commands/tests/__init__.py b/lpcraft/commands/tests/__init__.py
index 86d857d..aba747f 100644
--- a/lpcraft/commands/tests/__init__.py
+++ b/lpcraft/commands/tests/__init__.py
@@ -3,7 +3,7 @@
from dataclasses import dataclass
from typing import List
-from unittest.mock import ANY, call, patch
+from unittest.mock import ANY, call
from craft_cli import CraftError
from testtools import TestCase
@@ -24,25 +24,24 @@ class _CommandResult:
class CommandBaseTestCase(TestCase):
def run_command(self, *args, **kwargs):
- with patch("sys.argv", ["lpcraft"] + list(args)):
- with RecordingEmitterFixture() as emitter:
- exit_code = main()
- result = _CommandResult(
- exit_code,
- [
- c.args[1]
- for c in emitter.recorder.interactions
- if c == call("message", ANY)
- ],
- [
- c.args[1]
- for c in emitter.recorder.interactions
- if c == call("error", ANY)
- ],
- [
- c.args[1]
- for c in emitter.recorder.interactions
- if c == call("trace", ANY)
- ],
- )
- return result
+ with RecordingEmitterFixture() as emitter:
+ exit_code = main(list(args))
+ result = _CommandResult(
+ exit_code,
+ [
+ c.args[1]
+ for c in emitter.recorder.interactions
+ if c == call("message", ANY)
+ ],
+ [
+ c.args[1]
+ for c in emitter.recorder.interactions
+ if c == call("error", ANY)
+ ],
+ [
+ c.args[1]
+ for c in emitter.recorder.interactions
+ if c == call("trace", ANY)
+ ],
+ )
+ return result
diff --git a/lpcraft/main.py b/lpcraft/main.py
index 124be7e..4b8cd18 100644
--- a/lpcraft/main.py
+++ b/lpcraft/main.py
@@ -4,8 +4,10 @@
"""Main entry point."""
import logging
+import sys
from argparse import ArgumentParser
from pathlib import Path
+from typing import List, Optional
from craft_cli import CraftError, EmitterMode, emit
@@ -28,7 +30,7 @@ def _configure_logger(name: str) -> None:
_configure_logger("craft_providers")
-def main() -> int:
+def main(argv: Optional[List[str]] = None) -> int:
"""lpcraft runs Launchpad CI jobs."""
parser = ArgumentParser(description="Run Launchpad CI jobs.")
parser.add_argument(
@@ -73,8 +75,11 @@ def main() -> int:
emit.init(EmitterMode.NORMAL, "lpcraft", f"Starting {lpcraft_version}")
+ if argv is None:
+ argv = sys.argv[1:]
+
try:
- args = parser.parse_args()
+ args = parser.parse_args(argv)
except SystemExit:
emit.ended_ok()
return 1
diff --git a/lpcraft/tests/test_main.py b/lpcraft/tests/test_main.py
index e8808e5..deeb8b1 100644
--- a/lpcraft/tests/test_main.py
+++ b/lpcraft/tests/test_main.py
@@ -1,7 +1,6 @@
# Copyright 2021 Canonical Ltd. This software is licensed under the
# GNU General Public License version 3 (see the file LICENSE).
-import sys
from unittest.mock import patch
from craft_cli import EmitterMode
@@ -16,10 +15,9 @@ from lpcraft.tests.fixtures import RecordingEmitterFixture
class TestMain(TestCase):
def test_ok(self):
# main() sets up the message handler and exits cleanly.
- self.useFixture(MockPatch("sys.argv", ["lpcraft", "--version"]))
mock_emit = self.useFixture(MockPatch("lpcraft.main.emit")).mock
- ret = main()
+ ret = main(["--version"])
self.assertEqual(0, ret)
mock_emit.init.assert_called_once_with(
@@ -30,24 +28,24 @@ class TestMain(TestCase):
def test_bad_arguments(self):
# main() exits appropriately if given bad arguments.
- self.useFixture(MockPatch("sys.argv", ["lpcraft", "--nonexistent"]))
mock_emit = self.useFixture(MockPatch("lpcraft.main.emit")).mock
mock_argparse_print_message = self.useFixture(
MockPatch("argparse.ArgumentParser._print_message")
).mock
- ret = main()
+ ret = main(["--nonexistent"])
self.assertEqual(1, ret)
- mock_argparse_print_message.assert_called_with(
- "lpcraft: error: unrecognized arguments: --nonexistent\n",
- sys.stderr,
+ # using `assert_called_with` is not possible as the message is
+ # different depending whether pytest or coverage is driving the tests
+ self.assertIn(
+ "error: unrecognized arguments: --nonexistent\n",
+ mock_argparse_print_message.call_args.args[0],
)
mock_emit.ended_ok.assert_called_once_with()
@patch("lpcraft.main.run")
def test_keyboard_interrupt(self, mock_run):
- self.useFixture(MockPatch("sys.argv", ["lpcraft"]))
mock_run.side_effect = KeyboardInterrupt()
with RecordingEmitterFixture() as emitter: