On Fri, Jan 17, 2014 at 09:58:06AM +0000, James Chapman wrote: > 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:
Your final *working* example? I don't think so. I can see at least two syntax errors, and a programming error. A word to the wise: code isn't working until you've actually seen it work :-) > pinger.py > > ---------------------------- > > import subprocess > class Pinger(object): There is your first SyntaxError, a stray space ahead of the "class" keyword. > def ping_host(self, host_to_ping): > cmd_string = 'ping %s' % (host_to_ping) > cmd_args = cmd_string.split() This is not a programming error, but it is wasteful. First you join two strings: "ping", and the host. Then, having glued them together, you split them apart exactly where you glued them. Better to do something like: cmd_args = ["ping", host_to_ping] assuming that you know that host_to_ping is only a single word. > proc = subprocess.Popen(cmd_args, shell=True) Why shell=True? The documentation for subprocess.Popen says: The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If shell is True, it is recommended to pass args as a string rather than as a sequence. and also warns that shell=True can be a security hazard. Do you have a good reason for using it? http://docs.python.org/2/library/subprocess.html > 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): And here you have two more SyntaxErrors: missing commas between arguments to import, and a stray space before the "class" again. > def test_ping_host_succeeds(self): > pinger = pinger.Pinger() And here is your programming error. Unlike some programming languages (Lua, I think) in Python you cannot use the same name to refer to both a global variable and a local variable inside the same function. In Python, either the variable is treated as a global, or as a local, but not both. The rules Python uses to decide are: * if you declare a name "global" inside the function, then it is treated as global inside that function; * otherwise, if you assign a value to the name *anywhere* inside the function, it is treated as local; * otherwise it is global. So in your example, you assign a value to the name "pinger", so it is treated as local. The offending line of code looks like this: pinger = pinger.Pinger() Your *intention* is to look up the global "pinger", which is a module, then create a pinger.Pinger() instance, then assign it to the local variable "pinger". But that's not what Python does. Instead, it tries to look up a local variable "pinger", finds it doesn't have one, and raises an UnboundLocalError exception. I recommend you change the name of the local variable "pinger" to something else, so it no longer clashes with the "pinger" module name. Hope this is of help to you, -- Steven _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor