Unit Testing in Python

Learn via video course
FREE
View all courses
Python Course for Beginners With Certification: Mastering the Essentials
Python Course for Beginners With Certification: Mastering the Essentials
by Rahul Janghu
1000
4.90
Start Learning
Python Course for Beginners With Certification: Mastering the Essentials
Python Course for Beginners With Certification: Mastering the Essentials
by Rahul Janghu
1000
4.90
Start Learning
Topics Covered

Overview

There are many aspects to testing in Python, and it can be quite complex, but it does not have to be complex. In a few easy steps, you can create simple tests for your application and then build upon them. In unit testing, a specific module is tested by the developer himself in order to determine whether there are any errors in it. Unit testing consists of analyzing, detecting, and fixing errors in individual units of a system.

What is Unit Testing in Python?

Individual units of source code are put through numerous tests as part of the software testing technique known as unit testing to see if they are ready for usage (Source). It establishes and evaluates the level of your code.

The criteria or findings that are known to be possibly practical and valuable are often coded into the test script once development is complete to ensure that a specific unit is accurate. Various frameworks record tests that fail any criterion when test cases are being executed and report those tests in a summary.

Let's understand the following example.

We test against the known output using Python's built-in sum() function for unit testing. We verify that (1, 2, 3) added together equals 6.

Because the numbers are accurate, the line above will provide the desired outcome. It will return an Assertion error if we give the incorrect parameters.

For example:

The code mentioned above can be added to the file and run once more from the command line.

Output:

Testing the Code

Manual Testing vs Automate

Exploratory testing is a different type of manual testing. It is a test that is conducted randomly. A list of the applications to be manually tested must be prepared. We then enter various inputs and wait for the desired results.

Every time we provide inputs or modify the code, we must walk through the list and double-check each and every feature.

It is the most common testing technique, although it takes a long time to complete.

In fact, automated testing executes the code in accordance with our code plan, which means a script, as opposed to a human, runs the part of the code we want to test in the sequence we want to test it.

In automated testing, a script is used in place of a human to carry out your test plan (the components of your application you want to test, the sequence in which you want to test them, and the expected results). Python currently has a number of tools and modules to help you in building automated testing for your application.

Integrate Tests vs Unit Test

Let's say we want to check the car's lights and how we may do so. We would either switch on the light and exit the car, or we would ask a buddy whether the lights were on. In such a case, turning on the light would be the test action, and walking outside or calling a buddy would be the test assertion. We can test numerous components simultaneously during integration testing.

Anything in our code, including functions, classes, and modules that we have created, can be one of these components.

Integration testing can have a drawback, though. What if the outcome of an integration test is unexpected? It will be difficult to determine which component of the system is malfunctioning in this circumstance. Take the light from the previous example; if it didn't turn on, the battery may be dead, the bulb could be damaged, or the computer in the car could have malfunctioned.

For this reason, we think of unit testing as a way to identify the precise issue in the tested code.

A simpler test called " unit testing" examines a single component to see whether it is functioning properly or not. Unit tests help us identify the parts of our system that require fixing.

So far, we've seen two different sorts of testing: unit testing, which examines little components in our program, and integration testing, which examines several components.

Introducing the Unittest Module

Understanding Terminologies of the Unittest Module

  • Test fixture: To guarantee that tests are executed in a constant environment that allows for repeatable results, a test fixture is used as a baseline.

Examples:

  • Creating temporary databases.

  • Starting a server process.

  • Test Case: A test case is a collection of conditions used to evaluate if a system is functioning properly.

  • Test Suite: A test suite is a group of test cases that are used to test a software program to demonstrate that it exhibits a particular set of behaviors by running the tests individually.

  • Test Runner: A test runner is a component that arranges for tests to be performed and gives users access to the results.

Important Functions in the unittest Module

MethodDescription
.assertEqual(a, b)a == b
.assertTrue(x)bool(x) is True
.assertFalse(x)bool(x) is False
.assertIs(a, b)a is b
.assertIsNone(x)x is None
.assertIn(a, b)a in b
.assertIsInstance(a, b)isinstance(a, b)
.assertNotIn(a, b)a not in b
.assertNotIsInstance(a,b)not isinstance(a, b)
.assertIsNot(a, b)a is not b

Writing the Unit Test

Where to Write the Test

Create a file named test.pytest.py, which will contain your first test case, to get started creating tests. Your directory tree should be like this since test.pytest.py must be placed above the package folder because it must be able to import your application in order to function:

Your single file will inevitably get crowded and difficult to manage as you add more tests, so you may create a folder named tests/ and divide the tests into numerous files in that folder. Since it is customary for each file to begin with test_, test runners will always presume that a Python file includes tests that need to be performed. Depending on their use or purpose, some extremely big projects divide tests into several subdirectories.

How to Structure a Simple Test

Prior to starting to write tests, you need first decide on a few things:

  1. What do you intend to examine?
  2. Do you have an integration test or a unit test?

The design of a test should therefore roughly follow this approach.

  1. Make your inputs.
  2. Test the code by running it and recording the results.
  3. Compare the results to what was anticipated.

You're testing the sum for this application (). There are other behaviours in sum() that you might examine, including:

  1. Can it add a list of integers that are all whole numbers?
  2. Can it sum a set or tuple?
  3. A list of floats can be summed?
  4. What transpires if you give it a subpar value, such as a single integer or string?
  5. What transpires if one of the values is adverse?

The most simple test would be a list of integers. Create a file, test.pytest.py, with the following Python code:

This is a sample code:

  • imports my sum package's sum() method.
  • defines the TestSum test case class, an inheritor of the unittest.TestCase class.
  • .test_list_int(), a test method that is defined, is used to test a list of integers. Using the method.test list int(), you can:
    • Declare a variable and a number list (1, 2, 3)
    • The output of my sum.sum(data) should be put into a result variable.
    • Use the.assertEqual() method on the unittest.TestCase class to declare that the value of the result equals 6.
  • establishes a command-line entry point that executes the unittest test-runner.main ()

Executing the Test

The test runner is the Python program that runs your test code, validates your assertions, and displays the test results on your console.

You inserted the following little section of code at the bottom of test.pytest.py:

This entry point is for the command line. In other words, if you run python test.pytest.py at the command line to run the script by itself, it will call unittest.main(). By identifying all classes in this file that derive from unittest.TestCase launches the test runner.

This is only one method of running the unittest test runner. Calling python test.pytest.py is a wonderful method to start when you only have one test file with the name test.pytest.py.

Using the unittest command line is another method. Try this: You added the following little piece of code to test.pytest.py's bottom:

By using the command line, this will run the exact same test module (named test).

To alter the result, you can provide more alternatives. One of them is verbose, or -v. Next, try that:

This ran the single test included within test.pytest.py and displayed the outcomes to the console. The names of the tests that were run first, together with their results, were given in verbose mode.

You can ask for an auto-discovery using the following syntax instead of supplying the name of a module containing tests:

This will look for any test*.py files in the current directory and try to test them.

As long as you use the test*.py naming convention and you have several test files, you may specify the directory name instead by using the -s flag and the directory name:

Each test in a single test plan will be executed by unittest, which will then report the results.

Last but not least, you may instruct unittest where to run the tests so that it can correctly import the modules if your source code is located in a subdirectory and not the directory root, for example, in a folder named src/:

Unittest will switch to the src/ directory, search the tests directory for any test*.py files, and then run those scripts.

Understanding Test Output

That was a very simple example where everything passes, so now you’re going to try a failing test and interpret the output.

sum() should be able to accept other lists of numeric types, like fractions.

At the top of the test.pytest.py file, add an import statement to import the Fraction type from the fractions module in the standard library:

Add a test now that makes an assertion assuming the wrong result, in this example supposing that the product of 1/4, 1/4, and 2/5 is 1:

You should get the following result if you run the tests again with the python -m unittest test:

You'll notice the following details in the output:

  • The first line displays the test execution results, with one test passing and one failing (F) (.).
  • The FAIL item contains information about the failed test, including:
    • Test list fraction is the name of the test method.
    • The test case and the test module (TestSum)
    • a link to the problematic line
    • The specifics of the assertion with the true result (Fraction(9, 10)) and the intended result (1).
  • Remember that by adding the -v parameter to the python -m unittest command, you may expand the test output.

Other Python Frameworks for Unit testing

List Of Python Testing Frameworks

  • Robot
  • PyTest
  • Unittest
  • DocTest
  • Nose2
  • Testify

Test-Driven Development

There is even a software development approach called Test Driven Development that is centered on testing because testing is so crucial to effective software development (TDD). Robert C. Martin` suggested the following three TDD rules:

  • No production code may be written until it is required to pass a failed unit test.
  • Unit tests may only contain as much code as necessary to fail, and compilation errors count as errors.
  • You are only permitted to write the amount of production code necessary to pass the one failed unit test.

Conclusion

In this article of topic Unit Testing in Python, we have learned that:

  • There are many aspects to testing in Python, and it can be quite complex, but it does not have to be complex. In a few easy steps, you can create simple tests for your application and then build upon them.
  • Individual units of source code are put through numerous tests as part of the software testing technique known as unit testing to see if they are ready for usage (Source).
  • Exploratory testing is a different type of manual testing. It is a test that is conducted randomly.
  • Integration testing can have a drawback, though. What if the outcome of an integration test is unexpected? It will be difficult to determine which component of the system is malfunctioning in this circumstance.
  • The test runner is the Python program that runs your test code, validates your assertions, and displays the test results on your console.

See Also: