mirror of
https://github.com/kubevirt/kubevirt.core.git
synced 2026-03-27 03:13:10 +00:00
cleanup: Migrate existing unit tests to pytest
Cleanup the existing unit tests and move them to pytest. By using pytest it becomes easier to add new tests for existing functionality in the collection. Signed-off-by: Felix Matouschek <fmatouschek@redhat.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
pytest
|
pytest
|
||||||
pytest-ansible
|
pytest-ansible
|
||||||
|
pytest-mock
|
||||||
pytest-xdist
|
pytest-xdist
|
||||||
tox-ansible
|
tox-ansible
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
import ansible.module_utils.basic
|
|
||||||
from ansible.module_utils.six import string_types
|
|
||||||
from ansible.module_utils._text import to_bytes
|
|
||||||
from ansible.module_utils.common._collections_compat import MutableMapping
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def stdin(mocker, request):
|
|
||||||
old_args = ansible.module_utils.basic._ANSIBLE_ARGS
|
|
||||||
ansible.module_utils.basic._ANSIBLE_ARGS = None
|
|
||||||
old_argv = sys.argv
|
|
||||||
sys.argv = ["ansible_unittest"]
|
|
||||||
|
|
||||||
if isinstance(request.param, string_types):
|
|
||||||
args = request.param
|
|
||||||
elif isinstance(request.param, MutableMapping):
|
|
||||||
if "ANSIBLE_MODULE_ARGS" not in request.param:
|
|
||||||
request.param = {"ANSIBLE_MODULE_ARGS": request.param}
|
|
||||||
if "_ansible_remote_tmp" not in request.param["ANSIBLE_MODULE_ARGS"]:
|
|
||||||
request.param["ANSIBLE_MODULE_ARGS"]["_ansible_remote_tmp"] = "/tmp"
|
|
||||||
if "_ansible_keep_remote_files" not in request.param["ANSIBLE_MODULE_ARGS"]:
|
|
||||||
request.param["ANSIBLE_MODULE_ARGS"]["_ansible_keep_remote_files"] = False
|
|
||||||
args = json.dumps(request.param)
|
|
||||||
else:
|
|
||||||
raise Exception("Malformed data to the stdin pytest fixture")
|
|
||||||
|
|
||||||
fake_stdin = BytesIO(to_bytes(args, errors="surrogate_or_strict"))
|
|
||||||
mocker.patch("ansible.module_utils.basic.sys.stdin", mocker.MagicMock())
|
|
||||||
mocker.patch("ansible.module_utils.basic.sys.stdin.buffer", fake_stdin)
|
|
||||||
|
|
||||||
yield fake_stdin
|
|
||||||
|
|
||||||
ansible.module_utils.basic._ANSIBLE_ARGS = old_args
|
|
||||||
sys.argv = old_argv
|
|
||||||
@@ -6,11 +6,9 @@ from __future__ import absolute_import, division, print_function
|
|||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import unittest
|
import pytest
|
||||||
|
|
||||||
from unittest.mock import patch, ANY
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
from ansible.module_utils import basic
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s import runner
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s import runner
|
||||||
from ansible_collections.kubevirt.core.plugins.modules import kubevirt_vm
|
from ansible_collections.kubevirt.core.plugins.modules import kubevirt_vm
|
||||||
from ansible_collections.kubevirt.core.tests.unit.utils.ansible_module_mock import (
|
from ansible_collections.kubevirt.core.tests.unit.utils.ansible_module_mock import (
|
||||||
@@ -19,47 +17,55 @@ from ansible_collections.kubevirt.core.tests.unit.utils.ansible_module_mock impo
|
|||||||
exit_json,
|
exit_json,
|
||||||
fail_json,
|
fail_json,
|
||||||
set_module_args,
|
set_module_args,
|
||||||
get_api_client,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
FIXTURE1 = {
|
|
||||||
"apiVersion": "kubevirt.io/v1",
|
@pytest.fixture(scope="module")
|
||||||
"kind": "VirtualMachine",
|
def vm_definition():
|
||||||
"metadata": {
|
return {
|
||||||
"name": "testvm",
|
"apiVersion": "kubevirt.io/v1",
|
||||||
"namespace": "default",
|
"kind": "VirtualMachine",
|
||||||
"labels": {"environment": "staging", "service": "loadbalancer"},
|
"metadata": {
|
||||||
},
|
"name": "testvm",
|
||||||
"spec": {
|
"namespace": "default",
|
||||||
"running": True,
|
"labels": {"environment": "staging", "service": "loadbalancer"},
|
||||||
"instancetype": {"name": "u1.medium"},
|
},
|
||||||
"preference": {"name": "fedora"},
|
"spec": {
|
||||||
"dataVolumeTemplates": [
|
"running": True,
|
||||||
{
|
"instancetype": {"name": "u1.medium"},
|
||||||
"metadata": {"name": "testdv"},
|
"preference": {"name": "fedora"},
|
||||||
"spec": {
|
"dataVolumeTemplates": [
|
||||||
"source": {
|
{
|
||||||
"registry": {
|
"metadata": {"name": "testdv"},
|
||||||
"url": "docker://quay.io/containerdisks/fedora:latest"
|
"spec": {
|
||||||
|
"source": {
|
||||||
|
"registry": {
|
||||||
|
"url": "docker://quay.io/containerdisks/fedora:latest"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"accessModes": ["ReadWriteOnce"],
|
||||||
|
"resources": {"requests": {"storage": "5Gi"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"storage": {
|
}
|
||||||
"accessModes": ["ReadWriteOnce"],
|
],
|
||||||
"resources": {"requests": {"storage": "5Gi"}},
|
"template": {
|
||||||
},
|
"metadata": {
|
||||||
|
"labels": {"environment": "staging", "service": "loadbalancer"}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"domain": {"devices": {}},
|
||||||
|
"terminationGracePeriodSeconds": 180,
|
||||||
},
|
},
|
||||||
}
|
|
||||||
],
|
|
||||||
"template": {
|
|
||||||
"metadata": {
|
|
||||||
"labels": {"environment": "staging", "service": "loadbalancer"}
|
|
||||||
},
|
},
|
||||||
"spec": {"domain": {"devices": {}}, "terminationGracePeriodSeconds": 180},
|
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
METADATA = """apiVersion: kubevirt.io/v1
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def vm_manifest():
|
||||||
|
return """apiVersion: kubevirt.io/v1
|
||||||
kind: VirtualMachine
|
kind: VirtualMachine
|
||||||
metadata:
|
metadata:
|
||||||
name: "testvm"
|
name: "testvm"
|
||||||
@@ -97,121 +103,96 @@ spec:
|
|||||||
terminationGracePeriodSeconds: 180
|
terminationGracePeriodSeconds: 180
|
||||||
"""
|
"""
|
||||||
|
|
||||||
FIXTURE2 = {
|
|
||||||
"name": "testvm",
|
@pytest.fixture(scope="module")
|
||||||
"namespace": "default",
|
def module_params_create():
|
||||||
"state": "present",
|
return {
|
||||||
"labels": {"service": "loadbalancer", "environment": "staging"},
|
"name": "testvm",
|
||||||
"instancetype": {"name": "u1.medium"},
|
"namespace": "default",
|
||||||
"preference": {"name": "fedora"},
|
"state": "present",
|
||||||
"data_volume_templates": [
|
"labels": {"service": "loadbalancer", "environment": "staging"},
|
||||||
{
|
"instancetype": {"name": "u1.medium"},
|
||||||
"metadata": {"name": "testdv"},
|
"preference": {"name": "fedora"},
|
||||||
"spec": {
|
"data_volume_templates": [
|
||||||
"source": {
|
{
|
||||||
"registry": {
|
"metadata": {"name": "testdv"},
|
||||||
"url": "docker://quay.io/containerdisks/fedora:latest"
|
"spec": {
|
||||||
|
"source": {
|
||||||
|
"registry": {
|
||||||
|
"url": "docker://quay.io/containerdisks/fedora:latest"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"accessModes": ["ReadWriteOnce"],
|
||||||
|
"resources": {"requests": {"storage": "5Gi"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"storage": {
|
|
||||||
"accessModes": ["ReadWriteOnce"],
|
|
||||||
"resources": {"requests": {"storage": "5Gi"}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spec": {"domain": {"devices": {}}, "terminationGracePeriodSeconds": 180},
|
|
||||||
"api_version": "kubevirt.io/v1",
|
|
||||||
"running": True,
|
|
||||||
"wait": False,
|
|
||||||
"wait_sleep": 5,
|
|
||||||
"wait_timeout": 120,
|
|
||||||
"force": False,
|
|
||||||
"generate_name": None,
|
|
||||||
"annotations": None,
|
|
||||||
"kubeconfig": None,
|
|
||||||
"context": None,
|
|
||||||
"host": None,
|
|
||||||
"api_key": None,
|
|
||||||
"username": None,
|
|
||||||
"password": None,
|
|
||||||
"validate_certs": None,
|
|
||||||
"ca_cert": None,
|
|
||||||
"client_cert": None,
|
|
||||||
"client_key": None,
|
|
||||||
"proxy": None,
|
|
||||||
"no_proxy": None,
|
|
||||||
"proxy_headers": None,
|
|
||||||
"persist_config": None,
|
|
||||||
"impersonate_user": None,
|
|
||||||
"impersonate_groups": None,
|
|
||||||
"delete_options": None,
|
|
||||||
"resource_definition": METADATA,
|
|
||||||
"wait_condition": {"type": "Ready", "status": True},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TestCreateVM(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.mock_module_helper = patch.multiple(
|
|
||||||
basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json
|
|
||||||
)
|
|
||||||
self.mock_module_helper.start()
|
|
||||||
|
|
||||||
self.mock_runner = patch.multiple(runner, get_api_client=get_api_client)
|
|
||||||
self.mock_runner.start()
|
|
||||||
|
|
||||||
# Stop the patch after test execution
|
|
||||||
# like tearDown but executed also when the setup failed
|
|
||||||
self.addCleanup(self.mock_module_helper.stop)
|
|
||||||
self.addCleanup(self.mock_runner.stop)
|
|
||||||
|
|
||||||
def test_module_fail_when_required_args_missing(self):
|
|
||||||
with self.assertRaises(AnsibleFailJson):
|
|
||||||
set_module_args({})
|
|
||||||
kubevirt_vm.main()
|
|
||||||
|
|
||||||
def test_create(self):
|
|
||||||
set_module_args(
|
|
||||||
{
|
|
||||||
"name": "testvm",
|
|
||||||
"namespace": "default",
|
|
||||||
"state": "present",
|
|
||||||
"labels": {"service": "loadbalancer", "environment": "staging"},
|
|
||||||
"instancetype": {"name": "u1.medium"},
|
|
||||||
"preference": {"name": "fedora"},
|
|
||||||
"data_volume_templates": [
|
|
||||||
{
|
|
||||||
"metadata": {"name": "testdv"},
|
|
||||||
"spec": {
|
|
||||||
"source": {
|
|
||||||
"registry": {
|
|
||||||
"url": "docker://quay.io/containerdisks/fedora:latest"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"storage": {
|
|
||||||
"accessModes": ["ReadWriteOnce"],
|
|
||||||
"resources": {"requests": {"storage": "5Gi"}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spec": {
|
|
||||||
"domain": {"devices": {}},
|
|
||||||
"terminationGracePeriodSeconds": 180,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
],
|
||||||
with patch.object(runner, "perform_action") as mock_run_command:
|
"spec": {
|
||||||
mock_run_command.return_value = {
|
"domain": {"devices": {}},
|
||||||
"method": "create",
|
"terminationGracePeriodSeconds": 180,
|
||||||
"changed": True,
|
},
|
||||||
"result": "success",
|
}
|
||||||
} # successful execution
|
|
||||||
with self.assertRaises(AnsibleExitJson) as result:
|
|
||||||
kubevirt_vm.main()
|
@pytest.fixture(scope="module")
|
||||||
mock_run_command.assert_called_once_with(
|
def k8s_module_params_create(module_params_create, vm_manifest):
|
||||||
ANY,
|
return module_params_create | {
|
||||||
FIXTURE1,
|
"api_version": "kubevirt.io/v1",
|
||||||
FIXTURE2,
|
"running": True,
|
||||||
)
|
"wait": False,
|
||||||
|
"wait_sleep": 5,
|
||||||
|
"wait_timeout": 120,
|
||||||
|
"force": False,
|
||||||
|
"generate_name": None,
|
||||||
|
"annotations": None,
|
||||||
|
"kubeconfig": None,
|
||||||
|
"context": None,
|
||||||
|
"host": None,
|
||||||
|
"api_key": None,
|
||||||
|
"username": None,
|
||||||
|
"password": None,
|
||||||
|
"validate_certs": None,
|
||||||
|
"ca_cert": None,
|
||||||
|
"client_cert": None,
|
||||||
|
"client_key": None,
|
||||||
|
"proxy": None,
|
||||||
|
"no_proxy": None,
|
||||||
|
"proxy_headers": None,
|
||||||
|
"persist_config": None,
|
||||||
|
"impersonate_user": None,
|
||||||
|
"impersonate_groups": None,
|
||||||
|
"delete_options": None,
|
||||||
|
"resource_definition": vm_manifest,
|
||||||
|
"wait_condition": {"type": "Ready", "status": True},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_module_fails_when_required_args_missing(monkeypatch):
|
||||||
|
monkeypatch.setattr(AnsibleModule, "fail_json", fail_json)
|
||||||
|
with pytest.raises(AnsibleFailJson):
|
||||||
|
set_module_args({})
|
||||||
|
kubevirt_vm.main()
|
||||||
|
|
||||||
|
|
||||||
|
def test_module_create(
|
||||||
|
monkeypatch, mocker, module_params_create, k8s_module_params_create, vm_definition
|
||||||
|
):
|
||||||
|
monkeypatch.setattr(AnsibleModule, "exit_json", exit_json)
|
||||||
|
monkeypatch.setattr(runner, "get_api_client", lambda _: None)
|
||||||
|
|
||||||
|
set_module_args(module_params_create)
|
||||||
|
|
||||||
|
perform_action = mocker.patch.object(runner, "perform_action")
|
||||||
|
perform_action.return_value = {
|
||||||
|
"method": "create",
|
||||||
|
"changed": True,
|
||||||
|
"result": "success",
|
||||||
|
}
|
||||||
|
|
||||||
|
with pytest.raises(AnsibleExitJson):
|
||||||
|
kubevirt_vm.main()
|
||||||
|
perform_action.assert_called_once_with(
|
||||||
|
mocker.ANY, vm_definition, k8s_module_params_create
|
||||||
|
)
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ from __future__ import absolute_import, division, print_function
|
|||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
from unittest import TestCase
|
import pytest
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||||
@@ -19,12 +18,10 @@ from ansible_collections.kubevirt.core.plugins.modules import (
|
|||||||
from ansible_collections.kubevirt.core.tests.unit.utils.ansible_module_mock import (
|
from ansible_collections.kubevirt.core.tests.unit.utils.ansible_module_mock import (
|
||||||
AnsibleExitJson,
|
AnsibleExitJson,
|
||||||
exit_json,
|
exit_json,
|
||||||
fail_json,
|
|
||||||
set_module_args,
|
set_module_args,
|
||||||
get_api_client,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
FIXTURE1 = {
|
FIND_ARGS_DEFAULT = {
|
||||||
"kind": "VirtualMachine",
|
"kind": "VirtualMachine",
|
||||||
"api_version": "kubevirt.io/v1",
|
"api_version": "kubevirt.io/v1",
|
||||||
"name": None,
|
"name": None,
|
||||||
@@ -37,7 +34,7 @@ FIXTURE1 = {
|
|||||||
"condition": {"type": "Ready", "status": True},
|
"condition": {"type": "Ready", "status": True},
|
||||||
}
|
}
|
||||||
|
|
||||||
FIXTURE2 = {
|
FIND_ARGS_NAME_NAMESPACE = {
|
||||||
"kind": "VirtualMachine",
|
"kind": "VirtualMachine",
|
||||||
"api_version": "kubevirt.io/v1",
|
"api_version": "kubevirt.io/v1",
|
||||||
"name": "testvm",
|
"name": "testvm",
|
||||||
@@ -51,43 +48,26 @@ FIXTURE2 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TestDescribeVM(TestCase):
|
@pytest.mark.parametrize(
|
||||||
def setUp(self):
|
"module_args,find_args",
|
||||||
self.mock_module_helper = patch.multiple(
|
[
|
||||||
AnsibleModule, exit_json=exit_json, fail_json=fail_json
|
({}, FIND_ARGS_DEFAULT),
|
||||||
)
|
({"name": "testvm", "namespace": "default"}, FIND_ARGS_NAME_NAMESPACE),
|
||||||
self.mock_module_helper.start()
|
],
|
||||||
|
)
|
||||||
|
def test_module(monkeypatch, mocker, module_args, find_args):
|
||||||
|
monkeypatch.setattr(AnsibleModule, "exit_json", exit_json)
|
||||||
|
monkeypatch.setattr(kubevirt_vm_info, "get_api_client", lambda _: None)
|
||||||
|
|
||||||
self.mock_main = patch.multiple(kubevirt_vm_info, get_api_client=get_api_client)
|
set_module_args(module_args)
|
||||||
self.mock_main.start()
|
|
||||||
|
|
||||||
# Stop the patch after test execution
|
find = mocker.patch.object(K8sService, "find")
|
||||||
# like tearDown but executed also when the setup failed
|
find.return_value = {
|
||||||
self.addCleanup(self.mock_module_helper.stop)
|
"api_found": True,
|
||||||
self.addCleanup(self.mock_main.stop)
|
"failed": False,
|
||||||
|
"resources": [],
|
||||||
|
}
|
||||||
|
|
||||||
def run_module(self, fixture):
|
with pytest.raises(AnsibleExitJson):
|
||||||
with patch.object(K8sService, "find") as mock_find_command:
|
kubevirt_vm_info.main()
|
||||||
mock_find_command.return_value = {
|
find.assert_called_once_with(**find_args)
|
||||||
"api_found": True,
|
|
||||||
"failed": False,
|
|
||||||
"resources": [],
|
|
||||||
} # successful execution
|
|
||||||
with self.assertRaises(AnsibleExitJson):
|
|
||||||
kubevirt_vm_info.main()
|
|
||||||
mock_find_command.assert_called_once_with(
|
|
||||||
**fixture,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_describe_without_args(self):
|
|
||||||
set_module_args({})
|
|
||||||
self.run_module(FIXTURE1)
|
|
||||||
|
|
||||||
def test_describe_with_args(self):
|
|
||||||
set_module_args(
|
|
||||||
{
|
|
||||||
"name": "testvm",
|
|
||||||
"namespace": "default",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
self.run_module(FIXTURE2)
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
# Copyright: (c) 2021, Ansible Project
|
# Copyright: (c) 2021, Ansible Project
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
# This module maock the AnsibleModule class for more information please visite
|
# This file allows to run modules in unit tests.
|
||||||
|
# It was taken from:
|
||||||
# https://docs.ansible.com/ansible/latest/dev_guide/testing_units_modules.html#module-argument-processing
|
# https://docs.ansible.com/ansible/latest/dev_guide/testing_units_modules.html#module-argument-processing
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
@@ -23,13 +24,11 @@ def set_module_args(args):
|
|||||||
|
|
||||||
class AnsibleExitJson(Exception):
|
class AnsibleExitJson(Exception):
|
||||||
"""Exception class to be raised by module.exit_json and caught by the test case"""
|
"""Exception class to be raised by module.exit_json and caught by the test case"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AnsibleFailJson(Exception):
|
class AnsibleFailJson(Exception):
|
||||||
"""Exception class to be raised by module.fail_json and caught by the test case"""
|
"""Exception class to be raised by module.fail_json and caught by the test case"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -44,8 +43,3 @@ def fail_json(*args, **kwargs):
|
|||||||
"""function to patch over fail_json; package return data into an exception"""
|
"""function to patch over fail_json; package return data into an exception"""
|
||||||
kwargs["failed"] = True
|
kwargs["failed"] = True
|
||||||
raise AnsibleFailJson(kwargs)
|
raise AnsibleFailJson(kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_api_client(*args, **kwargs):
|
|
||||||
"""function to patch over get_api_client"""
|
|
||||||
pass
|
|
||||||
|
|||||||
Reference in New Issue
Block a user