Unit tests (python)
Introduction
Framework 'unittest' is part of Python standard library since Python 2.1.
The another framework Python has is 'PyTest'.
TOX is a tool for running tests, used by sixqueue/jsonapi
TOC (Fixtures and Mocking in Python), used by sixqueue/jsonapi
https://code-maven.com/slides/python-mocking/toc
Reference
A Beginner’s Guide to Unit Tests in Python (2023)
Note: Where it says 'should contain an init.py file' it works fine with a empty __init__.py one (eg: cou sixqueue)
https://www.dataquest.io/blog/unit-tests-python/
Python Mock Cookbook
https://chase-seibert.github.io/blog/2015/06/25/python-mocking-cookbook.html
Samples
Big Upfront Caveat (from the Python Mock Cookbook):
"The biggest mistake people make is mocking something out in the wrong place. You always need to mock the thing where it’s imported TO, not where it’s imported FROM. Translation: if you’re importing from foo import bar into a package bat.baz, you need to mock it as @mock.patch('bat.baz.bar'). This can be confusing if you think you should be mocking it where it’s defined, not where it’s used."
Mock a function
Eg: cou sixqueue
The mocked function:
def mocked_get_ssm_salesforce(*args, **kwargs):
"""SalesforceClient.get_ssm_salesforce(name: str)
"""
pName = args[0]
env = config_mock['env']
ci = config_mock['ci']
print('DEBUG mocked_get_ssm_salesforce:', pName, env, ci)
if pName == "/{env}/{ci}/salesforce_url_login".format(env=env, ci=ci):
return config_mock['SALESFORCE_URL_LOGIN']
elif pName == "/{env}/{ci}/salesforce_client_id".format(env=env, ci=ci):
return config_mock['SALESFORCE_CLIENT_ID']
elif pName == "/{env}/{ci}/salesforce_client_secret".format(env=env, ci=ci):
return config_mock['SALESFORCE_CLIENT_SECRET']
elif pName == "/{env}/{ci}/salesforce_username".format(env=env, ci=ci):
return config_mock['SALESFORCE_USERNAME']
elif pName == "/{env}/{ci}/salesforce_password".format(env=env, ci=ci):
return config_mock['SALESFORCE_PASSWORD']
elif pName == "/{env}/{ci}/salesforce_token".format(env=env, ci=ci):
return config_mock['SALESFORCE_TOKEN']
else:
return config_mock[pName] #doesn't make much sense but it should never be executed
and where it is used:
class MockTestCase(unittest.TestCase):
sol_info = json.load(open(os.path.join(here, 'test_tutoritzacio_matricula.json')))
def setUp(self):
os.environ['env'] = config_mock['env']
os.environ['ci'] = config_mock['ci']
@mock.patch('src.jsonapi.cuacrm.dispatcher_crm.SalesforceClient.get_ssm_salesforce', side_effect=mocked_get_ssm_salesforce)
@mock.patch('src.jsonapi.cuacrm.common.salesforce.requests.post', side_effect=mocked_requests_post_great)
def test_entry_great(self, mock_post, mock_get_ssm_salesforce):
mgc = MockClass()
result, text = mgc.execute(self.sol_info, logger)
logger.info('RESULT: ' + str(result))
logger.info('MESSAGE: ' + str(text))
self.assertEqual(result, status['PROCESSED'])
self.assertTrue(text['crm_result'])
crm_result = text['crm_result']
self.assertEqual(crm_result['codeResult'], 'OK')
self.assertTrue(crm_result['msgResult'])
self.assertTrue(crm_result['idTransaction'])
self.assertTrue(crm_result['personCode'])
self.assertTrue(crm_result['opportunityCode'])