diff --git a/.config/dictionary.txt b/.config/dictionary.txt index 939e1ba..42c71e5 100644 --- a/.config/dictionary.txt +++ b/.config/dictionary.txt @@ -130,12 +130,15 @@ subschema subspec substring superfences +sysargs templatable templated templating +testcol testhost testname testns +testorg testpaths tmplt topbar diff --git a/.config/requirements-test.txt b/.config/requirements-test.txt new file mode 100644 index 0000000..53a02db --- /dev/null +++ b/.config/requirements-test.txt @@ -0,0 +1,3 @@ +pytest +pytest-xdist +tox diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml new file mode 100644 index 0000000..9aaf21d --- /dev/null +++ b/.github/workflows/tox.yml @@ -0,0 +1,67 @@ +--- +name: tox + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +on: + pull_request: + schedule: + - cron: "0 0 * * *" + +jobs: + pre: + name: pre + runs-on: ubuntu-22.04 + outputs: + matrix: ${{ steps.generate_matrix.outputs.matrix }} + steps: + - name: Determine matrix + id: generate_matrix + uses: coactions/dynamic-matrix@v1 + with: + min_python: "3.9" + max_python: "3.11" + default_python: "3.11" + other_names: lint + + tox: + name: ${{ matrix.name }} / python ${{ matrix.python_version }} + runs-on: ubuntu-20.04 + needs: pre + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.pre.outputs.matrix) }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # needed by setuptools-scm + + - name: Set up Python ${{ matrix.python_version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python_version }} + + - name: Install tox + run: python3 -m pip install --upgrade "tox>=4.0.2" + + - name: Log Python info (${{ matrix.python_version }}) + run: | + command -v python + python --version --version + python3 -m pip freeze --all + + - name: "tox -e ${{ matrix.passed_name }}" + continue-on-error: ${{ matrix.devel || false }} + run: python3 -m tox -e ${{ matrix.passed_name }} + + tox_passed: + needs: tox + runs-on: ubuntu-latest + steps: + - run: >- + python -c "assert set([ + '${{ needs.tox.result }}', + ]) == {'success'}" diff --git a/.gitignore b/.gitignore index da80dd6..7372343 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ build/ *.mypy_cache/ +*.tox/ + __pycache__/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 16870b3..6469fba 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -80,6 +80,8 @@ repos: - jinja2 - jsonschema - black + - pytest + - tox - repo: https://github.com/pre-commit/mirrors-mypy.git rev: v1.6.1 @@ -91,6 +93,7 @@ repos: - black - types-jsonschema - types-pyyaml + - pytest args: - src - tests diff --git a/.vscode/settings.json b/.vscode/settings.json index 97d43d0..a6459b9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,5 +11,8 @@ "[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "python.analysis.typeCheckingMode": "basic" + "python.analysis.typeCheckingMode": "basic", + "python.testing.pytestArgs": ["tests"], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true } diff --git a/pyproject.toml b/pyproject.toml index 4446362..08f6606 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -106,6 +106,7 @@ convention = "pep257" [tool.setuptools.dynamic] dependencies = {file = "requirements.txt"} +optional-dependencies.test = {file = [".config/requirements-test.txt"]} [tool.setuptools_scm] local_scheme = "no-local-version" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..5ee6477 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = tests diff --git a/tests/units/__init__.py b/tests/units/__init__.py new file mode 100644 index 0000000..d4f4303 --- /dev/null +++ b/tests/units/__init__.py @@ -0,0 +1 @@ +"""Unit tests for ansible-creator.""" diff --git a/tests/units/conftest.py b/tests/units/conftest.py new file mode 100644 index 0000000..40c2e16 --- /dev/null +++ b/tests/units/conftest.py @@ -0,0 +1,6 @@ +"""conftest.""" +import os + + +os.environ["HOME"] = "/home/ansible" +os.environ["DEV_WORKSPACE"] = "collections/ansible_collections" diff --git a/tests/units/test_basic.py b/tests/units/test_basic.py new file mode 100644 index 0000000..d5191fc --- /dev/null +++ b/tests/units/test_basic.py @@ -0,0 +1,89 @@ +"""Basic unit tests for ansible-creator.""" +from pathlib import Path + +import pytest + +from ansible_creator.cli import Cli +from ansible_creator.config import Config +from ansible_creator.utils import expand_path + + +def test_expand_path() -> None: + """Test expand_path utils.""" + assert ( + expand_path("~/$DEV_WORKSPACE/namespace/collection") + == "/home/ansible/collections/ansible_collections/namespace/collection" + ) + + +@pytest.mark.parametrize( + argnames=["sysargs", "expected"], + argvalues=[ + [ + ["ansible-creator", "init", "testorg.testcol"], + { + "subcommand": "init", + "no_ansi": False, + "log_file": str(Path.cwd() / "ansible-creator.log"), + "log_level": "notset", + "log_append": "true", + "json": False, + "verbose": 0, + "collection": "testorg.testcol", + "init_path": "./", + "force": False, + }, + ], + [ + [ + "ansible-creator", + "init", + "testorg.testcol", + "--init-path=/home/ansible", + "-vvv", + "--json", + "--no-ansi", + "--la=false", + "--lf=test.log", + "--ll=debug", + "--force", + ], + { + "subcommand": "init", + "no_ansi": True, + "log_file": "test.log", + "log_level": "debug", + "log_append": "false", + "json": True, + "verbose": 3, + "collection": "testorg.testcol", + "init_path": "/home/ansible", + "force": True, + }, + ], + ], +) +def test_cli_parser(monkeypatch, sysargs, expected) -> None: # noqa: ANN001 + """Test CLI args parsing.""" + monkeypatch.setattr("sys.argv", sysargs) + assert vars(Cli().parse_args()) == expected + + +def test_configuration_class() -> None: + """Test Config() dataclass post_init.""" + cli_args: dict = { + "creator_version": "0.0.1", + "json": True, + "log_append": True, + "log_file": "./ansible-creator.log", + "log_level": "debug", + "no_ansi": False, + "subcommand": "init", + "verbose": 2, + "collection": "testorg.testcol", + "init_path": "$HOME", + } + app_config = Config(**cli_args) + assert app_config.namespace == "testorg" + assert app_config.collection_name == "testcol" + assert app_config.init_path == "/home/ansible" diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..886ca28 --- /dev/null +++ b/tox.ini @@ -0,0 +1,26 @@ +[tox] +requires = + tox>=4.2 +env_list = + py + lint +no_package = true +skip_missing_interpreters = true +work_dir = {env:TOX_WORK_DIR:.tox} + +[testenv:py] +description = Run pytest under {basepython} ({envpython}) +deps = + -e .[test] +commands = + python --version + pip list + pytest {posargs:tests} + +[testenv:lint] +description = Enforce quality standards under {basepython} ({envpython}) +skip_install = true +deps = + pre-commit +commands = + pre-commit run --show-diff-on-failure --all-files