Merge ~arturo-seijas/charm-ubuntu-advantage:add-integration-test into charm-ubuntu-advantage:master
- Git
- lp:~arturo-seijas/charm-ubuntu-advantage
- add-integration-test
- Merge into master
Proposed by
Arturo Enrique Seijas Fernández
Status: | Merged |
---|---|
Approved by: | Tom Haddon |
Approved revision: | 417aba595b2ec06797d0f93c2300ab1ce9519bf2 |
Merged at revision: | 6911d2a1237a9bf43802556d96e9fd974683357e |
Proposed branch: | ~arturo-seijas/charm-ubuntu-advantage:add-integration-test |
Merge into: | charm-ubuntu-advantage:master |
Diff against target: |
1021 lines (+347/-236) 7 files modified
README.md (+0/-15) dev/null (+0/-0) pyproject.toml (+38/-0) src/charm.py (+23/-24) tests/integration/test_charm.py (+24/-0) tests/unit/test_charm.py (+184/-197) tox.ini (+78/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tom Haddon | Approve | ||
Canonical IS Reviewers | Pending | ||
Review via email:
|
Commit message
Add integration test and use tox instead of script
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Tom Haddon (mthaddon) wrote : | # |
Can you also update the README since the instructions for running tests have changed?
Probably best to update copyright info to be 2022 for newly created files, 2021-2022 for pre-existing ones.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Arturo Enrique Seijas Fernández (arturo-seijas) wrote : | # |
> Can you also update the README since the instructions for running tests have
> changed?
>
> Probably best to update copyright info to be 2022 for newly created files,
> 2021-2022 for pre-existing ones.
Done
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Change successfully merged at revision 6911d2a1237a9bf
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.flake8 b/.flake8 |
2 | deleted file mode 100644 |
3 | index 8ef84fc..0000000 |
4 | --- a/.flake8 |
5 | +++ /dev/null |
6 | @@ -1,9 +0,0 @@ |
7 | -[flake8] |
8 | -max-line-length = 99 |
9 | -select: E,W,F,C,N |
10 | -exclude: |
11 | - venv |
12 | - .git |
13 | - build |
14 | - dist |
15 | - *.egg_info |
16 | diff --git a/README.md b/README.md |
17 | index a89be47..6884762 100644 |
18 | --- a/README.md |
19 | +++ b/README.md |
20 | @@ -11,18 +11,3 @@ Be sure to replace `<token>` with a valid value from [the Ubuntu Advantage websi |
21 | juju deploy ubuntu |
22 | juju deploy ubuntu-advantage --config token=<token> |
23 | juju add-relation ubuntu ubuntu-advantage |
24 | - |
25 | -## Developing |
26 | - |
27 | -Create and activate a virtualenv with the development requirements: |
28 | - |
29 | - virtualenv -p python3 venv |
30 | - source venv/bin/activate |
31 | - pip install -r requirements-dev.txt |
32 | - |
33 | -## Testing |
34 | - |
35 | -The Python operator framework includes a very nice harness for testing |
36 | -operator behaviour without full deployment. Just `run_tests`: |
37 | - |
38 | - ./run_tests |
39 | diff --git a/pyproject.toml b/pyproject.toml |
40 | new file mode 100644 |
41 | index 0000000..754fb1a |
42 | --- /dev/null |
43 | +++ b/pyproject.toml |
44 | @@ -0,0 +1,38 @@ |
45 | +# Copyright 2022 Canonical Ltd. |
46 | +# See LICENSE file for licensing details. |
47 | + |
48 | +# Testing tools configuration |
49 | +[tool.coverage.run] |
50 | +branch = true |
51 | + |
52 | +[tool.coverage.report] |
53 | +show_missing = true |
54 | + |
55 | +[tool.pytest.ini_options] |
56 | +minversion = "6.0" |
57 | +log_cli_level = "INFO" |
58 | + |
59 | +# Formatting tools configuration |
60 | +[tool.black] |
61 | +line-length = 99 |
62 | +target-version = ["py38"] |
63 | + |
64 | +[tool.isort] |
65 | +profile = "black" |
66 | + |
67 | +# Linting tools configuration |
68 | +[tool.flake8] |
69 | +max-line-length = 99 |
70 | +max-doc-length = 99 |
71 | +max-complexity = 10 |
72 | +exclude = [".git", "__pycache__", ".tox", "build", "dist", "*.egg_info", "venv"] |
73 | +select = ["E", "W", "F", "C", "N", "R", "D", "H"] |
74 | +# Ignore D107 Missing docstring in __init__ |
75 | +ignore = ["D107"] |
76 | +# D100, D101, D102, D103: Ignore missing docstrings in tests |
77 | +per-file-ignores = ["tests/*:D100,D101,D102,D103,D104"] |
78 | +docstring-convention = "google" |
79 | +# Check for properly formatted copyright header in each file |
80 | +copyright-check = "True" |
81 | +copyright-author = "Canonical Ltd." |
82 | +copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s" |
83 | \ No newline at end of file |
84 | diff --git a/requirements-dev.txt b/requirements-dev.txt |
85 | deleted file mode 100644 |
86 | index 4f2a3f5..0000000 |
87 | --- a/requirements-dev.txt |
88 | +++ /dev/null |
89 | @@ -1,3 +0,0 @@ |
90 | --r requirements.txt |
91 | -coverage |
92 | -flake8 |
93 | diff --git a/run_tests b/run_tests |
94 | deleted file mode 100755 |
95 | index ef9f058..0000000 |
96 | --- a/run_tests |
97 | +++ /dev/null |
98 | @@ -1,18 +0,0 @@ |
99 | -#!/bin/sh -e |
100 | -# Copyright 2021 Canonical Ltd. |
101 | -# See LICENSE file for licensing details. |
102 | -PYTHONPATH_INCLUDES="src:lib" |
103 | - |
104 | -if [ -z "$VIRTUAL_ENV" -a -d venv/ ]; then |
105 | - . venv/bin/activate |
106 | -fi |
107 | - |
108 | -if [ -z "$PYTHONPATH" ]; then |
109 | - export PYTHONPATH="$PYTHONPATH_INCLUDES" |
110 | -else |
111 | - export PYTHONPATH="$PYTHONPATH_INCLUDES:$PYTHONPATH" |
112 | -fi |
113 | - |
114 | -flake8 --extend-exclude operator_libs_linux |
115 | -coverage run --source=src -m unittest -v "$@" |
116 | -coverage report -m |
117 | diff --git a/src/charm.py b/src/charm.py |
118 | index 84362d3..f2e6e41 100755 |
119 | --- a/src/charm.py |
120 | +++ b/src/charm.py |
121 | @@ -1,37 +1,37 @@ |
122 | #!/usr/bin/env python3 |
123 | - |
124 | # Copyright 2021 Canonical Ltd. |
125 | # See LICENSE file for licensing details. |
126 | |
127 | +"""Charmed Operator to enable Ubuntu Advantage (https://ubuntu.com/advantage) subscriptions.""" |
128 | + |
129 | import hashlib |
130 | import json |
131 | import logging |
132 | import os |
133 | import subprocess |
134 | -import yaml |
135 | |
136 | +import yaml |
137 | from charms.operator_libs_linux.v0 import apt |
138 | from ops.charm import CharmBase |
139 | from ops.framework import StoredState |
140 | from ops.main import main |
141 | from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus |
142 | |
143 | - |
144 | logger = logging.getLogger(__name__) |
145 | |
146 | |
147 | def install_ppa(ppa, env): |
148 | - """Install specified ppa""" |
149 | + """Install specified ppa.""" |
150 | subprocess.check_call(["add-apt-repository", "--yes", ppa], env=env) |
151 | |
152 | |
153 | def remove_ppa(ppa, env): |
154 | - """Remove specified ppa""" |
155 | + """Remove specified ppa.""" |
156 | subprocess.check_call(["add-apt-repository", "--remove", "--yes", ppa], env=env) |
157 | |
158 | |
159 | def update_configuration(contract_url): |
160 | - """Write the contract_url to the uaclient configuration file""" |
161 | + """Write the contract_url to the uaclient configuration file.""" |
162 | with open("/etc/ubuntu-advantage/uaclient.conf", "r+") as f: |
163 | client_config = yaml.safe_load(f) |
164 | client_config["contract_url"] = contract_url |
165 | @@ -41,17 +41,17 @@ def update_configuration(contract_url): |
166 | |
167 | |
168 | def detach_subscription(): |
169 | - """Detach from any ubuntu-advantage subscription""" |
170 | + """Detach from any ubuntu-advantage subscription.""" |
171 | subprocess.check_call(["ubuntu-advantage", "detach", "--assume-yes"]) |
172 | |
173 | |
174 | def attach_subscription(token): |
175 | - """Attach an ubuntu-advantage subscription using the specified token""" |
176 | + """Attach an ubuntu-advantage subscription using the specified token.""" |
177 | return subprocess.call(["ubuntu-advantage", "attach", token]) |
178 | |
179 | |
180 | def get_status_output(): |
181 | - """Return the parsed output from ubuntu-advantage status""" |
182 | + """Return the parsed output from ubuntu-advantage status.""" |
183 | output = subprocess.check_output(["ubuntu-advantage", "status", "--all", "--format", "json"]) |
184 | # handle different return type from xenial |
185 | if isinstance(output, bytes): |
186 | @@ -60,26 +60,25 @@ def get_status_output(): |
187 | |
188 | |
189 | class UbuntuAdvantageCharm(CharmBase): |
190 | - """Charm to handle ubuntu-advantage installation and configuration""" |
191 | + """Charm to handle ubuntu-advantage installation and configuration.""" |
192 | + |
193 | _state = StoredState() |
194 | |
195 | def __init__(self, *args): |
196 | super().__init__(*args) |
197 | self._setup_proxy_env() |
198 | self._state.set_default( |
199 | - contract_url=None, |
200 | - hashed_token=None, |
201 | - package_needs_installing=True, |
202 | - ppa=None) |
203 | + contract_url=None, hashed_token=None, package_needs_installing=True, ppa=None |
204 | + ) |
205 | |
206 | self.framework.observe(self.on.config_changed, self.config_changed) |
207 | |
208 | def _setup_proxy_env(self): |
209 | - """Setup proxy variables from model""" |
210 | + """Setup proxy variables from model.""" |
211 | self.env = dict(os.environ) |
212 | - self.env['http_proxy'] = self.env.get('JUJU_CHARM_HTTP_PROXY', '') |
213 | - self.env['https_proxy'] = self.env.get('JUJU_CHARM_HTTPS_PROXY', '') |
214 | - self.env['no_proxy'] = self.env.get('JUJU_CHARM_NO_PROXY', '') |
215 | + self.env["http_proxy"] = self.env.get("JUJU_CHARM_HTTP_PROXY", "") |
216 | + self.env["https_proxy"] = self.env.get("JUJU_CHARM_HTTPS_PROXY", "") |
217 | + self.env["no_proxy"] = self.env.get("JUJU_CHARM_NO_PROXY", "") |
218 | |
219 | # The values for 'http_proxy' and 'https_proxy' will be used for the |
220 | # PPA install/remove operations (passed as environment variables), as |
221 | @@ -93,7 +92,7 @@ class UbuntuAdvantageCharm(CharmBase): |
222 | logger.debug("Envvar '%s' => '%s'", envvar, value) |
223 | |
224 | def config_changed(self, event): |
225 | - """Install and configure ubuntu-advantage tools and attachment""" |
226 | + """Install and configure ubuntu-advantage tools and attachment.""" |
227 | logger.info("Beginning config_changed") |
228 | self.unit.status = MaintenanceStatus("Configuring") |
229 | self._handle_ppa_state() |
230 | @@ -105,7 +104,7 @@ class UbuntuAdvantageCharm(CharmBase): |
231 | logger.info("Finished config_changed") |
232 | |
233 | def _handle_ppa_state(self): |
234 | - """Handle installing/removing ppa based on configuration and state""" |
235 | + """Handle installing/removing ppa based on configuration and state.""" |
236 | ppa = self.config.get("ppa", "").strip() |
237 | old_ppa = self._state.ppa |
238 | |
239 | @@ -124,7 +123,7 @@ class UbuntuAdvantageCharm(CharmBase): |
240 | self._state.package_needs_installing = True |
241 | |
242 | def _handle_package_state(self): |
243 | - """Install apt package if necessary""" |
244 | + """Install apt package if necessary.""" |
245 | if self._state.package_needs_installing: |
246 | logger.info("Removing package ubuntu-advantage-tools") |
247 | apt.remove_package("ubuntu-advantage-tools") |
248 | @@ -133,7 +132,7 @@ class UbuntuAdvantageCharm(CharmBase): |
249 | self._state.package_needs_installing = False |
250 | |
251 | def _handle_subscription_state(self): |
252 | - """Handle uaclient configuration and subscription attachment""" |
253 | + """Handle uaclient configuration and subscription attachment.""" |
254 | token = self.config.get("token", "").strip() |
255 | hashed_token = hashlib.sha256(token.encode("utf-8")).hexdigest() |
256 | old_hashed_token = self._state.hashed_token |
257 | @@ -172,7 +171,7 @@ class UbuntuAdvantageCharm(CharmBase): |
258 | self._state.hashed_token = hashed_token |
259 | |
260 | def _handle_status_state(self): |
261 | - """Parse status output to determine which services are active""" |
262 | + """Parse status output to determine which services are active.""" |
263 | status = get_status_output() |
264 | services = [] |
265 | for service in status.get("services"): |
266 | @@ -182,7 +181,7 @@ class UbuntuAdvantageCharm(CharmBase): |
267 | self.unit.status = ActiveStatus(message) |
268 | |
269 | def _configure_ua_proxy(self): |
270 | - """Configure the proxy options for the ubuntu-advantage client""" |
271 | + """Configure the proxy options for the ubuntu-advantage client.""" |
272 | for config_key in ("http_proxy", "https_proxy"): |
273 | subprocess.check_call( |
274 | [ |
275 | diff --git a/tests/__init__.py b/tests/__init__.py |
276 | deleted file mode 100644 |
277 | index e69de29..0000000 |
278 | --- a/tests/__init__.py |
279 | +++ /dev/null |
280 | diff --git a/tests/integration/test_charm.py b/tests/integration/test_charm.py |
281 | new file mode 100644 |
282 | index 0000000..2066e26 |
283 | --- /dev/null |
284 | +++ b/tests/integration/test_charm.py |
285 | @@ -0,0 +1,24 @@ |
286 | +# Copyright 2022 Canonical Ltd. |
287 | +# See LICENSE file for licensing details. |
288 | + |
289 | +import pytest |
290 | +from ops.model import ActiveStatus, BlockedStatus |
291 | +from pytest_operator.plugin import OpsTest |
292 | + |
293 | + |
294 | +@pytest.mark.abort_on_fail |
295 | +async def test_build_and_deploy(ops_test: OpsTest): |
296 | + |
297 | + charm = await ops_test.build_charm(".") |
298 | + await ops_test.model.deploy("ubuntu") |
299 | + await ops_test.model.deploy(charm, num_units=0) |
300 | + await ops_test.model.add_relation( |
301 | + "ubuntu", |
302 | + "ubuntu-advantage", |
303 | + ) |
304 | + await ops_test.model.wait_for_idle() |
305 | + |
306 | + |
307 | +async def test_status(ops_test: OpsTest): |
308 | + assert ops_test.model.applications["ubuntu"].status == ActiveStatus.name |
309 | + assert ops_test.model.applications["ubuntu-advantage"].status == BlockedStatus.name |
310 | diff --git a/tests/test_charm.py b/tests/unit/test_charm.py |
311 | similarity index 50% |
312 | rename from tests/test_charm.py |
313 | rename to tests/unit/test_charm.py |
314 | index 37da2a7..14369f5 100644 |
315 | --- a/tests/test_charm.py |
316 | +++ b/tests/unit/test_charm.py |
317 | @@ -12,24 +12,14 @@ from ops.testing import Harness |
318 | |
319 | from charm import UbuntuAdvantageCharm |
320 | |
321 | - |
322 | STATUS_ATTACHED = json.dumps( |
323 | { |
324 | "attached": True, |
325 | "services": [ |
326 | - { |
327 | - "name": "esm-apps", |
328 | - "status": "enabled" |
329 | - }, |
330 | - { |
331 | - "name": "esm-infra", |
332 | - "status": "enabled" |
333 | - }, |
334 | - { |
335 | - "name": "livepatch", |
336 | - "status": "enabled" |
337 | - } |
338 | - ] |
339 | + {"name": "esm-apps", "status": "enabled"}, |
340 | + {"name": "esm-infra", "status": "enabled"}, |
341 | + {"name": "livepatch", "status": "enabled"}, |
342 | + ], |
343 | } |
344 | ) |
345 | |
346 | @@ -38,19 +28,10 @@ STATUS_DETACHED = json.dumps( |
347 | { |
348 | "attached": False, |
349 | "services": [ |
350 | - { |
351 | - "name": "esm-apps", |
352 | - "available": "yes" |
353 | - }, |
354 | - { |
355 | - "name": "esm-infra", |
356 | - "available": "yes" |
357 | - }, |
358 | - { |
359 | - "name": "livepatch", |
360 | - "available": "yes" |
361 | - } |
362 | - ] |
363 | + {"name": "esm-apps", "available": "yes"}, |
364 | + {"name": "esm-infra", "available": "yes"}, |
365 | + {"name": "livepatch", "available": "yes"}, |
366 | + ], |
367 | } |
368 | ) |
369 | |
370 | @@ -81,11 +62,9 @@ class TestCharm(TestCase): |
371 | "check_output": patch("subprocess.check_output").start(), |
372 | "open": patch("builtins.open").start(), |
373 | "environ": patch.dict("os.environ", clear=True).start(), |
374 | - "apt": patch("charm.apt").start() |
375 | + "apt": patch("charm.apt").start(), |
376 | } |
377 | - self.mocks["check_output"].side_effect = [ |
378 | - STATUS_DETACHED |
379 | - ] |
380 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED] |
381 | self.mocks["call"].return_value = 0 |
382 | mock_open(self.mocks["open"], read_data=DEFAULT_CLIENT_CONFIG) |
383 | self.harness = Harness(UbuntuAdvantageCharm) |
384 | @@ -94,17 +73,22 @@ class TestCharm(TestCase): |
385 | self.env = self.harness.charm.env |
386 | |
387 | def test_config_defaults(self): |
388 | - self.assertEqual(self.harness.charm.config.get("contract_url"), |
389 | - "https://contracts.canonical.com") |
390 | + self.assertEqual( |
391 | + self.harness.charm.config.get("contract_url"), "https://contracts.canonical.com" |
392 | + ) |
393 | self.assertEqual(self.harness.charm.config.get("ppa"), "ppa:ua-client/stable") |
394 | self.assertEqual(self.harness.charm.config.get("token"), "") |
395 | |
396 | def test_config_changed_ppa_new(self): |
397 | self.harness.update_config({"ppa": "ppa:ua-client/stable"}) |
398 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
399 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
400 | - call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
401 | - ])) |
402 | + self.mocks["check_call"].assert_has_calls( |
403 | + self._add_ua_proxy_setup_calls( |
404 | + [ |
405 | + call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
406 | + ] |
407 | + ) |
408 | + ) |
409 | self._assert_apt_calls() |
410 | self.assertEqual(self.harness.charm._state.ppa, "ppa:ua-client/stable") |
411 | self.assertFalse(self.harness.charm._state.package_needs_installing) |
412 | @@ -112,26 +96,36 @@ class TestCharm(TestCase): |
413 | def test_config_changed_ppa_updated(self): |
414 | self.harness.update_config({"ppa": "ppa:ua-client/stable"}) |
415 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
416 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
417 | - call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
418 | - ])) |
419 | + self.mocks["check_call"].assert_has_calls( |
420 | + self._add_ua_proxy_setup_calls( |
421 | + [ |
422 | + call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
423 | + ] |
424 | + ) |
425 | + ) |
426 | self._assert_apt_calls() |
427 | self.assertEqual(self.harness.charm._state.ppa, "ppa:ua-client/stable") |
428 | self.assertFalse(self.harness.charm._state.package_needs_installing) |
429 | |
430 | - self.mocks["check_output"].side_effect = [ |
431 | - STATUS_DETACHED |
432 | - ] |
433 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED] |
434 | self.mocks["check_call"].reset_mock() |
435 | self.mocks["apt"].reset_mock() |
436 | self.harness.update_config({"ppa": "ppa:different-client/unstable"}) |
437 | self.assertEqual(self.mocks["check_call"].call_count, 4) |
438 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
439 | - call(["add-apt-repository", "--remove", "--yes", "ppa:ua-client/stable"], |
440 | - env=self.env), |
441 | - call(["add-apt-repository", "--yes", "ppa:different-client/unstable"], |
442 | - env=self.env), |
443 | - ])) |
444 | + self.mocks["check_call"].assert_has_calls( |
445 | + self._add_ua_proxy_setup_calls( |
446 | + [ |
447 | + call( |
448 | + ["add-apt-repository", "--remove", "--yes", "ppa:ua-client/stable"], |
449 | + env=self.env, |
450 | + ), |
451 | + call( |
452 | + ["add-apt-repository", "--yes", "ppa:different-client/unstable"], |
453 | + env=self.env, |
454 | + ), |
455 | + ] |
456 | + ) |
457 | + ) |
458 | self._assert_apt_calls() |
459 | self.assertEqual(self.harness.charm._state.ppa, "ppa:different-client/unstable") |
460 | self.assertFalse(self.harness.charm._state.package_needs_installing) |
461 | @@ -139,18 +133,20 @@ class TestCharm(TestCase): |
462 | def test_config_changed_ppa_unmodified(self): |
463 | self.harness.update_config({"ppa": "ppa:ua-client/stable"}) |
464 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
465 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
466 | - call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
467 | - ])) |
468 | + self.mocks["check_call"].assert_has_calls( |
469 | + self._add_ua_proxy_setup_calls( |
470 | + [ |
471 | + call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
472 | + ] |
473 | + ) |
474 | + ) |
475 | self._assert_apt_calls() |
476 | self.assertEqual(self.harness.charm._state.ppa, "ppa:ua-client/stable") |
477 | self.assertFalse(self.harness.charm._state.package_needs_installing) |
478 | |
479 | self.mocks["check_call"].reset_mock() |
480 | self.mocks["check_output"].reset_mock() |
481 | - self.mocks["check_output"].side_effect = [ |
482 | - STATUS_DETACHED |
483 | - ] |
484 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED] |
485 | self.harness.update_config({"ppa": "ppa:ua-client/stable"}) |
486 | self.assertEqual(self.mocks["check_call"].call_count, 2) |
487 | self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([])) |
488 | @@ -160,9 +156,13 @@ class TestCharm(TestCase): |
489 | def test_config_changed_ppa_unset(self): |
490 | self.harness.update_config({"ppa": "ppa:ua-client/stable"}) |
491 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
492 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
493 | - call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
494 | - ])) |
495 | + self.mocks["check_call"].assert_has_calls( |
496 | + self._add_ua_proxy_setup_calls( |
497 | + [ |
498 | + call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
499 | + ] |
500 | + ) |
501 | + ) |
502 | self._assert_apt_calls() |
503 | self.assertEqual(self.harness.charm._state.ppa, "ppa:ua-client/stable") |
504 | self.assertFalse(self.harness.charm._state.package_needs_installing) |
505 | @@ -170,22 +170,27 @@ class TestCharm(TestCase): |
506 | self.mocks["check_call"].reset_mock() |
507 | self.mocks["check_output"].reset_mock() |
508 | self.mocks["apt"].reset_mock() |
509 | - self.mocks["check_output"].side_effect = [ |
510 | - STATUS_DETACHED |
511 | - ] |
512 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED] |
513 | self.harness.update_config({"ppa": ""}) |
514 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
515 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
516 | - call(["add-apt-repository", "--remove", "--yes", "ppa:ua-client/stable"], |
517 | - env=self.env), |
518 | - ])) |
519 | + self.mocks["check_call"].assert_has_calls( |
520 | + self._add_ua_proxy_setup_calls( |
521 | + [ |
522 | + call( |
523 | + ["add-apt-repository", "--remove", "--yes", "ppa:ua-client/stable"], |
524 | + env=self.env, |
525 | + ), |
526 | + ] |
527 | + ) |
528 | + ) |
529 | self._assert_apt_calls() |
530 | self.assertIsNone(self.harness.charm._state.ppa) |
531 | self.assertFalse(self.harness.charm._state.package_needs_installing) |
532 | |
533 | def test_config_changed_ppa_apt_failure(self): |
534 | - self.mocks["check_call"].side_effect = CalledProcessError("apt failure", |
535 | - "add-apt-repository") |
536 | + self.mocks["check_call"].side_effect = CalledProcessError( |
537 | + "apt failure", "add-apt-repository" |
538 | + ) |
539 | with self.assertRaises(CalledProcessError): |
540 | self.harness.update_config({"ppa": "ppa:ua-client/stable"}) |
541 | self.assertIsNone(self.harness.charm._state.ppa) |
542 | @@ -193,78 +198,81 @@ class TestCharm(TestCase): |
543 | self.assertIsInstance(self.harness.model.unit.status, MaintenanceStatus) |
544 | |
545 | def test_config_changed_token_unattached(self): |
546 | - self.mocks["check_output"].side_effect = [ |
547 | - STATUS_DETACHED, |
548 | - STATUS_ATTACHED |
549 | - ] |
550 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_ATTACHED] |
551 | self.harness.update_config({"token": "test-token"}) |
552 | self.mocks["open"].assert_called_with("/etc/ubuntu-advantage/uaclient.conf", "r+") |
553 | handle = self.mocks["open"]() |
554 | - expected = dedent("""\ |
555 | + expected = dedent( |
556 | + """\ |
557 | contract_url: https://contracts.canonical.com |
558 | data_dir: /var/lib/ubuntu-advantage |
559 | log_file: /var/log/ubuntu-advantage.log |
560 | log_level: debug |
561 | - """) |
562 | + """ |
563 | + ) |
564 | self.assertEqual(_written(handle), expected) |
565 | handle.truncate.assert_called_once() |
566 | self.assertEqual(self.mocks["call"].call_count, 1) |
567 | - self.mocks["call"].assert_has_calls([ |
568 | - call(["ubuntu-advantage", "attach", "test-token"]) |
569 | - ]) |
570 | - self.assertEqual(self.harness.charm._state.hashed_token, |
571 | - "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e") |
572 | - self.assertEqual(self.harness.model.unit.status, |
573 | - ActiveStatus("Attached (esm-apps,esm-infra,livepatch)")) |
574 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token"])]) |
575 | + self.assertEqual( |
576 | + self.harness.charm._state.hashed_token, |
577 | + "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e", |
578 | + ) |
579 | + self.assertEqual( |
580 | + self.harness.model.unit.status, ActiveStatus("Attached (esm-apps,esm-infra,livepatch)") |
581 | + ) |
582 | |
583 | def test_config_changed_token_reattach(self): |
584 | - self.mocks["check_output"].side_effect = [ |
585 | - STATUS_DETACHED, |
586 | - STATUS_ATTACHED |
587 | - ] |
588 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_ATTACHED] |
589 | self.harness.update_config({"token": "test-token"}) |
590 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
591 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
592 | - call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
593 | - ])) |
594 | + self.mocks["check_call"].assert_has_calls( |
595 | + self._add_ua_proxy_setup_calls( |
596 | + [ |
597 | + call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
598 | + ] |
599 | + ) |
600 | + ) |
601 | self.mocks["open"].assert_called_with("/etc/ubuntu-advantage/uaclient.conf", "r+") |
602 | self._assert_apt_calls() |
603 | handle = self.mocks["open"]() |
604 | - expected = dedent("""\ |
605 | + expected = dedent( |
606 | + """\ |
607 | contract_url: https://contracts.canonical.com |
608 | data_dir: /var/lib/ubuntu-advantage |
609 | log_file: /var/log/ubuntu-advantage.log |
610 | log_level: debug |
611 | - """) |
612 | + """ |
613 | + ) |
614 | self.assertEqual(_written(handle), expected) |
615 | handle.truncate.assert_called_once() |
616 | self.assertEqual(self.mocks["call"].call_count, 1) |
617 | - self.mocks["call"].assert_has_calls([ |
618 | - call(["ubuntu-advantage", "attach", "test-token"]) |
619 | - ]) |
620 | - self.assertEqual(self.harness.charm._state.hashed_token, |
621 | - "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e") |
622 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token"])]) |
623 | + self.assertEqual( |
624 | + self.harness.charm._state.hashed_token, |
625 | + "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e", |
626 | + ) |
627 | |
628 | self.mocks["call"].reset_mock() |
629 | self.mocks["check_call"].reset_mock() |
630 | self.mocks["check_output"].reset_mock() |
631 | - self.mocks["check_output"].side_effect = [ |
632 | - STATUS_ATTACHED, |
633 | - STATUS_ATTACHED |
634 | - ] |
635 | + self.mocks["check_output"].side_effect = [STATUS_ATTACHED, STATUS_ATTACHED] |
636 | self.harness.update_config({"token": "test-token-2"}) |
637 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
638 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
639 | - call(["ubuntu-advantage", "detach", "--assume-yes"]) |
640 | - ], append=False)) |
641 | + self.mocks["check_call"].assert_has_calls( |
642 | + self._add_ua_proxy_setup_calls( |
643 | + [call(["ubuntu-advantage", "detach", "--assume-yes"])], append=False |
644 | + ) |
645 | + ) |
646 | self.assertEqual(self.mocks["call"].call_count, 1) |
647 | - self.mocks["call"].assert_has_calls([ |
648 | - call(["ubuntu-advantage", "attach", "test-token-2"]) |
649 | - ]) |
650 | - self.assertEqual(self.harness.charm._state.hashed_token, |
651 | - "ab8a83efb364bf3f6739348519b53c8e8e0f7b4c06b6eeb881ad73dcf0059107") |
652 | - self.assertEqual(self.harness.model.unit.status, |
653 | - ActiveStatus("Attached (esm-apps,esm-infra,livepatch)")) |
654 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token-2"])]) |
655 | + self.assertEqual( |
656 | + self.harness.charm._state.hashed_token, |
657 | + "ab8a83efb364bf3f6739348519b53c8e8e0f7b4c06b6eeb881ad73dcf0059107", |
658 | + ) |
659 | + self.assertEqual( |
660 | + self.harness.model.unit.status, ActiveStatus("Attached (esm-apps,esm-infra,livepatch)") |
661 | + ) |
662 | |
663 | def test_config_changed_attach_failure(self): |
664 | self.mocks["call"].return_value = 1 |
665 | @@ -273,30 +281,26 @@ class TestCharm(TestCase): |
666 | self.assertEqual(self.harness.model.unit.status, BlockedStatus(message)) |
667 | |
668 | def test_config_changed_token_detach(self): |
669 | - self.mocks["check_output"].side_effect = [ |
670 | - STATUS_DETACHED, |
671 | - STATUS_ATTACHED |
672 | - ] |
673 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_ATTACHED] |
674 | self.harness.update_config({"token": "test-token"}) |
675 | self.assertEqual(self.mocks["call"].call_count, 1) |
676 | - self.mocks["call"].assert_has_calls([ |
677 | - call(["ubuntu-advantage", "attach", "test-token"]) |
678 | - ]) |
679 | - self.assertEqual(self.harness.charm._state.hashed_token, |
680 | - "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e") |
681 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token"])]) |
682 | + self.assertEqual( |
683 | + self.harness.charm._state.hashed_token, |
684 | + "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e", |
685 | + ) |
686 | |
687 | self.mocks["call"].reset_mock() |
688 | self.mocks["check_call"].reset_mock() |
689 | self.mocks["check_output"].reset_mock() |
690 | - self.mocks["check_output"].side_effect = [ |
691 | - STATUS_ATTACHED, |
692 | - STATUS_DETACHED |
693 | - ] |
694 | + self.mocks["check_output"].side_effect = [STATUS_ATTACHED, STATUS_DETACHED] |
695 | self.harness.update_config({"token": ""}) |
696 | self.assertEqual(self.mocks["check_call"].call_count, 3) |
697 | - self.mocks["check_call"].assert_has_calls(self._add_ua_proxy_setup_calls([ |
698 | - call(["ubuntu-advantage", "detach", "--assume-yes"]) |
699 | - ], append=False)) |
700 | + self.mocks["check_call"].assert_has_calls( |
701 | + self._add_ua_proxy_setup_calls( |
702 | + [call(["ubuntu-advantage", "detach", "--assume-yes"])], append=False |
703 | + ) |
704 | + ) |
705 | self.assertEqual(self.mocks["call"].call_count, 0) |
706 | self.assertIsNone(self.harness.charm._state.hashed_token) |
707 | self.assertEqual(self.harness.model.unit.status, BlockedStatus("No token configured")) |
708 | @@ -307,132 +311,118 @@ class TestCharm(TestCase): |
709 | |
710 | self.mocks["call"].reset_mock() |
711 | self.mocks["check_output"].reset_mock() |
712 | - self.mocks["check_output"].side_effect = [ |
713 | - STATUS_DETACHED, |
714 | - STATUS_ATTACHED |
715 | - ] |
716 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_ATTACHED] |
717 | self.harness.update_config({"token": "test-token"}) |
718 | self.assertEqual(self.mocks["call"].call_count, 1) |
719 | - self.mocks["call"].assert_has_calls([ |
720 | - call(["ubuntu-advantage", "attach", "test-token"]) |
721 | - ]) |
722 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token"])]) |
723 | self.assertIsInstance(self.harness.model.unit.status, ActiveStatus) |
724 | |
725 | def test_config_changed_token_contains_newline(self): |
726 | - self.mocks["check_output"].side_effect = [ |
727 | - STATUS_DETACHED, |
728 | - STATUS_ATTACHED |
729 | - ] |
730 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_ATTACHED] |
731 | self.harness.update_config({"token": "test-token\n"}) |
732 | - self.mocks["call"].assert_has_calls([ |
733 | - call(["ubuntu-advantage", "attach", "test-token"]) |
734 | - ]) |
735 | - self.assertEqual(self.harness.charm._state.hashed_token, |
736 | - "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e") |
737 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token"])]) |
738 | + self.assertEqual( |
739 | + self.harness.charm._state.hashed_token, |
740 | + "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e", |
741 | + ) |
742 | |
743 | def test_config_changed_ppa_contains_newline(self): |
744 | self.harness.update_config({"ppa": "ppa:ua-client/stable\n"}) |
745 | - self.mocks["check_call"].assert_has_calls([ |
746 | - call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
747 | - ]) |
748 | + self.mocks["check_call"].assert_has_calls( |
749 | + [ |
750 | + call(["add-apt-repository", "--yes", "ppa:ua-client/stable"], env=self.env), |
751 | + ] |
752 | + ) |
753 | self.assertEqual(self.harness.charm._state.ppa, "ppa:ua-client/stable") |
754 | |
755 | def test_config_changed_check_output_returns_bytes(self): |
756 | self.mocks["check_output"].side_effect = [ |
757 | bytes(STATUS_DETACHED, "utf-8"), |
758 | - bytes(STATUS_ATTACHED, "utf-8") |
759 | + bytes(STATUS_ATTACHED, "utf-8"), |
760 | ] |
761 | self.harness.update_config({"token": "test-token"}) |
762 | - self.assertEqual(self.harness.model.unit.status, |
763 | - ActiveStatus("Attached (esm-apps,esm-infra,livepatch)")) |
764 | + self.assertEqual( |
765 | + self.harness.model.unit.status, ActiveStatus("Attached (esm-apps,esm-infra,livepatch)") |
766 | + ) |
767 | |
768 | def test_config_changed_contract_url(self): |
769 | - self.mocks["check_output"].side_effect = [ |
770 | - STATUS_DETACHED, |
771 | - STATUS_ATTACHED |
772 | - ] |
773 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_ATTACHED] |
774 | self.harness.update_config({"contract_url": "https://contracts.staging.canonical.com"}) |
775 | self.mocks["open"].assert_called_with("/etc/ubuntu-advantage/uaclient.conf", "r+") |
776 | handle = self.mocks["open"]() |
777 | - expected = dedent("""\ |
778 | + expected = dedent( |
779 | + """\ |
780 | contract_url: https://contracts.staging.canonical.com |
781 | data_dir: /var/lib/ubuntu-advantage |
782 | log_file: /var/log/ubuntu-advantage.log |
783 | log_level: debug |
784 | - """) |
785 | + """ |
786 | + ) |
787 | self.assertEqual(_written(handle), expected) |
788 | handle.truncate.assert_called_once() |
789 | - self.assertEqual(self.harness.charm._state.contract_url, |
790 | - "https://contracts.staging.canonical.com") |
791 | + self.assertEqual( |
792 | + self.harness.charm._state.contract_url, "https://contracts.staging.canonical.com" |
793 | + ) |
794 | |
795 | def test_config_changed_contract_url_reattach(self): |
796 | - self.mocks["check_output"].side_effect = [ |
797 | - STATUS_DETACHED, |
798 | - STATUS_ATTACHED |
799 | - ] |
800 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_ATTACHED] |
801 | self.harness.update_config({"token": "test-token"}) |
802 | - self.mocks["call"].assert_has_calls([ |
803 | - call(["ubuntu-advantage", "attach", "test-token"]) |
804 | - ]) |
805 | - self.assertEqual(self.harness.charm._state.hashed_token, |
806 | - "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e") |
807 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token"])]) |
808 | + self.assertEqual( |
809 | + self.harness.charm._state.hashed_token, |
810 | + "4c5dc9b7708905f77f5e5d16316b5dfb425e68cb326dcd55a860e90a7707031e", |
811 | + ) |
812 | |
813 | self.mocks["call"].reset_mock() |
814 | self.mocks["check_call"].reset_mock() |
815 | self.mocks["check_output"].reset_mock() |
816 | self.mocks["open"].reset_mock() |
817 | - self.mocks["check_output"].side_effect = [ |
818 | - STATUS_ATTACHED, |
819 | - STATUS_ATTACHED |
820 | - ] |
821 | + self.mocks["check_output"].side_effect = [STATUS_ATTACHED, STATUS_ATTACHED] |
822 | mock_open(self.mocks["open"], read_data=DEFAULT_CLIENT_CONFIG) |
823 | self.harness.update_config({"contract_url": "https://contracts.staging.canonical.com"}) |
824 | self.mocks["open"].assert_called_with("/etc/ubuntu-advantage/uaclient.conf", "r+") |
825 | handle = self.mocks["open"]() |
826 | - expected = dedent("""\ |
827 | + expected = dedent( |
828 | + """\ |
829 | contract_url: https://contracts.staging.canonical.com |
830 | data_dir: /var/lib/ubuntu-advantage |
831 | log_file: /var/log/ubuntu-advantage.log |
832 | log_level: debug |
833 | - """) |
834 | + """ |
835 | + ) |
836 | self.assertEqual(_written(handle), expected) |
837 | handle.truncate.assert_called_once() |
838 | - self.mocks["check_call"].assert_has_calls([ |
839 | - call(["ubuntu-advantage", "detach", "--assume-yes"]) |
840 | - ]) |
841 | - self.mocks["call"].assert_has_calls([ |
842 | - call(["ubuntu-advantage", "attach", "test-token"]) |
843 | - ]) |
844 | - self.assertEqual(self.harness.model.unit.status, |
845 | - ActiveStatus("Attached (esm-apps,esm-infra,livepatch)")) |
846 | + self.mocks["check_call"].assert_has_calls( |
847 | + [call(["ubuntu-advantage", "detach", "--assume-yes"])] |
848 | + ) |
849 | + self.mocks["call"].assert_has_calls([call(["ubuntu-advantage", "attach", "test-token"])]) |
850 | + self.assertEqual( |
851 | + self.harness.model.unit.status, ActiveStatus("Attached (esm-apps,esm-infra,livepatch)") |
852 | + ) |
853 | |
854 | self.mocks["call"].reset_mock() |
855 | self.mocks["check_call"].reset_mock() |
856 | self.mocks["check_output"].reset_mock() |
857 | self.mocks["open"].reset_mock() |
858 | - self.mocks["check_output"].side_effect = [ |
859 | - STATUS_ATTACHED, |
860 | - STATUS_ATTACHED |
861 | - ] |
862 | + self.mocks["check_output"].side_effect = [STATUS_ATTACHED, STATUS_ATTACHED] |
863 | mock_open(self.mocks["open"], read_data=DEFAULT_CLIENT_CONFIG) |
864 | self.harness.update_config() |
865 | self.mocks["open"].assert_not_called() |
866 | self.mocks["call"].assert_not_called() |
867 | |
868 | def test_config_changed_unset_contract_url(self): |
869 | - self.mocks["check_output"].side_effect = [ |
870 | - STATUS_DETACHED, |
871 | - STATUS_DETACHED |
872 | - ] |
873 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_DETACHED] |
874 | self.harness.update_config({"contract_url": "https://contracts.staging.canonical.com"}) |
875 | self.mocks["open"].assert_called_with("/etc/ubuntu-advantage/uaclient.conf", "r+") |
876 | handle = self.mocks["open"]() |
877 | - expected = dedent("""\ |
878 | + expected = dedent( |
879 | + """\ |
880 | contract_url: https://contracts.staging.canonical.com |
881 | data_dir: /var/lib/ubuntu-advantage |
882 | log_file: /var/log/ubuntu-advantage.log |
883 | log_level: debug |
884 | - """) |
885 | + """ |
886 | + ) |
887 | self.assertEqual(_written(handle), expected) |
888 | handle.truncate.assert_called_once() |
889 | self.mocks["call"].assert_not_called() |
890 | @@ -441,19 +431,18 @@ class TestCharm(TestCase): |
891 | self.mocks["call"].reset_mock() |
892 | self.mocks["check_call"].reset_mock() |
893 | self.mocks["check_output"].reset_mock() |
894 | - self.mocks["check_output"].side_effect = [ |
895 | - STATUS_DETACHED, |
896 | - STATUS_DETACHED |
897 | - ] |
898 | + self.mocks["check_output"].side_effect = [STATUS_DETACHED, STATUS_DETACHED] |
899 | self.harness.update_config({"contract_url": "https://contracts.canonical.com"}) |
900 | self.mocks["open"].assert_called_with("/etc/ubuntu-advantage/uaclient.conf", "r+") |
901 | handle = self.mocks["open"]() |
902 | - expected = dedent("""\ |
903 | + expected = dedent( |
904 | + """\ |
905 | contract_url: https://contracts.canonical.com |
906 | data_dir: /var/lib/ubuntu-advantage |
907 | log_file: /var/log/ubuntu-advantage.log |
908 | log_level: debug |
909 | - """) |
910 | + """ |
911 | + ) |
912 | self.assertEqual(_written(handle), expected) |
913 | handle.truncate.assert_called_once() |
914 | self.mocks["call"].assert_not_called() |
915 | @@ -474,7 +463,7 @@ class TestCharm(TestCase): |
916 | self.assertEqual(self.harness.charm.env["no_proxy"], TEST_NO_PROXY) |
917 | |
918 | def _add_ua_proxy_setup_calls(self, call_list, append=True): |
919 | - """Helper to generate the calls used for UA proxy setup""" |
920 | + """Helper to generate the calls used for UA proxy setup.""" |
921 | proxy_calls = [ |
922 | call( |
923 | [ |
924 | @@ -496,10 +485,8 @@ class TestCharm(TestCase): |
925 | return call_list + proxy_calls if append else proxy_calls + call_list |
926 | |
927 | def _assert_apt_calls(self): |
928 | - """Helper to run the assertions for apt install/remove""" |
929 | - self.mocks["apt"].remove_package.assert_called_once_with( |
930 | - "ubuntu-advantage-tools" |
931 | - ) |
932 | + """Helper to run the assertions for apt install/remove.""" |
933 | + self.mocks["apt"].remove_package.assert_called_once_with("ubuntu-advantage-tools") |
934 | self.mocks["apt"].add_package.assert_called_once_with( |
935 | "ubuntu-advantage-tools", update_cache=True |
936 | ) |
937 | diff --git a/tox.ini b/tox.ini |
938 | new file mode 100644 |
939 | index 0000000..f17fc45 |
940 | --- /dev/null |
941 | +++ b/tox.ini |
942 | @@ -0,0 +1,78 @@ |
943 | +# Copyright 2022 Canonical Ltd. |
944 | +# See LICENSE file for licensing details. |
945 | + |
946 | +[tox] |
947 | +skipsdist=True |
948 | +skip_missing_interpreters = True |
949 | +envlist = lint, unit |
950 | + |
951 | +[vars] |
952 | +src_path = {toxinidir}/src/ |
953 | +tst_path = {toxinidir}/tests/ |
954 | +lib_path = {toxinidir}/lib/charms/operator_libs_linux |
955 | +all_path = {[vars]src_path} {[vars]tst_path} |
956 | + |
957 | +[testenv] |
958 | +setenv = |
959 | + PYTHONPATH = {toxinidir}:{toxinidir}/lib:{[vars]src_path} |
960 | + PYTHONBREAKPOINT=ipdb.set_trace |
961 | + PY_COLORS=1 |
962 | +passenv = |
963 | + PYTHONPATH |
964 | + HOME |
965 | + PATH |
966 | + CHARM_BUILD_DIR |
967 | + MODEL_SETTINGS |
968 | + HTTP_PROXY |
969 | + HTTPS_PROXY |
970 | + NO_PROXY |
971 | + |
972 | +[testenv:fmt] |
973 | +description = Apply coding style standards to code |
974 | +deps = |
975 | + black |
976 | + isort |
977 | +commands = |
978 | + isort {[vars]all_path} |
979 | + black {[vars]all_path} |
980 | + |
981 | +[testenv:lint] |
982 | +description = Check code against coding style standards |
983 | +deps = |
984 | + black |
985 | + flake8 |
986 | + flake8-docstrings |
987 | + flake8-copyright |
988 | + flake8-builtins |
989 | + pyproject-flake8 |
990 | + pep8-naming |
991 | + isort |
992 | + codespell |
993 | +commands = |
994 | + codespell {toxinidir}/*.yaml {toxinidir}/*.ini {toxinidir}/*.md \ |
995 | + {toxinidir}/*.toml {toxinidir}/*.txt {toxinidir}/.github |
996 | + # pflake8 wrapper supports config from pyproject.toml |
997 | + pflake8 {[vars]all_path} |
998 | + isort --check-only --diff {[vars]all_path} |
999 | + black --check --diff {[vars]all_path} |
1000 | + |
1001 | +[testenv:unit] |
1002 | +description = Run unit tests |
1003 | +deps = |
1004 | + pytest |
1005 | + coverage[toml] |
1006 | + -r{toxinidir}/requirements.txt |
1007 | +commands = |
1008 | + coverage run --source={[vars]src_path} \ |
1009 | + -m pytest --ignore={[vars]tst_path}integration -v --tb native -s {posargs} |
1010 | + coverage report |
1011 | + |
1012 | +[testenv:integration] |
1013 | +description = Run integration tests |
1014 | +deps = |
1015 | + git+https://github.com/juju/python-libjuju.git |
1016 | + pytest |
1017 | + git+https://github.com/charmed-kubernetes/pytest-operator.git |
1018 | + -r{toxinidir}/requirements.txt |
1019 | +commands = |
1020 | + pytest -v --tb native --ignore={[vars]tst_path}unit --log-cli-level=INFO -s {posargs} |
1021 | \ No newline at end of file |
This merge proposal is being monitored by mergebot. Change the status to Approved to merge.