===========================================
GUÍA COMPLETA DE INTEGRACIÓN CON AZURE DEVOPS
Framework Hakalab - Plugin de Azure DevOps
===========================================

ÍNDICE
------
1. Introducción
2. Instalación y Configuración
3. Configuración del .env
4. Uso en Features
5. Sistema de Plugins
6. Personalización Avanzada
7. Ejemplos Prácticos
8. Troubleshooting
9. Mejores Prácticas

===========================================
1. INTRODUCCIÓN
===========================================

¿Qué es el Plugin de Azure DevOps?
-----------------------------------
Plugin que integra automáticamente tus tests de Behave con Azure DevOps,
permitiendo:
- Actualizar el estado de Test Cases automáticamente
- Adjuntar reportes HTML a Tasks
- Mantener sincronizado el estado de tus tests en Azure DevOps

¿Por qué usar esta integración?
--------------------------------
✅ Automatización completa: No necesitas actualizar manualmente Azure DevOps
✅ Trazabilidad: Cada test actualiza su Test Case correspondiente
✅ Reportes adjuntos: Los reportes se adjuntan automáticamente a las Tasks
✅ Configuración simple: Todo se configura desde .env
✅ No invasivo: Se activa/desactiva con una variable de entorno

¿Cuándo usar esta funcionalidad?
---------------------------------
- Cuando usas Azure DevOps para gestionar tus Test Cases
- Cuando necesitas mantener actualizado el estado de los tests
- Cuando quieres adjuntar reportes automáticamente
- Cuando trabajas en equipos que usan Azure DevOps como fuente de verdad

===========================================
2. INSTALACIÓN Y CONFIGURACIÓN
===========================================

Paso 1: Instalar Dependencias
------------------------------
El plugin requiere la librería requests:

pip install requests

O instalar todas las dependencias del framework:
pip install haka-playwright-engine[all]

Paso 2: Obtener Personal Access Token (PAT)
--------------------------------------------
1. Ve a Azure DevOps: https://dev.azure.com/{tu-organizacion}
2. Click en tu avatar (esquina superior derecha) > Personal access tokens
3. Click en "New Token"
4. Configura:
   - Name: "Automation Testing"
   - Organization: Selecciona tu organización
   - Expiration: Elige la duración (recomendado: 90 días o más)
   - Scopes: Selecciona "Work Items" con permisos de Read & Write
5. Click en "Create"
6. Copia el token generado (solo se muestra una vez)
7. Guárdalo de forma segura

Paso 3: Configurar Campos Personalizados en Azure DevOps
---------------------------------------------------------
Si tu proyecto usa campos personalizados para el estado del test:

1. Ve a Azure DevOps > Project Settings > Process
2. Encuentra el tipo de work item que usas para Test Cases
3. Identifica el campo personalizado que usas para el estado
4. Copia el nombre del campo (ej: "Custom.TestStatus", "Custom.QAStatus")
5. Anota los valores posibles (ej: "Passed", "Failed", "Blocked")

===========================================
3. CONFIGURACIÓN DEL .ENV
===========================================

Variables Requeridas:
---------------------

# Habilitar/deshabilitar integración
AZURE_DEVOPS_ENABLED=true

# Datos de conexión
AZURE_DEVOPS_ORG=tu-organizacion
AZURE_DEVOPS_PROJECT=tu-proyecto
AZURE_DEVOPS_PAT=tu-personal-access-token

Variables Opcionales:
---------------------

# Campo personalizado para el estado del test
AZURE_DEVOPS_STATUS_FIELD=Custom.TestStatus

# Valores para el campo de estado
AZURE_DEVOPS_STATUS_PASSED=Passed
AZURE_DEVOPS_STATUS_FAILED=Failed

# Configuración de reportes
AZURE_DEVOPS_ATTACH_REPORT=true
AZURE_DEVOPS_REPORT_PATH=reports/report.html

# Versión de la API (opcional)
AZURE_DEVOPS_API_VERSION=7.1

Ejemplo Completo de .env:
--------------------------

# Azure DevOps Configuration
AZURE_DEVOPS_ENABLED=true
AZURE_DEVOPS_ORG=miempresa
AZURE_DEVOPS_PROJECT=MiProyecto
AZURE_DEVOPS_PAT=abcd1234efgh5678ijkl9012mnop3456qrst7890
AZURE_DEVOPS_STATUS_FIELD=Custom.TestStatus
AZURE_DEVOPS_STATUS_PASSED=Passed
AZURE_DEVOPS_STATUS_FAILED=Failed
AZURE_DEVOPS_ATTACH_REPORT=true
AZURE_DEVOPS_REPORT_PATH=reports/report.html

===========================================
4. USO EN FEATURES
===========================================

Convención de Tags:
-------------------
El plugin usa los tags de los escenarios para identificar los work items:

- Primer tag: ID del Test Case a actualizar
- Segundo tag: ID de la Task donde adjuntar el reporte

Formatos de Tags Soportados:
-----------------------------
- @123 (solo número)
- @TC-123 (prefijo + número)
- @TASK-456 (prefijo + número)
- @US-789 (cualquier prefijo + número)

Ejemplo Básico:
----------------

Feature: Login Tests

  @TC-1234 @TASK-5678
  Scenario: Login exitoso
    Given navego a "https://example.com/login"
    When ingreso "user@example.com" en el campo "email"
    And ingreso "password123" en el campo "password"
    And hago click en el botón "Login"
    Then veo el elemento "Dashboard"

Resultado:
- Test Case 1234 se actualiza con estado "Passed" o "Failed"
- Task 5678 recibe el reporte HTML adjunto

Ejemplo Solo Test Case:
------------------------

  @TC-1235
  Scenario: Login con credenciales inválidas
    Given navego a "https://example.com/login"
    When ingreso "invalid@example.com" en el campo "email"
    Then veo el elemento "Error message"

Resultado:
- Test Case 1235 se actualiza con estado "Passed" o "Failed"
- No se adjunta reporte (no hay segundo tag)

Ejemplo Sin Tags:
-----------------

  Scenario: Test exploratorio
    Given navego a "https://example.com"
    Then veo el elemento "Home"

Resultado:
- No se actualiza Azure DevOps
- Útil para tests exploratorios o en desarrollo

===========================================
5. SISTEMA DE PLUGINS
===========================================

Environment.py Simplificado:
----------------------------
El plugin se activa automáticamente, no necesitas código adicional:

from hakalab_framework.behave_plugin import (
    before_all,
    after_all,
    before_feature,
    after_feature,
    before_scenario,
    after_scenario,
    before_step,
    after_step
)
from hakalab_framework.steps import *

# ¡ESO ES TODO!
# El plugin de Azure DevOps se activa automáticamente si AZURE_DEVOPS_ENABLED=true

Cómo Funciona:
--------------
1. El framework detecta AZURE_DEVOPS_ENABLED=true en .env
2. Inicializa el AzureDevOpsPlugin automáticamente
3. Después de cada escenario, el plugin:
   - Lee los tags del escenario
   - Determina el estado (Passed/Failed)
   - Actualiza el Test Case en Azure DevOps
   - Adjunta el reporte a la Task (si existe segundo tag)

Ventajas del Sistema de Plugins:
---------------------------------
✅ No necesitas código adicional en environment.py
✅ Se activa/desactiva solo con variables de entorno
✅ No interfiere con otros plugins (Jira/Xray, HTML Report, etc.)
✅ Fácil de mantener y actualizar
✅ Cada proyecto puede tener su propia configuración

===========================================
6. PERSONALIZACIÓN AVANZADA
===========================================

Personalización 1: Ruta de Reporte Dinámica
--------------------------------------------

from hakalab_framework.behave_plugin import (
    before_all as framework_before_all,
    after_scenario as framework_after_scenario
)
from hakalab_framework.steps import *

def before_all(context):
    framework_before_all(context)
    
    # Personalizar ruta de reporte
    if hasattr(context, 'azure_devops') and context.azure_devops.enabled:
        context.azure_devops.config['report_path'] = 'custom/path/report.html'

def after_scenario(context, scenario):
    framework_after_scenario(context, scenario)

Personalización 2: Procesamiento Condicional
---------------------------------------------

def after_scenario(context, scenario):
    # Solo actualizar Azure DevOps para tests críticos
    if hasattr(context, 'azure_devops') and context.azure_devops.enabled:
        if 'critical' in [tag.lower() for tag in scenario.tags]:
            # Cambiar configuración para tests críticos
            context.azure_devops.config['report_path'] = f'reports/critical/{scenario.name}.html'
    
    framework_after_scenario(context, scenario)

Personalización 3: Múltiples Archivos Adjuntos
-----------------------------------------------

def after_scenario(context, scenario):
    framework_after_scenario(context, scenario)
    
    # Adjuntar archivos adicionales
    if hasattr(context, 'azure_devops') and context.azure_devops.enabled:
        if len(scenario.tags) >= 2:
            task_id = context.azure_devops._extract_work_item_id(scenario.tags[1])
            if task_id:
                # Adjuntar screenshot
                context.azure_devops.attach_file_to_work_item(
                    task_id,
                    "screenshots/screenshot.png",
                    "Screenshot del test"
                )
                # Adjuntar logs
                context.azure_devops.attach_file_to_work_item(
                    task_id,
                    "logs/test.log",
                    "Logs de ejecución"
                )

Personalización 4: Estados Personalizados
------------------------------------------

def after_scenario(context, scenario):
    if hasattr(context, 'azure_devops') and context.azure_devops.enabled:
        # Lógica personalizada para determinar el estado
        if scenario.status == 'failed':
            status = 'Failed'
        elif scenario.status == 'skipped':
            status = 'Skipped'
        elif 'flaky' in [tag.lower() for tag in scenario.tags]:
            status = 'Flaky'
        else:
            status = 'Passed'
        
        # Actualizar manualmente con estado personalizado
        if len(scenario.tags) >= 1:
            test_case_id = context.azure_devops._extract_work_item_id(scenario.tags[0])
            if test_case_id:
                context.azure_devops.update_work_item_status(
                    test_case_id,
                    status,
                    f"Test: {scenario.name}"
                )
    
    framework_after_scenario(context, scenario)

===========================================
7. EJEMPLOS PRÁCTICOS
===========================================

Ejemplo 1: Test de UI con Azure DevOps
---------------------------------------

Feature: Login Tests

  @TC-1234 @TASK-5678
  Scenario: Login exitoso
    Given navego a "https://example.com/login"
    When ingreso "user@example.com" en el campo "email"
    And ingreso "password123" en el campo "password"
    And hago click en el botón "Login"
    Then veo el elemento "Dashboard"

Ejemplo 2: Test de API con Azure DevOps
----------------------------------------

Feature: API Tests

  @TC-2345 @TASK-6789 @no_browser
  Scenario: Validar API de usuarios
    When realizo una petición GET a "https://api.example.com/users"
    Then el código de respuesta debe ser 200
    And el JSON de respuesta debe contener la clave "users"

Ejemplo 3: Test con Validación Semántica
-----------------------------------------

Feature: Chatbot Tests

  @TC-3456 @TASK-7890
  Scenario: Validar mensaje de bienvenida
    Given uso la configuración semántica por defecto
    When navego a "https://example.com/dashboard"
    And extraigo el texto del elemento "Welcome Message" y lo guardo en "mensaje"
    Then el texto de la variable "mensaje" debe ser semánticamente similar a "Bienvenido"

Ejemplo 4: Test con Gemini como Juez
-------------------------------------

Feature: AI Testing

  @TC-4567 @TASK-8901 @no_browser
  Scenario: Validar respuesta de chatbot
    Given el contexto de reglas de negocio "support" está cargado desde "context/support.txt"
    When establezco la respuesta del SUT como "Nuestro horario es de 9am a 6pm"
    Then el Juez Gemini debe validar la respuesta con un umbral mínimo de 0.8

Ejemplo 5: Múltiples Tests para la Misma Task
----------------------------------------------

Feature: Registration Tests

  @TC-5678 @TASK-9012
  Scenario: Registro - Paso 1
    When hago click en el botón "Sign Up"
    Then veo el elemento "Email Field"
  
  @TC-5679 @TASK-9012
  Scenario: Registro - Paso 2
    When ingreso "user@example.com" en el campo "email"
    Then veo el elemento "Continue Button"

Resultado:
- Test Case 5678 actualizado
- Test Case 5679 actualizado
- Ambos reportes adjuntados a Task 9012

===========================================
8. TROUBLESHOOTING
===========================================

Error: "401 Unauthorized"
--------------------------
Causa: PAT inválido o expirado
Solución:
1. Verifica que el PAT sea correcto
2. Verifica que el PAT no haya expirado
3. Verifica que el PAT tenga permisos de Work Items (Read & Write)
4. Genera un nuevo PAT si es necesario

Error: "404 Not Found"
----------------------
Causa: Organización, proyecto o work item no encontrado
Solución:
1. Verifica que AZURE_DEVOPS_ORG sea correcto
2. Verifica que AZURE_DEVOPS_PROJECT sea correcto
3. Verifica que el work item ID exista en el proyecto
4. Verifica que tengas acceso al proyecto

Error: "Field does not exist"
------------------------------
Causa: El campo personalizado no existe
Solución:
1. Ve a Project Settings > Process en Azure DevOps
2. Verifica el nombre exacto del campo personalizado
3. Actualiza AZURE_DEVOPS_STATUS_FIELD con el nombre correcto
4. El formato suele ser "Custom.NombreCampo"

Error: "Invalid field value"
-----------------------------
Causa: El valor del campo no es válido
Solución:
1. Verifica los valores permitidos para el campo en Azure DevOps
2. Actualiza AZURE_DEVOPS_STATUS_PASSED y AZURE_DEVOPS_STATUS_FAILED
3. Los valores deben coincidir exactamente (case-sensitive)

Error: "File not found"
-----------------------
Causa: El archivo de reporte no existe
Solución:
1. Verifica que AZURE_DEVOPS_REPORT_PATH sea correcto
2. Verifica que el reporte se genere antes de adjuntarlo
3. Usa rutas relativas desde la raíz del proyecto

Error: "requests module not found"
-----------------------------------
Causa: La librería requests no está instalada
Solución:
pip install requests

Plugin No Se Activa:
--------------------
Causa: AZURE_DEVOPS_ENABLED no está configurado correctamente
Solución:
1. Verifica que .env existe en la raíz del proyecto
2. Verifica que AZURE_DEVOPS_ENABLED=true (sin espacios)
3. Reinicia el terminal después de editar .env
4. Verifica que el .env se está cargando correctamente

===========================================
9. MEJORES PRÁCTICAS
===========================================

1. Gestión de PAT:
------------------
✅ Usa PATs con expiración limitada (90 días)
✅ Renueva PATs antes de que expiren
✅ No compartas PATs en el código
✅ Usa .env y .gitignore para proteger PATs
✅ Usa diferentes PATs para diferentes entornos

2. Convención de Tags:
----------------------
✅ Usa prefijos consistentes (@TC-, @TASK-)
✅ Documenta la convención en el README del proyecto
✅ Valida que los tags sean correctos antes de ejecutar
✅ Usa tags descriptivos que identifiquen el work item

3. Organización de Reportes:
-----------------------------
✅ Usa rutas de reporte consistentes
✅ Organiza reportes por feature o módulo
✅ Incluye timestamp en nombres de reporte
✅ Limpia reportes antiguos periódicamente

4. Testing:
-----------
✅ Prueba la integración en un proyecto de prueba primero
✅ Verifica que los work items se actualizan correctamente
✅ Verifica que los reportes se adjuntan correctamente
✅ Monitorea logs para detectar errores

5. Mantenimiento:
-----------------
✅ Revisa periódicamente los work items actualizados
✅ Limpia work items obsoletos
✅ Actualiza la configuración cuando cambien los campos
✅ Documenta cambios en la configuración

6. Seguridad:
-------------
✅ No incluyas PATs en el código
✅ Usa .gitignore para excluir .env
✅ Rota PATs periódicamente
✅ Usa PATs con permisos mínimos necesarios
✅ Revoca PATs cuando ya no se usen

7. CI/CD:
---------
✅ Configura variables de entorno en el CI/CD
✅ Usa secrets para almacenar PATs
✅ Verifica que el CI/CD tenga acceso a Azure DevOps
✅ Monitorea fallos de integración en el CI/CD

===========================================
RECURSOS ADICIONALES
===========================================

Documentación:
--------------
- Azure DevOps REST API: https://learn.microsoft.com/en-us/rest/api/azure/devops/
- Work Items API: https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/
- Personal Access Tokens: https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate

Ejemplos:
---------
- hakalab_framework/examples/azure_devops_integration_example.feature
- hakalab_framework/examples/environment_simple_with_azure.py
- hakalab_framework/examples/.env.azure_devops_example

Código:
-------
- hakalab_framework/core/azure_devops_manager.py
- hakalab_framework/plugins/azure_devops_plugin.py

===========================================
FIN DE LA GUÍA
===========================================

Versión: 1.0.0
Última actualización: 2026-03-12
