Skip to content

Commit

Permalink
[PR #9242/88ea025d backport][stable-10] test helper improvements (#9247)
Browse files Browse the repository at this point in the history
test helper improvements (#9242)

(cherry picked from commit 88ea025)

Co-authored-by: Alexei Znamensky <[email protected]>
  • Loading branch information
patchback[bot] and russoz authored Dec 14, 2024
1 parent 7bc937b commit a89990a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
65 changes: 43 additions & 22 deletions tests/unit/plugins/modules/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,25 @@
import pytest


from ansible.module_utils.common._collections_compat import Sequence


class Helper(object):
TEST_SPEC_VALID_SECTIONS = ["anchors", "test_cases"]

@staticmethod
def from_list(test_module, ansible_module, test_cases):
helper = Helper(test_module, ansible_module, test_cases=test_cases)
def from_spec(test_module, ansible_module, test_spec, mocks=None):
helper = Helper(test_module, ansible_module, test_spec=test_spec, mocks=mocks)
return helper

@staticmethod
def from_file(test_module, ansible_module, filename):
def from_file(test_module, ansible_module, filename, mocks=None):
with open(filename, "r") as test_cases:
test_cases_data = yaml.safe_load(test_cases)
return Helper.from_list(test_module, ansible_module, test_cases_data)
test_spec = yaml.safe_load(test_cases)
return Helper.from_spec(test_module, ansible_module, test_spec, mocks)

@staticmethod
def from_module(ansible_module, test_module_name, test_spec=None):
def from_module(ansible_module, test_module_name, test_spec=None, mocks=None):
test_module = sys.modules[test_module_name]
if test_spec is None:
test_spec = test_module.__file__.replace('.py', '.yaml')
Expand All @@ -35,14 +40,22 @@ def from_module(ansible_module, test_module_name, test_spec=None):
def add_func_to_test_module(self, name, func):
setattr(self.test_module, name, func)

def __init__(self, test_module, ansible_module, test_cases):
def __init__(self, test_module, ansible_module, test_spec, mocks=None):
self.test_module = test_module
self.ansible_module = ansible_module
self.test_cases = []
self.fixtures = {}
if isinstance(test_spec, Sequence):
test_cases = test_spec
else: # it is a dict
test_cases = test_spec['test_cases']
spec_diff = set(test_spec.keys()) - set(self.TEST_SPEC_VALID_SECTIONS)
if spec_diff:
raise ValueError("Test specification contain unknown keys: {0}".format(", ".join(spec_diff)))
self.mocks_map = {m.name: m for m in mocks} if mocks else {}

for test_case in test_cases:
tc = ModuleTestCase.make_test_case(test_case, test_module)
tc = ModuleTestCase.make_test_case(test_case, test_module, self.mocks_map)
self.test_cases.append(tc)
self.fixtures.update(tc.fixtures)
self.set_test_func()
Expand Down Expand Up @@ -99,7 +112,7 @@ def __init__(self, id, input, output, mocks, flags):
self.id = id
self.input = input
self.output = output
self._mocks = mocks
self.mock_specs = mocks
self.mocks = {}
self.flags = flags

Expand All @@ -124,23 +137,23 @@ def __repr__(self):
)

@staticmethod
def make_test_case(test_case, test_module):
def make_test_case(test_case_spec, test_module, mocks_map):
tc = ModuleTestCase(
id=test_case["id"],
input=test_case.get("input", {}),
output=test_case.get("output", {}),
mocks=test_case.get("mocks", {}),
flags=test_case.get("flags", {})
id=test_case_spec["id"],
input=test_case_spec.get("input", {}),
output=test_case_spec.get("output", {}),
mocks=test_case_spec.get("mocks", {}),
flags=test_case_spec.get("flags", {})
)
tc.build_mocks(test_module)
tc.build_mocks(test_module, mocks_map)
return tc

def build_mocks(self, test_module):
for mock, mock_spec in self._mocks.items():
mock_class = self.get_mock_class(test_module, mock)
self.mocks[mock] = mock_class.build_mock(mock_spec)
def build_mocks(self, test_module, mocks_map):
for mock_name, mock_spec in self.mock_specs.items():
mock_class = mocks_map.get(mock_name, self.get_mock_class(test_module, mock_name))
self.mocks[mock_name] = mock_class.build_mock(mock_spec)

self._fixtures.update(self.mocks[mock].fixtures())
self._fixtures.update(self.mocks[mock_name].fixtures())

@staticmethod
def get_mock_class(test_module, mock):
Expand Down Expand Up @@ -187,6 +200,10 @@ def check_mocks(self, test_case, results):


class TestCaseMock:
@property
def name(self):
raise NotImplementedError()

@classmethod
def build_mock(cls, mock_specs):
return cls(mock_specs)
Expand All @@ -205,6 +222,10 @@ def check(self, test_case, results):


class RunCommandMock(TestCaseMock):
@property
def name(self):
return "run_command"

def __str__(self):
return "<RunCommandMock specs={specs}>".format(specs=self.mock_specs)

Expand All @@ -214,7 +235,7 @@ def __repr__(self):
def fixtures(self):
@pytest.fixture
def patch_bin(mocker):
def mockie(self, path, *args, **kwargs):
def mockie(self_, path, *args, **kwargs):
return "/testbin/{0}".format(path)
mocker.patch('ansible.module_utils.basic.AnsibleModule.get_bin_path', mockie)

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/plugins/modules/test_snap.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,4 +475,4 @@
),
]

Helper.from_list(sys.modules[__name__], snap, TEST_CASES)
Helper.from_spec(sys.modules[__name__], snap, TEST_CASES)
4 changes: 2 additions & 2 deletions tests/unit/plugins/modules/test_xfconf_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


from ansible_collections.community.general.plugins.modules import xfconf_info
from .helper import Helper, RunCommandMock # pylint: disable=unused-import
from .helper import Helper, RunCommandMock


Helper.from_module(xfconf_info, __name__)
Helper.from_module(xfconf_info, __name__, mocks=[RunCommandMock])
5 changes: 4 additions & 1 deletion tests/unit/plugins/modules/test_xfconf_info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later

---
anchors:
environ: &env-def {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
test_cases:
- id: test_simple_property_get
input:
channel: xfwm4
Expand All @@ -14,7 +17,7 @@
mocks:
run_command:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/inactive_opacity]
environ: &env-def {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
environ: *env-def
rc: 0
out: "100\n"
err: ""
Expand Down

0 comments on commit a89990a

Please sign in to comment.