0

How do I write a unittest for the run_7zip method below please? I am trying to use mock correctly. I read several stackoverflow solutions and the documentation. I use python 3.6 on Linux through the pydev module in Eclipse with py.test as the test runner.

Please find my best guess below, with the output. My test is based on the stackoverflow answer:

Mocking a subprocess call in Python

import unittest.mock as mock

SEVENZIPPATH = <path to 7zip executable>

def run_7zip(input_file, output_file):
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = subprocess.SW_HIDE
    arglist = [SEVENZIPPATH, "a", "-t7z", "-mx9","-aoa",output_file,input_file] 
    process = subprocess.Popen(args = arglist, shell = False, startupinfo = startupinfo)
    output,err = process.communicate()
    return process.returncode

@mock.patch('subprocess.Popen')
def test_run_7zip(mock_subproc_popen):
    process_mock = mock.Mock()
    attrs = {'communicate.return_value': ('output', 'error')}
    process_mock.configure_mock(**attrs)
    mock_subproc_popen.return_value = process_mock
    assert mock_subproc_popen.called is True

ouput (truncated):

mock_subproc_popen = <MagicMock name='Popen' id='84153624'>
assert mock_subproc_popen.called == True
>       assert mock_subproc_popen.called is True
E       AssertionError: assert False is True
E        +  where False = <MagicMock name='Popen' id='84152952'>.called

Following de1's helpful comments, I get the following to pass:

@mock.patch('subprocess.Popen')
def test_run_7zip(mock_subproc_popen):
    process_mock = mock.Mock()
    attrs = {'communicate.return_value': ('output', 'error')}
    process_mock.configure_mock(**attrs)
    mock_subproc_popen.return_value = process_mock
    run_7zip('path1', 'path2')
    assert mock_subproc_popen.called is True
Oppy
  • 2,662
  • 16
  • 22

1 Answers1

2

Are you missing the call to run_7zip in your test case?

de1
  • 2,986
  • 1
  • 15
  • 32
  • py.test will call run_7zip as the test case is called test_run_7zip. Or am I missing something obvious? Which is often the case... I have other unit tests in the test file, which are called test_ which work as expected. – Oppy Jan 09 '18 at 17:54
  • I don't think that is true. That is rather a convention. It wouldn't know when to call it within your test case and with what parameters. In your case you want to call it before your last assertion. – de1 Jan 09 '18 at 17:59
  • I see! I added a test that passes at the end of my question. – Oppy Jan 09 '18 at 18:13