Like any programming language, testing in python is checking individual units of source code. After the software is developed, it is important to test the source code by undergoing various forms of tests. With testing, we ensure that the code is working as expected and is free from any bugs. The main idea is to test it against several inputs. In this article, we shall be comparing two such testing methods – python unittest vs pytest.
Automated vs Manual Testing
There are two ways of performing testing in python – automated testing and manual testing. In manual testing, the code is tested manually by a human. The tester needs to manually make lists of all possible inputs and the expected output. It is a tedious job and also time-consuming.
This is where automated testing comes into play. Python consists of built-in frameworks that make testing code easier. Since automated testing is script-based, it is accurate. Python has tools and libraries – such as unittest and pytest.
Testing using Unittest framework
The unit testing framework in python is known as unittest. We can have a single function, a class, or an entire module as the unit for testing. The idea behind unit testing is to validate the smallest unit first and then gradually move to other units. The unittest in python is actually inspired by Java’s JUnit.
Using the unittest framework, there are three possible outputs – OK, FAIL, and ERROR.
- OK: This is the output when all the tests are passed.
- FAILED: This is the output shown when all the tests did not pass successfully. When an AssertionError exception is raised, the output shows FAIL.
- ERROR: This was the output when all the test cases did not pass, and it raises an exception other than the AssertionError.
Test Code example
Let us consider a python code for running the tests. First, we will have to import the unittest module.
Now, we shall define a function named square() which takes a number ‘n’ as a parameter and returns the square of the number as the output.
def square(n): return n*n
Now, we will define a class named ‘Test’. The class test will inherit the unittest module by ‘unittest.TestCase’. We define a function inside the class named test_square. Here, the naming convention should be used such that the name ‘test’ precedes the function name.
We will pass ‘self’ as a parameter to the function. Inside the function, we will call self.assertEquals(). There are several assert methods present for testing, and assertEquals() is one of them. In assertEquals(), the first and the second argument should be equal for the test to be successful.
So here, we will pass the square(2) function as the first argument and 4 as the second argument.
class Test(unittest.TestCase): def test_square(self): self.assertEquals(square(2), 4)
To run the file ‘test_Calculation.py’, we shall use the following piece of code:
python -m unittest test_Calculation
The output shall be:
. --------------------------------------------------------------- Ran 1 test in 0.001s OK
Because the output of the function square(2) was equal to 4, the test ran successfuly and OK was printed.
Now, let us try to run two functions as two different test cases.
We shall define a second function named ‘cube’ which takes a single number as an argument and returns its cube as the output.
def cube(n): return n*n*n
Now, inside the class Test, we shall define another function named test_cube(). We shall use self.assertEquals() and pass cube(2) and 8 as first and second arguments.
def test_cube(self): self.assertEquals(cube(2), 8)
Now, we shall again run the same code in the terminal:
python -m unittest test_Calculation
Since, there were two tests here, the output will be OK signifying that the two tests were run successfully.
.. --------------------------------------------------------------- Ran 2 tests in 0.001s OK
Also, Read | PIP vs PIP3: What is the Difference?
The Entire Code is:
import unittest def square(n): return n*n def cube(n): return n*n*n class Test(unittest.TestCase): def test_square(self): self.assertEquals(square(2), 4) def test_cube(self): self.assertEquals(cube(2), 8)
Failed Test Example
Now, we shall look into a scenario where the tests will fail. Let us take the same example as mentioned above. Inside the cube function, we will pass a string value as an argument instead of an integer.
import unittest def square(n): return n*n def cube(n): return n*n*n class Test(unittest.TestCase): def test_square(self): self.assertEquals(square(2), 4) def test_cube(self): self.assertEquals(cube('abc'), 8)
On running the following code inside command line, the test will FAIL.
python -m unittest test_Calculation
--------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (errors=1)
The output shows that two tests were run where one of them failed.
Testing Using Pytest framework
Pytest in python is another framework that is used for testing. With pytest, we can run several tests in parallel. Because of that a considerable amount of computation time is saved. Using pytest is simple and does not involve complex codes.
Pytest code example
Let us perform testing using pytest. For that, we simply have to define two functions – test_square() and test_cube(). Inside the test_square() function, we take a variable ‘n’ and return the square of that function ‘n’.
Similarly in test_cube() function we take variable ‘n’ and return the cube of that function ‘n’. We use assert statements to check if the respective conditions are True.
def test_square(): n = 2 assert n*n == 4 def test_cube(): n = 2 assert n*n*n == 8
Inside the terminal for that file, we simply have to write pytest.
Since the assert statements output True values, the following output will be printed.
collected 2 items test_Calculation.py .. [100%] =================================================================== 2 passed in 0.78s ====================================================================
It shows that two items were collected successfully.
Failed Test example
Let us take an example where the assert conditions output False values. In that scenario, if the pytest command would be False then it would throw AssertionError and indicate that the tests FAILED.
def test_square(): n = 2 assert n*n == 40 def test_cube(): n = 2 assert n*n*n == 80
The output is:
collected 2 items test_Calculation.py FF [100%] ======================================================================== FAILURES ======================================================================== ______________________________________________________________________ test_square _______________________________________________________________________ def test_square(): n = 2 > assert n*n == 40 E assert (2 * 2) == 40 test_Calculation.py:5: AssertionError _______________________________________________________________________ test_cube ________________________________________________________________________ def test_cube(): n = 2 > assert n*n*n == 80 E assert ((2 * 2) * 2) == 80 test_Calculation.py:9: AssertionError ================================================================ short test summary info ================================================================= FAILED test_Calculation.py::test_square - assert (2 * 2) == 40 FAILED test_Calculation.py::test_cube - assert ((2 * 2) * 2) == 80 =================================================================== 2 failed in 0.90s ====================================================================
Python Unittest vs Pytest
Both unittest and pytest are testing frameworks in python. Unittest is the testing framework set in python by default. In unittest, we create classes that are derived from the unittest.TestCase module. It comes in handy because it is universally understood.
Whereas using pytest involves a compact piece of code. Pytest has rich inbuilt features which require less piece of code compared to unittest. In the case of unittest, we have to import a module, create a class and then define testing functions inside the class. But in the case of pytest, we have to define the functions and assert the conditions inside them.
Pytest Vs Unittest FAQs
Here are a few questions we often hear when comparing Pytest and Unittest.
Although both the frameworks are great for performing testing in python, pytest is easier to work with. The code in pytest is simple, compact, and efficient.
For unittest, we will have to import modules, create a class and define the testing functions within that class. But for pytest, we only have to define the testing function. Pytest is also fast and efficient.
This sums up the comparison between Python Unittest vs Pytest. If you have any questions in mind, leave them below in the comments.
Until next time, Keep Learning!