diff --git a/.gitignore b/.gitignore index 35013a4..eba8e8f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ client.py +.coverage +htmlcov __pycache__/ +.pytest_cache diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 305ada7..dfe554a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,4 +23,4 @@ lint: - source /var/venv/bin/activate - pip install -r requirements.txt - pip install -r requirements-dev.txt - - make --no-print-directory lint + - make --no-print-directory --quiet lint diff --git a/Makefile b/Makefile index c163908..75be1bc 100644 --- a/Makefile +++ b/Makefile @@ -7,14 +7,14 @@ help: # Print help on Makefile open_all: # Open all projects files ${EDITOR} ${VBIN}/activate - ${EDITOR} .gitignore .gitlab-ci.yaml client* main.py Makefile pyproject.toml README.md requirements-dev.txt requirements.txt + ${EDITOR} .gitignore .gitlab-ci.yaml client* main.py Makefile pyproject.toml README.md requirements-dev.txt requirements.txt tests_* ${EDITOR} .git/hooks/p*-commit pre_commit: # Run the pre-commit hook .git/hooks/pre-commit clean: # Remove files not tracked in source control - rm -rf __pycache__ + rm -rf .pytest_cache htmlcov __pycache__ find . -type f -name "*.orig" -delete find . -type f -name "*.pyc" -delete find . -type d -empty -delete @@ -24,3 +24,9 @@ lint: # Lint code ${VBIN}/pflake8 --config=pyproject.toml && echo "✅ pflake8" || echo "🚨 pflake8" ${VBIN}/pydocstyle && echo "✅ pydocstyle" || echo "🚨 pydocstyle" ${VBIN}/pylint --rcfile=pyproject.toml *.py && echo "✅ pylint" || echo "🚨 pylint" + +test: # Test code + ${VBIN}/pytest tests_*.py + +test_pdb: # Test code and open debugger if fail + ${VBIN}/pytest --pdb tests_*.py diff --git a/README.md b/README.md index 84a90d5..de226f4 100644 --- a/README.md +++ b/README.md @@ -61,4 +61,3 @@ python main.py -h Details in [`requirements.txt`](requirements.txt) & [`requirements-dev.txt`](requirements-dev.txt) - [`opensearch-py`](https://opensearch.org/docs/latest/clients/python/) -- [`opensearch_dsl`](https://pypi.org/project/opensearch-dsl/) diff --git a/pyproject.toml b/pyproject.toml index 3fc10b8..0ea49a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,3 +5,6 @@ max-line-length = 90 score = false disable = ["W0107", "W0102"] ignore = "client.sample.py" + +[tool.pytest.ini_options] +addopts = "--doctest-modules --exitfirst --failed-first --cov-report=html --cov-report=term:skip-covered --cov=." diff --git a/requirements-dev.txt b/requirements-dev.txt index 7577837..6c6bf80 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,9 @@ black +coverage flake8==4 # see: https://github.com/johnthagen/python-blueprint/issues/113 pydocstyle pylint pyproject-flake8 +pytest +pytest-cov +toml diff --git a/tests_main.py b/tests_main.py new file mode 100644 index 0000000..1f6ddf0 --- /dev/null +++ b/tests_main.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +# coding: utf8 + +"""test_main. + +Testing `main.py` + +Author: frederic zind 2022-09-24 +Licenses: GNU AGPL v3: http://www.gnu.org/licenses/ +""" +import logging +from pytest import raises + +import main + + +# Faking options from argparse +class FakeOptions: # pylint: disable=too-few-public-methods + """Options object mock.""" + + debug = False + mapping = False + + def __init__(self, options): + """Built loggers options.""" + if "debug" in options: + self.debug = True + if "mapping" in options: + self.mapping = True + + +# ### +# Testing setup_logging() +# ### +def test_logging_debug(): + """Logger level is DEBUG. Set up with --debug argument.""" + options = FakeOptions(["debug"]) + main.setup_logging(options) + + assert isinstance((main.logger), logging.Logger) + assert main.logger.level == 10 + + +def test_logging_default(): + """Logger level is INFO. Set up without arguments.""" + options = FakeOptions([]) + main.setup_logging(options) + + assert isinstance((main.logger), logging.Logger) + assert main.logger.level == 20 + + +# ### +# Testing parse_args() +# ### +def test_parse_args(): + """Defaults arguments are here.""" + cli_options = main.parse_args(["--debug", "--mapping"]) + assert cli_options.debug + assert cli_options.mapping + + +# ### +# Testing get_map_props() +# ### +def test_get_map_props(): + """This is an integration test. + + It need credentials to guery LDP stream. + """ + pass + + +# ### +# Testing main() +# ### +def test_main_whithout_option(): + """Called without option.""" + options = FakeOptions([]) + + with raises(RuntimeError): + main.main(options) + + +def test_main_demo_whith_mapping(): + """Called with mapping option. + + `main()` just tranfers `get_map_props()` return: this test is not really useful + """ + options = FakeOptions(["mapping"]) + response = main.main(options) + + assert isinstance(response, list)