,

Automatización Robótica de Procesos (RPA): Verificación del Login en Moodle con Python y Selenium

Publicado el

· Actualizado el

· Por

Automatización del login de Moodle con Python Selenium y FastAPI es una forma práctica de comprobar, de manera automática, si una plataforma Moodle permite el acceso correcto de un usuario de prueba. En este tutorial vas a construir una prueba sintética que abre un navegador headless, accede al formulario de login de Moodle, introduce credenciales controladas y devuelve una respuesta JSON consumible desde una API REST.

El objetivo no es sustituir las pruebas funcionales completas ni la monitorización de infraestructura. La idea es añadir una verificación técnica desde la perspectiva del usuario: no solo saber si el servidor responde, sino confirmar si el flujo real de autenticación funciona correctamente.

Este enfoque resulta útil cuando gestionas plataformas LMS, campus Moodle de cliente o entornos de preproducción donde necesitas detectar fallos tras una actualización, un cambio de tema, una modificación de autenticación, una incidencia con sesiones o una integración SSO.

Además, esta automatización del login de Moodle con Python Selenium y FastAPI puede integrarse con herramientas de observabilidad como Prometheus, Grafana o sistemas internos de alertas, siempre con cuidado de no exponer credenciales ni lanzar pruebas agresivas contra producción.

Resumen rápido

En esta guía construirás una prueba automática para validar el login de Moodle con Selenium y Python.

Después encapsularás esa prueba en una API REST con FastAPI para poder ejecutarla bajo demanda o integrarla en monitorización.

El tutorial parte de un entorno Moodle de pruebas, pero el patrón puede adaptarse a entornos reales con credenciales técnicas, límites de frecuencia, endpoint protegido y medidas de seguridad.

Automatización del login de Moodle con Python Selenium y FastAPI
Flujo de automatización para comprobar el login de Moodle mediante Selenium, Python y una API REST con FastAPI.

Qué problema resuelve automatizar el login de Moodle

En una plataforma Moodle real no basta con saber que el servidor responde a una petición HTTP. Puede ocurrir que Apache esté activo, que PHP-FPM funcione y que la base de datos esté disponible, pero que el formulario de login falle por un cambio en autenticación, una sesión mal configurada, una actualización del tema, un error de JavaScript o una incidencia con cookies.

Por eso una prueba sintética de login aporta una capa adicional de información. Simula una acción real de usuario y permite responder a una pregunta concreta: ¿puede un usuario iniciar sesión correctamente en Moodle ahora mismo?

Esta comprobación tiene valor para administradores de Moodle, equipos DevOps, responsables de soporte LMS y desarrolladores que trabajan con integraciones de autenticación, SSO, temas personalizados o cambios en la experiencia de acceso.

Idea clave

Una comprobación HTTP te dice si la web responde. Una prueba de login con Selenium te dice si una acción crítica del usuario funciona.

No sustituye la monitorización de servidor, pero sí la complementa desde la perspectiva de experiencia real.

Si quieres profundizar en otros enfoques de automatización dentro de Moodle, también puedes revisar esta guía sobre API REST de Moodle para automatizar tu LMS.

Arquitectura de la automatización del login de Moodle con Python Selenium y FastAPI

La solución se apoya en varias piezas sencillas. Primero, un script en Python controla un navegador mediante Selenium. Segundo, un fichero .env separa credenciales y configuración del código. Tercero, FastAPI expone la comprobación como servicio HTTP. Por último, la respuesta JSON permite integrar el resultado con otros sistemas.

El flujo es sencillo: FastAPI recibe una petición, llama a la función de comprobación, Selenium abre Moodle en modo headless, intenta iniciar sesión y devuelve un resultado estructurado. Ese resultado puede consultarse manualmente, integrarse en un panel interno o convertirse en una señal para alertas.

Flujo de automatización del login de Moodle con Selenium y FastAPI
Arquitectura de una prueba sintética de login para Moodle usando Python, Selenium y FastAPI.

En producción

Usa siempre un usuario técnico de prueba, con permisos mínimos y sin acceso a datos sensibles.

Evita lanzar estas comprobaciones con demasiada frecuencia para no generar ruido en logs, sesiones o sistemas de seguridad.

Este patrón se complementa bien con una estrategia más amplia de automatización en Moodle con cron, tareas programadas y arquitectura backend.

Requisitos previos para automatizar el login de Moodle

Antes de empezar, necesitas un entorno Python funcional y acceso a una instancia Moodle de pruebas. El ejemplo puede adaptarse a Moodle Sandbox, a un entorno de preproducción o a una instalación local. Lo importante es no empezar directamente contra producción sin controlar frecuencia, permisos y trazabilidad.

  • Python 3.9 o superior: suficiente para ejecutar Selenium, FastAPI y python-dotenv.
  • Selenium: biblioteca para automatizar interacciones con navegador.
  • ChromeDriver: controlador que permite a Selenium comunicarse con Chrome o Chromium.
  • FastAPI: framework para exponer la comprobación como API REST.
  • Uvicorn: servidor ASGI para ejecutar la aplicación FastAPI.
  • python-dotenv: librería para cargar variables desde un fichero .env.
  • Un usuario técnico de Moodle: usuario de prueba, con permisos mínimos y sin acceso a información sensible.

Instala las dependencias principales con el siguiente comando:

Bash
pip install selenium fastapi uvicorn python-dotenv

También necesitarás ChromeDriver o una configuración equivalente compatible con tu versión de Chrome o Chromium. En algunos entornos modernos, Selenium Manager puede ayudarte a resolver el driver automáticamente, pero para servidores y despliegues controlados suele ser recomendable definir la ruta de forma explícita.

Configurar el entorno y el fichero .env

El fichero .env permite separar configuración y credenciales del código fuente. Es una práctica sencilla, pero fundamental para evitar credenciales hardcodeadas en scripts, repositorios o ejemplos reutilizables.

En una automatización del login de Moodle con Python Selenium y FastAPI, el fichero .env debería contener al menos la URL de login, el usuario técnico, la contraseña y la ruta del driver si tu entorno la necesita.

Precaución importante

El fichero .env debe estar excluido de Git mediante .gitignore y gestionarse como secreto de entorno.

En un proyecto real, no uses cuentas personales ni usuarios administradores. Crea un usuario técnico específico para esta prueba.

Un ejemplo de fichero .env sería el siguiente:

INI
# .env
MOODLE_LOGIN_URL=https://campus.demo/login/index.php
MOODLE_USERNAME=usuario_demo
MOODLE_PASSWORD=********
CHROME_DRIVER_PATH=./chromedriver
LOGIN_TIMEOUT_SECONDS=15

Y el fichero .gitignore debería excluirlo:

Bash
# .gitignore
.env
__pycache__/
*.pyc
.venv/
venv/
Automatización del login de Moodle con Python Selenium y FastAPI usando navegador headless
Selenium permite validar el login de Moodle simulando la navegación de un usuario real en modo headless

Automatizar el login de Moodle con Selenium

El primer paso consiste en crear un script llamado moodle_login.py. Este script abre el navegador en modo headless, carga la URL de login, localiza los campos de usuario y contraseña, envía las credenciales y verifica si el acceso ha funcionado.

En lugar de depender de esperas fijas con time.sleep(), la versión mejorada utiliza WebDriverWait. Esto hace que la prueba sea más estable, porque espera a que aparezcan los elementos necesarios antes de interactuar con ellos.

Python
# moodle_login.py
import os
import time
from dataclasses import dataclass
from typing import Any

from dotenv import load_dotenv
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, WebDriverException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


load_dotenv()


@dataclass
class MoodleLoginConfig:
    login_url: str
    username: str
    password: str
    chrome_driver_path: str | None
    timeout_seconds: int


def load_config() -> MoodleLoginConfig:
    login_url = os.getenv("MOODLE_LOGIN_URL")
    username = os.getenv("MOODLE_USERNAME")
    password = os.getenv("MOODLE_PASSWORD")
    chrome_driver_path = os.getenv("CHROME_DRIVER_PATH")
    timeout_seconds = int(os.getenv("LOGIN_TIMEOUT_SECONDS", "15"))

    missing = [
        name
        for name, value in {
            "MOODLE_LOGIN_URL": login_url,
            "MOODLE_USERNAME": username,
            "MOODLE_PASSWORD": password,
        }.items()
        if not value
    ]

    if missing:
        raise ValueError(f"Faltan variables de entorno: {', '.join(missing)}")

    return MoodleLoginConfig(
        login_url=login_url,
        username=username,
        password=password,
        chrome_driver_path=chrome_driver_path,
        timeout_seconds=timeout_seconds,
    )


def create_driver(config: MoodleLoginConfig) -> webdriver.Chrome:
    chrome_options = Options()
    chrome_options.add_argument("--headless=new")
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    chrome_options.add_argument("--window-size=1440,1200")

    if config.chrome_driver_path:
        service = Service(config.chrome_driver_path)
        return webdriver.Chrome(service=service, options=chrome_options)

    return webdriver.Chrome(options=chrome_options)


def check_moodle_login() -> dict[str, Any]:
    config = load_config()
    driver = None
    started_at = time.perf_counter()

    try:
        driver = create_driver(config)
        wait = WebDriverWait(driver, config.timeout_seconds)

        driver.get(config.login_url)

        username_field = wait.until(
            EC.presence_of_element_located((By.ID, "username"))
        )
        password_field = wait.until(
            EC.presence_of_element_located((By.ID, "password"))
        )
        login_button = wait.until(
            EC.element_to_be_clickable((By.ID, "loginbtn"))
        )

        username_field.clear()
        username_field.send_keys(config.username)

        password_field.clear()
        password_field.send_keys(config.password)

        login_button.click()

        wait.until(
            lambda current_driver: "login/index.php" not in current_driver.current_url
        )

        current_url = driver.current_url
        elapsed_ms = round((time.perf_counter() - started_at) * 1000, 2)

        login_successful = any(
            path in current_url
            for path in ["/my", "/dashboard", "/course"]
        )

        return {
            "login_successful": login_successful,
            "status": "ok" if login_successful else "failed",
            "current_url": current_url,
            "elapsed_ms": elapsed_ms,
        }

    except TimeoutException as exception:
        elapsed_ms = round((time.perf_counter() - started_at) * 1000, 2)

        return {
            "login_successful": False,
            "status": "timeout",
            "error": str(exception),
            "elapsed_ms": elapsed_ms,
        }

    except WebDriverException as exception:
        elapsed_ms = round((time.perf_counter() - started_at) * 1000, 2)

        return {
            "login_successful": False,
            "status": "webdriver_error",
            "error": str(exception),
            "elapsed_ms": elapsed_ms,
        }

    except Exception as exception:
        elapsed_ms = round((time.perf_counter() - started_at) * 1000, 2)

        return {
            "login_successful": False,
            "status": "error",
            "error": str(exception),
            "elapsed_ms": elapsed_ms,
        }

    finally:
        if driver:
            driver.quit()


if __name__ == "__main__":
    import json

    result = check_moodle_login()
    print(json.dumps(result, indent=4, ensure_ascii=False))

Este script concentra la parte central de la prueba. La automatización abre el navegador, espera los campos del formulario, introduce las credenciales y comprueba si Moodle redirige a una zona autenticada.

Detalle importante

Validar únicamente por URL puede ser suficiente para una prueba sencilla, pero en entornos reales conviene reforzar la comprobación buscando un elemento visible del área privada: el menú de usuario, el dashboard, un enlace de cierre de sesión o una marca propia del tema.

WebDriverWait y ChromeDriver en la automatización del login de Moodle

Dos piezas son especialmente importantes en este tipo de prueba: ChromeDriver y WebDriverWait. ChromeDriver actúa como puente entre Selenium y el navegador. WebDriverWait, por su parte, permite sincronizar la automatización con el estado real de la página.

La diferencia entre una prueba frágil y una prueba razonablemente estable suele estar en las esperas. Si usas time.sleep(5), el script espera siempre cinco segundos, aunque la página haya cargado antes o tarde más. Si usas WebDriverWait, el script espera hasta que se cumpla una condición concreta.

Python
wait = WebDriverWait(driver, 15)

username_field = wait.until(
    EC.presence_of_element_located((By.ID, "username"))
)

login_button = wait.until(
    EC.element_to_be_clickable((By.ID, "loginbtn"))
)

Este patrón hace que la prueba sea más robusta frente a pequeñas variaciones de carga, cambios en el servidor, latencias temporales o diferencias entre entornos.

Si el problema no es solo validar el login, sino conectar Moodle con herramientas externas, puede interesarte también esta guía sobre integración LTI Moodle.

Exponer la automatización del login de Moodle con FastAPI

La siguiente mejora consiste en convertir el script en un pequeño servicio HTTP. De esta forma, la automatización del login de Moodle con Python Selenium y FastAPI puede ejecutarse bajo demanda desde una URL interna, desde un sistema de monitorización o desde una tarea programada.

Crea un fichero llamado main.py y expón un endpoint de comprobación:

Python
# main.py
from fastapi import FastAPI, HTTPException
from moodle_login import check_moodle_login

app = FastAPI(
    title="Moodle Login Synthetic Check",
    description="API para comprobar automáticamente el login de Moodle con Selenium.",
    version="1.0.0",
)


@app.get("/")
def root():
    return {
        "service": "moodle-login-check",
        "status": "available",
    }


@app.get("/health")
def health():
    return {
        "status": "ok",
    }


@app.get("/check-login")
def check_login():
    result = check_moodle_login()

    if not result.get("login_successful"):
        raise HTTPException(
            status_code=503,
            detail=result,
        )

    return result

Ejecuta la API con Uvicorn:

Bash
uvicorn main:app --host 0.0.0.0 --port 8000

A partir de ese momento, puedes consultar la prueba desde el navegador, desde curl, desde un monitor interno o desde un sistema de alertas:

Bash
curl http://localhost:8000/check-login

No expongas este endpoint públicamente sin protección

Si publicas esta API en un servidor, añade autenticación, limita IPs, controla frecuencia y evita devolver información sensible en los errores.

Respuesta JSON de la automatización del login de Moodle

Una de las ventajas de exponer la prueba con FastAPI es que el resultado se devuelve como JSON. Esto facilita su integración con dashboards, scripts, alertas, pipelines o herramientas internas.

Si el login funciona, la respuesta puede ser similar a esta:

Bash
{
  "login_successful": true,
  "status": "ok",
  "current_url": "https://campus.demo/my/",
  "elapsed_ms": 1842.31
}

Si el login falla, la respuesta debe indicar que la comprobación no ha sido satisfactoria:

Bash
{
  "login_successful": false,
  "status": "timeout",
  "error": "No se encontró el formulario de login dentro del tiempo configurado.",
  "elapsed_ms": 15012.55
}

Es importante usar valores booleanos reales de JSON: true y false. No conviene traducirlos a verdadero o falso, porque dejarían de ser JSON válido.

La respuesta JSON permite que la automatización del login de Moodle con Python Selenium y FastAPI deje de ser un script aislado y se convierta en una señal técnica integrable.

Monitorizar el login de Moodle automatizado con FastAPI

Una vez que tienes una API REST, puedes integrarla con distintos sistemas de monitorización. El caso más simple es una tarea programada que llame al endpoint cada cierto tiempo y registre el resultado. Un caso más avanzado sería exportar métricas para Prometheus y visualizarlas en Grafana.

Algunas métricas útiles para una prueba de login son:

  • Estado del login: correcto o fallido.
  • Tiempo de respuesta: milisegundos necesarios para completar el flujo.
  • Tipo de error: timeout, error de WebDriver, error de credenciales o fallo inesperado.
  • Fecha y hora de ejecución: útil para correlacionar incidencias.
  • Entorno comprobado: producción, preproducción, staging o demo.

Esta capa de observabilidad ayuda a detectar errores que una comprobación HTTP tradicional no vería. Por ejemplo, una página puede responder con código 200, pero el login puede estar roto por un cambio en el formulario, una redirección incorrecta, una cookie mal configurada o un problema con el proveedor de identidad.

Cuando esta prueba sintética forma parte de una solución más amplia, puede encajar dentro de un proyecto de desarrollo de software a medida con APIs, Moodle e integraciones.

Pregunta incómoda

¿Tu monitorización actual te dice que Moodle está vivo o te dice que un usuario puede entrar realmente?

Son dos señales distintas. Y en soporte LMS, la segunda suele ser la que más importa al usuario final.

Buenas prácticas antes de llevar esta prueba a producción

Una automatización de login no debe tratarse como un juguete técnico. Aunque el script sea pequeño, está interactuando con una parte sensible del LMS: la autenticación.

Antes de ejecutar esta prueba contra un Moodle real, conviene aplicar una serie de medidas mínimas:

  • Usa un usuario técnico: nunca una cuenta personal ni una cuenta de administración.
  • Limita permisos: el usuario de prueba debe tener el acceso mínimo necesario.
  • Protege el endpoint: añade autenticación, restricción por IP o acceso solo desde red interna.
  • Controla la frecuencia: no lances la prueba cada pocos segundos si no es necesario.
  • No registres contraseñas: los logs nunca deben incluir credenciales.
  • Distingue entornos: separa producción, preproducción y desarrollo.
  • Controla capturas: si guardas screenshots de error, revisa que no incluyan datos sensibles.
  • Documenta el propósito: el equipo debe saber que existe una prueba sintética de login.

También es recomendable revisar periódicamente los selectores utilizados por Selenium. Un cambio de tema, una actualización de Moodle o una personalización del formulario puede modificar los identificadores del HTML y romper la prueba.

Errores habituales

  • Usar time.sleep() como única estrategia de espera.
  • Guardar credenciales reales en el repositorio.
  • Ejecutar la prueba con un usuario administrador.
  • Exponer la API sin autenticación.
  • No diferenciar entre fallo de login, timeout y fallo de navegador.
  • No cerrar el navegador con driver.quit() en caso de error.
  • Validar el éxito solo por una URL demasiado genérica.

La automatización del login de Moodle con Python Selenium y FastAPI debe ser sencilla, pero no ingenua. Es una prueba útil si aporta señal fiable, no si genera ruido o riesgo operativo.

Preguntas frecuentes sobre automatizar el login de Moodle

¿Puedo usar esta prueba en producción?

¿Selenium es la única opción?

¿Por qué usar FastAPI?

¿Es mejor comprobar el login con Selenium o con una petición HTTP?

¿Qué usuario debería usar para esta automatización?

¿Qué ocurre si Moodle cambia el formulario de login?

Conclusión: automatización del login de Moodle con Python Selenium y FastAPI

La automatización del login de Moodle con Python Selenium y FastAPI permite validar una de las acciones más críticas de cualquier campus virtual: el acceso de los usuarios. No se trata solo de comprobar si la web responde, sino de saber si el flujo de autenticación funciona desde la perspectiva de una sesión real.

Este tipo de prueba sintética resulta especialmente útil en entornos Moodle con actualizaciones frecuentes, integraciones SSO, cambios de tema, personalizaciones del login o despliegues en varios entornos. Selenium permite simular la navegación, Python concentra la lógica de automatización y FastAPI convierte el resultado en una respuesta estructurada que otros sistemas pueden consumir.

La clave está en tratar esta solución como una herramienta de observabilidad sensible: usuario técnico, permisos mínimos, endpoint protegido, frecuencia controlada y logs sin credenciales. Bien aplicada, esta automatización no sustituye tu monitorización de servidor, pero sí añade una señal muy valiosa: saber si Moodle sigue permitiendo iniciar sesión correctamente.

Cierre

Una buena monitorización LMS no solo mira servidores. También comprueba experiencias críticas de usuario.

Y pocas experiencias son tan críticas como poder entrar correctamente en Moodle.

Deja una respuesta

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

Sobre mí

Soy Andrés Martínez Soto, CTO y consultor EdTech especializado en Moodle, LTI, IA educativa, arquitectura de plataformas e integración de sistemas educativos.

Ver perfil profesional

¿Necesitas ordenar tu ecosistema EdTech?

Te ayudo a revisar plataformas, LMS, integraciones, automatizaciones, datos e IA educativa con una visión técnica y pedagógica.

Buscar