I am new to Python and writing a unit test for the already existing code.
I have the following Python code structure:
root_project:
-- src
-- signUp
-- __init__.py
-- abc.py
-- xyz.py
abc.py contains the following code:
from . import xyz
class Abc:
def __init__(self):
pass
def start_process(self):
xyz.start_timer()
I want to mock xyz.start_timer() inside method start_process of class Abc so that start_timer() mock version can be used.
How can I achieve this?
You can simply patch the start_timer function using mock.patch().
abc.py
import xyz
class Abc:
def __init__(self):
pass
def start_process(self):
xyz.start_timer()
test_abc.py
from unittest import mock, TestCase
from abc import Abc
class Test_Abc(TestCase):
#mock.patch("abc.start_timer")
def test_start_process(self, mock_start_timer):
# your test code
Notice that I have patched abc.start_timer and not xyz.start_timer.
You just need to patchxyz.start_timer(), I just added return to start_process to show that the patching really does what it should:
import xyz
import unittest
from unittest import mock
class Abc:
def __init__(self):
pass
def start_process(self):
return xyz.start_timer()
class Test_Abc(unittest.TestCase):
#mock.patch('xyz.start_timer', return_value=True)
def test_start_process(self, start_process):
a = Abc()
self.assertTrue(a.start_process())
if __name__ == '__main__':
unittest.main()
Out:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Related
I want to test that method a calls method b. These methods are in separate files, and are not a part of class object.
# file_a.py
from file_b import b
def a():
b()
# file_b.py
def b():
test
import unittest
from unittest import mock
from file_a import a
class MyTestCase(unittest.TestCase):
#mock.patch('file_b.b')
def test_b_called(self, mock):
a()
mock.assert_called()
if __name__ == "__main__":
unittest.main()
This fails with AssertionError: Expected 'b' to have been called.
Is there a right way to do this?
When you import a function into the current namespace, like in your example, the function will need to be patched in that namespace. In your case, you need:
#mock.patch('file_a.b')
You would patch file_b.b if you had done the import and use like this:
import file_b
def a():
file_b.b()
Example abc.py:
from pack.def import Def
class Abc(object):
def f(self):
return Def().response()
Example test_abc.py
from unittest import mock, TestCase
from pack.abc import Abc
class TestAbc(TestCase):
#mock.patch('pack.def.Def')
def test_f(self, mock_def):
responses = ['response1', 'response2', 'response3']
mock_def.return_value.response.return_value = responses
assert responses == Abc().f()
I assumed the mock def has been patched, but I'm doing something wrong, does someone know I'm doing wrong?
You must mock the object your are working. You are using the Def that belongs to pack.def package in abc module. When you write test for Abc class, and want to mock Def calls, you must mock the Def that is imported in abc, not from original module.
Use #mock.patch('pack.abc.Def') instead of #mock.patch('pack.def.Def').
I am trying unit test in Python.
test.py
from unittest import TestCase,main
from unittest.mock import patch
import file
def mock_return(*args):
return -1
class Tests(TestCase):
#patch("file.Foo.a", side_effect=mock_return)
def test_1(self, mock_fun):
self.assertEqual(file.Foo().a(), -1)
#patch("os.urandom", side_effect=mock_return)
def test_2(self, mock_fun):
self.assertEqual(file.Foo().b(), -1)
if __name__ == "__main__":
main()
file.py
from os import urandom
class Foo:
def a(self):
return 1
def b(self):
return urandom(1)
Why test_1 passed but test_2 failed? Is there a way to mock a method used by other class?
You must patch the binding used by the function being tested.
from os import urandom # in file.py
binds name urandom to the function os.urandom in the file module. Foo.b accesses the function via the file.urandom binding. So the test for Foo.b must patch file.urandom, not os.urandom.
I can't seem to get the Test1.test_something() in test2 to work.. not sure if it's because they are both inheriting from the same base?
Helper.py:
class baseTest(unittest.TestCase):
def setUp(self, param="Something"):
print param
pass
Test1.py
from Helper import baseTest
class test1(baseTest):
def setUp(self):
super(test1, self).setUp('foo')
def test_something(self):
assert 1 == 1, "One does not equal one."
Test2.py
from Helper import baseTest
import Test1
class test2(baseTest):
def setUp(self):
super(test2, self).setUp('bar')
def test_something(self):
Test1.test_somehing()
Now, I had this working previously, when I had the setUp for test1 and test2 within their classes, but once I had them both inherit from baseTest, I started getting a unbound method <method> must be called with Test instance as first argument (got nothing instead). Any suggestions?
The problem is that Test1.test_something() is an instance method, not a class method. So you can't just call it like that (besides, even if it is class method, it should have been Test1.test1.test_something).
One way to do it (without messing around with the unittest.TestCase mechanism):
Test2.py
import Test1
class test2(Test1.test1):
# whatever else
And you're done, test2 inherits Test1.test1.test_something() automatically. If you need your test2's test_something to do extra stuff, just do super(test2, self).test_something() within your overridden definition of test_something in test2 class.
Move the tests that are shared by both Test1 and Test2 classes into BaseTest:
test.py:
import unittest
import sys
class BaseTest(unittest.TestCase):
def setUp(self, param="Something"):
print param
pass
def test_something(self):
assert 1 == 1, "One does not equal one."
class Test1(BaseTest):
def setUp(self):
super(Test1, self).setUp('foo')
test2.py:
import test
import unittest
import sys
class Test2(test.BaseTest):
def setUp(self):
super(Test2, self).setUp('bar')
I have a bunch of tests written using pytest. There are all under a directory dir. For example:
dir/test_base.py
dir/test_something.py
dir/test_something2.py
...
The simplified version of code in them is as follows:
test_base.py
import pytest
class TestBase:
def setup_module(module):
assert False
def teardown_module(module):
assert False
test_something.py
import pytest
from test_base import TestBase
class TestSomething(TestBase):
def test_dummy():
pass
test_something2.py
import pytest
from test_base import TestBase
class TestSomethingElse(TestBase):
def test_dummy2():
pass
All my test_something*.py files extend the base class in test_base.py. Now I wrote setup_module(module) and teardown_module(module) methods in test_base.py. I was expecting the setup_module to be called once for all tests, and teardown_module() to be called at the end, once all tests are finished.
But the functions don’t seem to be getting called? Do I need some decorators for this to work?
The OP's requirement was for setup and teardown each to execute only once, not one time per module. This can be accomplished with a combination of a conftest.py file, #pytest.fixture(scope="session") and passing the fixture name to each test function.
These are described in the Pytest fixtures documentation
Here's an example:
conftest.py
import pytest
#pytest.fixture(scope="session")
def my_setup(request):
print '\nDoing setup'
def fin():
print ("\nDoing teardown")
request.addfinalizer(fin)
test_something.py
def test_dummy(my_setup):
print '\ntest_dummy'
test_something2.py
def test_dummy2(my_setup):
print '\ntest_dummy2'
def test_dummy3(my_setup):
print '\ntest_dummy3'
The output when you run py.test -s:
collected 3 items
test_something.py
Doing setup
test_dummy
.
test_something2.py
test_dummy2
.
test_dummy3
.
Doing teardown
The name conftest.py matters: you can't give this file a different name and expect Pytest to find it as a source of fixtures.
Setting scope="session" is important. Otherwise setup and teardown will be repeated for each test module.
If you'd prefer not to pass the fixture name my_setup as an argument to each test function, you can place test functions inside a class and apply the pytest.mark.usefixtures decorator to the class.
Put setup_module and teardown_module outside of a class on module level. Then add your class with your tests.
def setup_module(module):
"""..."""
def teardown_module(module):
"""..."""
class TestSomething:
def test_dummy(self):
"""do some tests"""
For more info refer to this article.
setup_module/teardown_module are called for the module where the eventual (derived) tests are defined. This also allows to customize the setup. If you only ever have one setup_module you can put it to test_base.py and import it from the other places. HTH.
First of all it is a good practice to put all tests in a module called "tests":
<product>
...
tests/
__init__.py
test_something.py
Secondly I think you should use setup_class/teardown_class methods in your base class:
import unittest
class MyBase(unittest.TestCase):
#classmethod
def setup_class(cls):
...
#classmethod
def teardown_class(cls):
...
More info: http://pytest.org/latest/xunit_setup.html