I have a module myTest.py in which I am going to overload the unittest.TestCase class. So in a testfile, tests are created like follows:
import myTest
class MyTest(myTest.MyTestCase):
...do something...
This works fine, but when I need other functionality from unittest, like unittest.skip, I also need to invoke unittest as well. I want to be able to invoke just myTest.skip, which should be a reference to unittest.skip. How can I achieve this behavior for every unittest attribute (except the inheritance from unittest.TestCase)? Is there another way instead doing from unittest import * in myTest.py?
In myTest.py:
from unittest import skip
Then you can do:
import myTest
#myTest.skip(...)
class OtherTest(myTest.MyTestCase):
...
Related
I need to write test cases for the module
to_be_tested.py
from module_x import X
_x = X() # creating X instance in test environment will raise error
#.....
In the test case,
from unittest import TestCase, mock
class Test1(TestCase):
#mock.patch('...to_be_tested._x')
#mock.patch('...to_be_tested.X.func1')
def test_1(self, mock_func1, mock_x):
...
However, this will not prevent the import from creating the instance. Is it a way to workaround it and write the test cases for the module? Or is it a way to refactory to_be_tested to be testable?
Maybe write in to_be_tested.py, just _x = None if detected test environment?
The instantiation of X at the global level seems problematic, but I don't have the full picture so I can't definitively say "don't do that". If you can refactor it so that the X() instance is created as needed or something along those lines, that would be ideal.
That said, here's a way to prevent module_x from being imported during the test. I'm basing that on the assumption that X() is used throughout the module_x module, so there's really no need for anything in that module and you only want to mock it.
import sys
import unittest
from unittest import TestCase, mock
class Test1(TestCase):
#classmethod
def setUpClass(cls):
sys.modules['module_x'] = mock.Mock()
#mock.patch('to_be_tested._x')
#mock.patch('to_be_tested.X.func1')
def test_1(self, mock_func1, mock_x):
from to_be_tested import _x
print(_x)
You can see that _x is a mock now, but note that you can't have the import outside of your tests (like at the top of the test module, like most imports usually are) because sys.modules['module_x'] hasn't been subbed out yet.
One possibility is to guard the creation of _x with an environment variable so that you can disable its initialization in test mode. For example,
import os
from module import X
_x = None
if 'TEST' not in os.environ:
_x = X()
Now, you just need to ensure that TEST is set in your environment before importing to_be_tested. This is proabably something you would do in with your test runner, but it's also possible to do directly in your test module.
from unittest import TestCase, mock
import os
os.environ['TEST'] = ''
import to_be_tested
class Test1(TestCase):
...
Let's say I have a fixture to mock a class using monkeypatch.
# conftest.py
#pytest.fixture
def mock_dummyclass(monkeypatch):
def mock_function():
return None
monkeypatch.setattr(dummypackage, "dummyclass", mock_function)
Now, I have to use this fixture in my test so that this class is mocked.
#test_dummy.py
#pytest.mark.usefixtures("mock_dummyclass")
class TestManyDummyMethods:
def test_dummy_one():
import dummypackage # Flag A
def test_dummy_two():
import dummypackage # Flag B
...
def test_dummy_n():
import dummypackage # Flag N
As you can see in the flagged lines, that I'll have to import this module dummypackage inside every function to ensure that the fixture is applied before the module is imported (otherwise the fixture would not be effective).
Importing dummypackage inside the class would work but calling self.dummypackage inside functions doesn't seem very elegant either.
Is there a more elegant way to achieve this?
Comment: The monkeypatch library doesn't seem to be maintained anymore. unittest.mock should probably offer all you need.
I would try to avoid a solution that depends on importing the module as part of your test because that would break if it was imported for another reason (e.g. import other functions).
I am using os as an example as that exists and makes it reproducible.
How best to patch seem to depend on how you import from another module.
Example 1: target_module1.py (importing the join method from os.path):
from os.path import join
def some_method_using_join():
return join('parent', 'child')
This requires us to patch the join method of target_module1.py:
target_module1_test.py:
from unittest.mock import patch, MagicMock
import pytest
from target_module1 import some_method_using_join
#patch('target_module1.join')
def some_test(join_mock: MagicMock):
some_method_using_join()
Example 2: target_module2.py (importing the os module):
import os
def some_method_using_join():
return os.path.join('parent', 'child')
This allows us to patch the join method on os.path:
target_module2_test.py:
from unittest.mock import patch, MagicMock
import pytest
from target_module2 import some_method_using_join
#patch('os.path.join')
def some_test(join_mock: MagicMock):
some_method_using_join()
This assumes that you don't need to patch a class or method that is used at the module level (i.e. while importing).
I want to store static information in a class, shared by all the instances. The information is something obtained by using another module, I only want to do this once, eg. let's say that this is what I have in mymodule.py:
import os
MyClass:
bus = os.environ.get('DBUS_SESSION_BUS_ADDRESS', None)
def __init__(self):
pass
How can I test this code and mock os.environ.get to make sure that the call is made correctly?
Since the execution happens at the time of the first import, I would need to reload the module in the test, but even so, I can't have os.environ.get mocked at the right time:
import unittest
from unittest import patch, MagicMock
import importlib
import mymodule
class TestMyClass(unittest.TestCase):
#patch('mymodule.os.environ', spec=['get'])
def test_class_init_patch(self, mock_env):
# Too early - the reload overrides the mock
importlib.reload(mymodule)
mock_env.get.assert_called_once_with('DBUS_SESSION_BUS_ADDRESS', None)
def test_class_init_mock(self):
importlib.reload(mymodule)
# Too late - the class body already executed
mymodule.MyClass.os.environ = MagickMock()
I have managed to come up with two alternatives, that make this testable:
Move the class initialization code into a class method and call it from the class body. I can test this class method in my unit test.
Move the class initialization into the __init__ method, guarded by a flag stored in a class variable so that it is only initialized once on the first instantiation.
While both of these should work just fine, it just feels more clean and straightforward to leave this in the class body if possible.
I have managed to figure out how to do this the right way (I hope)!
If you have imported only the module and not the class, function into your code's namespace, eg.:
like this: import os
and not like this: from os import geteuid
You can do this in your test to patch the os module directly:
import os
import unittest
from unittest import patch
import importlib
import mymodule
class TestMyClass(unittest.TestCase):
#patch('os.environ.get')
def test_class_init_patch(self, mock_env_get):
importlib.reload(mymodule)
mock_env_get.assert_called_once_with('DBUS_SESSION_BUS_ADDRESS', None)
This is described in the official documentation as well:
However, consider the alternative scenario where instead of from a import SomeClass module b does import a and some_function uses a.SomeClass. Both of these import forms are common. In this case the class we want to patch is being looked up in the module and so we have to patch a.SomeClass instead:
More details in the official documentation.
This way the module is being patched directly and reloading your own module doesn't affect the patching.
Once the test has run, the patching of the module is undone as usual, however, keep in mind, that the state of your class remains the same way as it was initialized while the external module was patched, so you might need to reload the module again before you run your other tests.
The easiest way to make sure, that you reclaim your "normal" class state, is to reload the module in your TestCase object's setUp method, eg.:
def setUp(self):
importlib.reload(mymodule)
I have used python unittest quite a bit and there is a decorator method you can use to conditionally skip tests like this:
import unittest
class TestStringMethods(unittest.TestCase):
#unittest.skipIf(1 == 1, 'Skipped because 1 does indeed equal 1')
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
I wanted to add some features to the unittest.TestCase class though, so I subclassed it to start adding my own custom code:
import unittest
class CustomTestCase(unittest.TestCase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # Just use whatever is in TestCase's init + our stuff
self.foo = 'foo' # our stuff
self.bar = 'bar'
def mymethod(self, param1, param2): # Some custom method I wanted to make for these custom test cases
pass
To continue using #unittest.skipIf I have been sticking import unittest at the top of any of my CustomTestCase test files, but I wonder if thats the correct way to be doing things. Am I importing more than I need? Or am I worried about nothing?
The fact that you've subclassed has little to do with what you're asking. In general, it's fine for subclasses to import or use their superclass: in fact, they must import their superclass when they're defined. It's the other way around that's the problem (superclass shouldn't know about its subclasses).
To continue using #unittest.skipIf I have been sticking import
unittest at the top of any of my CustomTestCase test files, but I
wonder if thats the correct way to be doing things. Am I importing
more than I need?
If you want to use any attribute off of the unittest module (including the skipIf decorator), then you have to import it into the module in question. It's no more complex than that.
If you're worried about something like header guards, like you need for C/C++ development, don't be. It doesn't work like the #include preprocessor directive (i.e. it's not actually including the source of the unittest module in your file).
If you're worried about importing unittest too many times, don't be. It's extremely common to import a module like unittest into many different modules of a given project.
Or am I worried about nothing?
Yes. Just import unittest whenever you need it and rid yourself of worry!
HTH.
I have a class called Test as follows
ViewTests.py
import unittest
class Tests(unittest.TestCase):
def testAddition(self):
self.assertTrue(True)
def testAddition2(self):
self.assertTrue(True)
The unit test runs all fine. The issue is when I import this class for other implementations somewhere else like this, from package import Tests on import the test cases get invoked automatically.
Is there a way to avoid this.
I would like to import as this:
TestRunner.py
from ViewTests import Tests
def some_method():
print "Testing"
In this case, When you execute this as nosetests TestRunner.py It will result as Ran 2 tests in 0.000s. Which means only by importing ViewTests it gets implemented.