Python unit tests run function after all test - python

I need to test smth on python via ssh. I don't want to make ssh connection for every test, because it is to long, I have written this:
class TestCase(unittest.TestCase):
client = None
def setUp(self):
if not hasattr(self.__class__, 'client') or self.__class__.client is None:
self.__class__.client = paramiko.SSHClient()
self.__class__.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.__class__.client.connect(hostname=consts.get_host(), port=consts.get_port(), username=consts.get_user(),
password=consts.get_password())
def test_a(self):
pass
def test_b(self):
pass
def test_c(self):
pass
def disconnect(self):
self.__class__.client.close()
and my runner
if __name__ == '__main__':
suite = unittest.TestSuite((
unittest.makeSuite(TestCase),
))
result = unittest.TextTestRunner().run(suite)
TestCase.disconnect()
sys.exit(not result.wasSuccessful())
In this version I get error TypeError: unbound method disconnect() must be called with TestCase instance as first argument (got nothing instead). So how i can call disconnect after all tests pass?
With best regards.

You should use setUpClass and tearDownClass instead, if you want to keep the same connection for all tests. You'll also need to make the disconnect method static, so it belongs to the class and not an instance of the class.
class TestCase(unittest.TestCase):
def setUpClass(cls):
cls.connection = <your connection setup>
#staticmethod
def disconnect():
... disconnect TestCase.connection
def tearDownClass(cls):
cls.disconnect()

you can do it by defining startTestRun,stopTestRun of unittest.TestResult class. setUpClass and tearDownClass are running per test class(per test file) so if you have multiple files this methods will run for each one.
by adding following code to my tests/__init__.py i managed to achieve it. this code runs only once for all tests(regardless of number of test classes and test files).
def startTestRun(self):
"""
https://docs.python.org/3/library/unittest.html#unittest.TestResult.startTestRun
Called once before any tests are executed.
:return:
"""
DockerCompose().start()
setattr(unittest.TestResult, 'startTestRun', startTestRun)
def stopTestRun(self):
"""
https://docs.python.org/3/library/unittest.html#unittest.TestResult.stopTestRun
Called once after all tests are executed.
:return:
"""
DockerCompose().compose.stop()
setattr(unittest.TestResult, 'stopTestRun', stopTestRun)

There seems to be a simple solution for the basic (beginner's) case:
def tmain():
setup()
unittest.main(verbosity=1, exit=False)
clean()
The trick is "exit=False" which lets the function tmain run until the end.
setup() and clean() can be any functions to do what the name implies.

Related

Mock an external service instantiated in python constructor

I'm working on unit tests for a service I made that uses confluent-kafka. The goal is to test successful function calls, exception errors, etc. The problem I'm running into is since I'm instantiating the client in the constructor of my service the tests are failing since I'm unsure how to patch a constructor. My question is how do I mock my service in order to properly test its functionality.
Example_Service.py:
from confluent_kafka.schema_registry import SchemaRegistryClient
class ExampleService:
def __init__(self, config):
self.service = SchemaRegistryClient(config)
def get_schema(self):
return self.service.get_schema()
Example_Service_tests.py
from unittest import mock
#mock.patch.object(SchemaRegistryClient, "get_schema")
def test_get_schema_success(mock_client):
schema_Id = ExampleService.get_schema()
mock_service.assert_called()
The problem is that you aren't creating an instance of ExampleService; __init__ never gets called.
You can avoid patching anything by allowing your class to accept a client maker as an argument (which can default to SchemaRegistryClient:
class ExampleService:
def __init__(self, config, *, client_factory=SchemaRegistryClient):
self.service = client_factory(config)
...
Then in your test, you can simply pass an appropriate stub as an argument:
def test_get_schema_success():
mock_client = Mock()
schema_Id = ExampleService(some_config, client_factory=mock_client)
mock_client.assert_called()
Two ways
mock entire class using #mock.patch(SchemaRegistryClient) OR
replace #mock.patch.object(SchemaRegistryClient, "get_schema") with
#mock.patch.object(SchemaRegistryClient, "__init__")
#mock.patch.object(SchemaRegistryClient, "get_schema")

Python unittest module invoking wrong class?

I am working on a Django project and some unittests seemed to be failing seemingly unexpectedly. I was able to track down the failures to how it seems the VSCode/unittest testing framework is calling the test cases. I was able to reproduce the behavior with the simple setup below.
import unittest
class USER_STORY_1_8_1(unittest.TestCase):
def setUp(self):
print('USER_STORY_1_8_1:setUp')
def tearDown(self):
print('USER_STORY_1_8_1:tearDown')
def test_run(self):
print('USER_STORY_1_8_1:test_run')
class USER_STORY_1_8_10(unittest.TestCase):
def setUp(self):
print('USER_STORY_1_8_10:setUp')
def tearDown(self):
print('USER_STORY_1_8_10:tearDown')
def test_run(self):
print('USER_STORY_1_8_10:test_run')
class USER_STORY_1_8_11(unittest.TestCase):
def setUp(self):
print('USER_STORY_1_8_11:setUp')
def tearDown(self):
print('USER_STORY_1_8_11:tearDown')
def test_run(self):
print('USER_STORY_1_8_11:test_run')
Screen Capture of VSCode project Here
It seems that for similarly named test cases like these:
class USER_STORY_1_8_1(unittest.TestCase)
class USER_STORY_1_8_10(unittest.TestCase)
class USER_STORY_1_8_11(unittest.TestCase)
instead of calling each one in an exact-match type of way, it's doing some kind of 'USER_STORY_1_8_1.*' ordered resolution so that a call to USER_STORY_1_8_1 actually calls into the setUp() for USER_STORY_1_8_11. If USER_STORY_1_8_11 is unavailable (e.g. commented out), then i resolves to USER_STORY_1_8_10. And if neither is available, only then it calls the correct USER_STORY_1_8_1.
Is there anyway to override this behavior?

pytest fixture in setup_method

I have a function scoped fixture.
import pytest
#pytest.fixture(scope="function")
def some_fixture(req):
print "This is not the end"
return "okay"
Is it possible to invoke the fixture in the setup_method somehow.?
Something like the following snippet...
class TestOne(object):
def setup_method(self, method, some_fixture): # this would give argument error
print "okay"
def test_one(self):
pass
I know fixture would work same as setup_method, but I have got a very corner case scenario and I want the fixture to be executed in setup_method itself.
You can mark your setup_method as fixture & then call it in your tests.
class TestOne(object):
#pytest.fixture(scope="class")
def setup_method(self, method, some_fixture): # this would give argument error
print "okay"
def test_one(self, setup_method):
pass

Is there a way to run "setup" only once for the entire suite of Python tests? [duplicate]

Is there a function that is fired at the beginning/end of a scenario of tests? The functions setUp and tearDown are fired before/after every single test.
I typically would like to have this:
class TestSequenceFunctions(unittest.TestCase):
def setUpScenario(self):
start() #launched at the beginning, once
def test_choice(self):
element = random.choice(self.seq)
self.assertTrue(element in self.seq)
def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
def tearDownScenario(self):
end() #launched at the end, once
For now, these setUp and tearDown are unit tests and spread in all my scenarios (containing many tests), one is the first test, the other is the last test.
As of 2.7 (per the documentation) you get setUpClass and tearDownClass which execute before and after the tests in a given class are run, respectively. Alternatively, if you have a group of them in one file, you can use setUpModule and tearDownModule (documentation).
Otherwise your best bet is probably going to be to create your own derived TestSuite and override run(). All other calls would be handled by the parent, and run would call your setup and teardown code around a call up to the parent's run method.
I have the same scenario, for me setUpClass and tearDownClass methods works perfectly
import unittest
class Test(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls._connection = createExpensiveConnectionObject()
#classmethod
def tearDownClass(cls):
cls._connection.destroy()
Here is an example: 3 test methods access a shared resource, which is created once, not per test.
import unittest
import random
class TestSimulateLogistics(unittest.TestCase):
shared_resource = None
#classmethod
def setUpClass(cls):
cls.shared_resource = random.randint(1, 100)
#classmethod
def tearDownClass(cls):
cls.shared_resource = None
def test_1(self):
print('test 1:', self.shared_resource)
def test_2(self):
print('test 2:', self.shared_resource)
def test_3(self):
print('test 3:', self.shared_resource)
For python 2.5, and when working with pydev, it's a bit hard. It appears that pydev doesn't use the test suite, but finds all individual test cases and runs them all separately.
My solution for this was using a class variable like this:
class TestCase(unittest.TestCase):
runCount = 0
def setUpClass(self):
pass # overridden in actual testcases
def run(self, result=None):
if type(self).runCount == 0:
self.setUpClass()
super(TestCase, self).run(result)
type(self).runCount += 1
With this trick, when you inherit from this TestCase (instead of from the original unittest.TestCase), you'll also inherit the runCount of 0. Then in the run method, the runCount of the child testcase is checked and incremented. This leaves the runCount variable for this class at 0.
This means the setUpClass will only be ran once per class and not once per instance.
I don't have a tearDownClass method yet, but I guess something could be made with using that counter.
import unittest
class Test(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.shared_data = "dddd"
#classmethod
def tearDownClass(cls):
cls.shared_data.destroy()
def test_one(self):
print("Test one")
def test_two(self):
print("Test 2")
For more visit Python
unit test document

How to mock up a class for several tests in Django

I have a class that calls a remote service through HTTP. Right now, this class detects if it is running in "TESTING" mode and acts accordingly: while "TESTING" it does not send the actual request to the remote service, it simply returns without executing anything at all.
class PushService(object):
def trigger_event(self, channel_name, event_name, data):
if satnet_cfg.TESTING:
logger.warning('[push] Service is in testing mode')
return
self._service.trigger(channel_name, event_name, data)
Several tests invoke parts of the code that end up by invoking this method. My questions are the following:
1. Do I have to patch this method/class for every test that, for some reason, also invoke that method?
2. Is it a good practice to try to patch it in the TestRunner?
If you need to do patch for all the tests you can do this in setUpClass method:
class RemoteServiceTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.patchers = []
patcher = patch('application.PushService.trigger_event')
cls.patchers.append(patcher)
trigger_mock = patcher.start()
trigger_mock.return_value = 'Some return value'
#classmethod
def tearDownClass(cls):
for patcher in cls.patchers:
patcher.stop()
def test1(self):
# Test actions
def test2(self):
# Test actions
def test3(self):
# Test actions
setUpClass is called once per class (test suite in this case). Inside this method you can set all patchers that you need to be used by all tests.

Categories