Pruebas de mutación usando el módulo Mutpy en Python

Requisito previo: prueba de mutación

Mutpy es una herramienta de prueba de mutación en Python que genera mutantes y calcula una puntuación de mutación. Es compatible con el módulo de prueba unitaria estándar, genera informes YAML/HTML y tiene una salida colorida. Aplica mutación a nivel de AST.

Instalación:

Este módulo no viene integrado con Python. Para instalarlo, escriba el siguiente comando en la terminal.

pip install mutpy

Aquí, usaremos la biblioteca Mutpy para ejecutar casos de prueba escritos para un programa simple.

Ahora, realizamos pruebas de mutación para un programa que verifica si un número es primo o no

Código: Este código se guarda como isPrime.py

Python3

# define a function 
def isPrime(num):
  
    if num > 1:
        
       # check for factors
       for i in range(2,num):
           if (num % i) == 0:
               return False
  
       else:
           return True
             
    # if input number is less than
    # or equal to 1, it is not prime
    else:
       return False;

Ahora, necesitamos escribir casos de prueba para el programa anterior usando la biblioteca Pytest o Unittest . Los casos de prueba deben escribirse con un enfoque para matar a todos los mutantes, es decir, los casos de prueba deben ser lo suficientemente efectivos para dar una buena puntuación de mutación. Los casos de prueba se escriben utilizando la biblioteca Unittest en el archivo que se muestra a continuación. 

Los casos de prueba se escriben utilizando self.assertEqual(), que es una aserción de prueba que generalmente se usa para determinar si un caso de prueba ha pasado o no. Hemos escrito tres funciones de prueba a continuación para verificar los tres tipos de entrada: 

  1. La entrada es principal
  2. La entrada no es prima
  3. La entrada no es válida

Nota: El nombre de la función y el nombre del archivo de prueba siempre deben comenzar con la palabra ‘prueba’.

Código: este código se guarda como test_isPrime.py.

Python3

# import required libraries
from unittest import TestCase
from isPrime import isPrime
  
# define a class
class CalculatorTest(TestCase):
      
    # test case for checking non prime nums
    def test_nonprime(self):
        self.assertEqual(isPrime(12),False)
      
    # test case to check prime nums
    def test_prime(self):
        self.assertEqual(isPrime(19),True)
  
    # test case to check invalid input
    def test_invalid(self):
        self.assertEqual(isPrime(-1),False)

Para ejecutar estos casos de prueba, necesitamos crear dos archivos separados isPrime.py y test_isPrime.py en una sola carpeta y ejecutar el siguiente comando en el símbolo del sistema: 

mut.py --target isPrime --unit-test test_isPrime -m --runner pytest

En el comando anterior, tenemos que especificar tres cosas: 

  • Destino: el archivo de destino en el que se ejecutarán los casos de prueba, que en nuestro caso es isPrime.py
  • Unit-test: el archivo que contiene las pruebas unitarias que deben ejecutarse, es decir, test_isPrime.py en nuestro caso.
  • Corredor: pytest o unittest

El resultado será un conjunto de mutantes junto con detalles como el puntaje de mutación, la cantidad de mutaciones muertas, sobrevivientes, 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 (

Podemos ver en la salida anterior, 6 mutantes han sido asesinados y solo 3 mutantes pudieron sobrevivir. Además, se logró una puntuación de mutación del 66,7%. Podemos mejorar aún más este puntaje de mutación analizando los mutantes que sobrevivieron a los casos de prueba y escribiendo casos de prueba nuevos o modificando para matar a los mutantes que sobrevivieron. 

Publicación traducida automáticamente

Artículo escrito por ps17 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *