Mutation Testing using Mutpy Module in Python
Last Updated :
20 Aug, 2020
Prerequisite: Mutation Testing
Mutpy is a Mutation testing tool in Python that generated mutants and computes a mutation score. It supports standard unittest module, generates YAML/HTML reports and has colorful output. It applies mutation on AST level.
Installation:
This module does not come built-in with Python. To install it type the below command in the terminal.
pip install mutpy
Here, we will use the Mutpy library to execute test cases written for a simple program.
Now, we perform Mutation Testing for a program that checks if a number is prime or not.
Code: This code is save as isPrime.py
Python3
def isPrime(num):
if num > 1 :
for i in range ( 2 ,num):
if (num % i) = = 0 :
return False
else :
return True
else :
return False ;
|
Now, we need to write test cases for the above program using Pytest or Unittest library. Test cases should be written with an approach to kill all the mutants, i.e. test cases should be effective enough to give a good mutation score. The test cases are written using the Unittest library in the file shown below.
Test cases are written using self.assertEqual() that is a test assertion generally used to determine if a test case has passed or failed. We have written three test functions below to check the three types of input:
- Input is prime
- Input is non-prime
- Input is invalid
Note: The function name and the test file name should always start with the word ‘test’.
Code: This code is save as test_isPrime.py.
Python3
from unittest import TestCase
from isPrime import isPrime
class CalculatorTest(TestCase):
def test_nonprime( self ):
self .assertEqual(isPrime( 12 ), False )
def test_prime( self ):
self .assertEqual(isPrime( 19 ), True )
def test_invalid( self ):
self .assertEqual(isPrime( - 1 ), False )
|
To execute these test cases, we need to create two separate files isPrime.py and test_isPrime.py in a single folder and run the following command in the command prompt:
mut.py --target isPrime --unit-test test_isPrime -m --runner pytest
In the above command, we have to specify three things:
- Target: the target file on which test cases will be run, which in our case is isPrime.py
- Unit-test: the file which has the unit tests that have to be executed, i.e. test_isPrime.py in our case.
- Runner: pytest or unittest
The output will be a set of mutants along with details like mutation score, the number of mutations killed, survived, etc.
[*] Start mutation process:
- targets: isPrime
- tests: test_isPrime
[*] 3 tests passed:
- test_isPrime [3.07469 s]
[*] Start mutants generation and execution:
- [# 1] AOR isPrime:
--------------------------------------------------------------------------------
3:
4: if num > 1:
5:
6: for i in range(2, num):
- 7: if num % i == 0:
+ 7: if num * i == 0:
8: return False
9: else:
10:
11: return True
--------------------------------------------------------------------------------
[1.45151 s] killed by testing program mutpy/test_isPrime.py::CalculatorTest::test_nonprime
- [# 2] COI isPrime:
--------------------------------------------------------------------------------
1:
2: def isPrime(num):
3:
- 4: if num > 1:
+ 4: if not (num > 1):
5:
6: for i in range(2, num):
7: if num % i == 0:
8: return False
--------------------------------------------------------------------------------
[1.25723 s] killed by testing program mutpy/test_isPrime.py::CalculatorTest::test_invalid
- [# 3] COI isPrime:
--------------------------------------------------------------------------------
3:
4: if num > 1:
5:
6: for i in range(2, num):
- 7: if num % i == 0:
+ 7: if not (num % i == 0):
8: return False
9: else:
10:
11: return True
--------------------------------------------------------------------------------
[1.28817 s] killed by testing program mutpy/test_isPrime.py::CalculatorTest::test_prime
- [# 4] CRP isPrime:
--------------------------------------------------------------------------------
1:
2: def isPrime(num):
3:
- 4: if num > 1:
+ 4: if num > 2:
5:
6: for i in range(2, num):
7: if num % i == 0:
8: return False
--------------------------------------------------------------------------------
[1.23510 s] survived
- [# 5] CRP isPrime:
--------------------------------------------------------------------------------
2: def isPrime(num):
3:
4: if num > 1:
5:
- 6: for i in range(2, num):
+ 6: for i in range(3, num):
7: if num % i == 0:
8: return False
9: else:
10:
--------------------------------------------------------------------------------
[1.20360 s] survived
- [# 6] CRP isPrime:
--------------------------------------------------------------------------------
3:
4: if num > 1:
5:
6: for i in range(2, num):
- 7: if num % i == 0:
+ 7: if num % i == 1:
8: return False
9: else:
10:
11: return True
--------------------------------------------------------------------------------
[1.23499 s] killed by testing program mutpy/test_isPrime.py::CalculatorTest::test_prime
- [# 7] ROR isPrime:
--------------------------------------------------------------------------------
1:
2: def isPrime(num):
3:
- 4: if num > 1:
+ 4: if num < 1:
5:
6: for i in range(2, num):
7: if num % i == 0:
8: return False
--------------------------------------------------------------------------------
[1.24164 s] killed by testing program mutpy/test_isPrime.py::CalculatorTest::test_invalid
- [# 8] ROR isPrime:
--------------------------------------------------------------------------------
1:
2: def isPrime(num):
3:
- 4: if num > 1:
+ 4: if num >= 1:
5:
6: for i in range(2, num):
7: if num % i == 0:
8: return False
--------------------------------------------------------------------------------
[1.21934 s] survived
- [# 9] ROR isPrime:
--------------------------------------------------------------------------------
3:
4: if num > 1:
5:
6: for i in range(2, num):
- 7: if num % i == 0:
+ 7: if num % i != 0:
8: return False
9: else:
10:
11: return True
--------------------------------------------------------------------------------
[1.32597 s] killed by testing program mutpy/test_isPrime.py::CalculatorTest::test_prime
[*] Mutation score [14.91747 s]: 66.7%
- all: 9
- killed: 6 (66.7%)
- survived: 3 (33.3%)
- incompetent: 0 (0.0%)
- timeout: 0 (
We can see from the output above, 6 mutants have been killed and only 3 mutant was able to survive. Also, a mutation score of 66.7% was achieved. We can further improve this mutation score by analyzing the mutants that survived the test cases and writing new or modifying test cases to kill the mutants that survived.
Similar Reads
Testing in Python using Doctest module
Docstrings in Python are used not only for the description of a class or a function to provide a better understanding of the code and use but, also used for Testing purposes. Testing is a critical aspect of software development that ensures code functions as expected and guards against bugs. In Pyth
8 min read
Detect Mutation using Python
Prerequisite: Random Numbers in Python The following article depicts how Python can be used to detect a mutated DNA strand. Functions UsedgenerateDNASequence(): This method generates a random DNA strand of length 40 characters using the list of DNA bases A,C,G,T. This method returns the generated DN
5 min read
Object oriented testing in Python
Prerequisite: Object-Oriented Testing Automated Object-Oriented Testing can be performed in Python using Pytest testing tool. In this article, we perform object-oriented testing by executing test cases for classes. We write a program that has one parent class called Product and three child classes -
5 min read
Network Scanning using scapy module - Python
Scapy is a library supported by both Python2 and Python3. It is used for interacting with the packets on the network. It has several functionalities through which we can easily forge and manipulate the packet. Through scapy module we can create different network tools like ARP Spoofer, Network Scann
3 min read
How to Publish Python package at PyPi using Twine module?
Python is so flexible and easy to use because of its available packages that are hosted on pypi.org, Let's see how to publish your own package on PyPi using Twine module. Requirements:You must have account of pypi.org, if don't create an accountThe twine library is created to simplify uploading pack
3 min read
SymPy | Permutation.mul_inv() in Python
Permutation.mul_inv() : mul_inv() is a sympy Python library function that returns the mul inverse other*~self, self and other have _array_form. Syntax : sympy.combinatorics.permutations.Permutation.mul_inv() Return : the mul inverse other*~self, self and other have _array_form. Code #1 : mul_inv() E
1 min read
Identifying Test files and Functions using Pytest
The Python framework used for API testing is called Pytest. For executing and running the tests, it is crucial to identify the test files and functions. Pytest, by default, executes all the test files under a certain package which are of the format test_*.py or *_test.py, in case there is no test fi
2 min read
How to Use Pytest for Efficient Testing in Python
Writing, organizing, and running tests is made easier with Pytest, a robust and adaptable testing framework for Python. Developers looking to guarantee code quality and dependability love it for its many capabilities and easy-to-use syntax. A critical component of software development is writing tes
5 min read
How to perform multiplication using CherryPy in Python?
CherryPy also known as a web application library is a Python web framework that provides a friendly interface to the HTTP protocol for Python developers. It allows developers to build web applications the same way as in traditional object-oriented Python programs. Thereby, resulting in smaller sourc
2 min read
Pylint module in Python
We often get stuck in the middle or encounter errors when we code/run some programs. We usually surf the internet for help and make our code run. But how do we understand the published code on the internet? Some of the typical answers to this question are docstrings, articles written above that code
4 min read