Unit integration and functional testing of Python application

mahesh reddy
6 min readApr 15, 2021

The act of evaluating a “unit” in your Python application is known as unit testing. A “unit” in this sense is usually a class instance’s function or process. A “unit under inspection” is another term for the unit.

A single unit test aims to test only one variation of the “unit under test.” You just need to validate the code that exists in the function body itself if you write a unit test that aims to verify the outcome of a specific code path via a Python function. If the function accepts a parameter that describes a complex Python application’s “domain object,” the argument passed to it during a unit test does not have to be a “true” object.

SMTP server

Since a function may accept an argument representing an SMTP server object, and the function may call a method of this object while the device is running normally, resulting in an email being sent, a unit test of this code path of the function does not need to test that an email is sent. It just needs to make sure that the function calls the method of the object passed in as an argument that would submit an email if the argument was the “true” SMTP server object.

If You are interested to Learn Python you can enroll for free live demo Python Online Training

Integration test

An integration test, on the other hand, is a form of testing that specifically tests the relationship between two or more “units.” Integration checks ensure that the Python application’s components work together. In an integration test, you might verify that an email was sent.

Functional test

A functional test is a form of an integration test that runs the Python application “literally.” Since a functional test checks the code from beginning to end, you’d have to make sure that an email was sent.

Writing each type of test for any given codebase is also called best practice. Unit testing also allows for greater “coverage”: it’s normally possible to provide arguments and/or an environment to a unit under test that causes all of its potential code paths to be implemented. This is normally more difficult to do with a series of integration or functional checks. But they do provide some assurance that your “modules” work together as intended when your Python application is run in production.

Unit test

The Python unit test module is recommended for unit and integration testing of Python applications. Even though this module is called a unit test, it is capable of running both unit and integration tests.

Python has a range of features that make writing units, integration, and functional tests much simpler. When your code calls Python-related framework functions, the facilities are particularly useful.

Test Setup and Dismantle

Python stores the current request and the current program registry in an “external” (actually thread-local) data structure. The Python.thread-local.get current request() and Python.thread-local.get current registry() functions provide access to these data structures. For more detail on these functions and the data structures they return, see Thread Locals.

Python testing

You must call Python. testing if your code uses these get current_* functions or calls Python code that uses get current_* functions. You’ll need to call Python. testing after calling setup() in your test setup. tearDown() in your teardown exam setUp() creates a registry on the thread-local stack, allowing the get current_* functions to run. It returns a Configurator object, which can be used to perform any additional configuration that the code under test requires. The thread-local stack is popped with tearDown().

Python configuration

When a Configurator is used directly with the main block of a Python program, it usually waits until it. Commit method (often indirectly called by the Python.config.Configurator.make WSGI app() method) is called before doing some “true work.” However, the Configurator returned by setUp() is an auto-committing Configurator, which means it immediately performs all behavior indicated by methods called on it. This is more convenient for unit testing than calling Python. config.Configurator.commit() after inserting additional configuration statements in each test.

Functions

The setUp() and tearDown() functions allow you to have an independent registry and isolated request for each unit test method in a test case for the duration of a single test. Here’s an example of how to make use of this function.

import unittest

from pyramid import testing

class MyTest(unittest.TestCase):

def setUp(self):

self.config = testing.setUp()

def tearDown(self):

testing.tearDown()

def test_view_fn_forbidden(self):

from pyramid.httpexceptions import HTTPForbidden

from my.package import view_fn

self.config.testing_securitypolicy(userid=’hank’,

permissive=False) request = testing.DummyRequest()

request.context = testing.DummyResource()

self.assertRaises(HTTPForbidden, view_fn, request)

def test_view_fn_allowed(self):

from my.package import view_fn

self.config.testing_securitypolicy(userid=’hank’,

permissive=True)

request = testing.DummyRequest()

request.context = testing.DummyResource()

response = view_fn(request)

self.assertEqual(response, {‘greeting’:’hello’})

The above code ensures that when get current registry() is called inside a MyTest test case process, the Python application registry associated with the config Configurator instance is returned. An isolated registry will be used by each test case method attached to MyTest.

The setUp() and tearDown() functions consider several arguments that affect the test environment. The extra arguments provided by these functions can be found in Python. testing API.

Setting up the test

You can transfer a request object to Python.testing.setUp() inside your test’s setUp method if you want to get a current request() to return anything other than None during a single test.

If you pass a request object to Python.testing.setUp() in your test case’s setUp, the request object will be passed to any test method attached to the MyTest test case. Then it calls to get the current request() directly or indirectly. Otherwise, get current request() would return None during testing. We use Python.testing.” dummy” DummyRequest’s request implementation because it’s easier to build than a “true” Python request object.

Using a context manager, test the configuration.

Using the with statement and Python.testing.test config() to build a context manager is another way to set up a test configuration. Python.testing.setUp() will be called before the code under test, and Python.testing.tearDown() will be called afterward by the context manager.

This format is appropriate for small, self-contained experiments.

Consider the following scenario.

Thread data structures

Thread local data structures can be perplexing, especially when they’re used by frameworks. Sorry for the inconvenience. So, if you’re not sure whether you’re calling code that uses the get current registry() or get current request() functions, or if you don’t care, but you do want to write test code, call Python.testing.setUp() in your setUp method and Python.testing.tearDown() in your tearDown method. If the program you’re checking doesn’t use any get current* functions, this won’t be a problem.

Unit Checking with the Configurator and Python.testing APIs

A variety of functions are available in the Configurator API and Python application. a testing module that you can use during unit testing. These functions call the current Python application registry for configuration declarations, but they usually register a “stub” or “dummy” feature in place of the “actual” feature that the code would call if it were running normally.

Consider the case where you want to unit test a Python view function.

View function

The call to has permission() in this view function will always return a True value without doing anything special during a unit test. When a Python application program begins normally, it uses configuration declaration calls against a Configurator to populate a Python application registry. Python API functions can either fail or return default results if you can generate this Python application registry. Then you can populate (e.g., by initializing the configurator with an authorization policy). Such as when you invoke Python application code through a unit test. So, how do you evaluate the HTTP Forbidden-raising branch of code in this view function?

Conclusion

Python’s testing API lets you simulate different ‘Python application registry’ registrations for use in unit testing frameworks without having to invoke the actual Python application configuration suggested by the key feature. You might, for example, write a unit test to evaluate the above view fn (assuming it was in the package called my. package). You can use the research API in this test case. You can learn in detail about testing through Python training.

--

--

mahesh reddy

Python certification training course will help you master the concepts and gain in-depth experience on writing Python code and packages like SciPy, Matplotlib,