[TIP] Mocked subprocess.check_output fails assertion

Chad Slater chad.slater at gmail.com
Sun Feb 2 13:05:44 PST 2014


I'm having a rather strange problem, and I don't know if I'm doing
something boneheaded, or there's a bug in or limitation with mock.

I'm able to successfully mock a call to subprocess.check_output.  When
I attempted to validate that it is called with the correct parameters,
the assert_called_with call fails; however, the printed output of the
failure appears to show that the correct values were called.

An excerpt from the failure:
Expected call: check_output(['pw', 'group', 'add', '-n', 'testgroup',
'-g', '1010', '-M', 'bar'], sdterr=<MagicMock name='subprocess.STDOUT'
id='34418164624'>)
Actual call:   check_output(['pw', 'group', 'add', '-n', 'testgroup',
'-g', '1010', '-M', 'bar'], stderr=<MagicMock name='subprocess.STDOUT'
id='34418164624'>)

I'm assuming I'm patching this incorrectly, but looking through the
documentation for mock, I'm not sure I see where I went wrong. Full
details, including the function, and test case, are included below,
including imports, but file paths, group, and modules names have been
changed to protect the guilty.


========================== Function in Module foo.py
==================================
import subprocess

from baz.exceptions import *


def create_group(name, gid):
    """Create a group called `name` with the `gid`.  Runs the following command
    on the host:

    pw group add -n `name` -g `gid` -M bar

    :param name: the group name
    :type name: `str`
    :param gid: the group id
    :type gid: `int`

    .. Warning:: Use :func:`get_gid` to find a valid gid and avoid potential
    security implications or other errors.

    """
    cmd = ["pw", "group", "add", "-n", name, "-g", str(gid), "-M", "bar"]
    try:
        out = subprocess.check_output(cmd, stderr=subprocess.STDOUT)

   except subprocess.CalledProcessError as cpe:
        print cpe.output
        return False

    except OSError as ose:
        print ose
        return False
    return True

========================== Test Module =========================================
import re
from unittest import TestCase
try:                                                # If we're running
Python3, mock is built-in to unnittest
    from unittest.mock import patch, mock_open, MagicMock, ANY
except ImportError:
    from mock import patch, mock_open, Mock, MagicMock, ANY

from baz.buzz import foo
from bazz.exceptions import *
from bazz.buzz.test.test_data import TEST_DATA1, TEST_DATA2, TEST_DATA3

class TestCreateGroup(TestCase):

    @patch('foo.subprocess')
    def test_create_group_cmds(self, mock_sp):
        name = "testgroup"
        gid = 1010
        res = executor.create_group(name, gid)
        cmd = ["pw", "group", "add", "-n", name, "-g", str(gid), "-M", "bar"]
        mock_sp.check_output.assert_called_with(cmd, sdterr=mock_sp.STDOUT)

========================= Test Results =========================================

Failure
Traceback (most recent call last):
  File "/path/to/venv/lib/python2.7/site-packages/mock.py", line 1201,
in patched
    return func(*args, **keywargs)
  File "/path/to/app/test/executor_tests.py", line 234, in
test_create_group_cmds
    mock_sp.check_output.assert_called_with(cmd, sdterr=mock_sp.STDOUT)
  File "/path/to/venv/lib/python2.7/site-packages/mock.py", line 835,
in assert_called_with
    raise AssertionError(msg)
AssertionError: Expected call: check_output(['pw', 'group', 'add',
'-n', 'testgroup', '-g', '1010', '-M', 'bar'], sdterr=<MagicMock
name='subprocess.STDOUT' id='34418164624'>)
Actual call: check_output(['pw', 'group', 'add', '-n', 'testgroup',
'-g', '1010', '-M', 'bar'], stderr=<MagicMock name='subprocess.STDOUT'
id='34418164624'>)



More information about the testing-in-python mailing list