El Data-Driven Testing (DDT) es una metodología de automatización que permite separar la lógica de las pruebas de los datos de entrada. En el ecosistema de Python, Pytest facilita esta tarea mediante su sistema de parametrización. A continuación, exploraremos cómo integrar fuentes de datos externas como archivos Excel y bases de datos relacionales en una suite de pruebas.
Pruebas basadas en archivos Excel
Para trabajar con archivos de Microsoft Excel, utilizaremos la biblioteca openpyxl. El primer paso consiste en desarrollar una utilidad que gestione la lectura del libro de trabajo y la extracción de filas de datos.
from openpyxl import load_workbook
class GestorExcel:
def __init__(self, ruta_archivo, nombre_hoja):
"""
Clase para manipular datos desde una hoja de cálculo.
:param ruta_archivo: Path del archivo .xlsx
:param nombre_hoja: Nombre de la pestaña de datos
"""
self.archivo = ruta_archivo
self.hoja_nombre = nombre_hoja
self.wb = load_workbook(self.archivo, data_only=True)
self.sheet = self.wb[self.hoja_nombre]
def obtener_set_datos(self):
"""
Extrae los valores de las celdas omitiendo la cabecera.
:return: Lista de listas con el contenido del archivo
"""
filas_totales = []
# Iteramos a partir de la segunda fila para ignorar los encabezados
for fila in self.sheet.iter_rows(min_row=2, values_only=True):
filas_totales.append(list(fila))
return filas_totales
if __name__ == "__main__":
# Ejemplo de uso rápido
procesador = GestorExcel("datos_pruebas.xlsx", "Resultados")
print(procesador.obtener_set_datos())
Una vez definida la utilidad, integramos estos datos en Pytest. La clave es el decorador @pytest.mark.parametrize, que inyectará cada fila del Excel como un caso de prueba independiente.
import pytest
# Función simulada que representa el sistema bajo prueba (SUT)
def calcular_impuesto(monto):
return monto * 0.15
def obtener_datos_excel():
# Instanciamos el gestor y devolvemos la lista para parametrizar
manejador = GestorExcel("casos_impuestos.xlsx", "Hoja1")
return manejador.obtener_set_datos()
@pytest.mark.parametrize("entrada_monto, salida_esperada", obtener_datos_excel())
def test_validar_impuestos(entrada_monto, salida_esperada):
resultado = calcular_impuesto(entrada_monto)
assert resultado == salida_esperada, f"Error: {resultado} != {salida_esperada}"
Integración con bases de datos SQL
En entornos empresariales, los datos de prueba suelen residir en bases de datos. Para este ejemplo, utilizaremos mysql-connector-python para extraer registros que servirán como parámetros de nuestras asercioens.
import pytest
import mysql.connector
def consultar_tabla_pruebas():
"""Conecta a la DB y recupera los parámetros de prueba."""
configuracion = {
'user': 'qa_tester',
'password': 'password_seguro',
'host': '127.0.0.1',
'database': 'entorno_qa'
}
conexion = None
datos = []
try:
conexion = mysql.connector.connect(**configuracion)
cursor = conexion.cursor()
# Seleccionamos los valores de entrada y el resultado esperado
query = "SELECT input_val, expected_val FROM suite_regresion"
cursor.execute(query)
datos = cursor.fetchall()
cursor.close()
except mysql.connector.Error as err:
print(f"Error en la conexión DB: {err}")
finally:
if conexion and conexion.is_connected():
conexion.close()
return datos
@pytest.mark.parametrize("valor, expectativa", consultar_tabla_pruebas())
def test_operacion_logica_db(valor, expectativa):
"""
Prueba que valida si un proceso duplica correctamente el valor.
"""
logica_negocio = valor * 2
assert logica_negocio == expectativa, f"Fallo con el valor de entrada: {valor}"
def test_verificar_conexion():
"""Prueba unitaria para validar la salud de la conexión a la base de datos."""
datos = consultar_tabla_pruebas()
assert len(datos) > 0, "No se pudieron recuperar datos de la tabla suite_regresion"
La ventaja de este enfoque es la escalabilidad. Si se añaden nuevos registros a la tabla SQL o nuevas filas al archivo Excel, Pytest detectará automáticamente los nuevos casos sin necesidad de modificar el código fuente de la prueba.