1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Unittests for some of module_common.py (#20812)

* Unittests for some of module_common.py
* Port test_run_command to use pytest-mock

The use of addCleanup(patch.stopall) from the unittest idiom was
conflicting with the pytest-mock idiom of closing all patches
automatically.  Switching to pytest-mock ensures that the patches are
closed and removing the stopall stops the conflict.
This commit is contained in:
Toshio Kuratomi 2017-01-30 13:51:27 -08:00 committed by GitHub
parent 83d767ca37
commit 1609afbd12
3 changed files with 127 additions and 8 deletions

View file

@ -5,6 +5,7 @@ nose
passlib passlib
pycrypto pycrypto
pytest pytest
pytest-mock
python-memcached python-memcached
pyyaml pyyaml
redis redis

View file

@ -0,0 +1,118 @@
# (c) 2017, Toshio Kuratomi <tkuratomi@ansible.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import pytest
import ansible.errors
from ansible.compat.six import PY2
from ansible.executor import module_common as amc
class TestStripComments(object):
def test_no_changes(self):
no_comments = u"""def some_code():
return False"""
assert amc._strip_comments(no_comments) == no_comments
def test_all_comments(self):
all_comments = u"""# This is a test
# Being as it is
# To be
"""
assert amc._strip_comments(all_comments) == u""
def test_all_whitespace(self):
# Note: Do not remove the spaces on the blank lines below. They're
# test data to show that the lines get removed despite having spaces
# on them
all_whitespace = u"""
\t\t\r\n
""" # nopep8
assert amc._strip_comments(all_whitespace) == u""
def test_somewhat_normal(self):
mixed = u"""#!/usr/bin/python
# here we go
def test(arg):
# this is a thing
thing = '# test'
return thing
# End
"""
mixed_results = u"""def test(arg):
thing = '# test'
return thing"""
assert amc._strip_comments(mixed) == mixed_results
class TestSlurp(object):
def test_slurp_nonexistent(self, mocker):
mocker.patch('os.path.exists', side_effect=lambda x: False)
with pytest.raises(ansible.errors.AnsibleError):
amc._slurp('no_file')
def test_slurp_file(self, mocker):
mocker.patch('os.path.exists', side_effect=lambda x: True)
m = mocker.mock_open(read_data='This is a test')
if PY2:
mocker.patch('__builtin__.open', m)
else:
mocker.patch('builtins.open', m)
assert amc._slurp('some_file') == 'This is a test'
def test_slurp_file_with_newlines(self, mocker):
mocker.patch('os.path.exists', side_effect=lambda x: True)
m = mocker.mock_open(read_data='#!/usr/bin/python\ndef test(args):\nprint("hi")\n')
if PY2:
mocker.patch('__builtin__.open', m)
else:
mocker.patch('builtins.open', m)
assert amc._slurp('some_file') == '#!/usr/bin/python\ndef test(args):\nprint("hi")\n'
class TestGetShebang(object):
"""Note: We may want to change the API of this function in the future. It isn't a great API"""
def test_no_interpreter_set(self):
assert amc._get_shebang(u'/usr/bin/python', {}) == (None, u'/usr/bin/python')
def test_non_python_interpreter(self):
assert amc._get_shebang(u'/usr/bin/ruby', {}) == (None, u'/usr/bin/ruby')
def test_interpreter_set_in_task_vars(self):
assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/pypy'}) == \
(u'#!/usr/bin/pypy', u'/usr/bin/pypy')
def test_non_python_interpreter_in_task_vars(self):
assert amc._get_shebang(u'/usr/bin/ruby', {u'ansible_ruby_interpreter': u'/usr/local/bin/ruby'}) == \
(u'#!/usr/local/bin/ruby', u'/usr/local/bin/ruby')
def test_with_args(self):
assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/python3'}, args=('-tt', '-OO')) == \
(u'#!/usr/bin/python3 -tt -OO', u'/usr/bin/python3')
def test_python_via_env(self):
assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/env python'}) == \
(u'#!/usr/bin/env python', u'/usr/bin/env python')

View file

@ -25,6 +25,8 @@ import sys
import time import time
from io import BytesIO, StringIO from io import BytesIO, StringIO
import pytest
from ansible.compat.six import PY3 from ansible.compat.six import PY3
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import call, MagicMock, Mock, patch, sentinel from ansible.compat.tests.mock import call, MagicMock, Mock, patch, sentinel
@ -44,7 +46,8 @@ class OpenBytesIO(BytesIO):
class TestAnsibleModuleRunCommand(unittest.TestCase): class TestAnsibleModuleRunCommand(unittest.TestCase):
def setUp(self): @pytest.fixture(autouse=True)
def run_command_mocked_env(self, mocker):
self.cmd_out = { self.cmd_out = {
# os.read() is returning 'bytes', not strings # os.read() is returning 'bytes', not strings
sentinel.stdout: BytesIO(), sentinel.stdout: BytesIO(),
@ -76,7 +79,7 @@ class TestAnsibleModuleRunCommand(unittest.TestCase):
self.module = ansible.module_utils.basic.AnsibleModule(argument_spec=dict()) self.module = ansible.module_utils.basic.AnsibleModule(argument_spec=dict())
self.module.fail_json = MagicMock(side_effect=SystemExit) self.module.fail_json = MagicMock(side_effect=SystemExit)
self.os = patch('ansible.module_utils.basic.os').start() self.os = mocker.patch('ansible.module_utils.basic.os')
self.os.path.expandvars.side_effect = lambda x: x self.os.path.expandvars.side_effect = lambda x: x
self.os.path.expanduser.side_effect = lambda x: x self.os.path.expanduser.side_effect = lambda x: x
self.os.environ = {'PATH': '/bin'} self.os.environ = {'PATH': '/bin'}
@ -86,7 +89,7 @@ class TestAnsibleModuleRunCommand(unittest.TestCase):
self.os.read.side_effect = mock_os_read self.os.read.side_effect = mock_os_read
self.os.path.abspath.side_effect = mock_os_abspath self.os.path.abspath.side_effect = mock_os_abspath
self.subprocess = patch('ansible.module_utils.basic.subprocess').start() self.subprocess = mocker.patch('ansible.module_utils.basic.subprocess')
self.cmd = Mock() self.cmd = Mock()
self.cmd.returncode = 0 self.cmd.returncode = 0
self.cmd.stdin = OpenBytesIO() self.cmd.stdin = OpenBytesIO()
@ -94,13 +97,10 @@ class TestAnsibleModuleRunCommand(unittest.TestCase):
self.cmd.stderr.fileno.return_value = sentinel.stderr self.cmd.stderr.fileno.return_value = sentinel.stderr
self.subprocess.Popen.return_value = self.cmd self.subprocess.Popen.return_value = self.cmd
self.select = patch('ansible.module_utils.basic.select').start() self.select = mocker.patch('ansible.module_utils.basic.select')
self.select.select.side_effect = mock_select self.select.select.side_effect = mock_select
yield
self.addCleanup(patch.stopall)
def tearDown(self):
# unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
self.stdin_swap.__exit__(None, None, None) self.stdin_swap.__exit__(None, None, None)