diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml new file mode 100644 index 0000000..f693cca --- /dev/null +++ b/.github/workflows/testing.yml @@ -0,0 +1,50 @@ +name: testing + +on: + pull_request: + branches: + - '*' + push: + branches: + - master + +jobs: + static_analysis: + name: ${{ matrix.make-command }} / Py${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: [3.7] + make-command: [doc8, flake8, pylint, test] + + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Python dependencies + run: | + sudo apt-get install virtualenv + pip install -r devel.txt + - name: Prepare for integration test + if: matrix.make-command == 'test' + run: | + echo "[tcms]" > ~/.tcms.conf + echo "url = https://tcms.kiwitcms.org/xml-rpc/" >> ~/.tcms.conf + echo "username = kiwitcms-bot" >> ~/.tcms.conf + echo "password = ${{ secrets.TCMS_PASSWORD }}" >> ~/.tcms.conf + sudo cp .ssl/*.pem /usr/lib/ssl/certs/ + sudo update-ca-certificates --fresh + - name: Verify ${{ matrix.make-command }} + run: | + export TCMS_PRODUCT=$GITHUB_REPOSITORY + # branch name or pull/123 + export TCMS_PRODUCT_VERSION=$(echo $GITHUB_REF | sed "s|refs/heads/||" | sed "s|refs/||" | sed "s|/merge||") + # short commit number + export TCMS_BUILD=$(echo $GITHUB_SHA | cut -c1-7) + make ${{ matrix.make-command }} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..33d22f0 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +.PHONY: doc8 +doc8: + doc8 README.rst + +.PHONY: flake8 +flake8: + @flake8 --exclude=.git *.py tcms_pytest_plugin tests + +.PHONY: pylint +pylint: + pylint -d missing-docstring tcms_pytest_plugin/ tests/ + +.PHONY: test +test: + pytest --kiwitcms \ No newline at end of file diff --git a/README.rst b/README.rst index b3aee3a..f463e4d 100644 --- a/README.rst +++ b/README.rst @@ -69,13 +69,15 @@ the coverage at least stays the same before you submit a pull request. License ------- -Distributed under the terms of the `GNU GPL v3.0`_ license, "kiwitcms-pytest-plugin" is free and open source software +Distributed under the terms of the `GNU GPL v3.0`_ license, +"kiwitcms-pytest-plugin" is free and open source software Issues ------ -If you encounter any problems, please `file an issue`_ along with a detailed description. +If you encounter any problems, +please `file an issue`_ along with a detailed description. .. _`GNU GPL v3.0`: http://www.gnu.org/licenses/gpl-3.0.txt .. _`file an issue`: https://github.com/kiwitcms/pytest-plugin/issues diff --git a/devel.txt b/devel.txt new file mode 100644 index 0000000..e046a3c --- /dev/null +++ b/devel.txt @@ -0,0 +1,5 @@ +-r requirements.txt + +doc8 +flake8 +pylint_django \ No newline at end of file diff --git a/tcms_pytest_plugin/plugin.py b/tcms_pytest_plugin/plugin.py index ca451d6..70ea1eb 100644 --- a/tcms_pytest_plugin/plugin.py +++ b/tcms_pytest_plugin/plugin.py @@ -1,14 +1,16 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019 Dmitry Dygalo # Licensed under the GPLv3: https://www.gnu.org/licenses/gpl.html -import configparser -import os +# pylint: disable=unused-argument, no-self-use + -import attr import pytest +from tcms_api.plugin_helpers import Backend DEFAULT_CONFIG_PATH = "~/.tcms.conf" +backend = Backend(prefix='[pytest]') + def pytest_addoption(parser): group = parser.getgroup("kiwitcms") @@ -19,42 +21,40 @@ def pytest_addoption(parser): def pytest_configure(config): if config.getoption("--kiwitcms"): - config_manager = ConfigManager(config) config.pluginmanager.register( - Plugin( - api_url=config_manager.get_option("url", "TCMS_API_URL"), - username=config_manager.get_option("username", "TCMS_USERNAME"), - password=config_manager.get_option("password", "TCMS_PASSWORD"), - ), + KiwiTCMSPlugin(), name="pytest-kiwitcms", ) -def is_not_none(instance, attribute, value): # pylint: disable=unused-argument - if not value: - pytest.exit(msg=f"Option {attribute.name} is empty", returncode=1) - - -@attr.s(hash=True) -class Plugin: # pylint: disable=too-few-public-methods - api_url = attr.ib(type=str, validator=is_not_none) - username = attr.ib(type=str, validator=is_not_none) - password = attr.ib(type=str, validator=is_not_none) - - -@attr.s -class ConfigManager: # pylint: disable=too-few-public-methods - """Helper for configuration parsing.""" - - pytest_config = attr.ib() - config_file = attr.ib(init=False) - - def __attrs_post_init__(self): - self.config_file = configparser.ConfigParser() - self.config_file.read(os.path.expanduser(DEFAULT_CONFIG_PATH)) - - def get_option(self, config_name, envvar): - try: - return self.config_file["tcms"][config_name] - except KeyError: - return os.getenv(envvar) +class KiwiTCMSPlugin: + test_execution_id = 0 + status_id = 0 + comment = '' + + def pytest_runtestloop(self, session): + backend.configure() + + def pytest_runtest_logstart(self, nodeid, location): + test_case, _ = backend.test_case_get_or_create(nodeid) + backend.add_test_case_to_plan(test_case['id'], backend.plan_id) + self.test_execution_id = backend.add_test_case_to_run(test_case['id'], backend.run_id) + + @pytest.hookimpl(hookwrapper=True) + def pytest_report_teststatus(self, report, config): + yield + if report.when == 'teardown': + if report.outcome == 'passed': + self.status_id = backend.get_status_id('PASSED') + elif report.outcome == 'failed': + self.status_id = backend.get_status_id('FAILED') + elif report.outcome == 'skipped': + self.status_id = backend.get_status_id('WAIVED') + + def pytest_runtest_logfinish(self, nodeid, location): + backend.update_test_execution(self.test_execution_id, self.status_id, self.comment) + + @pytest.hookimpl(hookwrapper=True) + def pytest_terminal_summary(self, terminalreporter, exitstatus, config): + yield + backend.finish_test_run() diff --git a/tests/conftest.py b/tests/conftest.py index 70dd6dd..6b8d2d7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,7 +2,7 @@ # Licensed under the GPLv3: https://www.gnu.org/licenses/gpl.html import pytest -pytest_plugins = "pytester" # pylint: disable=invalid-name +pytest_plugins = ['pytester'] # pylint: disable=invalid-name DEFAULT_CONFIG_CONTENT = """ diff --git a/tests/test_pytest_kiwitcms.py b/tests/test_pytest_kiwitcms.py index c548e9d..7499b0c 100644 --- a/tests/test_pytest_kiwitcms.py +++ b/tests/test_pytest_kiwitcms.py @@ -11,68 +11,85 @@ ) -@pytest.mark.usefixtures("config_file") -def test_file_configuration(testdir): - """Load configuration from ~/.tcms.conf.""" - testdir.makepyfile( - """ - def test_file_configuration(pytestconfig): - plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") - assert plugin.api_url == "http://example.com" - assert plugin.username == "admin" - assert plugin.password == "secret" - """ - ) - result = testdir.runpytest("--kiwitcms", "-v") - result.stdout.fnmatch_lines(["*::test_file_configuration PASSED*"]) - assert result.ret == 0 +# @pytest.mark.usefixtures("config_file") +# def test_file_configuration(testdir): +# """Load configuration from ~/.tcms.conf.""" +# testdir.makepyfile( +# """ +# def test_file_configuration(pytestconfig): +# plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") +# assert plugin.api_url == "http://example.com" +# assert plugin.username == "admin" +# assert plugin.password == "secret" +# """ +# ) +# result = testdir.runpytest("--kiwitcms", "-v") +# result.stdout.fnmatch_lines(["*::test_file_configuration PASSED*"]) +# assert result.ret == 0 -def test_env_configuration(testdir, monkeypatch): - """If ~/.tcms.conf doesn't exist - use env variables.""" - for envvar, value in DEFAULT_CONFIG: - monkeypatch.setenv(envvar, value) - testdir.makepyfile( - """ - def test_env_configuration(pytestconfig): - plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") - assert plugin.api_url == "http://another.com" - assert plugin.username == "user" - assert plugin.password == "random" - """ - ) - result = testdir.runpytest("--kiwitcms", "-v") - result.stdout.fnmatch_lines(["*::test_env_configuration PASSED*"]) - assert result.ret == 0 +# def test_env_configuration(testdir, monkeypatch): +# """If ~/.tcms.conf doesn't exist - use env variables.""" +# for envvar, value in DEFAULT_CONFIG: +# monkeypatch.setenv(envvar, value) +# testdir.makepyfile( +# """ +# def test_env_configuration(pytestconfig): +# plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") +# assert plugin.api_url == "http://another.com" +# assert plugin.username == "user" +# assert plugin.password == "random" +# """ +# ) +# result = testdir.runpytest("--kiwitcms", "-v") +# result.stdout.fnmatch_lines(["*::test_env_configuration PASSED*"]) +# assert result.ret == 0 -@pytest.mark.parametrize("envvar, value", DEFAULT_CONFIG) -@pytest.mark.usefixtures("config_file") -def test_config_file_precedence(testdir, monkeypatch, envvar, value): - """Values from ~/.tcms.conf have higher priority than env variables.""" - monkeypatch.setenv(envvar, value) - testdir.makepyfile( - """ - def test_config_file_precedence(pytestconfig): - plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") - assert plugin.api_url == "http://example.com" - assert plugin.username == "admin" - assert plugin.password == "secret" - """ - ) - result = testdir.runpytest("--kiwitcms", "-v") - result.stdout.fnmatch_lines(["*::test_config_file_precedence PASSED*"]) - assert result.ret == 0 +# @pytest.mark.parametrize("envvar, value", DEFAULT_CONFIG) +# @pytest.mark.usefixtures("config_file") +# def test_config_file_precedence(testdir, monkeypatch, envvar, value): +# """Values from ~/.tcms.conf have higher priority than env variables.""" +# monkeypatch.setenv(envvar, value) +# testdir.makepyfile( +# """ +# def test_config_file_precedence(pytestconfig): +# plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") +# assert plugin.api_url == "http://example.com" +# assert plugin.username == "admin" +# assert plugin.password == "secret" +# """ +# ) +# result = testdir.runpytest("--kiwitcms", "-v") +# result.stdout.fnmatch_lines(["*::test_config_file_precedence PASSED*"]) +# assert result.ret == 0 + +# def test_empty_variable(testdir): +# """Any empty value in config variables will lead to program exiting.""" +# testdir.makepyfile( +# """ +# def test_empty_variable(pytestconfig): +# plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") +# """ +# ) +# result = testdir.runpytest("--kiwitcms", "-v") +# result.stderr.fnmatch_lines(["Exit: Option api_url is empty"]) +# assert result.ret == 1 -def test_empty_variable(testdir): - """Any empty value in config variables will lead to program exiting.""" +def test_kiwitcms_pytest(testdir): testdir.makepyfile( """ - def test_empty_variable(pytestconfig): - plugin = pytestconfig.pluginmanager.get_plugin("pytest-kiwitcms") + import pytest + def test_pass(): + assert 1 == 1 + def test_fail(): + assert 1 == 2 + @pytest.mark.skip() + def test_skip(): + assert 1 == 1 + def test_error(test): + assert 1 == "" """ ) - result = testdir.runpytest("--kiwitcms", "-v") - result.stderr.fnmatch_lines(["Exit: Option api_url is empty"]) - assert result.ret == 1 + testdir.runpytest("--kiwitcms") \ No newline at end of file