La integración continua (CI) crea, prueba y valida automáticamente el código de investigación en cada confirmación. Para el software científico, CI es esencial para la reproducibilidad, la detección temprana de errores y el mantenimiento de la calidad a lo largo del tiempo. Implementar CI: (1) Escribir pruebas automatizadas con PyTest, (2) configurar una canalización de CI utilizando GitHub Actions o GitLab CI, (3) usar Docker/Conda para la coherencia del entorno, (4) agregar informes de cobertura y (5) incorporar puntos de referencia de rendimiento. Maneje las pruebas numéricas con pytest.approx, use estrategias de matriz para probar en versiones de Python y dependencias de caché para reducir el tiempo de ejecución. CI transforma el código de investigación de scripts frágiles en software confiable y mantenible.
Introducción: ¿Por qué la integración continua es importante para la investigación?
El software de investigación es conocido por romper en silencio. Un pequeño cambio en una parte del código puede producir resultados sutilmente diferentes aguas abajo, invalidando los hallazgos publicados o perdiendo meses de tiempo de cálculo. Las pruebas manuales tradicionales, ejecutando algunos ejemplos a mano, no se escalan a códigos de simulación complejos con docenas de módulos interdependientes.
La integración continua (CI) soluciona esto ejecutando automáticamente un conjunto de pruebas completo cada vez que se confirma el código. Pero CI es más que solo automatización; Es una disciplina de calidad que hace cumplir la reproducibilidad y valida la corrección continuamente. Como Mejores prácticas de computación científica Notas en papel, «Automated Las pruebas no son negociables para un software científico de confianza» (Wilson et al., 2012).
Para los equipos de investigación, CI ofrece beneficios concretos:
- Reproducibilidad: CI verifica que el código produce resultados consistentes en entornos y en el tiempo.
- Detección temprana de defectos: los errores se detectan minutos después de que se introducen, no semanas después durante la preparación del manuscrito.
- Confianza para refactor: Con una red de seguridad de pruebas, puedes mejorar la estructura del código sin temor a romper algo.
- Habilitación de colaboración: varios contribuyentes pueden trabajar en la misma base de código con comprobaciones automatizadas que evitan las regresiones.
- Documentación de las expectativas: las pruebas sirven como especificaciones ejecutables que documentan cómo debe comportarse el código.
A pesar de estos beneficios, muchos proyectos de investigación aún carecen de IC. Las excusas comunes incluyen «nuestro código es demasiado complejo para probar», «las pruebas tardan demasiado» o «no tenemos tiempo para configurar CI». Esta guía desmantela estas objeciones y proporciona un enfoque práctico y paso a paso para CI adaptado al software científico.
¿Qué es la integración continua, realmente?
La integración continua es la práctica de fusionar los cambios de código en un repositorio compartido con frecuencia, idealmente varias veces al día, y verificar automáticamente cada combinación con una compilación y una canalización de prueba automatizadas. La parte «continua» significa que la retroalimentación es rápida; Los desarrolladores saben en cuestión de minutos si su cambio rompió algo.
Una canalización de CI generalmente incluye:
- checkout: el sistema CI obtiene el código más reciente.
- Configuración de entorno: Las dependencias se instalan (a menudo dentro de un contenedor).
- Análisis estático: el código está enlazado por problemas de estilo y posibles errores.
- Pruebas unitarias: Las funciones y los módulos individuales se prueban de forma aislada.
- Pruebas de integración: se prueban varios componentes juntos.
- Informes de cobertura: se mide la fracción de código ejercido por las pruebas.
- Edificio de artefacto: se generan documentación, paquetes o binarios.
- Benchmarks de rendimiento (opcional): se realiza un seguimiento de la velocidad de ejecución y el uso de memoria.
Para el software de investigación, agregamos:
- Validación numérica: pruebas que dan cuenta de las tolerancias de punto flotante y la variación estocástica.
- Verificaciones de reproducibilidad: verificación de que los resultados coinciden con los resultados de referencia dentro de los límites aceptables.
- Validación de datos: garantiza la integridad de los datos de entrada y salida.
Componentes centrales: Construyendo una tubería de CI lista para la investigación
Una tubería de CI sólida para proyectos científicos de Python debe incluir estos componentes, cada uno de los cuales aborda un aspecto de calidad específico.
Pruebas automatizadas con PyTest
La Fundación es un conjunto de pruebas completo que utiliza pytest. PyTest es el estándar de facto para las pruebas de Python debido a su simplicidad, potentes accesorios y rico ecosistema.
Para el código científico, concéntrese en:
- Pruebas unitarias para funciones individuales (por ejemplo, ¿un solucionador de difusión calcula correctamente en una malla simple?).
- Pruebas de regresión que comparan los resultados con los buenos resultados conocidos (esencial para los solucionadores de PDE).
- Pruebas basadas en la propiedad usando hipótesis para generar entradas aleatorias y verificar invariantes.
La prueba unitaria para el borrador del Código Científico (en progreso) cubre en profundidad las estrategias de PyTest, incluido el manejo de la precisión numérica.
Manejo de comparaciones numéricas
El código científico se ocupa de la aritmética de punto flotante, donde la igualdad exacta suele ser imposible debido a errores de redondeo. PyTest proporciona pytest.approx para comparaciones aproximadas:
def test_diffusion_result():
result = run_simulation()
expected = 0.123456
assert result == pytest.approx(expected, rel=1e-6) # 0.1% tolerance
Para matrices, use numpy.testing.assert_allclose:
import numpy.testing as npt
def test_field_solution():
computed = solve_pde()
reference = load_reference_solution()
npt.assert_allclose(computed, reference, rtol=1e-5, atol=1e-10)
Elija tolerancias basadas en la precisión de la física y la discretización. Documente por qué se eligieron tolerancias específicas.
Medición de cobertura de código
La cobertura de código mide cuánto de su base de código se ejecuta durante las pruebas. Si bien la cobertura del 100% no siempre es necesaria (o alcanzable), el seguimiento de la cobertura ayuda a identificar las rutas de código no probadas.
Utilice pytest-cov para generar informes de cobertura:
pytest --cov=src/ --cov-report=xml --cov-report=html
Integre con codecov o coveralls para rastrear la cobertura a lo largo del tiempo y hacer cumplir los umbrales mínimos en CI.
El guía de desarrollo de Python científico proporciona ejemplos detallados de configuración de cobertura.
Análisis estático y pelusa
Las herramientas de análisis estático detectan errores y aplican la coherencia del estilo antes de que se fusione el código:
- Flake8: Aplicación de la guía de estilo de PEP 8 y verificación básica de errores.
- MyPy: comprobación de tipo estático (la escritura gradual es valiosa incluso en el código de investigación).
- negro: formato automático de código (elimina los debates de estilo).
- Pylint: análisis de calidad de código más profundo (utilícelo con cautela; algunas reglas pueden ser demasiado estrictas para el código de investigación).
Ejecute estos como trabajos de CI separados para que las fallas no bloqueen las iteraciones de prueba rápida.
Consistencia del entorno con Docker o Conda
Uno de los mayores desafíos de reproducibilidad es el infierno de la dependencia: las diferentes versiones de las bibliotecas producen resultados diferentes. CI elimina esto instalando dependencias en un entorno limpio y controlado.
Opción A: Docker (Recomendado para CI)
Docker proporciona una completa contenedorización a nivel de sistema. A Dockerfile define el entorno exacto:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
Boettiger (2015) argumenta que Docker «es lo mejor que le ha pasado a la reproducibilidad científica» porque bloquea toda la pila de software, desde el sistema operativo hasta las bibliotecas.
Opción B: Entornos de Conda
Si su proyecto se basa en dependencias que no son de Python (p. ej., HDF5, MPI), utilice Conda:
# environment.yml
name: research-ci
dependencies:
- python=3.11
- numpy>=1.24
- scipy
- pip:
- pytest
- pytest-cov
Los sistemas CI pueden crear y activar este entorno con conda env create -f environment.yml.
Importante: Docker no garantiza la reproducibilidad advierte que incluso los contenedores pueden tener diferencias sutiles (timestamps, aleatorio semillas). Para una máxima reproducibilidad, también corrija las versiones de la biblioteca y las semillas.
Edificio de documentación
Incluya un paso para crear la documentación (Sphinx, MKDOC) y, opcionalmente, despliegue. La documentación como código garantiza que los documentos se mantengan sincronizados con el código. El borrador de paquetes de Python Scientific Python analiza esto en detalle.
Puntos de referencia de rendimiento
Para software de investigación computacionalmente intensivo, monitoree el rendimiento para detectar regresiones. Herramientas como asv (velocidad airspeed) Ejecutar puntos de referencia automáticamente y comparar con ejecuciones anteriores.
Waller et al. (2015) describen incluidos los puntos de referencia de rendimiento en CI para detectar las degradaciones de rendimiento antes de tiempo. Esto es particularmente importante para los solucionadores de PDE donde los cambios algorítmicos pueden afectar drásticamente el tiempo de ejecución.
Comparación de plataformas: Acciones de GitHub vs Gitlab CI
Existen dos plataformas de CI dominantes: GitHub Actions y Gitlab CI. Ambos son maduros y listos para la producción. La elección a menudo depende de dónde esté alojado su código.
Acciones de GitHub
Fuerzas:
- Integración profunda con GitHub (cheques de solicitud de extracción, mercado de acciones).
- Sintaxis de configuración más simple para flujos de trabajo comunes.
- comunidad más grande y más acciones de terceros.
- gratis para repositorios públicos; Nivel gratuito generoso para repositorios privados.
Debilidades:
- Menos potente para flujos de trabajo complejos en comparación con Gitlab.
- Funciones integradas limitadas para el almacenamiento en caché de dependencias en las primeras versiones (ahora mejoradas).
- Atado al ecosistema de GitHub.
adopción: el 33% de las organizaciones usan acciones de GitHub (JetBrains, 2026).
GITLAB CI
Fuerzas:
- Más rico en funciones fuera de la caja (todo en una plataforma).
- Potentes estrategias matriciales y canalizaciones padre-hijo.
- Mejor soporte para monorepos.
- Opción de autohospedaje para entornos de investigación con espacios de aire.
Debilidades:
- Curva de aprendizaje más pronunciada.
- comunidad más pequeña que las acciones de GitHub.
- La interfaz puede sentirse menos pulida.
Adopción: 19% de las organizaciones (JetBrains, 2026).
Recomendación
Si su código está en GitHub, use acciones de github para la simplicidad y la integración del ecosistema. Si está en GitLab o necesita funciones avanzadas de canalización, seleccione Gitlab CI. Para entornos HPC con espacios de aire, considere Gitlab autohospedado.
Ambas plataformas pueden lograr los mismos resultados; Las diferencias son en su mayoría preferencias de flujo de trabajo. Los ejemplos a continuación utilizan acciones de GitHub debido a su popularidad, pero los equivalentes de Gitlab CI son fáciles de construir.
Configuración de CI: un flujo de trabajo completo de acciones de GitHub
Esta sección proporciona un flujo de trabajo de acciones de GitHub listo para la producción para un paquete científico de Python. Adaptalo a la estructura de tu proyecto.
requisitos previos
- Existen pruebas (
tests/directorio). - Los requisitos están anclados (
requirements.txtoenvironment.yml). - opcional pero recomendado:
Dockerfilepara la reproducibilidad del entorno. - El repositorio de código está en GitHub.
Flujo de trabajo básico
Crear .github/workflows/ci.yml:
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements.txt'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov
- name: Run tests with coverage
run: |
pytest --cov=src/ --cov-report=xml --cov-report=term-missing --junitxml=test-results.xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.python-version }}
path: test-results.xml
Características clave:
- Estrategia de matriz: las pruebas se ejecutan en Python 3.9–3.12 en paralelo, detectando problemas de compatibilidad con anticipación.
- Caché:
actions/setup-pythonAlmacenamiento en cachés de paquetes PIP, reduciendo drásticamente el tiempo de instalación. - Cobertura: salida terminal y XML para CodeCoV.
- artefactos: los resultados de las pruebas se cargan incluso si fallan las pruebas, conservando la evidencia.
Uso de Docker en CI
Si tiene un Dockerfile, úselo para garantizar la coherencia del entorno:
- name: Build Docker image
run: docker build -t myproject-ci -f Dockerfile.ci .
- name: Run tests in Docker
run: |
docker run --rm
-v ${{ github.workspace }}:/app
myproject-ci
pytest --cov=src/ --cov-report=xml
Manejo de pruebas de larga duración
Las simulaciones científicas pueden tomar horas. Los corredores de CI tienen límites de tiempo (a menudo 6 horas). Estrategias:
- Separe las pruebas rápidas y lentas: use marcadores PyTest.
# In test file
import pytest
@pytest.mark.slow
def test_large_simulation():
# Takes >5 minutes
pass
en CI:
- name: Run quick tests
run: pytest -m "not slow"
- name: Run slow tests (optional, separate job)
if: github.event_name == 'schedule' # Only on schedule, not on every PR
run: pytest -m slow
- Selección de prueba: Ejecutar solo las pruebas afectadas por el cambio de código usando
pytest --last-failedopytest -k "test_name". - paralelizar: divida las pruebas en varios trabajos de CI usando
pytest-xdist.
Dependencias de almacenamiento en caché
Más allá del almacenamiento en caché de paquetes de Python, extensiones compiladas de caché y archivos de datos grandes:
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache pytest
uses: actions/cache@v4
with:
path: .pytest_cache
key: ${{ runner.os }}-pytest-${{ hashFiles('**/*.py') }}
Agregando pelusas
Agregue un trabajo separado para que los problemas de estilo no bloqueen la ejecución de la prueba:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install flake8 black mypy
- run: flake8 src/ tests/
- run: black --check src/ tests/
- run: mypy src/
Trampas comunes y cómo evitarlas
Basado en los desafíos de CI/CD identificados en el software de investigación (testmu AI, 2026), aquí hay errores y soluciones frecuentes.
Escoma 1: Pruebas que escama
Las pruebas escamosas pasan a veces y fallan a otras, erosionando la confianza en CI. Son especialmente comunes con:
- Condiciones de carrera en pruebas paralelas.
- Supuestos de tiempo (por ejemplo, «espera 1 segundo»).
- Aleatoriedad sin semillas fijas.
Solución: Determine todo. Use pytest accesorios con scope="session" para recursos compartidos. Establezca semillas aleatorias al comienzo de cada prueba:
import random
import numpy as np
def setup_function():
random.seed(42)
np.random.seed(42)
Escoma 2: CI que lleva demasiado tiempo
Si su canalización toma horas, los desarrolladores lo pasarán por alto.
Solución:
- Dividido en trabajos rápidos (en cada compromiso) y lentos (noche).
- Caché agresivamente (PIP, capas de Docker, datos de prueba).
- Paralelice utilizando estrategias de matriz.
- Marque las pruebas de Slow Know con
@pytest.mark.slowy ejecútelas por separado.
Escollo 3: Deriva del medio ambiente entre CI y desarrollo
Las pruebas pasan en CI pero fallan localmente porque los entornos difieren.
Solución: use la misma definición de entorno en todas partes. Docker es ideal: los desarrolladores ejecutan docker-compose run test localmente y CI usa el mismo Dockerfile. Alternativamente, use tox para administrar múltiples entornos de manera consistente.
Escollo 4: Dependencias faltantes o desactualizadas
CI falla porque se actualizó una dependencia ascendente y se rompió la compatibilidad.
Solución: Dependencias de pines exactamente en requirements.txt (package==1.2.3), no con rangos (>=1.0). Utilice un archivo de bloqueo de dependencia (pip freeze > requirements.txt). Actualice regularmente las dependencias de manera controlada (por ejemplo, PRS semanal dependabot).
Escolar 5: Sin monitoreo de rendimiento
El código se vuelve más lento con el tiempo, pero solo se nota cuando es catastrófico.
Solución: agregue puntos de referencia a CI con asv. Configúrelo para que falle si el rendimiento se degrada más allá de un umbral (por ejemplo, un 5% más lento). Consulte guía de la velocidad de Python para la implementación.
Escolar 6: Ignorar la validación numérica
Las pruebas usan == en flotadores y fallan de forma intermitente, o peor, pasan incorrectamente.
Solución: use pytest.approx y numpy.testing.assert_allclose en todas partes. Elija tolerancias basadas en el análisis numérico (por ejemplo, el error de discretización debe ser O(H²) para los métodos de segundo orden). Justificación de la tolerancia del documento en las cadenas de documentos de prueba.
Guía de Decisiones: Cuándo usar lo que
Selección de plataforma
| Situación | plataforma recomendada |
|---|---|
| Código alojado en GitHub | Acciones de GitHub |
| Código alojado en Gitlab | GITLAB CI |
| Necesita corredores auto-hospedados (con espacios en el aire) | Gitlab CI (auto-hospedado) |
| Quiere la configuración más simple | Acciones de GitHub |
| Pipelines complejos multiproyectos | Gitlab CI (Tuberías padre-hijo) |
estrategia de prueba
| Tipo de código | Enfoque recomendado |
|---|---|
| Funciones de pitón pura | Pruebas unitarias con PyTest, objetivo de alta cobertura (>90%) |
| Solucionados de PDE | Pruebas de regresión contra soluciones de referencia, pruebas basadas en la propiedad |
| Algoritmos estocásticos | Semilla aleatoria fija + pruebas estadísticas (media, varianza) |
| Simulaciones grandes (>5 min) | Separe las pruebas lentas, ejecute todas las noches; Usar @pytest.mark.slow |
| Acoplamiento multicomponente | Pruebas de integración con pequeños casos de prueba, validar la corrección de acoplamiento |
Opción de contenedor
| Necesidad | Recomendación |
|---|---|
| Máxima reproducibilidad, incluye DEPS de nivel OS | Estibador |
| Gestión de Python, más simple | Medio Ambiente |
| HPC con bibliotecas MPI | conda (o acoplador con --network=host y --ipc=host) |
| Entorno con espacios de aire | Conda Pack o Docker Guardar/Cargar |
Integración de CI con flujos de trabajo de investigación
CI no existe de forma aislada. Se conecta con otras herramientas y prácticas.
Integración de seguimiento de problemas
El estado de CI aparece automáticamente en las solicitudes de extracción de GitHub/Gitlab. Configure las reglas de protección de rama para requerir el paso de CI antes de la combinación. Esto garantiza que solo el código validado entre en la rama principal.
Las publicaciones existentes de MatForge en seguimiento de problemas y deuda técnica complementar CI definiendo cómo se gestionan los problemas. CI proporciona verificación automatizada de que los problemas se solucionan correctamente.
Conexión de reproducibilidad
Como se discutió en reproducibilidad y su papel en la depuración, CI es una piedra angular de la investigación reproducible. Se puede confiar en cada confirmación que pasa CI para producir los mismos resultados en cualquier máquina con el mismo entorno. Esto es esencial para:
- Reproducibilidad del papel: cuando los revisores piden código, puede señalar un compromiso específico que pasó CI y produjo las cifras.
- Colaboración: los contribuyentes externos pueden ejecutar las mismas pruebas localmente.
- Mantenimiento a largo plazo: años más tarde, aún puede reconstruir los resultados de una confirmación CI-validada.
Flujo de trabajo de revisión de código
Empareja CI con revisión de código obligatoria:
- El desarrollador empuja la rama, CI se ejecuta.
- Si pasa CI, abra una solicitud de extracción.
- Los revisores verifican la lógica del código y aseguran que las pruebas sean adecuadas.
- Fusionar solo después de que CI pase y revisar aprobado.
Este flujo de trabajo es estándar en la industria, pero aún es raro en la investigación. Implementarlo aumenta drásticamente la calidad del software.
Temas avanzados
Pruebas de matriz para múltiples dependencias
Los paquetes científicos a menudo dependen de Numpy/Scipy con un comportamiento específico de versión. Pruebe a través de una matriz de versiones de Python y dependencias:
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
numpy-version: ["1.24", "1.25", "1.26"]
Instale la versión numpy específica en el paso Install dependencies:
- run: |
pip install "numpy==${{ matrix.numpy-version }}" scipy
Esto detecta problemas de compatibilidad con anticipación.
Detección de regresión de rendimiento
Use asv para realizar un seguimiento del rendimiento a lo largo del tiempo:
- name: Run benchmarks
run: |
asv run --quick --show-stderr
# asv compares against previous commits and reports regressions
Configure ASV para que falle el trabajo de CI si un punto de referencia es >10% más lento que la ejecución anterior. Consulte artículo de pythonspeed para obtener más detalles.
Despliegue continuo de documentación
CI puede implementar la documentación automáticamente en las páginas de GitHub:
deploy-docs:
needs: test # Only run after tests pass
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -r requirements-docs.txt
- run: sphinx-build -b html docs/ public/
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
Esto mantiene la documentación sincronizada con los cambios de código.
Guías relacionadas
- La reproducibilidad y su papel en la depuración: cómo las prácticas de reproducibilidad mejoran la eficiencia de la depuración.
- seguimiento de la deuda técnica a largo plazo en software de investigación – gestión de la calidad del código a lo largo del tiempo; IC ayuda a prevenir nuevas deudas.
- administrar software de investigación a través de tickets: integrando CI con flujos de trabajo de seguimiento de problemas.
- Por qué el seguimiento de problemas es fundamental en los proyectos científicos – Comprender la importancia del seguimiento de problemas en el software científico desarrollo.
- Colaboración entre desarrolladores y Investigadores: convertir la innovación en un impacto escalable a través del trabajo en equipo efectivo.
Resumen y próximos pasos
La integración continua transforma el software de investigación de scripts frágiles e indocumentados en activos confiables y mantenibles. Los pasos centrales son:
- Escriba las pruebas automatizadas con PyTest, usando
pytest.approxpara comparaciones numéricas. - Configure una canalización de CI (Acciones de GitHub o CI de Gitlab) que se ejecuta en cada solicitud de empuje y extracción.
- Use Docker o Conda para garantizar la coherencia del entorno entre CI y el desarrollo.
- Agregue informes de cobertura, pelusas y creación de documentación.
- Supervise el rendimiento con puntos de referencia para capturar regresiones.
- Integre CI con sus procesos existentes de seguimiento de problemas y revisión de código.
Acciones inmediatas:
- Si no tiene pruebas, comience escribiendo algunas para las funciones más críticas. Incluso la cobertura del 20% es mejor que ninguna.
- Cree un archivo de configuración de CI básico (
.github/workflows/ci.ymlcomo se muestra arriba) e iterar. - Arregle las pruebas escamosas de inmediato: erosionan la confianza.
- Agregue una «insignia» a su Léame que muestra el estado de CI (por ejemplo,
).
Cuándo buscar consulta: si su proyecto involucra dependencias complejas (MPi, código GPU, bibliotecas patentadas) o tiene >10,000 líneas de código, considere una revisión profesional de su configuración de CI. Ofrecemos servicios de implementación personalizados de CI/CD para equipos de investigación.
Referencias y lectura adicional
- Wilson, G., et al. (2012). Mejores prácticas de computación científica. PLOS BIOLOGÍA.
- Boettiger, C. (2015). Una introducción a Docker para la investigación reproducible. ACM Sigops.
- Waller, J., et al. (2015). Incluyendo puntos de referencia de rendimiento en integración continua. Sean.
- Integración continua de software de investigación – Guía de mejores prácticas de Imperial College London.
- Acciones de GitHub: Creación y prueba de Python – Documentación oficial.
- Prácticas lo suficientemente buenas en informática científica – Carpintería de software.
Recuento de palabras: ~2,200
Tiempo de lectura: ~10 minutos
Audiencia de destino: investigadores, estudiantes graduados y desarrolladores que trabajan en proyectos científicos de Python que necesitan establecer una calidad automatizada y confiable seguridad.