Repository: ansible/ansible-navigator (language: python)

Issue:
Guard against using unittest ecosystem within pylint
This patch implements recommendations to use `pytest`-native fixtures
instead of importing `unittest`-world helper untilities directly using
a built-in `pylint` rule `preferred-module`.


Discussion / hints:

Fix patch:
diff --git a/.flake8 b/.flake8
index 5b21f51ee..3944a67d8 100644
--- a/.flake8
+++ b/.flake8
@@ -249,10 +249,10 @@ per-file-ignores =
   tests/integration/actions/templar/test_welcome_interactive_ee.py: D200, D400, WPS115, WPS300, WPS436
   tests/integration/actions/templar/test_welcome_interactive_noee.py: D200, D400, WPS115, WPS300, WPS436
   tests/integration/conftest.py: D205, D400, D401, D403, DAR101, DAR201, DAR301, PT001, PT003, PT004, PT022, S108, WPS300, WPS407, WPS433, WPS436
-  tests/integration/test_execution_environment_image.py: D200, D205, D400, D403, DAR101, S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS226, WPS300, WPS301, WPS436
-  tests/integration/test_execution_environment.py: D200, D205, D400, D403, DAR101, S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS300, WPS301, WPS436
-  tests/integration/test_pass_environment_variable.py: D200, D205, D400, D403, DAR101, S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS226, WPS300, WPS301, WPS436
-  tests/integration/test_set_environment_variable.py: D200, D205, D400, D403, DAR101, S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS300, WPS301, WPS436
+  tests/integration/test_execution_environment_image.py: S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS226, WPS300, WPS301, WPS436
+  tests/integration/test_execution_environment.py: S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS300, WPS301, WPS436
+  tests/integration/test_pass_environment_variable.py: S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS226, WPS300, WPS301, WPS436
+  tests/integration/test_set_environment_variable.py: S101, WPS110, WPS111, WPS115, WPS210, WPS211, WPS220, WPS221, WPS300, WPS301, WPS436
   tests/integration/test_stdout_exit_codes.py: D200, D400, D403, DAR101, DAR201, S101, WPS110, WPS226, WPS300
   tests/unit/__init__.py: D104
   tests/unit/actions/__init__.py: D104


Test patch:
diff --git a/tests/integration/_cli2runner.py b/tests/integration/_cli2runner.py
index 25fbcb695..363071c50 100644
--- a/tests/integration/_cli2runner.py
+++ b/tests/integration/_cli2runner.py
@@ -24,9 +24,17 @@ class Cli2Runner:
         "run": "override in subclass",
     }
 
-    def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
+    def run_test(self, mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected):
         # pylint: disable=no-self-use
-        """the function to run the test and assert"""
+        """Confirm execution of ``cli.main()`` produces the desired results.
+
+        :param mocked_runner: A patched instance of runner
+        :param monkeypatch: The monkey patch fixture
+        :param tmpdir: A fixture generating a unique temporary directory
+        :param cli_entry: The CLI entry to set as :data:`sys.argv`
+        :param config_fixture: The settings fixture
+        :param expected: the expected return value
+        """
         raise Exception("Override in subclass")
 
     @pytest.fixture(autouse=True)
@@ -37,6 +45,7 @@ def _setup(self):
     def test_config_interactive(
         self,
         mocked_runner,
+        monkeypatch,
         tmpdir,
         comment,
         cli_entry,
@@ -46,12 +55,13 @@ def test_config_interactive(
     ):
         """test use of set_environment_variable"""
         cli_entry = self.cli_entry.format(self.INTERACTIVE["config"], cli_entry, "interactive")
-        self.run_test(mocked_runner, tmpdir, cli_entry, config_fixture, expected)
+        self.run_test(mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected)
 
     @mock.patch("ansible_navigator.runner.command.run_command")
     def test_config_stdout(
         self,
         mocked_runner,
+        monkeypatch,
         tmpdir,
         comment,
         cli_entry,
@@ -61,12 +71,13 @@ def test_config_stdout(
         # pylint: disable=unused-argument
         """test use of set_environment_variable"""
         cli_entry = self.cli_entry.format(self.STDOUT["config"], cli_entry, "stdout")
-        self.run_test(mocked_runner, tmpdir, cli_entry, config_fixture, expected)
+        self.run_test(mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected)
 
     @mock.patch("ansible_navigator.runner.ansible_inventory.get_inventory")
     def test_inventory_interactive(
         self,
         mocked_runner,
+        monkeypatch,
         tmpdir,
         comment,
         cli_entry,
@@ -76,12 +87,13 @@ def test_inventory_interactive(
     ):
         """test use of set_environment_variable"""
         cli_entry = self.cli_entry.format(self.INTERACTIVE["inventory"], cli_entry, "interactive")
-        self.run_test(mocked_runner, tmpdir, cli_entry, config_fixture, expected)
+        self.run_test(mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected)
 
     @mock.patch("ansible_navigator.runner.command.run_command")
     def test_inventory_stdout(
         self,
         mocked_runner,
+        monkeypatch,
         tmpdir,
         comment,
         cli_entry,
@@ -91,12 +103,13 @@ def test_inventory_stdout(
         # pylint: disable=unused-argument
         """test use of set_environment_variable"""
         cli_entry = self.cli_entry.format(self.STDOUT["inventory"], cli_entry, "stdout")
-        self.run_test(mocked_runner, tmpdir, cli_entry, config_fixture, expected)
+        self.run_test(mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected)
 
     @mock.patch("ansible_navigator.runner.command_async.run_command_async")
     def test_run_interactive(
         self,
         mocked_runner,
+        monkeypatch,
         tmpdir,
         comment,
         cli_entry,
@@ -107,11 +120,20 @@ def test_run_interactive(
         # pylint: disable=unused-argument
         """test use of set_environment_variable"""
         cli_entry = self.cli_entry.format(self.INTERACTIVE["run"], cli_entry, "interactive")
-        self.run_test(mocked_runner, tmpdir, cli_entry, config_fixture, expected)
+        self.run_test(mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected)
 
     @mock.patch("ansible_navigator.runner.command_async.run_command_async")
-    def test_run_stdout(self, mocked_runner, tmpdir, comment, cli_entry, config_fixture, expected):
+    def test_run_stdout(
+        self,
+        mocked_runner,
+        monkeypatch,
+        tmpdir,
+        comment,
+        cli_entry,
+        config_fixture,
+        expected,
+    ):
         # pylint: disable=unused-argument
         """test use of set_environment_variable"""
         cli_entry = self.cli_entry.format(self.STDOUT["run"], cli_entry, "stdout")
-        self.run_test(mocked_runner, tmpdir, cli_entry, config_fixture, expected)
+        self.run_test(mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected)
diff --git a/tests/integration/test_execution_environment.py b/tests/integration/test_execution_environment.py
index e0cdcdaa2..560059676 100644
--- a/tests/integration/test_execution_environment.py
+++ b/tests/integration/test_execution_environment.py
@@ -1,11 +1,7 @@
-"""test the use of execution-environment through to runner
-"""
+"""Test the use of ``execution-environment`` through to runner."""
 import os
 import shlex
 
-# pylint: disable=preferred-module  # FIXME: remove once migrated per GH-872
-from unittest import mock
-
 import pytest
 
 from ansible_navigator import cli
@@ -32,7 +28,7 @@
     ids=[f"{idx}: {i[0]}" for idx, i in enumerate(test_data)],
 )
 class Test(Cli2Runner):
-    """test execution-environment"""
+    """Test the use of ``execution-environment`` through to runner."""
 
     TEST_DIR_NAME = os.path.basename(__file__).replace("test_", "").replace(".py", "")
     TEST_FIXTURE_DIR = f"{FIXTURES_DIR}/integration/{TEST_DIR_NAME}"
@@ -49,12 +45,16 @@ class Test(Cli2Runner):
         "run": f"run {TEST_FIXTURE_DIR}/site.yml",
     }
 
-    def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
+    def run_test(self, mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected):
         # pylint: disable=too-many-arguments
-        """mock the runner call so it raises an exception
-        mock the command line with ``sys.argv``
-        set the ANSIBLE_NAVIGATOR_CONFIG environment variable
-        call ``cli.main()``, check the arguments passed to the runner function
+        """Confirm execution of ``cli.main()`` produces the desired results.
+
+        :param mocked_runner: A patched instance of runner
+        :param monkeypatch: The monkey patch fixture
+        :param tmpdir: A fixture generating a unique temporary directory
+        :param cli_entry: The CLI entry to set as ``sys.argv``
+        :param config_fixture: The settings fixture
+        :param expected: the expected return value
         """
         mocked_runner.side_effect = Exception("called")
         cfg_path = f"{self.TEST_FIXTURE_DIR}/{config_fixture}"
@@ -64,14 +64,12 @@ def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
 
         params = shlex.split(cli_entry) + ["--pp", "never"]
 
-        with mock.patch("sys.argv", params):
-            with mock.patch.dict(os.environ, {"ANSIBLE_NAVIGATOR_CONFIG": cfg_path}):
-                with mock.patch.dict(
-                    os.environ,
-                    {"ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH": coll_cache_path},
-                ):
-                    with pytest.raises(Exception, match="called"):
-                        cli.main()
+        monkeypatch.setattr("sys.argv", params)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_CONFIG", cfg_path)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH", coll_cache_path)
+
+        with pytest.raises(Exception, match="called"):
+            cli.main()
 
         _args, kwargs = mocked_runner.call_args
 
diff --git a/tests/integration/test_execution_environment_image.py b/tests/integration/test_execution_environment_image.py
index 340567018..ec2074dfa 100644
--- a/tests/integration/test_execution_environment_image.py
+++ b/tests/integration/test_execution_environment_image.py
@@ -1,11 +1,7 @@
-"""Test the use of execution-environment-image through to runner.
-"""
+"""Test the use of ``execution-environment-image`` through to runner."""
 import os
 import shlex
 
-# pylint: disable=preferred-module  # FIXME: remove once migrated per GH-872
-from unittest import mock
-
 import pytest
 
 from ansible_navigator import cli
@@ -43,7 +39,7 @@
     ids=[f"{idx}: {i[0]}" for idx, i in enumerate(test_data)],
 )
 class Test(Cli2Runner):
-    """test the use of execution-environment-image through to runner"""
+    """Test the use of ``execution-environment-image`` through to runner."""
 
     TEST_DIR_NAME = os.path.basename(__file__).replace("test_", "").replace(".py", "")
     TEST_FIXTURE_DIR = f"{FIXTURES_DIR}/integration/{TEST_DIR_NAME}"
@@ -60,13 +56,16 @@ class Test(Cli2Runner):
         "run": "run site.yaml",
     }
 
-    def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
+    def run_test(self, mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected):
         # pylint: disable=too-many-arguments
-        """mock the runner call so it raises an exception
-        mock the command line with ``sys.argv``
-        set the ANSIBLE_NAVIGATOR_CONFIG environment variable
-        set the expected environment variables
-        call ``cli.main()``, check the arguments passed to the runner function
+        """Confirm execution of ``cli.main()`` produces the desired results.
+
+        :param mocked_runner: A patched instance of runner
+        :param monkeypatch: The monkey patch fixture
+        :param tmpdir: A fixture generating a unique temporary directory
+        :param cli_entry: The CLI entry to set as ``sys.argv``
+        :param config_fixture: The settings fixture
+        :param expected: the expected return value
         """
         mocked_runner.side_effect = Exception("called")
         cfg_path = f"{self.TEST_FIXTURE_DIR}/{config_fixture}"
@@ -76,14 +75,12 @@ def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
 
         params = shlex.split(cli_entry) + ["--pp", "never"]
 
-        with mock.patch("sys.argv", params):
-            with mock.patch.dict(os.environ, {"ANSIBLE_NAVIGATOR_CONFIG": cfg_path}):
-                with mock.patch.dict(
-                    os.environ,
-                    {"ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH": coll_cache_path},
-                ):
-                    with pytest.raises(Exception, match="called"):
-                        cli.main()
+        monkeypatch.setattr("sys.argv", params)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_CONFIG", cfg_path)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH", coll_cache_path)
+
+        with pytest.raises(Exception, match="called"):
+            cli.main()
 
         _args, kwargs = mocked_runner.call_args
 
diff --git a/tests/integration/test_pass_environment_variable.py b/tests/integration/test_pass_environment_variable.py
index b8aee738c..32ea49078 100644
--- a/tests/integration/test_pass_environment_variable.py
+++ b/tests/integration/test_pass_environment_variable.py
@@ -1,11 +1,7 @@
-"""test the use of pass_environment_variable through to runner
-"""
+"""Test the use of ``pass-environment-variable`` through to runner."""
 import os
 import shlex
 
-# pylint: disable=preferred-module  # FIXME: remove once migrated per GH-872
-from unittest import mock
-
 import pytest
 
 from ansible_navigator import cli
@@ -48,7 +44,7 @@
     ids=[f"{idx}: {i[0]}" for idx, i in enumerate(test_data)],
 )
 class Test(Cli2Runner):
-    """test the use of pass_environment_variable through to runner"""
+    """Test the use of ``pass-environment-variable`` through to runner."""
 
     TEST_DIR_NAME = os.path.basename(__file__).replace("test_", "").replace(".py", "")
     TEST_FIXTURE_DIR = f"{FIXTURES_DIR}/integration/{TEST_DIR_NAME}"
@@ -65,13 +61,16 @@ class Test(Cli2Runner):
         "run": f"run {TEST_FIXTURE_DIR}/site.yml",
     }
 
-    def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
+    def run_test(self, mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected):
         # pylint: disable=too-many-arguments
-        """mock the runner call so it raises an exception
-        mock the command line with ``sys.argv``
-        set the ANSIBLE_NAVIGATOR_CONFIG environment variable
-        set the expected environmental variables
-        call ``cli.main()``, check the ``envvars`` argument passed to the runner function
+        """Confirm execution of ``cli.main()`` produces the desired results.
+
+        :param mocked_runner: A patched instance of runner
+        :param monkeypatch: The monkey patch fixture
+        :param tmpdir: A fixture generating a unique temporary directory
+        :param cli_entry: The CLI entry to set as ``sys.argv``
+        :param config_fixture: The settings fixture
+        :param expected: the expected return value
         """
         mocked_runner.side_effect = Exception("called")
         cfg_path = f"{self.TEST_FIXTURE_DIR}/{config_fixture}"
@@ -81,15 +80,13 @@ def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
 
         params = shlex.split(cli_entry) + ["--pp", "never"]
 
-        with mock.patch("sys.argv", params):
-            with mock.patch.dict(os.environ, {"ANSIBLE_NAVIGATOR_CONFIG": cfg_path}):
-                with mock.patch.dict(
-                    os.environ,
-                    {"ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH": coll_cache_path},
-                ):
-                    with mock.patch.dict(os.environ, expected):
-                        with pytest.raises(Exception, match="called"):
-                            cli.main()
+        monkeypatch.setattr("sys.argv", params)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_CONFIG", cfg_path)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH", coll_cache_path)
+        for envvar, value in expected.items():
+            monkeypatch.setenv(envvar, value)
+        with pytest.raises(Exception, match="called"):
+            cli.main()
 
         _args, kwargs = mocked_runner.call_args
 
diff --git a/tests/integration/test_set_environment_variable.py b/tests/integration/test_set_environment_variable.py
index d9b048406..8e9cf53db 100644
--- a/tests/integration/test_set_environment_variable.py
+++ b/tests/integration/test_set_environment_variable.py
@@ -1,11 +1,7 @@
-"""test the use of set_environment_variable through to runner
-"""
+"""Test the use of ``set-environment-variable`` through to runner."""
 import os
 import shlex
 
-# pylint: disable=preferred-module  # FIXME: remove once migrated per GH-872
-from unittest import mock
-
 import pytest
 
 from ansible_navigator import cli
@@ -48,7 +44,7 @@
     ids=[f"{idx}: {i[0]}" for idx, i in enumerate(test_data)],
 )
 class Test(Cli2Runner):
-    """test the use of set_environment_variable through to runner"""
+    """Test the use of ``set-environment-variable`` through to runner."""
 
     TEST_DIR_NAME = os.path.basename(__file__).replace("test_", "").replace(".py", "")
     TEST_FIXTURE_DIR = f"{FIXTURES_DIR}/integration/{TEST_DIR_NAME}"
@@ -65,13 +61,16 @@ class Test(Cli2Runner):
         "run": f"run {TEST_FIXTURE_DIR}/site.yml",
     }
 
-    def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
+    def run_test(self, mocked_runner, monkeypatch, tmpdir, cli_entry, config_fixture, expected):
         # pylint: disable=too-many-arguments
-        """Mock the runner call so it raises an exception.
-
-        mock the command line with ``sys.argv``
-        set the ANSIBLE_NAVIGATOR_CONFIG environment variable
-        call ``cli.main()``, check the ``envvars`` argument passed to the runner function
+        """Confirm execution of ``cli.main()`` produces the desired results.
+
+        :param mocked_runner: A patched instance of runner
+        :param monkeypatch: The monkey patch fixture
+        :param tmpdir: A fixture generating a unique temporary directory
+        :param cli_entry: The CLI entry to set as ``sys.argv``
+        :param config_fixture: The settings fixture
+        :param expected: the expected return value
         """
         mocked_runner.side_effect = Exception("called")
         cfg_path = f"{self.TEST_FIXTURE_DIR}/{config_fixture}"
@@ -81,14 +80,12 @@ def run_test(self, mocked_runner, tmpdir, cli_entry, config_fixture, expected):
 
         params = shlex.split(cli_entry) + ["--pp", "never"]
 
-        with mock.patch("sys.argv", params):
-            with mock.patch.dict(os.environ, {"ANSIBLE_NAVIGATOR_CONFIG": cfg_path}):
-                with mock.patch.dict(
-                    os.environ,
-                    {"ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH": coll_cache_path},
-                ):
-                    with pytest.raises(Exception, match="called"):
-                        cli.main()
+        monkeypatch.setattr("sys.argv", params)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_CONFIG", cfg_path)
+        monkeypatch.setenv("ANSIBLE_NAVIGATOR_COLLECTION_DOC_CACHE_PATH", coll_cache_path)
+
+        with pytest.raises(Exception, match="called"):
+            cli.main()
 
         _args, kwargs = mocked_runner.call_args