Thanks eryksun. There's a list for testing in python which I also posed the question to and got pretty much the same answer as you provided.
The line if proc.returncode != 1 was a mistake. That 1 should have been a zero. As this question was just about mock and not really dealing with the bad return code or exception handling or raising my final working example looks like this: pinger.py ---------------------------- import subprocess class Pinger(object): def ping_host(self, host_to_ping): cmd_string = 'ping %s' % (host_to_ping) cmd_args = cmd_string.split() proc = subprocess.Popen(cmd_args, shell=True) proc.wait() if proc.returncode != 0: raise Exception('Error code was: %d' % (proc.returncode)) if __name__ == '__main__': PINGER = Pinger() PINGER.ping_host('localhost') ---------------------------- test_pinger.py ---------------------------- import mockimport unittestimport pinger class Test_Pinger(unittest.TestCase): def test_ping_host_succeeds(self): pinger = pinger.Pinger() with mock.patch("pinger.subprocess") as subprocess: subprocess.Popen.return_value.returncode = 0 pinger.ping_host('localhost') subprocess.Popen.assert_called_once_with(['ping','localhost'], shell=True) def test_ping_host_fails_and_throws_exception(self): pinger = pinger.Pinger() with mock.patch('pinger.subprocess') as subprocess: subprocess.Popen.return_value.returncode = 1 self.assertRaises(Exception, pinger.ping_host, 'localhost') if __name__ == '__main__': unittest.main() ---------------------------- -- James On 17 January 2014 01:05, eryksun <eryk...@gmail.com> wrote: > On Thu, Jan 16, 2014 at 5:32 AM, James Chapman <ja...@uplinkzero.com> > wrote: > > > > In my unittest I don't want to run the ping command, (It might not be > > available on the build system) I merely want to check that a call to > > subprocess.Popen is made and that the parameters are what I expect? > > You can mock `Popen` where it's accessed. > > @mock.patch('subprocess.Popen') > def test_ping_host(self, Popen): > Popen.return_value.returncode = 0 > pinger = Pinger() > pinger.ping_host('127.0.0.1') > Popen.assert_called_once_with(['ping','127.0.0.1'], shell=True) > > If the tutor_q module imported `Popen` into its namespace, then you'd > patch tutor_q.Popen. > > > def ping_host(self, host_to_ping): > > cmd_string = 'ping %s' % (host_to_ping) > > cmd_args = cmd_string.split() > > Splitting on spaces doesn't work generally. Use `shlex.split`, or > build the list manually. > > > proc = subprocess.Popen(cmd_args, shell=True) > > Maybe you really need the shell to process your command, but generally > there's no reason to run the shell just to have it execute the command > and wait. Plus it opens the door to security exploits. > > > proc.wait() > > if proc.returncode != 1: > > raise Exception('Error code was: %d' % (proc.returncode)) > > A non-zero return code signals an error. When using `Popen` directly, > you can be consistent with `check_call` and `check_output` if you > raise a `CalledProcessError` in this case: > > retcode = proc.wait() > if retcode: > raise subprocess.CalledProcessError(retcode, cmd_args) >
_______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor