summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Clay <matt@mystile.com>2024-10-08 22:29:37 +0200
committerGitHub <noreply@github.com>2024-10-08 22:29:37 +0200
commit955e310b4c33112b6eb261590c925d16da4ca965 (patch)
treecd872d6270056fdbfc0adcfc950474fbdafbe4a5
parentUpdate unique filter docs (#84078) (diff)
downloadansible-955e310b4c33112b6eb261590c925d16da4ca965.tar.xz
ansible-955e310b4c33112b6eb261590c925d16da4ca965.zip
Cover unit tests with mypy (#84084)
* Added support for testing unit tests with mypy. * Added support for ignoring individual mypy error codes. * Added missing assert on unit tests and marked xfail. * Added type hints for some unit tests. * Added ignores for unit tests not passing mypy. * Fixed incorrect autouse argument in unit test fixtures. * Fixed minor issues causing problems with mypy in unit tests.
-rw-r--r--test/sanity/code-smell/mypy.json2
-rw-r--r--test/sanity/code-smell/mypy.py2
-rw-r--r--test/sanity/code-smell/mypy.requirements.in1
-rw-r--r--test/sanity/code-smell/mypy.requirements.txt3
-rw-r--r--test/sanity/code-smell/mypy/ansible-core.ini10
-rw-r--r--test/sanity/ignore.txt69
-rw-r--r--test/units/cli/test_galaxy.py2
-rw-r--r--test/units/cli/test_vault.py2
-rw-r--r--test/units/galaxy/test_api.py2
-rw-r--r--test/units/galaxy/test_collection.py2
-rw-r--r--test/units/galaxy/test_collection_install.py6
-rw-r--r--test/units/galaxy/test_role_install.py2
-rw-r--r--test/units/module_utils/basic/test_argument_spec.py7
-rw-r--r--test/units/module_utils/basic/test_exit_json.py5
-rw-r--r--test/units/module_utils/basic/test_no_log.py3
-rw-r--r--test/units/module_utils/basic/test_safe_eval.py5
-rw-r--r--test/units/module_utils/common/arg_spec/test_aliases.py2
-rw-r--r--test/units/module_utils/common/test_collections.py6
-rw-r--r--test/units/module_utils/facts/hardware/test_linux.py2
-rw-r--r--test/units/module_utils/facts/test_ansible_collector.py2
-rw-r--r--test/units/modules/test_copy.py170
-rw-r--r--test/units/parsing/test_splitter.py2
-rw-r--r--test/units/plugins/connection/test_psrp.py3
-rw-r--r--test/units/plugins/connection/test_winrm.py3
-rw-r--r--test/units/plugins/filter/test_mathstuff.py4
-rw-r--r--test/units/plugins/lookup/test_password.py16
26 files changed, 218 insertions, 115 deletions
diff --git a/test/sanity/code-smell/mypy.json b/test/sanity/code-smell/mypy.json
index 57a6ad6c15..c8cd6fb8f5 100644
--- a/test/sanity/code-smell/mypy.json
+++ b/test/sanity/code-smell/mypy.json
@@ -3,11 +3,13 @@
"lib/ansible/",
"test/lib/ansible_test/_internal/",
"packaging/",
+ "test/units",
"test/lib/ansible_test/_util/target/sanity/import/"
],
"extensions": [
".py"
],
"multi_version": "controller",
+ "error_code": "ansible-test",
"output": "path-line-column-code-message"
}
diff --git a/test/sanity/code-smell/mypy.py b/test/sanity/code-smell/mypy.py
index fda83e8b0d..b7feffc503 100644
--- a/test/sanity/code-smell/mypy.py
+++ b/test/sanity/code-smell/mypy.py
@@ -36,6 +36,8 @@ def main() -> None:
MyPyContext('ansible-core', ['lib/ansible/'], controller_python_versions),
MyPyContext('modules', ['lib/ansible/modules/', 'lib/ansible/module_utils/'], remote_only_python_versions),
MyPyContext('packaging', ['packaging/'], controller_python_versions),
+ MyPyContext('modules', ['test/units/modules/', 'test/units/module_utils/'], remote_only_python_versions),
+ MyPyContext('ansible-core', ['test/units/'], controller_python_versions),
)
unfiltered_messages: list[SanityMessage] = []
diff --git a/test/sanity/code-smell/mypy.requirements.in b/test/sanity/code-smell/mypy.requirements.in
index 073513bdf8..2c6dee1267 100644
--- a/test/sanity/code-smell/mypy.requirements.in
+++ b/test/sanity/code-smell/mypy.requirements.in
@@ -2,6 +2,7 @@ mypy
cryptography # type stubs not published separately
jinja2 # type stubs not published separately
packaging # type stubs not published separately
+pytest # type stubs not published separately
tomli # type stubs not published separately, required for toml inventory plugin
types-backports
types-paramiko
diff --git a/test/sanity/code-smell/mypy.requirements.txt b/test/sanity/code-smell/mypy.requirements.txt
index c5a3ece72c..59a253d9f9 100644
--- a/test/sanity/code-smell/mypy.requirements.txt
+++ b/test/sanity/code-smell/mypy.requirements.txt
@@ -1,12 +1,15 @@
# edit "mypy.requirements.in" and generate with: hacking/update-sanity-requirements.py --test mypy
cffi==1.17.1
cryptography==43.0.1
+iniconfig==2.0.0
Jinja2==3.1.4
MarkupSafe==2.1.5
mypy==1.11.2
mypy-extensions==1.0.0
packaging==24.1
+pluggy==1.5.0
pycparser==2.22
+pytest==8.3.3
tomli==2.0.2
types-backports==0.1.3
types-paramiko==3.5.0.20240928
diff --git a/test/sanity/code-smell/mypy/ansible-core.ini b/test/sanity/code-smell/mypy/ansible-core.ini
index 0d2208be2d..83b63e52ee 100644
--- a/test/sanity/code-smell/mypy/ansible-core.ini
+++ b/test/sanity/code-smell/mypy/ansible-core.ini
@@ -11,6 +11,16 @@ strict_optional = False
# The safe-super rule is disabled because it reports false positives on methods which return None.
disable_error_code = attr-defined,safe-super
+# Some controller unit tests use ansible_collections imports, both real and test-specific.
+# The real imports are not currently visible to mypy.
+# There's little point in exposing the test-specific imports.
+[mypy-ansible_collections.*]
+ignore_missing_imports = True
+
+# Some unit tests for ansible-test use ansible_test imports, which are not currently visible to mypy.
+[mypy-ansible_test.*]
+ignore_missing_imports = True
+
[mypy-ansible.module_utils.six.moves.*]
ignore_missing_imports = True
diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt
index 17f893aabf..926fb4bf92 100644
--- a/test/sanity/ignore.txt
+++ b/test/sanity/ignore.txt
@@ -164,3 +164,72 @@ lib/ansible/module_utils/pycompat24.py pylint:ansible-deprecated-version
lib/ansible/plugins/connection/__init__.py pylint:ansible-deprecated-version
lib/ansible/plugins/filter/core.py pylint:ansible-deprecated-version
lib/ansible/vars/manager.py pylint:ansible-deprecated-version
+test/units/module_utils/basic/test_exit_json.py mypy-3.13:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.13:misc
+test/units/module_utils/common/text/converters/test_json_encode_fallback.py mypy-3.13:abstract
+test/units/module_utils/facts/other/test_facter.py mypy-3.13:assignment
+test/units/module_utils/facts/other/test_ohai.py mypy-3.13:assignment
+test/units/module_utils/facts/system/test_lsb.py mypy-3.13:assignment
+test/units/module_utils/facts/test_collectors.py mypy-3.13:assignment
+test/units/module_utils/facts/test_facts.py mypy-3.13:assignment
+test/units/modules/mount_facts_data.py mypy-3.13:arg-type
+test/units/modules/test_apt.py mypy-3.13:name-match
+test/units/modules/test_mount_facts.py mypy-3.13:index
+test/units/playbook/test_base.py mypy-3.13:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.12:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.12:misc
+test/units/module_utils/common/text/converters/test_json_encode_fallback.py mypy-3.12:abstract
+test/units/module_utils/facts/other/test_facter.py mypy-3.12:assignment
+test/units/module_utils/facts/other/test_ohai.py mypy-3.12:assignment
+test/units/module_utils/facts/system/test_lsb.py mypy-3.12:assignment
+test/units/module_utils/facts/test_collectors.py mypy-3.12:assignment
+test/units/module_utils/facts/test_facts.py mypy-3.12:assignment
+test/units/modules/mount_facts_data.py mypy-3.12:arg-type
+test/units/modules/test_apt.py mypy-3.12:name-match
+test/units/modules/test_mount_facts.py mypy-3.12:index
+test/units/playbook/test_base.py mypy-3.12:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.11:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.11:misc
+test/units/module_utils/common/text/converters/test_json_encode_fallback.py mypy-3.11:abstract
+test/units/module_utils/facts/other/test_facter.py mypy-3.11:assignment
+test/units/module_utils/facts/other/test_ohai.py mypy-3.11:assignment
+test/units/module_utils/facts/system/test_lsb.py mypy-3.11:assignment
+test/units/module_utils/facts/test_collectors.py mypy-3.11:assignment
+test/units/module_utils/facts/test_facts.py mypy-3.11:assignment
+test/units/modules/mount_facts_data.py mypy-3.11:arg-type
+test/units/modules/test_apt.py mypy-3.11:name-match
+test/units/modules/test_mount_facts.py mypy-3.11:index
+test/units/playbook/test_base.py mypy-3.11:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.10:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.10:misc
+test/units/module_utils/common/text/converters/test_json_encode_fallback.py mypy-3.10:abstract
+test/units/module_utils/facts/other/test_facter.py mypy-3.10:assignment
+test/units/module_utils/facts/other/test_ohai.py mypy-3.10:assignment
+test/units/module_utils/facts/system/test_lsb.py mypy-3.10:assignment
+test/units/module_utils/facts/test_collectors.py mypy-3.10:assignment
+test/units/module_utils/facts/test_facts.py mypy-3.10:assignment
+test/units/modules/mount_facts_data.py mypy-3.10:arg-type
+test/units/modules/test_apt.py mypy-3.10:name-match
+test/units/modules/test_mount_facts.py mypy-3.10:index
+test/units/module_utils/basic/test_exit_json.py mypy-3.9:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.9:misc
+test/units/module_utils/common/text/converters/test_json_encode_fallback.py mypy-3.9:abstract
+test/units/module_utils/facts/other/test_facter.py mypy-3.9:assignment
+test/units/module_utils/facts/other/test_ohai.py mypy-3.9:assignment
+test/units/module_utils/facts/system/test_lsb.py mypy-3.9:assignment
+test/units/module_utils/facts/test_collectors.py mypy-3.9:assignment
+test/units/module_utils/facts/test_facts.py mypy-3.9:assignment
+test/units/modules/mount_facts_data.py mypy-3.9:arg-type
+test/units/modules/test_apt.py mypy-3.9:name-match
+test/units/modules/test_mount_facts.py mypy-3.9:index
+test/units/module_utils/basic/test_exit_json.py mypy-3.8:assignment
+test/units/module_utils/basic/test_exit_json.py mypy-3.8:misc
+test/units/module_utils/common/text/converters/test_json_encode_fallback.py mypy-3.8:abstract
+test/units/module_utils/facts/other/test_facter.py mypy-3.8:assignment
+test/units/module_utils/facts/other/test_ohai.py mypy-3.8:assignment
+test/units/module_utils/facts/system/test_lsb.py mypy-3.8:assignment
+test/units/module_utils/facts/test_collectors.py mypy-3.8:assignment
+test/units/module_utils/facts/test_facts.py mypy-3.8:assignment
+test/units/modules/mount_facts_data.py mypy-3.8:arg-type
+test/units/modules/test_apt.py mypy-3.8:name-match
+test/units/modules/test_mount_facts.py mypy-3.8:index
diff --git a/test/units/cli/test_galaxy.py b/test/units/cli/test_galaxy.py
index 5444d148d0..9d6d32bb2a 100644
--- a/test/units/cli/test_galaxy.py
+++ b/test/units/cli/test_galaxy.py
@@ -45,7 +45,7 @@ import unittest
from unittest.mock import patch, MagicMock
-@pytest.fixture(autouse='function')
+@pytest.fixture(autouse=True)
def reset_cli_args():
co.GlobalCLIArgs._Singleton__instance = None
yield
diff --git a/test/units/cli/test_vault.py b/test/units/cli/test_vault.py
index c6f41c5b91..6305a02350 100644
--- a/test/units/cli/test_vault.py
+++ b/test/units/cli/test_vault.py
@@ -35,7 +35,7 @@ from ansible.utils import context_objects as co
# mock calls
-@pytest.fixture(autouse='function')
+@pytest.fixture(autouse=True)
def reset_cli_args():
co.GlobalCLIArgs._Singleton__instance = None
yield
diff --git a/test/units/galaxy/test_api.py b/test/units/galaxy/test_api.py
index 6acd165b1d..2ef1d07325 100644
--- a/test/units/galaxy/test_api.py
+++ b/test/units/galaxy/test_api.py
@@ -29,7 +29,7 @@ from ansible.utils import context_objects as co
from ansible.utils.display import Display
-@pytest.fixture(autouse='function')
+@pytest.fixture(autouse=True)
def reset_cli_args():
co.GlobalCLIArgs._Singleton__instance = None
# Required to initialise the GalaxyAPI object
diff --git a/test/units/galaxy/test_collection.py b/test/units/galaxy/test_collection.py
index bfabd81d9e..73e915dee6 100644
--- a/test/units/galaxy/test_collection.py
+++ b/test/units/galaxy/test_collection.py
@@ -31,7 +31,7 @@ from ansible.utils.display import Display
from ansible.utils.hashing import secure_hash_s
-@pytest.fixture(autouse='function')
+@pytest.fixture(autouse=True)
def reset_cli_args():
co.GlobalCLIArgs._Singleton__instance = None
yield
diff --git a/test/units/galaxy/test_collection_install.py b/test/units/galaxy/test_collection_install.py
index 6559535f93..dc6dbe5b6f 100644
--- a/test/units/galaxy/test_collection_install.py
+++ b/test/units/galaxy/test_collection_install.py
@@ -53,7 +53,7 @@ def call_galaxy_cli(args):
co.GlobalCLIArgs._Singleton__instance = orig
-@pytest.fixture(autouse='function')
+@pytest.fixture(autouse=True)
def reset_cli_args():
co.GlobalCLIArgs._Singleton__instance = None
yield
@@ -992,9 +992,7 @@ def test_install_collection_with_no_dependency(collection_artifact, monkeypatch)
(["good_signature", "good_signature"], '2', [], True),
]
)
-def test_verify_file_signatures(signatures, required_successful_count, ignore_errors, expected_success):
- # type: (List[bool], int, bool, bool) -> None
-
+def test_verify_file_signatures(signatures: list[str], required_successful_count: str, ignore_errors: list[str], expected_success: bool) -> None:
def gpg_error_generator(results):
for result in results:
if isinstance(result, collection.gpg.GpgBaseError):
diff --git a/test/units/galaxy/test_role_install.py b/test/units/galaxy/test_role_install.py
index 25dff80cd6..8e77352a30 100644
--- a/test/units/galaxy/test_role_install.py
+++ b/test/units/galaxy/test_role_install.py
@@ -28,7 +28,7 @@ def call_galaxy_cli(args):
co.GlobalCLIArgs._Singleton__instance = orig
-@pytest.fixture(autouse='function')
+@pytest.fixture(autouse=True)
def reset_cli_args():
co.GlobalCLIArgs._Singleton__instance = None
yield
diff --git a/test/units/module_utils/basic/test_argument_spec.py b/test/units/module_utils/basic/test_argument_spec.py
index 46a3e9d9f3..4fea474505 100644
--- a/test/units/module_utils/basic/test_argument_spec.py
+++ b/test/units/module_utils/basic/test_argument_spec.py
@@ -8,6 +8,7 @@ from __future__ import annotations
import json
import os
+import typing as t
import pytest
@@ -69,7 +70,7 @@ VALID_SPECS = (
({'arg': {'type': 'int'}}, {'arg': 1, 'invalid': True, '_ansible_ignore_unknown_opts': True}, 1),
)
-INVALID_SPECS = (
+INVALID_SPECS: tuple[tuple[dict[str, t.Any], dict[str, t.Any], str], ...] = (
# Type is int; unable to convert this string
({'arg': {'type': 'int'}}, {'arg': "wolf"}, f"is of type {type('wolf')} and we were unable to convert to int:"),
# Type is list elements is int; unable to convert this string
@@ -495,7 +496,7 @@ class TestComplexOptions:
)
# (Parameters, failure message)
- FAILING_PARAMS_LIST = (
+ FAILING_PARAMS_LIST: tuple[tuple[dict[str, list[dict[str, t.Any]]], str], ...] = (
# Missing required option
({'foobar': [{}]}, 'missing required arguments: foo found in foobar'),
# Invalid option
@@ -518,7 +519,7 @@ class TestComplexOptions:
)
# (Parameters, failure message)
- FAILING_PARAMS_DICT = (
+ FAILING_PARAMS_DICT: tuple[tuple[dict[str, dict[str, t.Any]], str], ...] = (
# Missing required option
({'foobar': {}}, 'missing required arguments: foo found in foobar'),
# Invalid option
diff --git a/test/units/module_utils/basic/test_exit_json.py b/test/units/module_utils/basic/test_exit_json.py
index 795e9c1eb6..0f6844b24a 100644
--- a/test/units/module_utils/basic/test_exit_json.py
+++ b/test/units/module_utils/basic/test_exit_json.py
@@ -7,12 +7,13 @@ from __future__ import annotations
import json
import sys
import datetime
+import typing as t
import pytest
from ansible.module_utils.common import warnings
-EMPTY_INVOCATION = {u'module_args': {}}
+EMPTY_INVOCATION: dict[str, dict[str, t.Any]] = {u'module_args': {}}
DATETIME = datetime.datetime.strptime('2020-07-13 12:50:00', '%Y-%m-%d %H:%M:%S')
@@ -20,7 +21,7 @@ class TestAnsibleModuleExitJson:
"""
Test that various means of calling exitJson and FailJson return the messages they've been given
"""
- DATA = (
+ DATA: tuple[tuple[dict[str, t.Any]], ...] = (
({}, {'invocation': EMPTY_INVOCATION}),
({'msg': 'message'}, {'msg': 'message', 'invocation': EMPTY_INVOCATION}),
({'msg': 'success', 'changed': True},
diff --git a/test/units/module_utils/basic/test_no_log.py b/test/units/module_utils/basic/test_no_log.py
index c8c3ecea68..409d919164 100644
--- a/test/units/module_utils/basic/test_no_log.py
+++ b/test/units/module_utils/basic/test_no_log.py
@@ -5,6 +5,7 @@
from __future__ import annotations
+import typing as t
import unittest
from ansible.module_utils.basic import remove_values
@@ -12,7 +13,7 @@ from ansible.module_utils.common.parameters import _return_datastructure_name
class TestReturnValues(unittest.TestCase):
- dataset = (
+ dataset: tuple[tuple[t.Any, frozenset[str]], ...] = (
('string', frozenset(['string'])),
('', frozenset()),
(1, frozenset(['1'])),
diff --git a/test/units/module_utils/basic/test_safe_eval.py b/test/units/module_utils/basic/test_safe_eval.py
index 62403e81e6..3df214c356 100644
--- a/test/units/module_utils/basic/test_safe_eval.py
+++ b/test/units/module_utils/basic/test_safe_eval.py
@@ -5,11 +5,14 @@
from __future__ import annotations
from itertools import chain
+
+import typing as t
+
import pytest
# Strings that should be converted into a typed value
-VALID_STRINGS = (
+VALID_STRINGS: tuple[tuple[str, t.Any], ...] = (
("'a'", 'a'),
("'1'", '1'),
("1", 1),
diff --git a/test/units/module_utils/common/arg_spec/test_aliases.py b/test/units/module_utils/common/arg_spec/test_aliases.py
index a7c82b03b4..34726465b8 100644
--- a/test/units/module_utils/common/arg_spec/test_aliases.py
+++ b/test/units/module_utils/common/arg_spec/test_aliases.py
@@ -67,7 +67,7 @@ ALIAS_TEST_CASES = [
# id, argument spec, parameters, expected parameters, error
-ALIAS_TEST_CASES_INVALID = [
+ALIAS_TEST_CASES_INVALID: list[tuple[str, dict, dict, dict, str]] = [
(
"alias-invalid",
{'path': {'aliases': 'bad'}},
diff --git a/test/units/module_utils/common/test_collections.py b/test/units/module_utils/common/test_collections.py
index 93cf3245ba..381d583004 100644
--- a/test/units/module_utils/common/test_collections.py
+++ b/test/units/module_utils/common/test_collections.py
@@ -39,16 +39,14 @@ class FakeAnsibleVaultEncryptedUnicode(Sequence):
TEST_STRINGS = u'he', u'Україна', u'Česká republika'
TEST_STRINGS = TEST_STRINGS + tuple(s.encode('utf-8') for s in TEST_STRINGS) + (FakeAnsibleVaultEncryptedUnicode(u'foo'),)
-TEST_ITEMS_NON_SEQUENCES = (
+TEST_ITEMS_NON_SEQUENCES: tuple = (
{}, object(), frozenset(),
4, 0.,
) + TEST_STRINGS
-TEST_ITEMS_SEQUENCES = (
+TEST_ITEMS_SEQUENCES: tuple = (
[], (),
SeqStub(),
-)
-TEST_ITEMS_SEQUENCES = TEST_ITEMS_SEQUENCES + (
# Iterable effectively containing nested random data:
TEST_ITEMS_NON_SEQUENCES,
)
diff --git a/test/units/module_utils/facts/hardware/test_linux.py b/test/units/module_utils/facts/hardware/test_linux.py
index 0a546f1516..74e8f20cd5 100644
--- a/test/units/module_utils/facts/hardware/test_linux.py
+++ b/test/units/module_utils/facts/hardware/test_linux.py
@@ -29,8 +29,6 @@ from . linux_data import LSBLK_OUTPUT, LSBLK_OUTPUT_2, LSBLK_UUIDS, MTAB, MTAB_E
with open(os.path.join(os.path.dirname(__file__), '../fixtures/findmount_output.txt')) as f:
FINDMNT_OUTPUT = f.read()
-GET_MOUNT_SIZE = {}
-
def mock_get_mount_size(mountpoint):
return STATVFS_INFO.get(mountpoint, {})
diff --git a/test/units/module_utils/facts/test_ansible_collector.py b/test/units/module_utils/facts/test_ansible_collector.py
index badfddd9d8..3293960d9f 100644
--- a/test/units/module_utils/facts/test_ansible_collector.py
+++ b/test/units/module_utils/facts/test_ansible_collector.py
@@ -200,7 +200,7 @@ class TestCollectedFacts(unittest.TestCase):
'env']
not_expected_facts = ['facter', 'ohai']
- collected_facts = {}
+ collected_facts: dict[str, str] = {}
def _mock_module(self, gather_subset=None):
return mock_module(gather_subset=self.gather_subset)
diff --git a/test/units/modules/test_copy.py b/test/units/modules/test_copy.py
index 49e332429a..6f15bed122 100644
--- a/test/units/modules/test_copy.py
+++ b/test/units/modules/test_copy.py
@@ -11,102 +11,109 @@ from ansible.modules.copy import AnsibleModuleError, split_pre_existing_dir
from ansible.module_utils.basic import AnsibleModule
+THREE_DIRS_DATA: tuple[tuple[str, tuple[str, list[str]] | None, tuple[str, list[str]], tuple[str, list[str]], tuple[str, list[str]]], ...] = (
+ ('/dir1/dir2',
+ # 0 existing dirs: error (because / should always exist)
+ None,
+ # 1 existing dir:
+ ('/', ['dir1', 'dir2']),
+ # 2 existing dirs:
+ ('/dir1', ['dir2']),
+ # 3 existing dirs:
+ ('/dir1/dir2', [])
+ ),
+ ('/dir1/dir2/',
+ # 0 existing dirs: error (because / should always exist)
+ None,
+ # 1 existing dir:
+ ('/', ['dir1', 'dir2']),
+ # 2 existing dirs:
+ ('/dir1', ['dir2']),
+ # 3 existing dirs:
+ ('/dir1/dir2', [])
+ ),
+)
+
-THREE_DIRS_DATA = (('/dir1/dir2',
- # 0 existing dirs: error (because / should always exist)
- None,
- # 1 existing dir:
- ('/', ['dir1', 'dir2']),
- # 2 existing dirs:
- ('/dir1', ['dir2']),
- # 3 existing dirs:
- ('/dir1/dir2', [])
- ),
- ('/dir1/dir2/',
- # 0 existing dirs: error (because / should always exist)
- None,
- # 1 existing dir:
- ('/', ['dir1', 'dir2']),
- # 2 existing dirs:
- ('/dir1', ['dir2']),
- # 3 existing dirs:
- ('/dir1/dir2', [])
- ),
- )
-
-
-TWO_DIRS_DATA = (('dir1/dir2',
- # 0 existing dirs:
- ('.', ['dir1', 'dir2']),
- # 1 existing dir:
- ('dir1', ['dir2']),
- # 2 existing dirs:
- ('dir1/dir2', []),
- # 3 existing dirs: Same as 2 because we never get to the third
- ),
- ('dir1/dir2/',
- # 0 existing dirs:
- ('.', ['dir1', 'dir2']),
- # 1 existing dir:
- ('dir1', ['dir2']),
- # 2 existing dirs:
- ('dir1/dir2', []),
- # 3 existing dirs: Same as 2 because we never get to the third
- ),
- ('/dir1',
- # 0 existing dirs: error (because / should always exist)
- None,
- # 1 existing dir:
- ('/', ['dir1']),
- # 2 existing dirs:
- ('/dir1', []),
- # 3 existing dirs: Same as 2 because we never get to the third
- ),
- ('/dir1/',
- # 0 existing dirs: error (because / should always exist)
- None,
- # 1 existing dir:
- ('/', ['dir1']),
- # 2 existing dirs:
- ('/dir1', []),
- # 3 existing dirs: Same as 2 because we never get to the third
- ),
- ) + THREE_DIRS_DATA
-
-
-ONE_DIR_DATA = (('dir1',
- # 0 existing dirs:
- ('.', ['dir1']),
- # 1 existing dir:
- ('dir1', []),
- # 2 existing dirs: Same as 1 because we never get to the third
- ),
- ('dir1/',
- # 0 existing dirs:
- ('.', ['dir1']),
- # 1 existing dir:
- ('dir1', []),
- # 2 existing dirs: Same as 1 because we never get to the third
- ),
- ) + TWO_DIRS_DATA
+TWO_DIRS_DATA: tuple[tuple[str, tuple[str, list[str]] | None, tuple[str, list[str]], tuple[str, list[str]]], ...] = (
+ ('dir1/dir2',
+ # 0 existing dirs:
+ ('.', ['dir1', 'dir2']),
+ # 1 existing dir:
+ ('dir1', ['dir2']),
+ # 2 existing dirs:
+ ('dir1/dir2', []),
+ # 3 existing dirs: Same as 2 because we never get to the third
+ ),
+ ('dir1/dir2/',
+ # 0 existing dirs:
+ ('.', ['dir1', 'dir2']),
+ # 1 existing dir:
+ ('dir1', ['dir2']),
+ # 2 existing dirs:
+ ('dir1/dir2', []),
+ # 3 existing dirs: Same as 2 because we never get to the third
+ ),
+ ('/dir1',
+ # 0 existing dirs: error (because / should always exist)
+ None,
+ # 1 existing dir:
+ ('/', ['dir1']),
+ # 2 existing dirs:
+ ('/dir1', []),
+ # 3 existing dirs: Same as 2 because we never get to the third
+ ),
+ ('/dir1/',
+ # 0 existing dirs: error (because / should always exist)
+ None,
+ # 1 existing dir:
+ ('/', ['dir1']),
+ # 2 existing dirs:
+ ('/dir1', []),
+ # 3 existing dirs: Same as 2 because we never get to the third
+ ),
+)
+TWO_DIRS_DATA += tuple(item[:4] for item in THREE_DIRS_DATA)
+
+
+ONE_DIR_DATA: tuple[tuple[str, tuple[str, list[str]] | None, tuple[str, list[str]]], ...] = (
+ ('dir1',
+ # 0 existing dirs:
+ ('.', ['dir1']),
+ # 1 existing dir:
+ ('dir1', []),
+ # 2 existing dirs: Same as 1 because we never get to the third
+ ),
+ ('dir1/',
+ # 0 existing dirs:
+ ('.', ['dir1']),
+ # 1 existing dir:
+ ('dir1', []),
+ # 2 existing dirs: Same as 1 because we never get to the third
+ ),
+)
+ONE_DIR_DATA += tuple(item[:3] for item in TWO_DIRS_DATA)
@pytest.mark.parametrize('directory, expected', ((d[0], d[4]) for d in THREE_DIRS_DATA))
+@pytest.mark.xfail(reason='broken test and/or code, original test missing assert', strict=False)
def test_split_pre_existing_dir_three_levels_exist(directory, expected, mocker):
mocker.patch('os.path.exists', side_effect=[True, True, True])
- split_pre_existing_dir(directory) == expected
+ assert split_pre_existing_dir(directory) == expected
@pytest.mark.parametrize('directory, expected', ((d[0], d[3]) for d in TWO_DIRS_DATA))
+@pytest.mark.xfail(reason='broken test and/or code, original test missing assert', strict=False)
def test_split_pre_existing_dir_two_levels_exist(directory, expected, mocker):
mocker.patch('os.path.exists', side_effect=[True, True, False])
- split_pre_existing_dir(directory) == expected
+ assert split_pre_existing_dir(directory) == expected
@pytest.mark.parametrize('directory, expected', ((d[0], d[2]) for d in ONE_DIR_DATA))
+@pytest.mark.xfail(reason='broken test and/or code, original test missing assert', strict=False)
def test_split_pre_existing_dir_one_level_exists(directory, expected, mocker):
mocker.patch('os.path.exists', side_effect=[True, False, False])
- split_pre_existing_dir(directory) == expected
+ assert split_pre_existing_dir(directory) == expected
@pytest.mark.parametrize('directory', (d[0] for d in ONE_DIR_DATA if d[1] is None))
@@ -118,9 +125,10 @@ def test_split_pre_existing_dir_root_does_not_exist(directory, mocker):
@pytest.mark.parametrize('directory, expected', ((d[0], d[1]) for d in ONE_DIR_DATA if not d[0].startswith('/')))
+@pytest.mark.xfail(reason='broken test and/or code, original test missing assert', strict=False)
def test_split_pre_existing_dir_working_dir_exists(directory, expected, mocker):
mocker.patch('os.path.exists', return_value=False)
- split_pre_existing_dir(directory) == expected
+ assert split_pre_existing_dir(directory) == expected
#
diff --git a/test/units/parsing/test_splitter.py b/test/units/parsing/test_splitter.py
index 9eb957d696..402ee74dcb 100644
--- a/test/units/parsing/test_splitter.py
+++ b/test/units/parsing/test_splitter.py
@@ -23,7 +23,7 @@ from ansible.errors import AnsibleParserError
import pytest
-SPLIT_DATA = (
+SPLIT_DATA: tuple[tuple[str | None, list[str], dict[str, str]], ...] = (
(None,
[],
{}),
diff --git a/test/units/plugins/connection/test_psrp.py b/test/units/plugins/connection/test_psrp.py
index 10902a1581..fcc5648d0f 100644
--- a/test/units/plugins/connection/test_psrp.py
+++ b/test/units/plugins/connection/test_psrp.py
@@ -6,6 +6,7 @@ from __future__ import annotations
import pytest
import sys
+import typing as t
from io import StringIO
from unittest.mock import MagicMock
@@ -46,7 +47,7 @@ def psrp_connection():
class TestConnectionPSRP(object):
- OPTIONS_DATA = (
+ OPTIONS_DATA: tuple[tuple[dict[str, t.Any], dict[str, t.Any]], ...] = (
# default options
(
{},
diff --git a/test/units/plugins/connection/test_winrm.py b/test/units/plugins/connection/test_winrm.py
index 00a29c9728..d5b76ca8f2 100644
--- a/test/units/plugins/connection/test_winrm.py
+++ b/test/units/plugins/connection/test_winrm.py
@@ -5,6 +5,7 @@
from __future__ import annotations
import os
+import typing as t
import pytest
@@ -22,7 +23,7 @@ pytest.importorskip("winrm")
class TestConnectionWinRM(object):
- OPTIONS_DATA = (
+ OPTIONS_DATA: tuple[tuple[dict[str, t.Any], dict[str, t.Any], dict[str, t.Any], bool], ...] = (
# default options
(
{'_extras': {}},
diff --git a/test/units/plugins/filter/test_mathstuff.py b/test/units/plugins/filter/test_mathstuff.py
index 4ac5487fa2..b473e305fd 100644
--- a/test/units/plugins/filter/test_mathstuff.py
+++ b/test/units/plugins/filter/test_mathstuff.py
@@ -11,7 +11,7 @@ import ansible.plugins.filter.mathstuff as ms
from ansible.errors import AnsibleFilterError, AnsibleFilterTypeError
-UNIQUE_DATA = [
+UNIQUE_DATA: list[tuple[list, list]] = [
([], []),
([1, 3, 4, 2], [1, 3, 4, 2]),
([1, 3, 2, 4, 2, 3], [1, 3, 2, 4]),
@@ -19,7 +19,7 @@ UNIQUE_DATA = [
([1, 1, 4, 2, 1, 4, 3, 2], [1, 4, 2, 3]),
]
-TWO_SETS_DATA = [
+TWO_SETS_DATA: list[tuple[list, list, tuple]] = [
([], [], ([], [], [])),
([1, 2], [1, 2], ([1, 2], [], [])),
([1, 2], [3, 4], ([], [1, 2], [1, 2, 3, 4])),
diff --git a/test/units/plugins/lookup/test_password.py b/test/units/plugins/lookup/test_password.py
index d615be998e..46c63db603 100644
--- a/test/units/plugins/lookup/test_password.py
+++ b/test/units/plugins/lookup/test_password.py
@@ -387,8 +387,11 @@ class TestWritePasswordFile(unittest.TestCase):
def setUp(self):
self.makedirs_safe = password.makedirs_safe
self.os_chmod = password.os.chmod
- password.makedirs_safe = lambda path, mode: None
- password.os.chmod = lambda path, mode: None
+ password.makedirs_safe = self.noop
+ password.os.chmod = self.noop
+
+ def noop(self, *args, **kwargs):
+ pass
def tearDown(self):
password.makedirs_safe = self.makedirs_safe
@@ -410,11 +413,14 @@ class BaseTestLookupModule(unittest.TestCase):
self.password_lookup._loader = self.fake_loader
self.os_path_exists = password.os.path.exists
self.os_open = password.os.open
- password.os.open = lambda path, flag: None
+ password.os.open = self.noop
self.os_close = password.os.close
- password.os.close = lambda fd: None
+ password.os.close = self.noop
self.makedirs_safe = password.makedirs_safe
- password.makedirs_safe = lambda path, mode: None
+ password.makedirs_safe = self.noop
+
+ def noop(self, *args, **kwargs):
+ pass
def tearDown(self):
password.os.path.exists = self.os_path_exists