CodeLearn PythonPythonWindows

The Comprehensive Guide To Built-In Python Testing Tools

pexels cottonbro 5473337

What is Python code testing and why does it matter?

In the software development life cycle, testing your code is essential. So, choosing – and using – the right Python testing tools should also be an essential part of writing good quality code.

Writing testing code and running it in parallel is now considered a good practice (that is often skipped by beginners). By implementing them wisely, testing would help to define your code’s intent more precisely and have a more decoupled architecture. If you don’t check your Python code BEFORE it reaches your end users, you run the risk of losing their goodwill if the program has bugs in it or, even worse, totally destroying your app’s reputation so nobody will want to use it in the first place.

The testing phases of the software development life cycle assist businesses in identifying all bugs and errors in the software prior to the implementation phase. If software bugs are not resolved prior to deployment, they can adversely affect the client’s business.

Furthermore, attempting to resolve these issues at a later stage can result in substantial costs. The longer you delay the detection of these issues, the greater the cost you are likely to face.

The following are different types of tests you should have and are often represented as a pyramid.

The Comprehensive Guide To Built In Python Testing Tools a diagram of the testing pyramid
Image credit Albin Larsson Abbe98 Wikipedia

The lower you go on the pyramid, the smaller the unit of code being tested, and the more tests you should have. For example, one UI (E2E) test phase might test the flow of creating, editing, and then saving a document. That flow is composed of many different functions, each one of them should have its own unit tests.

In this article, we will limit our scope to Python’s built-in unit testing framework.

If you are looking for articles about Python profiling tools, read it here:

 

Does Python have a built-in unit testing library?

The Python standard library provides unittest as a built-in unit testing framework. The unittest framework was inspired by JUnit in Java and has a similar flavor to major unit testing frameworks in other programming languages.

It allows for test automation, the sharing of test setup and shutdown code, the grouping of tests into collections, and the independence of the tests from the reporting framework.

The Comprehensive Guide To Built In Python Testing Tools showing a collection of developers discussing unit testing for Python

The following are some unittest important concepts in an object-oriented way:

test fixtureRepresents the preparation needed to perform one or more tests, and any associated cleanup actions. This could include things like making temporary or proxy databases, directories, or starting a server process.
test caseThe individual testing unit. It looks for a specific response to a specific set of inputs. unittest includes a base class called TestCase that can be used to create new test cases.
test suiteA collection of test cases, test suites, or both. It is used to group tests that should be run together.
test runnerA component that orchestrates test execution and reports the results to the user. To indicate the results of running the tests, the runner may use a graphical interface, a textual interface, or return a special value.

 

How do I get the unittest library?

As unittest is a built-in Python unit testing library, no further installation is needed.

 

How to perform unit testing with the unittest Python testing tools?

The following is a short script to test three-string methods (source: docs.python.org): 

Creating test cases is accomplished by subclassing unittest.TestCase. The code above has three individual tests that are:

  1. test_upper: To test if we were able to successfully change the string cases to upper case. 
  2. test_isupper: To verify the conditions of the given strings if it is upper or not.
  3. test_split: To check for an expected result, whether we successfully split the given string input.

The naming convention for performing testing is to inform the test runner about which methods represent tests.

The heart of each test is a call to assertEqual(), which checks for an expected result; assertTrue() or assertFalse(), which verifies a condition; or assertRaises(), which verifies that a specific exception is raised. These methods are used in place of the assert statement to allow the test runner to compile all test results and generate a report.

Here is the output on PyScripter IDE:

The Comprehensive Guide To Built In Python Testing Tools an image showing some unit tests in the PyScripter IDE

Save the script above as 01_testThreeStringMethods.py, and let’s try to perform unit testing from the command prompt in the next section.

 

How to conduct Python unit testing at runtime?

The following is the command to run Python unittest:

The Comprehensive Guide To Built In Python Testing Tools a command line prompt showing a unit test result

Or you can specifically call your test class like this:

The Comprehensive Guide To Built In Python Testing Tools another prompt showing test results

For more detailed results (higher verbosity), pass this -v flag:

The Comprehensive Guide To Built In Python Testing Tools the results of the three Python unit tests

Or you can also use this command:

The Comprehensive Guide To Built In Python Testing Tools a command prompt with 3 unittest results

 

What does a failed Python unit test look like?

Try the following code, to see how the failure in unittest would look like (source: realpython.com):

If you execute the above code, you’ll see one success (indicated with .) and one failure (indicated with F). Here is the output on PyScripter IDE:

The Comprehensive Guide To Built In Python Testing Tools showing Pyscripter running a collection of Python unit tests

 

How to do test skipping and expecting failures with unittest?

unittest allows you to skip individual test methods as well as entire classes of tests. Furthermore, it supports marking a test as an “expected failure,” which is a broken test that will fail but should not be counted as a failure on a TestResult.

Try the following code, to see what the output of the skipping test and expected failure in unittest would look like (the following code is modified from docs.python.org, to show you different test outputs in a series of tests):

This is the output of running the example above in verbose mode:

The Comprehensive Guide To Built In Python Testing Tools showing how to skip Python unit tests

We got 2 ok, 1 skipping test, and 1 expected failure.

 

What are the command line options provided by unittest?

unittest supports these command-line options:

-h, --help

To access a list of all the command-line options. Here is the command to do it:

The Comprehensive Guide To Built In Python Testing Tools showing the available command line options for Python unit tests with unittest

-b, --buffer

The standard output and standard error streams are buffered during the test run. Output during a passing test is discarded. Output is echoed normally on test fail or error and is added to the failure messages.

-c, --catch

During the test run, Control-C waits for the current test to finish and then reports all the results so far.

A second Control-C raises the normal KeyboardInterrupt exception

-f, --failfast

On the first error or failure, the test is terminated.

-k

Only test methods and classes that match the pattern or substring are executed. This option may be used multiple times, in which case all test cases that match any of the given patterns are included.

Patterns that contain a wildcard character (*) are matched against the test name using fnmatch.fnmatchcase(); otherwise simple case-sensitive substring matching is used.

Patterns are matched against the fully qualified test method name as imported by the test loader.

For example, -k foo matches foo_tests.SomeTest.test_something, bar_tests.SomeTest.test_foo, but not bar_tests.FooTest.test_something.

--locals

Show local variables in tracebacks.

 Amazing isn’t it? Now you can easily test your Python code using unittest.

Congratulations, now you have learned about built-in Python testing tools! Now you can implement it to write more professional code that is tested well before delivered to users!


Click here to start using PyScripter, a free, feature-rich, and lightweight IDE for Python developers.

Download RAD Studio to build more powerful Python GUI Windows Apps 5x Faster with Less Code.

Check out Python4Delphi which easily allows you to build Python GUIs for Windows using Delphi.

Also, check out DelphiVCL which easily allows you to build GUIs for Windows using Python.


References & further readings

[1] Chng, Z. M. (2022).

A Gentle Introduction to Unit Testing in Python. Machine Learning Mastery. machinelearningmastery.com/a-gentle-introduction-to-unit-testing-in-python

[2] Shaw, A. (Retrieved in 2022).

Getting Started With Testing in Python. Real Python. realpython.com/python-testing

[3] Python Software Foundation. (2022).

unittest — Unit testing framework. Python 3.11.1 documentation. docs.python.org/3/library/unittest.html

Related posts
CodeIDELearn PythonPythonPython GUITkinter

How To Make More Than 20 ChatGPT Prompts Work With Python GUI Builders And NumPy Library?

CodeIDEProjectsPythonWindows

Unlock the Power of Python for Deep Learning with Generative Adversarial Networks (GANs) - The Engine behind DALL-E

CodeIDELearn PythonPythonPython GUITkinter

How To Make More Than 20 ChatGPT Prompts Work With Python GUI Builders And Matplotlib Library?

CodeIDELearn PythonPythonPython GUITkinter

How To Make More Than 20 ChatGPT Prompts Work With Python GUI Builders And Pillow Library?

Leave a Reply

Your email address will not be published. Required fields are marked *