Merge ~aluria/charm-etckeeper:makefile-20.08 into charm-etckeeper:master
- Git
- lp:~aluria/charm-etckeeper
- makefile-20.08
- Merge into master
Proposed by
Alvaro Uria
Status: | Merged |
---|---|
Merged at revision: | 25aa486ceb8e90d497f1d83d507ca11a86bb655b |
Proposed branch: | ~aluria/charm-etckeeper:makefile-20.08 |
Merge into: | charm-etckeeper:master |
Prerequisite: | ~aluria/charm-etckeeper:fix-tests |
Diff against target: |
535 lines (+151/-113) 10 files modified
.gitignore (+26/-7) Makefile (+55/-39) dev/null (+0/-1) src/lib/lib_charm_etckeeper.py (+6/-3) src/reactive/charm_etckeeper.py (+3/-1) src/tests/functional/conftest.py (+9/-5) src/tests/functional/juju_tools.py (+2/-1) src/tests/functional/test_deploy.py (+9/-5) src/tests/unit/conftest.py (+1/-0) src/tox.ini (+40/-51) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paul Goins | Approve | ||
Celia Wang | Approve | ||
Review via email: mp+388980@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Paul Goins (vultaire) wrote : | # |
LGTM. Withholding approval until "make tests" can be run against this branch.
Revision history for this message
Paul Goins (vultaire) wrote : | # |
Approved and merged
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.gitignore b/.gitignore |
2 | index 32e2995..6f1f367 100644 |
3 | --- a/.gitignore |
4 | +++ b/.gitignore |
5 | @@ -1,22 +1,41 @@ |
6 | +# Juju files |
7 | +.unit-state.db |
8 | +.go-cookies |
9 | + |
10 | +layers/* |
11 | +interfaces/* |
12 | + |
13 | # Byte-compiled / optimized / DLL files |
14 | __pycache__/ |
15 | *.py[cod] |
16 | *$py.class |
17 | |
18 | +# Tests files and dir |
19 | +.pytest_cache/ |
20 | +.coverage |
21 | +.tox |
22 | +report/ |
23 | +htmlcov/ |
24 | + |
25 | # Log files |
26 | *.log |
27 | |
28 | -.tox/ |
29 | -.coverage |
30 | +# pycharm |
31 | +.idea/ |
32 | |
33 | # vi |
34 | .*.swp |
35 | |
36 | -# pycharm |
37 | -.idea/ |
38 | - |
39 | # version data |
40 | repo-info |
41 | +version |
42 | + |
43 | +# Python builds |
44 | +deb_dist/ |
45 | +dist/ |
46 | + |
47 | +# Snaps |
48 | +*.snap |
49 | |
50 | -# reports |
51 | -report/* |
52 | +# Builds |
53 | +.build/ |
54 | \ No newline at end of file |
55 | diff --git a/.unit-state.db b/.unit-state.db |
56 | deleted file mode 100644 |
57 | index 014b82c..0000000 |
58 | Binary files a/.unit-state.db and /dev/null differ |
59 | diff --git a/Makefile b/Makefile |
60 | index ec627d8..5416279 100644 |
61 | --- a/Makefile |
62 | +++ b/Makefile |
63 | @@ -1,64 +1,80 @@ |
64 | +PYTHON := /usr/bin/python3 |
65 | + |
66 | +PROJECTPATH=$(dir $(realpath $(MAKEFILE_LIST))) |
67 | ifndef CHARM_BUILD_DIR |
68 | - CHARM_BUILD_DIR=/tmp/charm-builds |
69 | + CHARM_BUILD_DIR=${PROJECTPATH}.build |
70 | endif |
71 | - |
72 | -BUILD_VARS=PYTEST_MODEL=$(PYTEST_MODEL) \ |
73 | - PYTEST_KEEP_MODEL=$(PYTEST_KEEP_MODEL) \ |
74 | - PYTEST_CLOUD_NAME=$(PYTEST_CLOUD_NAME) \ |
75 | - PYTEST_CLOUD_REGION=$(PYTEST_CLOUD_REGION) \ |
76 | - CHARM_BUILD_DIR=$(CHARM_BUILD_DIR) |
77 | - |
78 | -ifneq ($(PYTEST_SELECT_TESTS),) |
79 | -BUILD_VARS+=PYTEST_SELECT_TESTS="$(PYTEST_SELECT_TESTS)" |
80 | +ifndef CHARM_LAYERS_DIR |
81 | + CHARM_LAYERS_DIR=${PROJECTPATH}/layers |
82 | endif |
83 | -ifneq ($(PYTEST_SELECT_MARKS),) |
84 | -BUILD_VARS+=PYTEST_SELECT_MARKS="$(PYTEST_SELECT_MARKS)" |
85 | +ifndef CHARM_INTERFACES_DIR |
86 | + CHARM_INTERFACES_DIR=${PROJECTPATH}/interfaces |
87 | endif |
88 | +METADATA_FILE="src/metadata.yaml" |
89 | +CHARM_NAME=$(shell cat ${PROJECTPATH}/${METADATA_FILE} | grep -E "^name:" | awk '{print $$2}') |
90 | |
91 | help: |
92 | @echo "This project supports the following targets" |
93 | @echo "" |
94 | @echo " make help - show this text" |
95 | + @echo " make clean - remove unneeded files" |
96 | @echo " make submodules - make sure that the submodules are up-to-date" |
97 | - @echo " make lint - run flake8" |
98 | - @echo " make test - run the unittests and lint" |
99 | - @echo " make unittest - run the tests defined in the unittest subdirectory" |
100 | + @echo " make submodules-update - update submodules to latest changes on remote branch" |
101 | + @echo " make build - build the charm" |
102 | + @echo " make release - run clean, submodules, and build targets" |
103 | + @echo " make lint - run flake8 and black --check" |
104 | + @echo " make black - run black and reformat files" |
105 | + @echo " make proof - run charm proof" |
106 | + @echo " make unittests - run the tests defined in the unittest subdirectory" |
107 | @echo " make functional - run the tests defined in the functional subdirectory" |
108 | - @echo " make release - build the charm" |
109 | - @echo " make clean - remove unneeded files" |
110 | + @echo " make test - run lint, proof, unittests and functional targets" |
111 | @echo "" |
112 | |
113 | +clean: |
114 | + @echo "Cleaning files" |
115 | + @git clean -ffXd -e '!.idea' |
116 | + @echo "Cleaning existing build" |
117 | + @rm -rf ${CHARM_BUILD_DIR}/${CHARM_NAME} |
118 | + |
119 | submodules: |
120 | @echo "Cloning submodules" |
121 | @git submodule update --init --recursive |
122 | |
123 | -lint: |
124 | - @echo "Running flake8" |
125 | - @tox -e lint |
126 | +submodules-update: |
127 | + @echo "Pulling latest updates for submodules" |
128 | + @git submodule update --init --recursive --remote --merge |
129 | + |
130 | +build: |
131 | + @echo "Building charm to directory ${CHARM_BUILD_DIR}/${CHARM_NAME}" |
132 | + @-git rev-parse --abbrev-ref HEAD > ./src/repo-info |
133 | + @CHARM_LAYERS_DIR=${CHARM_LAYERS_DIR} CHARM_INTERFACES_DIR=${CHARM_INTERFACES_DIR} \ |
134 | + TERM=linux CHARM_BUILD_DIR=${CHARM_BUILD_DIR} charm build src/ |
135 | |
136 | -test: lint unittest functional |
137 | +release: clean build |
138 | + @echo "Charm is built at ${CHARM_BUILD_DIR}/${CHARM_NAME}" |
139 | |
140 | -unittest: |
141 | - @tox -e unit |
142 | +lint: |
143 | + @echo "Running lint checks" |
144 | + @cd src && tox -e lint |
145 | |
146 | -functional: build |
147 | - @echo Executing with: $(BUILD_VARS) tox -e functional |
148 | - @$(BUILD_VARS) tox -e functional |
149 | +black: |
150 | + @echo "Reformat files with black" |
151 | + @cd src && tox -e black |
152 | |
153 | -build: |
154 | - @echo "Building charm to base directory $(CHARM_BUILD_DIR)" |
155 | - @-git describe --tags > ./repo-info |
156 | - @CHARM_LAYERS_DIR=./layers CHARM_INTERFACES_DIR=./interfaces TERM=linux \ |
157 | - CHARM_BUILD_DIR=$(CHARM_BUILD_DIR) charm build . --force |
158 | +proof: build |
159 | + @echo "Running charm proof" |
160 | + @charm proof ${CHARM_BUILD_DIR}/${CHARM_NAME} |
161 | |
162 | -release: clean build |
163 | - @echo "Charm is built at $(JUJU_REPOSITORY)/builds" |
164 | +unittests: |
165 | + @echo "Running unit tests" |
166 | + @cd src && tox -e unit |
167 | |
168 | -clean: |
169 | - @echo "Cleaning files" |
170 | - @if [ -d .tox ] ; then rm -r .tox ; fi |
171 | - @if [ -d .pytest_cache ] ; then rm -r .pytest_cache ; fi |
172 | - @find . -iname __pycache__ -exec rm -r {} + |
173 | +functional: build |
174 | + @echo "Executing functional tests in ${CHARM_BUILD_DIR}" |
175 | + @cd src && CHARM_BUILD_DIR=${CHARM_BUILD_DIR} tox -e func |
176 | + |
177 | +test: lint proof unittests functional |
178 | + @echo "Tests completed for charm ${CHARM_NAME}." |
179 | |
180 | # The targets below don't depend on a file |
181 | -.PHONY: lint test unittest functional build release clean help submodules |
182 | +.PHONY: help submodules submodules-update clean build release lint black proof unittests functional test |
183 | diff --git a/requirements.txt b/requirements.txt |
184 | deleted file mode 100644 |
185 | index 8462291..0000000 |
186 | --- a/requirements.txt |
187 | +++ /dev/null |
188 | @@ -1 +0,0 @@ |
189 | -# Include python requirements here |
190 | diff --git a/README.md b/src/README.md |
191 | similarity index 100% |
192 | rename from README.md |
193 | rename to src/README.md |
194 | diff --git a/actions.yaml b/src/actions.yaml |
195 | similarity index 100% |
196 | rename from actions.yaml |
197 | rename to src/actions.yaml |
198 | diff --git a/actions/commit b/src/actions/commit |
199 | similarity index 100% |
200 | rename from actions/commit |
201 | rename to src/actions/commit |
202 | diff --git a/config.yaml b/src/config.yaml |
203 | similarity index 100% |
204 | rename from config.yaml |
205 | rename to src/config.yaml |
206 | diff --git a/icon.svg b/src/icon.svg |
207 | similarity index 100% |
208 | rename from icon.svg |
209 | rename to src/icon.svg |
210 | diff --git a/layer.yaml b/src/layer.yaml |
211 | similarity index 100% |
212 | rename from layer.yaml |
213 | rename to src/layer.yaml |
214 | diff --git a/lib/lib_charm_etckeeper.py b/src/lib/lib_charm_etckeeper.py |
215 | similarity index 96% |
216 | rename from lib/lib_charm_etckeeper.py |
217 | rename to src/lib/lib_charm_etckeeper.py |
218 | index 594299f..7fd1176 100644 |
219 | --- a/lib/lib_charm_etckeeper.py |
220 | +++ b/src/lib/lib_charm_etckeeper.py |
221 | @@ -1,8 +1,10 @@ |
222 | """The EtcKeeper helper module.""" |
223 | -from charmhelpers.core import hookenv, unitdata, host, templating |
224 | -from charms.reactive.helpers import any_file_changed |
225 | from subprocess import check_call |
226 | |
227 | +from charmhelpers.core import hookenv, host, templating, unitdata |
228 | + |
229 | +from charms.reactive.helpers import any_file_changed |
230 | + |
231 | |
232 | class EtcKeeper: |
233 | """The EtcKeeper helper class.""" |
234 | @@ -58,7 +60,8 @@ class EtcKeeper: |
235 | def bootstrap_etc(self): |
236 | """Set up repo and update KV with status.""" |
237 | if self.is_initialized: |
238 | - hookenv.log("Skipping etckeeper init on already-initialised repo.", hookenv.DEBUG) |
239 | + hookenv.log("Skipping etckeeper init on already-initialised repo.", |
240 | + hookenv.DEBUG) |
241 | return True |
242 | if self.init_repo(): |
243 | return True |
244 | diff --git a/metadata.yaml b/src/metadata.yaml |
245 | similarity index 100% |
246 | rename from metadata.yaml |
247 | rename to src/metadata.yaml |
248 | diff --git a/reactive/charm_etckeeper.py b/src/reactive/charm_etckeeper.py |
249 | similarity index 100% |
250 | rename from reactive/charm_etckeeper.py |
251 | rename to src/reactive/charm_etckeeper.py |
252 | index 153b38a..1728526 100644 |
253 | --- a/reactive/charm_etckeeper.py |
254 | +++ b/src/reactive/charm_etckeeper.py |
255 | @@ -1,8 +1,10 @@ |
256 | """Main reactive charm layer for etckeeper.""" |
257 | -from lib_charm_etckeeper import EtcKeeper |
258 | from charmhelpers.core import hookenv |
259 | + |
260 | from charms.reactive import is_flag_set, when, when_not |
261 | |
262 | +from lib_charm_etckeeper import EtcKeeper |
263 | + |
264 | helper = EtcKeeper() |
265 | |
266 | |
267 | diff --git a/templates/etckeeper.conf.j2 b/src/templates/etckeeper.conf.j2 |
268 | similarity index 100% |
269 | rename from templates/etckeeper.conf.j2 |
270 | rename to src/templates/etckeeper.conf.j2 |
271 | diff --git a/tests/functional/conftest.py b/src/tests/functional/conftest.py |
272 | similarity index 91% |
273 | rename from tests/functional/conftest.py |
274 | rename to src/tests/functional/conftest.py |
275 | index 104791c..d4fbac0 100644 |
276 | --- a/tests/functional/conftest.py |
277 | +++ b/src/tests/functional/conftest.py |
278 | @@ -5,25 +5,29 @@ Reusable pytest fixtures for functional testing. |
279 | Environment variables |
280 | --------------------- |
281 | |
282 | -PYTEST_CLOUD_REGION, PYTEST_CLOUD_NAME: cloud name and region to use for juju model creation |
283 | +PYTEST_CLOUD_REGION, PYTEST_CLOUD_NAME: cloud name and region to use for juju model |
284 | +creation |
285 | |
286 | -PYTEST_KEEP_MODEL: if set, the testing model won't be torn down at the end of the testing session |
287 | +PYTEST_KEEP_MODEL: if set, the testing model won't be torn down at the end of the |
288 | +testing session |
289 | |
290 | """ |
291 | |
292 | import asyncio |
293 | import os |
294 | -import uuid |
295 | -import pytest |
296 | import subprocess |
297 | +import uuid |
298 | |
299 | from juju.controller import Controller |
300 | + |
301 | from juju_tools import JujuTools |
302 | |
303 | +import pytest |
304 | + |
305 | |
306 | @pytest.fixture(scope="module") |
307 | def event_loop(): |
308 | - """Override the default pytest event loop to allow for fixtures using a broader scope.""" |
309 | + """Override default pytest event loop to allow fixtures using a broader scope.""" |
310 | loop = asyncio.get_event_loop_policy().new_event_loop() |
311 | asyncio.set_event_loop(loop) |
312 | loop.set_debug(True) |
313 | diff --git a/tests/functional/juju_tools.py b/src/tests/functional/juju_tools.py |
314 | similarity index 100% |
315 | rename from tests/functional/juju_tools.py |
316 | rename to src/tests/functional/juju_tools.py |
317 | index 9840c79..f14c5d4 100644 |
318 | --- a/tests/functional/juju_tools.py |
319 | +++ b/src/tests/functional/juju_tools.py |
320 | @@ -1,7 +1,8 @@ |
321 | """Juju tools fixture library.""" |
322 | +import base64 |
323 | import pickle |
324 | + |
325 | import juju |
326 | -import base64 |
327 | |
328 | # from juju.errors import JujuError |
329 | |
330 | diff --git a/tests/functional/requirements.txt b/src/tests/functional/requirements.txt |
331 | similarity index 100% |
332 | rename from tests/functional/requirements.txt |
333 | rename to src/tests/functional/requirements.txt |
334 | diff --git a/tests/functional/test_deploy.py b/src/tests/functional/test_deploy.py |
335 | similarity index 91% |
336 | rename from tests/functional/test_deploy.py |
337 | rename to src/tests/functional/test_deploy.py |
338 | index 3943b20..9c58d73 100644 |
339 | --- a/tests/functional/test_deploy.py |
340 | +++ b/src/tests/functional/test_deploy.py |
341 | @@ -1,8 +1,9 @@ |
342 | """Functional tests for etckeeper charm.""" |
343 | import os |
344 | -import pytest |
345 | -import subprocess |
346 | import stat |
347 | +import subprocess |
348 | + |
349 | +import pytest |
350 | |
351 | # Treat all tests as coroutines |
352 | pytestmark = pytest.mark.asyncio |
353 | @@ -89,7 +90,8 @@ async def test_etckeeper_relate(model, series, app, request): |
354 | """Test relating etckeeper subordinte to ubuntu.""" |
355 | application_name = "ubuntu-{}".format(series) |
356 | ubuntu = model.applications[application_name] |
357 | - await model.block_until(lambda: ubuntu.status == "active" or ubuntu.status == "error") |
358 | + await model.block_until(lambda: ubuntu.status == "active" |
359 | + or ubuntu.status == "error") |
360 | await model.add_relation(app.name, application_name) |
361 | |
362 | |
363 | @@ -97,8 +99,10 @@ async def test_charmetckeeper_status(model, app, series): |
364 | """Test the status of the application in the model.""" |
365 | application_name = "ubuntu-{}".format(series) |
366 | ubuntu = model.applications[application_name] |
367 | - await model.block_until(lambda: ubuntu.status == "active" or ubuntu.status == "error") |
368 | - await model.block_until(lambda: app.status == "active" or app.status == "error") |
369 | + await model.block_until(lambda: ubuntu.status == "active" |
370 | + or ubuntu.status == "error") |
371 | + await model.block_until(lambda: app.status == "active" |
372 | + or app.status == "error") |
373 | assert ubuntu.status != "error" |
374 | assert app.status != "error" |
375 | |
376 | diff --git a/tests/unit/conftest.py b/src/tests/unit/conftest.py |
377 | similarity index 100% |
378 | rename from tests/unit/conftest.py |
379 | rename to src/tests/unit/conftest.py |
380 | index 20b62ba..0b9f3cd 100644 |
381 | --- a/tests/unit/conftest.py |
382 | +++ b/src/tests/unit/conftest.py |
383 | @@ -1,6 +1,7 @@ |
384 | #!/usr/bin/python3 |
385 | """Unit tests for the etckeeper charm.""" |
386 | import mock |
387 | + |
388 | import pytest |
389 | |
390 | |
391 | diff --git a/tests/unit/example.cfg b/src/tests/unit/example.cfg |
392 | similarity index 100% |
393 | rename from tests/unit/example.cfg |
394 | rename to src/tests/unit/example.cfg |
395 | diff --git a/tests/unit/requirements.txt b/src/tests/unit/requirements.txt |
396 | similarity index 100% |
397 | rename from tests/unit/requirements.txt |
398 | rename to src/tests/unit/requirements.txt |
399 | diff --git a/tests/unit/test_actions.py b/src/tests/unit/test_actions.py |
400 | similarity index 100% |
401 | rename from tests/unit/test_actions.py |
402 | rename to src/tests/unit/test_actions.py |
403 | diff --git a/tests/unit/test_lib.py b/src/tests/unit/test_lib.py |
404 | similarity index 100% |
405 | rename from tests/unit/test_lib.py |
406 | rename to src/tests/unit/test_lib.py |
407 | diff --git a/tox.ini b/src/tox.ini |
408 | similarity index 52% |
409 | rename from tox.ini |
410 | rename to src/tox.ini |
411 | index 94527af..b3f3a73 100644 |
412 | --- a/tox.ini |
413 | +++ b/src/tox.ini |
414 | @@ -1,81 +1,70 @@ |
415 | [tox] |
416 | skipsdist=True |
417 | -envlist = unit, functional |
418 | skip_missing_interpreters = True |
419 | +envlist = lint, unit, func |
420 | |
421 | [testenv] |
422 | basepython = python3 |
423 | setenv = |
424 | - PYTHONPATH = . |
425 | - |
426 | -[testenv:unit] |
427 | -commands = pytest -v \ |
428 | - --ignore {toxinidir}/tests/functional \ |
429 | - --ignore {toxinidir}/interfaces \ |
430 | - --ignore {toxinidir}/layers \ |
431 | - --cov=lib \ |
432 | - --cov=reactive \ |
433 | - --cov=actions \ |
434 | - --cov-report=term \ |
435 | - --cov-report=annotate:report/unit/coverage-annotated \ |
436 | - --cov-report=html:report/unit/coverage-html \ |
437 | - --html=report/unit/tests/index.html \ |
438 | - --junitxml=report/unit/junit.xml |
439 | -deps = -r{toxinidir}/tests/unit/requirements.txt |
440 | - -r{toxinidir}/requirements.txt |
441 | -setenv = PYTHONPATH={toxinidir}/lib |
442 | - |
443 | -[testenv:functional] |
444 | + PYTHONPATH = {toxinidir}:{toxinidir}/lib/:{toxinidir}/hooks/ |
445 | passenv = |
446 | HOME |
447 | - CHARM_BUILD_DIR |
448 | PATH |
449 | - PYTEST_MODEL |
450 | + CHARM_BUILD_DIR |
451 | PYTEST_KEEP_MODEL |
452 | PYTEST_CLOUD_NAME |
453 | PYTEST_CLOUD_REGION |
454 | -commands = pytest -x -v \ |
455 | - -k {env:PYTEST_SELECT_TESTS:test} \ |
456 | - -m "{env:PYTEST_SELECT_MARKS:not excluded}" \ |
457 | - --ignore {toxinidir}/tests/unit \ |
458 | - --ignore {toxinidir}/interfaces \ |
459 | - --ignore {toxinidir}/layers \ |
460 | - --html=report/functional/index.html \ |
461 | - --junitxml=report/functional/junit.xml |
462 | -deps = -r{toxinidir}/tests/functional/requirements.txt |
463 | - -r{toxinidir}/requirements.txt |
464 | + PYTEST_MODEL |
465 | + MODEL_SETTINGS |
466 | + HTTP_PROXY |
467 | + HTTPS_PROXY |
468 | + NO_PROXY |
469 | + SNAP_HTTP_PROXY |
470 | + SNAP_HTTPS_PROXY |
471 | |
472 | [testenv:lint] |
473 | -commands = flake8 |
474 | -deps = |
475 | +commands = |
476 | flake8 |
477 | - flake8-colors |
478 | - flake8-docstrings |
479 | - pep8-naming |
480 | - |
481 | -[testenv:lintjunit] |
482 | -commands = flake8 --format junit-xml --output-file=report/lint/junit.xml |
483 | + # black --check --exclude "/(\.eggs|\.git|\.tox|\.venv|\.build|dist|charmhelpers|mod)/" . |
484 | deps = |
485 | + black |
486 | flake8 |
487 | - flake8-colors |
488 | flake8-docstrings |
489 | - flake8-formatter-junit-xml |
490 | flake8-import-order |
491 | pep8-naming |
492 | + flake8-colors |
493 | |
494 | [flake8] |
495 | exclude = |
496 | .git, |
497 | __pycache__, |
498 | .tox, |
499 | - layers, |
500 | - interfaces, |
501 | -max-line-length = 120 |
502 | + charmhelpers, |
503 | + mod, |
504 | + .build |
505 | + |
506 | +max-line-length = 88 |
507 | max-complexity = 10 |
508 | |
509 | -[pytest] |
510 | -markers = |
511 | - deploy: mark deployment tests to allow running w/o redeploy |
512 | -filterwarnings = |
513 | - ignore::DeprecationWarning |
514 | +[testenv:black] |
515 | +commands = |
516 | + black --exclude "/(\.eggs|\.git|\.tox|\.venv|\.build|dist|charmhelpers|mod)/" . |
517 | +deps = |
518 | + black |
519 | |
520 | +[testenv:unit] |
521 | +commands = |
522 | + pytest -v --ignore {toxinidir}/tests/functional \ |
523 | + --cov=lib \ |
524 | + --cov=reactive \ |
525 | + --cov=actions \ |
526 | + --cov=hooks \ |
527 | + --cov=src \ |
528 | + --cov-report=term \ |
529 | + --cov-report=annotate:report/annotated \ |
530 | + --cov-report=html:report/html |
531 | +deps = -r{toxinidir}/tests/unit/requirements.txt |
532 | + |
533 | +[testenv:func] |
534 | +commands = pytest -v --ignore {toxinidir}/tests/unit |
535 | +deps = -r{toxinidir}/tests/functional/requirements.txt |
LGTM.