A comprehensive API testing framework for Python, inspired by Karate Framework
Project description
Judo Framework
Framework completo de pruebas de API para Python, inspirado en Karate Framework
"As simple as Karate, as powerful as Python"
¿Qué es Judo Framework?
Judo Framework trae la simplicidad de Karate Framework al ecosistema Python. Escribe pruebas de API en lenguaje natural (inglés o español), obtén reportes HTML automáticos y aprovecha el poder del ecosistema Python.
199 pasos en inglés · 229 pasos en español · Evaluación de GenAI · Mock Server integrado · Reportes HTML personalizables
Instalación
pip install judo-framework
Para funcionalidades específicas:
pip install judo-framework[excel] # Soporte Excel
pip install judo-framework[websocket] # WebSocket
pip install judo-framework[graphql] # GraphQL
pip install judo-framework[full] # Todo incluido
Inicio rápido
1. Crear el feature
# features/api_test.feature
Feature: Pruebas de API
Scenario: Obtener usuario
Given the base URL is "https://jsonplaceholder.typicode.com"
When I send a GET request to "/users/1"
Then the response status should be 200
And the response should contain "name"
2. Configurar environment.py
# features/environment.py
from judo.behave import *
before_all = before_all_judo
before_feature = before_feature_judo
after_feature = after_feature_judo
before_scenario = before_scenario_judo
after_scenario = after_scenario_judo
before_step = before_step_judo
after_step = after_step_judo
after_all = after_all_judo
3. Ejecutar
behave features/
Los reportes HTML se generan automáticamente en judo_reports/.
Soporte bilingüe completo
Inglés
Feature: User API
Scenario: Create user
Given the base URL is "https://api.example.com"
And I use bearer token "my-token"
When I send a POST request to "/users" with JSON:
"""
{"name": "John Doe", "email": "john@example.com"}
"""
Then the response status should be 201
And the response field "name" should equal "John Doe"
And I extract "id" from the response as "userId"
Español
# language: es
Característica: API de Usuarios
Escenario: Crear usuario
Dado que la URL base es "https://api.example.com"
Y uso el token bearer "mi-token"
Cuando hago una petición POST a "/users" con el cuerpo:
"""
{"name": "Juan Pérez", "email": "juan@example.com"}
"""
Entonces el código de respuesta debe ser 201
Y el campo "name" debe ser "Juan Pérez"
Y guardo el valor del campo "id" en la variable "userId"
Modo mixto
Feature: API de Usuarios
Scenario: Crear usuario
Given la URL base es "https://api.example.com"
When hago una petición POST a "/users" con el cuerpo:
"""
{"name": "Juan Pérez"}
"""
Then el código de respuesta debe ser 201
Evaluación de GenAI (nuevo)
Judo permite evaluar respuestas de sistemas de IA generativa. El flujo es: llamas tu API GenAI con pasos REST normales, extraes la respuesta y la evalúas con tres estrategias.
Configuración en .env (solo para el juez LLM)
JUDO_AI_PROVIDER=openai # openai | claude | gemini
JUDO_OPENAI_API_KEY=sk-...
JUDO_AI_MODEL=gpt-4o
Importar en environment.py
from judo.genai.steps_genai_es import * # español
# from judo.genai.steps_genai import * # inglés
Estrategia 1: RAG — comparar contra documentos
Dado que cargo el contexto RAG desde el archivo "docs/manual.pdf"
Cuando envío una petición POST a "/chat" con el cuerpo
"""
{"pregunta": "¿Cuál es el precio del plan básico?"}
"""
Entonces el código de respuesta debe ser 200
Y uso el campo de respuesta "respuesta" como respuesta de IA
Y la respuesta de IA debe estar fundamentada en el contexto RAG con umbral 0.7
Estrategia 2: Validaciones semánticas
Cuando envío una petición POST a "/ai/explain" con el cuerpo
"""
{"topic": "HTTP methods"}
"""
Entonces el código de respuesta debe ser 200
Y uso el campo de respuesta "explanation" como respuesta de IA
Y la respuesta de IA no debe ser tóxica con umbral 0.9
Y la respuesta de IA debe ser relevante para "HTTP methods" con umbral 0.4
Y la respuesta de IA debe cubrir los temas requeridos con umbral 0.8
| tema |
| GET |
| POST |
| DELETE |
Estrategia 3: LLM como juez
Dado que configuro el juez de IA con proveedor "openai" y modelo "gpt-4o"
Y establezco el prompt del juez como "Explica qué es una API REST"
Cuando envío una petición POST a "/ai/explain" con el cuerpo
"""
{"question": "Explica qué es una API REST"}
"""
Entonces el código de respuesta debe ser 200
Y uso el campo de respuesta "answer" como respuesta de IA
Y evalúo la respuesta de IA con el juez usando umbral 0.7
"""
La respuesta debe explicar correctamente REST,
mencionar al menos un método HTTP y ser comprensible.
"""
Y la evaluación del juez debe pasar
Mock Server integrado
from judo import Judo
judo = Judo()
mock = judo.start_mock(port=8080)
mock.get("/api/users", {
"status": 200,
"body": [{"id": 1, "name": "Juan"}, {"id": 2, "name": "Ana"}]
})
mock.post("/api/users", {"status": 201, "body": {"id": 3, "message": "Created"}})
mock.get("/api/users/*", {"status": 200, "body": {"id": 1, "name": "Juan"}})
# Ejecutar pruebas contra http://localhost:8080
judo.stop_mock()
Desde CLI:
judo mock --port 8080
Reportes HTML personalizables
Crea un archivo report_config.json en judo_reports/:
{
"project": {
"name": "Mi Proyecto - API Tests",
"engineer": "Ana García",
"team": "Equipo QA",
"company": "Mi Empresa S.A."
},
"branding": {
"primary_logo": "data:image/png;base64,TU_LOGO_AQUI",
"primary_color": "#1e40af",
"secondary_color": "#3b82f6"
},
"theme": {
"background_color": "#f0f2f5"
},
"charts": {
"enabled": true,
"type": "doughnut",
"animation": true
},
"footer": {
"show_creator": false,
"show_logo": true,
"company_name": "Mi Empresa S.A.",
"company_url": "https://www.miempresa.com"
}
}
El reporte incluye gráficos donut animados, detalles de request/response, métricas de rendimiento y branding corporativo completo.
Características principales
Pruebas REST completas
Scenario: CRUD completo
Given the base URL is "https://api.example.com"
When I send a POST request to "/users" with JSON:
"""
{"name": "John", "email": "john@example.com"}
"""
Then the response status should be 201
And I extract "id" from the response as "userId"
When I send a GET request to "/users/{userId}"
Then the response status should be 200
And the response field "name" should equal "John"
When I send a DELETE request to "/users/{userId}"
Then the response status should be 204
Autenticación
Given I use bearer token "eyJhbGci..."
Given I use basic authentication with username "admin" and password "secret"
Validación de esquemas JSON
Then the response should match schema file "schemas/user.json"
Then the response should match JSON schema:
"""
{
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"},
"email": {"type": "string", "format": "email"}
}
}
"""
Ejecución paralela
from judo.runner.base_runner import BaseRunner
runner = BaseRunner(
features_dir="features",
parallel=True,
max_workers=8,
output_dir="judo_reports"
)
runner.run_all_features()
Características avanzadas
- Circuit Breaker — previene fallos en cascada
- Retry con backoff — reintentos automáticos (linear, exponential, fibonacci)
- Rate limiting — respeta límites de la API
- Caché de respuestas — evita requests repetidos
- WebSocket — pruebas en tiempo real
- GraphQL — queries y mutations
- Chaos Engineering — inyección de latencia y errores
- Data-driven testing — desde CSV, JSON, Excel
- Monitoreo de performance — avg, p95, p99, error rate
- Validación de contratos OpenAPI — verifica cumplimiento de specs
Estructura de proyecto recomendada
mi_proyecto/
├── .env # Variables de entorno
├── features/
│ ├── environment.py # Configuración de Behave
│ ├── api_tests.feature
│ └── steps/ # Pasos personalizados (opcional)
├── test_data/
│ └── users.json
├── judo_reports/
│ └── report_config.json # Configuración de reportes
└── runner.py # Runner personalizado (opcional)
Runner personalizado
from judo.runner.base_runner import BaseRunner
class MiRunner(BaseRunner):
def __init__(self):
super().__init__(
features_dir="features",
output_dir="judo_reports",
parallel=True,
max_workers=4
)
if __name__ == "__main__":
runner = MiRunner()
success = runner.run_all_features()
exit(0 if success else 1)
Variables de entorno (.env)
# Directorios
JUDO_FEATURES_DIR=features
JUDO_OUTPUT_DIR=judo_reports
# Ejecución
JUDO_PARALLEL=false
JUDO_MAX_WORKERS=4
JUDO_TIMEOUT=300
JUDO_RETRY_COUNT=0
JUDO_FAIL_FAST=false
# Reportes
JUDO_GENERATE_CUCUMBER_JSON=true
JUDO_SAVE_REQUESTS_RESPONSES=false
JUDO_REPORT_CONFIG_FILE=judo_reports/report_config.json
# GenAI (solo para evaluación con LLM como juez)
JUDO_AI_PROVIDER=openai
JUDO_OPENAI_API_KEY=sk-...
JUDO_AI_MODEL=gpt-4o
JUDO_AI_TEMPERATURE=0.0
Integración CI/CD
GitHub Actions
name: API Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install judo-framework
- run: python runner.py
- uses: actions/upload-artifact@v3
with:
name: test-reports
path: judo_reports/
Documentación
| Recurso | Descripción |
|---|---|
| documentacion/JUDO_STEPS_REFERENCE_ES.md | Referencia completa de pasos en español |
| documentacion/JUDO_STEPS_REFERENCE_EN.md | Complete step reference in English |
| documentacion/referencia_judo.md | Referencia consolidada del framework |
| documentacion/GUIA_INSTALACION_Y_CONFIGURACION.txt | Guía de instalación y configuración |
| documentacion/CUSTOM_REPORTS_GUIDE.txt | Guía de reportes personalizables |
| documentacion/GUIA_LOGOS_REPORTES.txt | Guía de logos en reportes |
| examples/ | Ejemplos de features y configuración |
Conteo de pasos
| Archivo | Pasos |
|---|---|
judo/behave/steps.py (inglés) |
162 |
judo/behave/steps_es.py (español) |
192 |
judo/genai/steps_genai.py (GenAI inglés) |
37 |
judo/genai/steps_genai_es.py (GenAI español) |
37 |
| Total inglés | 199 |
| Total español | 229 |
Soporte
- GitHub Issues: github.com/FelipeFariasAlfaro/Judo-Framework/issues
- Email: felipe.farias@centyc.cl
- Documentación: centyc.cl/judo-framework
Licencia
MIT License — ver LICENSE
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file judo_framework-1.6.9.tar.gz.
File metadata
- Download URL: judo_framework-1.6.9.tar.gz
- Upload date:
- Size: 510.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ce98b476a8e05a15c9c996f4e5cbd1a79d10e5028a1ba729950134f5a137c20
|
|
| MD5 |
014fed0136ec0d2fe0c98593d47cc819
|
|
| BLAKE2b-256 |
45adad43102ecba0438f5bdfdf21a744689d3ae33bd218a7321bd098a5fac91b
|
File details
Details for the file judo_framework-1.6.9-py3-none-any.whl.
File metadata
- Download URL: judo_framework-1.6.9-py3-none-any.whl
- Upload date:
- Size: 329.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d62f48e4d2a05db5acd69ac72a6031508d287ebb7bfef53ef16139d1b8abfed
|
|
| MD5 |
d0f927558326819275f8545a48e33d58
|
|
| BLAKE2b-256 |
416f958836f48f464b8c4f215dde41efe7f1b884c1608064a5650177cae12ac1
|