Python Unit Testing a loop function - python

This is a followup question from 1
I need to test the function with two given cases in a loop. However, based on the printed results, it seems like only the first iteration is checked? Is this related to runner.run(unittest.makeSuite(MyTestCase))?
import unittest
from StringIO import StringIO
import rice_output
class MyTestCase(unittest.TestCase):
def setUp(self):
#####Pre-defined inputs########
self.dsed_in=[1,2]
self.a_in=[2,3]
self.pb_in=[3,4]
#####Pre-defined outputs########
self.msed_out=[6,24]
#####TestCase run variables########
self.tot_iter=len(self.a_in)
def testMsed(self):
for i in range(self.tot_iter):
print i
fun = rice_output.msed(self.dsed_in[i],self.a_in[i],self.pb_in[i])
value = self.msed_out[i]
testFailureMessage = "Test of function name: %s iteration: %i expected: %i != calculated: %i" % ("msed",i,value,fun)
return self.assertEqual(round(fun,3),round(self.msed_out[i],3),testFailureMessage)
from pprint import pprint
stream = StringIO()
runner = unittest.TextTestRunner(stream=stream)
result = runner.run(unittest.makeSuite(MyTestCase))
print 'Tests run ', result.testsRun
print 'Errors ', result.errors
Here is he output:
0
Tests run 1
Errors []
[]
Test output
testMsed (__main__.MyTestCase) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Any suggestions? Thanks!

Remove the return statement
def testMsed(self):
for i in range(self.tot_iter):
print i
fun = rice_output.msed(self.dsed_in[i],self.a_in[i],self.pb_in[i])
value = self.msed_out[i]
testFailureMessage = "Test of function name: %s iteration: %i expected: %i != calculated: %i" % ("msed",i,value,fun)
self.assertEqual(round(fun,3),round(self.msed_out[i],3),testFailureMessage)

Related

How do I mock an internally used python function with pytest_mock? [duplicate]

I am trying to write a test case test_is_user_present() which calls another function execute_redshift_sql() from redshift_util.py script
I set the expected return value from the function execute_redshift_sql() to 1 . But I never get this value returned from result after the function is called ! I also printed some values for debugging purpose
You can take a look at test case below
from mock import patch, Mock, MagicMock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
print(mock_execute_redshift_sql())
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
print(result())
> assert result() == 1
E AssertionError: assert <Mock name='m...749067684720'> == 1
E -<Mock name='mock.query().getresult()()' id='139749067684720'>
E +1
test/test_cia_admin_operations.py:51: AssertionError
----------------------------- Captured stdout call -----------------------------
1
<Mock name='mock.query().getresult()' id='139749067684776'>
<Mock name='mock.query().getresult()()' id='139749067684720'>
redshift_util.py
def execute_redshift_sql(connection, sqlQuery):
"""Executes redshift query"""
logger.info("Executing following SQL query :\n %s" % sqlQuery)
try:
result = connection.query(sqlQuery)
logger.info("Redshift query is successfully executed.")
except Exception as e:
logger.error("Query not executed : %s" % e)
return None
# return only if the result has some data
if result:
logger.info("Query result :\n %s" % result)
return result.getresult()
else:
return 0
You have to patch the function as it is imported. One possibility to fix this is to use:
from mock import patch, Mock
import cia_admin_operations.redshift_util
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = cia_admin_operations.redshift_util.execute_redshift_sql(mock_out, user_check_sql)
print(result)
In your case, you had mocked the function from the package, but used a locally imported module. You always have to check where to patch.
Above, I adapted the import, you can also adapt the patching:
from mock import patch, Mock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('redshift_test.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
(you have to substitute redshift_test for the name of your test module in the patch decorator)

python unit test patch mock method not returning the return values

I am trying to write a test case test_is_user_present() which calls another function execute_redshift_sql() from redshift_util.py script
I set the expected return value from the function execute_redshift_sql() to 1 . But I never get this value returned from result after the function is called ! I also printed some values for debugging purpose
You can take a look at test case below
from mock import patch, Mock, MagicMock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
print(mock_execute_redshift_sql())
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
print(result())
> assert result() == 1
E AssertionError: assert <Mock name='m...749067684720'> == 1
E -<Mock name='mock.query().getresult()()' id='139749067684720'>
E +1
test/test_cia_admin_operations.py:51: AssertionError
----------------------------- Captured stdout call -----------------------------
1
<Mock name='mock.query().getresult()' id='139749067684776'>
<Mock name='mock.query().getresult()()' id='139749067684720'>
redshift_util.py
def execute_redshift_sql(connection, sqlQuery):
"""Executes redshift query"""
logger.info("Executing following SQL query :\n %s" % sqlQuery)
try:
result = connection.query(sqlQuery)
logger.info("Redshift query is successfully executed.")
except Exception as e:
logger.error("Query not executed : %s" % e)
return None
# return only if the result has some data
if result:
logger.info("Query result :\n %s" % result)
return result.getresult()
else:
return 0
You have to patch the function as it is imported. One possibility to fix this is to use:
from mock import patch, Mock
import cia_admin_operations.redshift_util
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = cia_admin_operations.redshift_util.execute_redshift_sql(mock_out, user_check_sql)
print(result)
In your case, you had mocked the function from the package, but used a locally imported module. You always have to check where to patch.
Above, I adapted the import, you can also adapt the patching:
from mock import patch, Mock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('redshift_test.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
(you have to substitute redshift_test for the name of your test module in the patch decorator)

Selenium: Execute third function after first two finished

I am using Selenium Webdriver with Firefox to run my code. I am using pytest so I can run the functions in parallel. I have three main functions: first and second function return something and third function uses the data from the pervious functions. My problem is that I want to execute third function with the data returned from two functions once the first two functions have finished.
The code itself is actually much more complex but to clarify I made a new code which demonstrates my problem. I have two functions, one is named "test1" and other is named "test2" - both of these run parallel and return information. I also have a third function named "test3" to process the data returned from test1 and test2 once they're both finished. In this example "comp" should just print out some text.
Here's the code:
import unittest
from time import sleep
from selenium import webdriver
# pytest -s -v tests.py <----- I use to execute this script
# py.test -s tests.py -d --tx 2*popen//python=python2.7 <------- I use this to run the tests in parallel
# For some reason program doesnt print in parallel mode. Although "-s" fixes that in the normal execution of pytest.
class TestParallel(unittest.TestCase):
def setUp(self):
self.browser = webdriver.Firefox(executable_path='./dependencies/geckodriver')
def test1(self):
browser = self.browser
browser.get('https://www.google.com/')
asd = browser.find_element_by_xpath("/html/body/div/div[3]/div[1]/div/div/div/div[1]/div[1]/a").text # returns "Gmail"
sleep(2)
print asd
return asd
def test2(self):
browser = self.browser
browser.get('https://www.google.com/')
asd2 = browser.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/div/div/div/div[1]/div[2]/a").text # returns "Images"
sleep(1)
print asd2
return asd2
def test3(self):
print "word from test1 is " + TestParallel.test1(self) + " and word from test2 is " + TestParallel.test2(self)
def tearDown(self):
self.browser.quit()
if __name__ == "__main__":
unittest.main()
Maybe someone has ideas/suggestions as to how I could resolve this issue. Thank you!
Edit
Ok, here's another idea:
Declare two empty global string variables before test1 and test2 are
run.
Have test1 and test2 write to those two variables
Have test3
wait with a while loop until both of the variables contain something
or until a specific amount of time passes.
class TestParallel(unittest.TestCase):
string_a = ""
string_b = ""
def setUp(self):
self.browser = webdriver.Firefox(executable_path='./dependencies/geckodriver')
def test1(self):
[..]
string_a = "result_a"
def test2(self):
[..]
string_b = "result_b"
def test3(self):
counter = 0;
while ("" in string_a && "" in string_b):
sleep(0.1)
counter = counter + 1
if counter > 200:
break
print "word from test1 is " + string_a + " and word from test2 is " + string_b
Hmm, perhaps:
def test3(self):
counter = 0;
while ("" in string_a && "" in string_b):
sleep(0.1)
counter = counter + 1
if counter > 1000:
break
print "word from test1 is " + string_b + " and word from test2 is " + string_b
test1 and test2 don't really look like tests... they look like they should be functions that return data from the page that are used in a test. I would do something more like
def get_thing1(self):
return self.browser.find_element_by_xpath("/html/body/div/div[3]/div[1]/div/div/div/div[1]/div[1]/a").text # returns "Gmail"
def get_thing2(self):
return self.browser.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/div/div/div/div[1]/div[2]/a").text # returns "Images"
def test1(self):
browser = self.browser
browser.get('https://www.google.com/')
print "word from test1 is " + get_thing1(self) + " and word from test2 is " + get_thing2(self)
These two methods, get_thing1 and get_thing2 assume that you are on the right page and all they do is return whatever you are looking for. Please change the names to something more descriptive... I wasn't sure what exactly they were returning so I made up some generic name.
Now you only have test1 that runs and two methods that pull things from the page. You can run test1 as many times as you want... in parallel, etc. ... in a loop or whatever you desire.
Extra notes:
You really don't want to use XPaths that are that many levels deep and/or that start at the HTML tag. They are very brittle (likely to break with any little change to the HTML).
You should take some time to read about the page object model. You should create a GoogleSearchResultsPage page object and have get_thing1() and get_thing2() be in that page object. You test would then progress from the GoogleSearchPage to the GoogleSearchResultsPage and would then call those two methods, etc. to get data from the page.

How to print the name and value of a variable?

This is what I have in mind because I find myself typing the name twice whenever I want to inspect the value of a variable:
a = 1
my_print(a) # "a: 1"
Is this possible in Python?
If you are in control of the calling function, you can hack this to work reasonably well like:
Code:
import inspect
def print_name_and_value(var):
lines = inspect.stack()[1][4]
var_name = ''.join(lines).strip().split('(')[-1].split(')')[0]
print("%s: %d" % (var_name, var))
a = 5
print_name_and_value(a)
Results:
a: 5
How does this work?
The inspect module can be used to inspect the caller, and get the line of code used by the caller. With a bit of string hacking the variable name (assuming it is a simple variable and not a more complex expression) can be gathered from the source code.
I would say "no", and any other magic doable is just... too much magic.
However there's something you can do, and that's looking at the stack trace using the inspect module.
import inspect
def my_print(thingy):
# print("id(thingy)=%s" % id(thingy))
previous_frame = inspect.currentframe().f_back
# print("locals: %s" % previous_frame.f_locals)
for variable_name, variable_value in previous_frame.f_locals.items():
if id(variable_value) == id(thingy):
return("%s: %s" % (variable_name, variable_value))
# print("globals: %s" % previous_frame.f_globals)
for variable_name, variable_value in previous_frame.f_globals.items():
if id(variable_value) == id(thingy):
return("%s: %s" % (variable_name, variable_value))
if __name__ == '__main__':
a = 1
print("Test %s" % my_print(a)) # "a: 1"
list_thingy = [1, 2, 3]
print("Test %s" % my_print(list_thingy))
def and_within_function():
d = {1: "a"}
print("Test %s" % my_print(d))
and_within_function()
But this is not reliable and I'd use it more as a curiosity, since there are plenty of "special cases". For instance: the first 255 integers (I think) in Python occupy a specific memory address so, if you have two variables that are =1 I don't think you're gonna really be guaranteed which one is it.

saving the data after it was printed to screen python

Is there a way to save data after it was printed to the screen?
for example:
lets have some arbitrary function
def main():
if something:
for i in range(n):
output= "%f %f" %(n,d)
print output
if something:
for i in range(n):
output="%f %f" %(n,d)
print output
fileout=open("data.csv", "a")
fileout.write(output)
this will only write the last data for the last range in for loop.
Edit: I want to ask a user if she/he wants to save that data
Declare your output variable(s) at the highest level of scope in your program first. This will allow it to be written to a file in the manner you've programmed.
If you want to prompt a user for a location to save the file(s), that's merely this:
out1 = raw_input("Where would you like to save this? ")
You can do the same for another output file variable.
just use this in the if conditions:
print >>fileout, output #this will save the output to the data.csv file
Change your code...
1: If you really want to use print, change sys.stdout to a different stream
2: use files
1
import sys
oldstdout=sys.stdout
f=open("myfile","w")
sys.stdout=f
def main():
if something:
for i in range(n):
print "%f %f"%(n,d)
if something:
for i in range(n):
print "%f %f"%(n,d)
2
f=open("myfile","w")
def main():
if something:
for i in range(n):
f.write("%f %f"%(n,d))
if something:
for i in range(n):
f.write("%f %f"%(n,d))
Here is a (somewhat pathological) example that will let you both print and save the statements that you print in a global list (which we'll call OUTPUT):
import sys
OUTPUT = []
def print_wrapper(method):
class result(object):
def __init__(self, file_obj):
self.file_obj = file_obj
def __getattr__(self, name):
return getattr(self.file_obj, name)
def write(self, value):
OUTPUT.append(value)
return self.file_obj.write(value)
return result(method)
original_stdout = sys.stdout
sys.stdout = print_wrapper(original_stdout)
# This will still print, but will add 'Hi' and '\n' to OUTPUT as well
print 'Hi'
# This will still print, but will add 'None' and '\n' to OUTPUT as well
print None
# This uses the original stdout to print, so won't change OUTPUT
original_stdout.write(repr(OUTPUT))
original_stdout.write('\n')
or you could alternately prepare yourself for Python 3 (or just use it) and wrap the print method itself:
from __future__ import print_function # must have Python >= 2.6
OUTPUT = []
def wrap_print(method):
def result(value):
OUTPUT.append(value)
return method(value)
return result
old_print = print
print = wrap_print(old_print)
print('Hi')
print(None)
old_print(OUTPUT)

Categories