unittest in Python - python

Below program:
import unittest
class my_class(unittest.TestCase):
def setUp(self):
print "In Setup"
self.x=100
self.y=200
def test_case1(self):
print "-------------"
print "test case1"
print self.x
print "-------------"
def test_case2(self):
print "-------------"
print "test case2"
print self.y
print "-------------"
def tearDown(self):
print "In Tear Down"
print " "
print " "
if __name__ == "__main__":
unittest.main()
Gives the output:
>>> ================================ RESTART ================================
>>>
In Setup
-------------
test case1
100
-------------
In Tear Down
.In Setup
-------------
test case2
200
-------------
In Tear Down
.
----------------------------------------------------------------------
Ran 2 tests in 0.113s
OK
>>>
>>>
Questions:
what's the meaning of: if __name__ == "__main__": unittest.main()?
Why do we have double underscores prefixed and postfixed for name and main?
Where will the object for my_class be created?

The if __name__ == "__main__": bit allows your code to be imported as a module without invoking the unittest.main() code - that will only be run if this code is invoked as the main entry point of your program (i.e. if you called it like python program.py if your program was in program.py).
The prefix and postfix of double underscores means:
__double_leading_and_trailing_underscore__ : "magic" objects or attributes that live in user-controlled namespaces. E.g. __init__ , __import__ or __file__ . Never invent such names; only use them as documented.
That comes from the PEP 8 Style Guide - this is a really useful resource to read and internalize.
Finally, your my_class class will be instantiated within the unittest framework as it runs, as it inherits from unittest.TestCase.

Related

Python unittest mock running program twice

Trying to understand unittest.mock more, but not sure why its running the program twice. For simplicity, consider the code below in a file test.py:
from unittest.mock import patch
class T():
def __init__(self):
self.setup()
def setup(self):
mock_testing = patch('test.testing').start()
mock_testing.return_value = "new testing"
def testing():
return "testing"
print("Hello")
t = T()
print("Setting up")
if testing() == "testing":
print("old style")
elif testing() == "new testing":
print("new style")
When I run the script with python test.py, I get:
Hello
Hello
Setting up
new style
Setting up
old style
Why does it run the code twice? And even if it does run it twice, how come 'hello' is printed back to back, should it be printed like:
Hello
Setting up
new style
Hello
Setting up
old style
Also how can I make it so that it just runs the code once, with the mock value of 'new testing'?
This is because the script is loaded as the module __main__ first, and yet you're calling patch with test.testing, so patch will import test.py again as the test module. Since patch is called before "Setting up" is printed, the loading of the test module, as well as the printing of "Hello" by both the __main__ module and the test module, will be done before "Setting up" is printed by the __main__ module.
If you add __name__ to the arguments for print, you'll more easily see what's going on:
from unittest.mock import patch
class T():
def __init__(self):
self.setup()
def setup(self):
mock_testing = patch('test.testing').start()
mock_testing.return_value = "new testing"
def testing():
return "testing"
print(__name__, "Hello")
t = T()
print(__name__, "Setting up")
if testing() == "testing":
print(__name__, "old style")
elif testing() == "new testing":
print(__name__, "new style")
This outputs:
__main__ Hello
test Hello
test Setting up
test new style
__main__ Setting up
__main__ old style
To avoid this, you should patch __main__.testing instead, so that after the modification, the above code will output:
__main__ Hello
__main__ Setting up
__main__ new style

Python equivalent of Ruby `if __FILE__ == $PROGRAM_NAME`

In Ruby, you can write a class/module such that it can be (a) loaded into an interactive Ruby terminal without actually executing code, or (b) run as a shell script.
For example, given file foo.rb:
class Foo
def bar
puts 'Foo bar'
end
end
if __FILE__ == $PROGRAM_NAME
foo = Foo.new
foo.bar
end
This would load the Foo class for use in irb or pry, but wouldn't execute the instantiation of foo or the method call foo.bar inside the if statement at the end.
But if run in the command line with ruby foo.bar it would return "Foo bar" and exit.
Is there a Python (v2 or v3) equivalent of this?
The closest I've come (in 2.7) is this, but I feel like there might be a cleaner way:
import os, sys
if os.__file__ == sys.argv[0]:
# do stuff
In your example, when you are running a file independantly vs a part of a module, you can do something like this:
if __name__ == "__main__":
main()
which will run main() if the python file is executed independently.
In your example, you would likely want something like this.
class Foo:
def bar(self):
print 'Foo bar'
def main():
foo = Foo()
foo.bar()
if __name__ == "__main__":
main()
I personally like to define a main function as the above example, but could easily just do:
if __name__ == "__main__":
foo = Foo()
foo.bar()
Python modules include a __name__ variable holding the module name. If its the top level script, the name is __main__.
class Foo:
def bar(self):
print('Foo bar')
if __name__ == "__main__":
foo = Foo()
foo.bar()

Sharing Global variables in python

I have 2 files a.py and b.py as follows:
a.py
import b.py
Test="abc"
def main(args):
global Test
if args.target=="this":
Test="klm"
b.fun()
#rest of the body which I intend to execute only once
#hence I cannot call main() again
if __name__ == "__main__":
#some arguments are parsed
args = parser.parse_args()
main(args)
b.py
import a
print a.Test
EDIT: Output:
python a.py
abc
So basically my question is why is the Test variable not getting updated in b.py and how can I make this work? Thanks.
import a
a.main()
print a.Test
a.Test = "new Value"
print a.Text
You never invoke the main function. When you import a module, __name__ is not "__main__", so your main() never runs. When you run a.py directly it will run main()
Added due to question edit:
You need to consider the ordering of the imports execution. Consider these working files.
a.py
print("Entering a")
import argparse
import b
Test="abc"
print("Id of Test: ", id(Test))
def main(args):
global Test
if args.target=="this":
Test="klm"
b.fun()
#rest of the body which I intend to execute only once
#hence I cannot call main() again
if __name__ == "__main__":
#some arguments are parsed
print('Entering main')
parser = argparse.ArgumentParser()
parser.add_argument('--target', dest='target', type=str)
args = parser.parse_args()
main(args)
b.py
print("Entering b")
import a
print a.Test
def fun():
pass
The console produces the following:
$ python a.py
Entering a
Entering b
Entering a
('Id of Test: ', 40012016L)
abc
('Id of Test: ', 40012016L)
Entering main
The problem is, when you import a python module/file, you will immediately execute all the statements in that module. As such, you have a problem with your dependencies (aka imports), because b is importing a before the value of Test is 'corrected' and then immediately acting on this.
Consider two changes. First, introduce a third file config.py that contains this configuration information and that b does not import a. Second, move all your statements that require this config in b into functions that are called/bootstrapped by a, as obviously intended.
Previous answer:
I have a solution demonstrating the issue, by only modifying b.py
def fun(): # Added because your main calls this. An error?
pass
from a import Test, main
import a
print Test # prints 'abc'
print a.Test # prints 'abc'
main()
print Test # prints 'abc'
print a.Test # prints 'klm'
Within the python interpretor, I can produce the following:
>>> import b
abc
abc
abc
klm
In your code, you create a new variable called Test with the command from a import Test that points to the original string object. You actually want to access the Test variable owned by the module a.
In a.py you run main in the if statement:
if __name__ == "__main__":
main()
Only executes main() if that is the main script. When you import the module all the code in the if block is not run because it is not the main script. To have the main method be called remove the if statement or just call main in b.py.

Can "attrib" of nosetests work with "__init__()" function in Python

I have a simple Python class here which has 3 functions. "test_a" (attr=slow), "test_b" (attr=fast) and init(). The print statement in init() does not get called irrespective of whether I use "attr" in it or not. How can I have init() also called? Or is it even possible to do it with nosetests?
from testconfig import config as c
from nose.plugins.attrib import attr
class TestMe(object):
#attr(speed='slow')
def __init__(self):
print "I am inside init of test_me"
#attr(speed='slow')
def test_a(self):
assert 'c' == 'c'
print "I am here_a"
#attr(speed='fast')
def test_b(self):
assert 'c' == 'c'
print "I am here_b"
__init__ isn't a test, so nosetests ignores the attribute. That function must run in order to instatiate the class in order to run test_b. I think you are not seeing the output because you aren't running nosetests with the -s option. Here's the output I get with that option and setting speed to "fast":
% nosetests -s -a speed=fast tmp.py
I am inside init of test_me
I am here_b
.
----------------------------------------------------------------------
Ran 1 test in 0.003s
OK

try: except: not working

So I'm running into a problem where the try: except: mechanism doesn't seem to be working correctly in python.
Here are the contents of my two files.
pytest1.py
import pytest2
class MyError( Exception ):
def __init__( self, value ):
self.value = value
def __str__( self ):
return repr( self.value )
def func1():
raise MyError( 'This is an error' )
def func3():
pytest2.func2()
if __name__ == '__main__':
try:
func3()
except MyError, e:
print 'I should catch here.'
except:
print 'Why caught here?'
pytest2.py
from pytest1 import func1
def func2():
func1()
Executing the first file yields the following output:
$ python pytest1.py
Why caught here?
Basically, the exception isn't being caught. If I print out the exception type, it prints as <pytest1.MyError> instead of just <MyError>. I imagine that this is some weird cyclical reference thing, but it still seems like it should work.
The main python program is always imported as the module __main__.
When you import pytest2, it doesn't reuse the existing module because the originally imported module has the name __main__ not pytest2. The result is that pytest1 is run multiple times generating multiple exception classes. __main__.MyError and pytest1.MyError You end up throwing one and trying to catch the other.
So, don't try to import your main module from other modules.
This problem is caused by importing the script you are running as a module. This produces two separate copies of the module!
Another example:
module.py
import module
class Foo: pass
def test():
print Foo
print module.Foo
print Foo is module.Foo
if __name__ == '__main__': test()
main_script.py
import module
if __name__ == '__main__': module.test()
Result
>python main_script.py
module.Foo
module.Foo
True
>python module.py
__main__.Foo
module.Foo
False
Running python somefile.py creates a module called __main__, not somefile, and runs the code in somefile.py in that module. This is why if __name__ == '__main__': is used to check if this file is being run as a script or imported from some other file.
... at a guess, you have a namespace problem which is producing a different exception.
Try replacing
except:
print 'Why caught here?'
with
except Exception, e:
print e
This may tell you more about what went wrong.

Categories

Resources