GitHub Actions para pruebas Selenium
GitHub Actions es la plataforma de CI/CD integrada en GitHub. Los runners ubuntu-latest ya tienen instalados Chrome, Firefox y Java, lo que los hace ideales para ejecutar pruebas Selenium sin configuración adicional de navegadores.
Ventajas frente a otras soluciones CI/CD:
- Integración nativa con GitHub (pull requests, issues, releases)
- Runners gratuitos con 2000 minutos/mes en planes free
- Chrome y Firefox preinstalados en los runners Ubuntu
- Marketplace de actions con miles de acciones reutilizables
Workflow básico para Maven + Selenium
Crea el archivo .github/workflows/selenium-tests.yml:
# .github/workflows/selenium-tests.yml
name: Pruebas Selenium
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
selenium-tests:
name: Tests Selenium en ${{ matrix.os }}
runs-on: ubuntu-latest # Chrome y Firefox preinstalados
steps:
# 1. Checkout del código
- name: Obtener código fuente
uses: actions/checkout@v4
# 2. Configurar Java
- name: Configurar JDK 21
uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "temurin"
cache: maven # Caché automático de ~/.m2
# 3. Verificar Chrome instalado
- name: Verificar versión de Chrome
run: google-chrome --version
# 4. Ejecutar tests
- name: Ejecutar pruebas Selenium
run: mvn test -B
env:
CHROME_HEADLESS: "true"
BASE_URL: ${{ vars.BASE_URL }}
# 5. Publicar reporte de tests
- name: Publicar reporte Surefire
uses: actions/upload-artifact@v4
if: always() # Publicar aunque los tests fallen
with:
name: reporte-selenium-${{ github.run_number }}
path: target/surefire-reports/
retention-days: 30
Configurar ChromeDriver para CI
Los runners de GitHub Actions son entornos sin interfaz gráfica. Selenium Manager detecta automáticamente el Chrome instalado, pero es necesario configurar las opciones correctas:
// src/test/java/utils/DriverFactory.java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
public class DriverFactory {
public static WebDriver crearDriver() {
String navegador = System.getProperty("navegador", "chrome");
boolean headless = Boolean.parseBoolean(
System.getenv().getOrDefault("CHROME_HEADLESS", "false")
);
return switch (navegador.toLowerCase()) {
case "chrome" -> crearChrome(headless);
case "firefox" -> crearFirefox(headless);
default -> throw new IllegalArgumentException(
"Navegador no soportado: " + navegador
);
};
}
private static WebDriver crearChrome(boolean headless) {
var options = new ChromeOptions();
if (headless) {
options.addArguments("--headless=new"); // Chrome 112+ headless moderno
}
// Opciones esenciales para contenedores Docker / GitHub Actions
options.addArguments("--no-sandbox");
options.addArguments("--disable-dev-shm-usage");
options.addArguments("--disable-gpu");
options.addArguments("--window-size=1920,1080");
options.addArguments("--disable-extensions");
return new ChromeDriver(options);
}
private static WebDriver crearFirefox(boolean headless) {
var options = new FirefoxOptions();
if (headless) {
options.addArguments("--headless");
}
return new FirefoxDriver(options);
}
}
Workflow con matriz de navegadores y versiones
Ejecutar las mismas pruebas en múltiples navegadores y versiones de Java:
# .github/workflows/selenium-matrix.yml
name: Pruebas Selenium - Matriz
on:
push:
branches: [ main ]
schedule:
- cron: "0 6 * * 1-5" # Lunes a viernes a las 6:00 AM
jobs:
tests-matriz:
name: Java ${{ matrix.java }} / ${{ matrix.navegador }}
runs-on: ubuntu-latest
strategy:
fail-fast: false # No cancelar otros jobs si uno falla
matrix:
java: [ "21", "17" ]
navegador: [ "chrome", "firefox" ]
steps:
- uses: actions/checkout@v4
- name: Configurar JDK ${{ matrix.java }}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: "temurin"
cache: maven
- name: Ejecutar tests con ${{ matrix.navegador }}
run: mvn test -B -Dnavegador=${{ matrix.navegador }}
env:
CHROME_HEADLESS: "true"
- name: Subir reporte
uses: actions/upload-artifact@v4
if: always()
with:
name: reporte-java${{ matrix.java }}-${{ matrix.navegador }}
path: target/surefire-reports/
Workflow con Gradle
# .github/workflows/selenium-gradle.yml
name: Pruebas Selenium con Gradle
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
selenium:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configurar JDK 21
uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "temurin"
# Caché manual para Gradle
- name: Caché de Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: gradle-
- name: Hacer ejecutable el wrapper de Gradle
run: chmod +x gradlew
- name: Ejecutar tests
run: ./gradlew test --no-daemon
env:
CHROME_HEADLESS: "true"
- name: Publicar resultados de tests
uses: actions/upload-artifact@v4
if: always()
with:
name: resultados-gradle
path: build/reports/tests/test/
retention-days: 7
Gestión de secretos y variables de entorno
# .github/workflows/selenium-con-secretos.yml
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "temurin"
cache: maven
- name: Ejecutar tests de integración
run: mvn test -B -Dgroups=integracion
env:
CHROME_HEADLESS: "true"
# Variables de entorno de configuración (GitHub Actions Variables)
BASE_URL: ${{ vars.STAGING_URL }}
APP_TIMEOUT: ${{ vars.TEST_TIMEOUT }}
# Secretos (GitHub Actions Secrets - no se muestran en logs)
TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
API_KEY: ${{ secrets.API_KEY }}
Lectura en Java:
// src/test/java/config/ConfiguracionPruebas.java
public class ConfiguracionPruebas {
public static String getBaseUrl() {
return System.getenv().getOrDefault("BASE_URL", "http://localhost:8080");
}
public static String getUsuarioPrueba() {
return System.getenv().getOrDefault("TEST_USER_EMAIL", "test@local.com");
}
public static String getPasswordPrueba() {
return System.getenv().getOrDefault("TEST_USER_PASSWORD", "test_password");
}
public static int getTimeoutSegundos() {
return Integer.parseInt(
System.getenv().getOrDefault("APP_TIMEOUT", "10")
);
}
}
Notificaciones de resultados en Pull Requests
# Publicar resumen de resultados en el PR
- name: Publicar resumen de tests
uses: dorny/test-reporter@v1
if: always()
with:
name: Resultados Selenium
path: target/surefire-reports/*.xml
reporter: java-junit
fail-on-error: true
Workflow completo con todas las optimizaciones
# .github/workflows/selenium-completo.yml
name: Suite Completa Selenium
on:
push:
branches: [ main ]
pull_request:
branches: [ main, develop ]
env:
JAVA_VERSION: "21"
MAVEN_OPTS: "-Xmx2048m"
jobs:
# Fase 1: Compilación y tests unitarios
compilar:
name: Compilar y tests unitarios
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: temurin
cache: maven
- run: mvn compile test-compile -B
# Fase 2: Tests Selenium en paralelo
selenium:
name: Selenium (${{ matrix.grupo }})
runs-on: ubuntu-latest
needs: compilar
strategy:
fail-fast: false
matrix:
grupo: [ autenticacion, catalogo, checkout, perfil ]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: temurin
cache: maven
- name: Tests del grupo ${{ matrix.grupo }}
run: mvn test -B -Dgroups=${{ matrix.grupo }}
env:
CHROME_HEADLESS: "true"
BASE_URL: ${{ vars.STAGING_URL }}
TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
- name: Captura de pantallas en fallos
uses: actions/upload-artifact@v4
if: failure()
with:
name: capturas-fallo-${{ matrix.grupo }}
path: target/capturas/
retention-days: 7
- name: Reportes de tests
uses: actions/upload-artifact@v4
if: always()
with:
name: reporte-${{ matrix.grupo }}-${{ github.run_number }}
path: target/surefire-reports/
retention-days: 14
Solución de problemas comunes en CI
Chrome falla en GitHub Actions
// Añadir siempre estas opciones en CI
options.addArguments("--headless=new");
options.addArguments("--no-sandbox"); // Requerido en contenedores
options.addArguments("--disable-dev-shm-usage"); // Evita crashes por falta de memoria compartida
options.addArguments("--disable-gpu"); // Evita problemas de renderizado
options.addArguments("--window-size=1920,1080"); // Resolución fija
options.addArguments("--remote-debugging-port=9222");
Tests lentos por timeouts
- name: Ejecutar tests con timeout extendido
run: mvn test -B
timeout-minutes: 30 # Timeout a nivel de GitHub Actions
env:
CHROME_HEADLESS: "true"
APP_TIMEOUT: "20" # Timeout de esperas Selenium en segundos
Verificar que Chrome está disponible
- name: Información del entorno
run: |
echo "Chrome: $(google-chrome --version)"
echo "Firefox: $(firefox --version)"
echo "Java: $(java -version 2>&1)"
echo "Maven: $(mvn -version)"
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en Selenium
Documentación oficial de Selenium
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Selenium es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Selenium
Explora más contenido relacionado con Selenium y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Crear un workflow de GitHub Actions que ejecute tests Selenium en cada push y PR. Configurar Chrome headless en entornos Ubuntu de GitHub Actions. Usar matrices de versiones para probar en múltiples versiones de Java y navegadores. Guardar y publicar reportes HTML de Surefire como artefactos de GitHub Actions. Gestionar variables de entorno y secretos para URLs y credenciales de prueba. Optimizar el pipeline con caché de dependencias Maven/Gradle para builds más rápidos.