Python mock.patch is not mocking my function? - python

So I wrote a pretty simple test case and function. I can't seem to figure out the problem. Anyone have an idea? I feel like it should work.
import pandas
import unittest
from unittest import mock
from unittest.mock import MagicMock, Mock
def my_func():
temp = pandas.ExcelFile('temp.xlsx')
return temp.parse()
#mock.patch('pandas.ExcelFile')
def test_func(pd):
pd.parse.return_value = 10
print(pd.parse())
print(my_func())
Output just gives this:
10
<MagicMock name='ExcelFile().parse()' id='140620591125360'>

Provide a completed unit test solution based on #MrBean Bremen's comment.
index_63929989.py:
import pandas
def my_func():
temp = pandas.ExcelFile('temp.xlsx')
return temp.parse()
test_index_63929989.py:
import unittest
from unittest import mock
from index_63929989 import my_func
class TestIndex(unittest.TestCase):
#mock.patch('pandas.ExcelFile')
def test_func(self, mock_pd_excelFile):
mock_pd_excelFile.return_value.parse.return_value = 10
actual = my_func()
mock_pd_excelFile.assert_called_with('temp.xlsx')
self.assertEqual(actual, 10)
if __name__ == '__main__':
unittest.main()
unit test result with coverage report:
coverage run /Users/ldu020/workspace/github.com/mrdulin/python-codelab/src/stackoverflow/63929989/test_index_63929989.py && coverage report -m --include="src/*"
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Name Stmts Miss Cover Missing
---------------------------------------------------------------------------------
src/stackoverflow/63929989/index_63929989.py 4 0 100%
src/stackoverflow/63929989/test_index_63929989.py 11 0 100%
---------------------------------------------------------------------------------
TOTAL 15 0 100%

Related

patching a function if that function is imported using the from statement

I have a case similar to the following code where I am trying to patch a fucntion that is imported using the from statement:
from module1 import function1
def function2():
function1_result = function1()
return 2*function1_result
and then the testing code is:
from unittest import patch
def test_function2():
func1_value = 5
with patch("module1.function1", return_value=func1_value) as patched_func1:
function2_value = function2()
assert function2_value==2*func1_value
However the code runs but it doesn't use the patched function 1 and actually calls the function. However, if I change the import statement to just import module1 then the test runs fine.
See Where to patch doc, the examples in the documentation are very clear.
module1.py:
def function1():
return 1
module2.py:
from module1 import function1
def function2():
function1_result = function1()
return 2*function1_result
test_module2.py:
from unittest import TestCase
from unittest.mock import patch
import unittest
from module2 import function2
class TestModule2(TestCase):
def test_function2(self):
func1_value = 5
with patch("module2.function1", return_value=func1_value) as patched_func1:
function2_value = function2()
assert function2_value == 2*func1_value
if __name__ == '__main__':
unittest.main()
Test result:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

Python Unittest Discover return exit code 0 even if fails

I have read several posts saying that if you call your unittests with unittest.main() that they should exit with a failure code if they fail. I call my unittests with the command: python -m unittest discover -v. I am using Python 3.6.6. An example unittest could look like this:
from server import app
import unittest
class ServerTestCase(unittest.TestCase):
"""
Unittesting for the server application.
"""
def setUp(self):
"""
Create a test client
"""
self.app = app.test_client()
self.app.testing = True
def tearDown(self):
pass
def test_root_endpoint(self):
"""
Testing the root endpoint
"""
result = self.app.get('/')
self.assertEqual(result.status_code, 200)
def test_health_endpoint(self):
"""
Testing the health endpoint
"""
result = self.app.get('/health')
assert b'UP' in result.data
if __name__ == '__main__':
unittest.main()
Even if one of my tests fails I get this when checking the exit code:
$ echo $?
0
What am I doing wrong?
Did you name the unittest files something like test_*.py? Because that's what discover is looking for. Otherwise no matter your tests, the result will be:
Ran 0 tests in 0.000s
OK
(BTW you don't have to if __name__ ... unittest.main() when using -m unittest discover)

Python : is coverage using skipped test

Here is a test :
#skip("my test is skipped")
def test_coverage():
my_function()
My question is simple :
If i run my coverage, will my_function will be covered or not (considering my test is skipped) ?
Thanks !
Skipped tests are not executed. Code that is not executed is not covered, by definition.
Demo; given a coverage_demo module:
def foo():
var = "This function has is covered"
def bar():
var = "This function is not"
and a coverage_demo_tests.py file:
from unittest import TestCase, skip
import coverage_demo
class DemoTests(TestCase):
def test_foo(self):
coverage_demo.foo()
#skip("No bar for us today")
def test_bar(self):
import coverage_demo
coverage_demo.bar()
if __name__ == '__main__':
import unittest
unittest.main()
running this under coverage shows that line 5 in coverage_demo is not executed:
$ coverage run coverage_demo_tests.py
s.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK (skipped=1)
$ coverage report --include=coverage_demo\.py -m
Name Stmts Miss Cover Missing
------------------------------------------------
coverage_demo.py 4 1 75% 5
The def statements at the top level are always executed, but line 5 is the only line in the bar() function.

Python mock object instantiation

Using Python 2.7, and mock library
How can I test that certain patched object has been initialized with some specific arguments using mock?
Here some sample code and pseudo-code:
unittest.py :
import mock
#mock.patch('mylib.SomeObject')
def test_mytest(self, mock_someobject):
test1 = mock_someobject.return_value
test1 = method_inside_someobject.side_effect = ['something']
mylib.method_to_test()
# How can I assert that method_to_test instanced SomeObject with certain arguments?
# I further test things with that method_inside_someobject call, no problems there...
mylib.py :
from someobjectmodule import SomeObject
def method_to_test():
obj = SomeObject(arg1=val1, arg2=val2, arg3=val3)
obj.method_inside_someobject()
So, how can I test SomeObject was instanced with arg1=val1, arg2=val2, arg3=val3?
If you replaced a class with a mock, creating an instance is just another call. Assert that the right parameters have been passed to that call, for example, with mock.assert_called_with():
mock_someobject.assert_called_with(arg1=val1, arg2=val2, arg3=val3)
To illustrate, I've updated your MCVE to a working example:
test.py:
import mock
import unittest
import mylib
class TestMyLib(unittest.TestCase):
#mock.patch('mylib.SomeObject')
def test_mytest(self, mock_someobject):
mock_instance = mock_someobject.return_value
mock_instance.method_inside_someobject.side_effect = ['something']
retval = mylib.method_to_test()
mock_someobject.assert_called_with(arg1='foo', arg2='bar', arg3='baz')
self.assertEqual(retval, 'something')
if __name__ == '__main__':
unittest.main()
mylib.py:
from someobjectmodule import SomeObject
def method_to_test():
obj = SomeObject(arg1='foo', arg2='bar', arg3='baz')
return obj.method_inside_someobject()
someobjectmodule.py:
class SomeObject(object):
def method_inside_someobject(self):
return 'The real thing'
and running the test:
$ python test.py
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK

TextTestRunner runs 2 tests (test_methods when one is called) in pyunit

I am just trying to understand the behavior of unittest's subclasses and methods. In the following code, I want to just run test_add method and not test_sub. Can someone please explain to me what I am doing wrong since the output proves that both the methods are being executed:
import unittest
def add(a,b):
x=a+b
return x
def sub(x,y):
z=x-y
return z
class addnum():
def calladd(self, a, b):
sum1 = add(a, b)
return sum1
def callsub(self,x,y):
diff = sub(x , y)
print "subtraction succ"
return diff
class test(addnum, unittest.TestCase):
def setup(self):
pass
def teardown(self):
pass
def test_add(self):
a1=addnum()
if a1.calladd(1, 2) ==3:
print "add successful"
assert addnum().calladd(1,2) == 3
def test_sub(self):
assert addnum().callsub(5, 3) == 2
print "abc"
#suite = unittest.TestSuite()
#suite.addTest(test('test_add'))
runner = unittest.TextTestRunner(verbosity=2)
runner.run(test(methodName='test_add'))
The output is as follows:
Finding files... done.
Importing test modules ... add successful
done.
add successful
subtraction succ
abc
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
test_add (trial2.test) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Please help. I admit my knowledge is pretty limited at this point.
First of all, you should not place those lines at the end of your module alone. Otherwise, every time you import the module, this test will be run. You should wrap them like this:
if __name__ == "__main__":
#suite = unittest.TestSuite()
#suite.addTest(test('test_add'))
runner = unittest.TextTestRunner(verbosity=2)
runner.run(test(methodName='test_add'))
In this way, your code will be run only when the .py module is called alone and not imported. Once like that seems to work just fine and only runs the requested test.
test_add (__main__.test) ... ok
add successful
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Always wrap it like that so it does not matter if you forget to remove your test.

Categories

Resources