{"id":1226,"date":"2026-08-21T14:28:41","date_gmt":"2026-08-21T14:28:41","guid":{"rendered":"https:\/\/matforge.org\/?p=1226","raw":"https:\/\/matforge.org\/?p=1226"},"modified":"2026-08-21T14:28:41","modified_gmt":"2026-08-21T14:28:41","slug":"continuous-integration-research-software-automated-testing-validation","status":"publish","type":"post","link":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/","title":{"rendered":"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s","raw":"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s"},"content":{"rendered":"<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 13<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span><p>L&rsquo;int\u00e9gration continue (CI) construit, teste et valide automatiquement le code de recherche \u00e0 chaque validation. Pour les logiciels scientifiques, CI est essentiel pour la reproductibilit\u00e9, la d\u00e9tection pr\u00e9coce des bogues et le maintien de la qualit\u00e9 dans le temps. Impl\u00e9mentez CI en&nbsp;: (1) la r\u00e9daction de tests automatis\u00e9s avec PyTest, (2) la configuration d&rsquo;un pipeline CI \u00e0 l&rsquo;aide d&rsquo;actions GitHub ou GitLab CI, (3) \u00e0 l&rsquo;aide de Docker\/CONDA pour la coh\u00e9rence de l&rsquo;environnement, (4) l&rsquo;ajout de rapports de couverture et (5) l&rsquo;int\u00e9gration de benchmarks de performance. G\u00e9rez les tests num\u00e9riques avec <code>pytest.approx<\/code>, utilisez des strat\u00e9gies matricielles pour tester les versions Python et les d\u00e9pendances de cache afin de r\u00e9duire le temps d&rsquo;ex\u00e9cution. CI transforme le code de recherche de scripts fragiles en logiciels fiables et maintenables.<\/p>\n<h2>Introduction&nbsp;: Pourquoi l&rsquo;int\u00e9gration continue est-elle importante pour la recherche&nbsp;?<\/h2>\n<p>Les logiciels de recherche sont connus pour leur rupture silencieuse. Un petit changement dans une partie du code peut produire des r\u00e9sultats subtilement diff\u00e9rents en aval, en invalidant les r\u00e9sultats publi\u00e9s ou en perdant des mois de temps de calcul. Les tests manuels traditionnels, en ex\u00e9cutant quelques exemples \u00e0 la main, ne sont pas \u00e9tendus \u00e0 des codes de simulation complexes avec des dizaines de modules interd\u00e9pendants.<\/p>\n<p>L&rsquo;int\u00e9gration continue (CI) r\u00e9sout ce probl\u00e8me en ex\u00e9cutant automatiquement une suite de tests compl\u00e8te \u00e0 chaque time code. Mais CI est plus qu&rsquo;une simple automatisation ; C&rsquo;est une discipline de qualit\u00e9 qui renforce la reproductibilit\u00e9 et valide l&rsquo;exactitude en permanence. Comme l&rsquo;indique le papier <a href=\"https:\/\/www.ee.columbia.edu\/~dpwe\/e6891\/resources\/1210.0530v3.pdf\">meilleures pratiques pour le calcul scientifique<\/a> n&rsquo;est pas n\u00e9gociable pour les logiciels scientifiques fiables\u00a0\u00bb (Wilson et al., 2012).<\/p>\n<p>Pour les \u00e9quipes de recherche, CI offre des avantages concrets :<\/p>\n<ul>\n<li><strong>Reproductibilit\u00e9<\/strong>&nbsp;: CI v\u00e9rifie que le code produit des r\u00e9sultats coh\u00e9rents dans les environnements et dans le temps.<\/li>\n<li><strong>D\u00e9tection pr\u00e9coce des d\u00e9fauts<\/strong>&nbsp;: les bogues sont d\u00e9tect\u00e9s quelques minutes apr\u00e8s leur introduction, pas des semaines plus tard lors de la pr\u00e9paration du manuscrit.<\/li>\n<li><strong>Confiance \u00e0 Refactor<\/strong>&nbsp;: Avec un filet de s\u00e9curit\u00e9 de tests, vous pouvez am\u00e9liorer la structure du code sans craindre de casser quelque chose.<\/li>\n<li><strong>Activation de la collaboration<\/strong>&nbsp;: plusieurs contributeurs peuvent fonctionner sur la m\u00eame base de code avec des v\u00e9rifications automatis\u00e9es emp\u00eachant les r\u00e9gressions.<\/li>\n<li><strong>Documentation des attentes<\/strong>&nbsp;: les tests servent de sp\u00e9cifications ex\u00e9cutables qui documentent le comportement du code.<\/li>\n<\/ul>\n<p>Malgr\u00e9 ces avantages, de nombreux projets de recherche n&rsquo;ont toujours pas de CI. Les excuses courantes incluent \u00ab\u00a0notre code est trop complexe pour \u00eatre test\u00e9\u00a0\u00bb, \u00ab\u00a0les tests prennent trop de temps\u00a0\u00bb ou \u00ab\u00a0nous n&rsquo;avons pas le temps de configurer CI\u00a0\u00bb. Ce guide d\u00e9mant\u00e8le ces objections et fournit une approche pratique, \u00e9tape par \u00e9tape, \u00e0 CI adapt\u00e9 aux logiciels scientifiques.<\/p>\n<h2>Qu&rsquo;est-ce que l&rsquo;int\u00e9gration continue, vraiment ?<\/h2>\n<p>L&rsquo;int\u00e9gration continue consiste \u00e0 fusionner fr\u00e9quemment des modifications de code dans un r\u00e9f\u00e9rentiel partag\u00e9, id\u00e9alement plusieurs fois par jour, et \u00e0 v\u00e9rifier automatiquement chaque fusion avec un pipeline de construction et de test automatis\u00e9. La partie \u00ab\u00a0continue\u00a0\u00bb signifie que la r\u00e9troaction est rapide&nbsp;; Les d\u00e9veloppeurs savent en quelques minutes si leur changement a cass\u00e9 quelque chose.<\/p>\n<p>Un pipeline CI comprend g\u00e9n\u00e9ralement :<\/p>\n<ol>\n<li><strong>Checkout<\/strong>&nbsp;: le syst\u00e8me CI r\u00e9cup\u00e8re le dernier code.<\/li>\n<li><strong>Configuration de l&rsquo;environnement<\/strong>&nbsp;: les d\u00e9pendances sont install\u00e9es (souvent dans un conteneur).<\/li>\n<li><strong>Analyse statique<\/strong>&nbsp;: le code est li\u00e9 aux probl\u00e8mes de style et aux bogues potentiels.<\/li>\n<li><strong>Tests unitaires<\/strong>&nbsp;: les fonctions et les modules individuels sont test\u00e9s isol\u00e9ment.<\/li>\n<li><strong>Tests d&rsquo;int\u00e9gration<\/strong>&nbsp;: plusieurs composants sont test\u00e9s ensemble.<\/li>\n<li><strong>Rapport de couverture<\/strong>&nbsp;: la fraction du code exerc\u00e9 par les tests est mesur\u00e9e.<\/li>\n<li><strong>Construction d&rsquo;artefacts<\/strong>&nbsp;: une documentation, des packages ou des fichiers binaires sont g\u00e9n\u00e9r\u00e9s.<\/li>\n<li><strong>Marques de performances<\/strong> (facultatif)&nbsp;: la vitesse d&rsquo;ex\u00e9cution et l&rsquo;utilisation de la m\u00e9moire sont suivies.<\/li>\n<\/ol>\n<p>Pour les logiciels de recherche, nous ajoutons :<\/p>\n<ul>\n<li><strong>Validation num\u00e9rique<\/strong>&nbsp;: tests qui tiennent compte des tol\u00e9rances en virgule flottante et des variations stochastiques.<\/li>\n<li><strong>V\u00e9rifications de reproductibilit\u00e9<\/strong>&nbsp;: v\u00e9rification des r\u00e9sultats correspondant aux r\u00e9sultats de r\u00e9f\u00e9rence dans des limites acceptables.<\/li>\n<li><strong>Validation des donn\u00e9es<\/strong>&nbsp;: Assurer l&rsquo;int\u00e9grit\u00e9 des donn\u00e9es d&rsquo;entr\u00e9e et de sortie.<\/li>\n<\/ul>\n<h2>Composants de base&nbsp;: cr\u00e9ation d&rsquo;un pipeline CI pr\u00eat pour la recherche<\/h2>\n<p>Un pipeline CI robuste pour les projets scientifiques Python devrait inclure ces composants, chacun traitant d&rsquo;un aspect de qualit\u00e9 sp\u00e9cifique.<\/p>\n<h3>Tests automatis\u00e9s avec PyTest<\/h3>\n<p>La fondation est une suite de tests compl\u00e8te utilisant <a href=\"https:\/\/docs.pytest.org\/\">pytest<\/a>. PyTest est la norme de facto pour les tests Python en raison de sa simplicit\u00e9, de ses appareils puissants et de son \u00e9cosyst\u00e8me riche.<\/p>\n<p>Pour le code scientifique, concentrez-vous sur :<\/p>\n<ul>\n<li><strong>Tests unitaires<\/strong> pour les fonctions individuelles (par exemple, un solveur de diffusion calcule-t-il correctement sur un simple maillage&nbsp;?).<\/li>\n<li><strong>Tests de r\u00e9gression<\/strong> qui comparent les r\u00e9sultats aux r\u00e9sultats connus de bons (essentiel pour les solveurs PDE).<\/li>\n<li><strong>Tests bas\u00e9s sur la propri\u00e9t\u00e9<\/strong> en utilisant <a href=\"https:\/\/hypothesis.readthedocs.io\/\">hypoth\u00e8se<\/a> pour g\u00e9n\u00e9rer des entr\u00e9es al\u00e9atoires et v\u00e9rifier les invariants.<\/li>\n<\/ul>\n<p>Les tests unitaires pour le brouillon de code scientifique (en cours) couvrent en profondeur les strat\u00e9gies Pytest, notamment la gestion de la pr\u00e9cision num\u00e9rique.<\/p>\n<h3>Gestion des comparaisons num\u00e9riques<\/h3>\n<p>Le code scientifique traite de l&rsquo;arithm\u00e9tique \u00e0 virgule flottante, o\u00f9 l&rsquo;\u00e9galit\u00e9 exacte est souvent impossible en raison d&rsquo;erreurs d&rsquo;arrondissement. PyTest fournit <code>pytest.approx<\/code> pour les comparaisons approximatives&nbsp;:<\/p>\n<pre><code class=\"language-python\">def test_diffusion_result():\n    result = run_simulation()\n    expected = 0.123456\n    assert result == pytest.approx(expected, rel=1e-6)  # 0.1% tolerance\n<\/code><\/pre>\n<p>Pour les tableaux, utilisez <code>numpy.testing.assert_allclose<\/code>&nbsp;:<\/p>\n<pre><code class=\"language-python\">import numpy.testing as npt\n\ndef test_field_solution():\n    computed = solve_pde()\n    reference = load_reference_solution()\n    npt.assert_allclose(computed, reference, rtol=1e-5, atol=1e-10)\n<\/code><\/pre>\n<p>Choisissez des tol\u00e9rances en fonction de la physique et de la pr\u00e9cision de la discr\u00e9tisation. Documentez la raison pour laquelle des tol\u00e9rances sp\u00e9cifiques ont \u00e9t\u00e9 choisies.<\/p>\n<h3>Mesure de couverture de code<\/h3>\n<p>La couverture du code mesure la quantit\u00e9 de votre base de code ex\u00e9cut\u00e9e lors des tests. Bien que la couverture \u00e0 100 % n&rsquo;est pas toujours n\u00e9cessaire (ou r\u00e9alisable), le suivi de la couverture permet d&rsquo;identifier les chemins de code non test\u00e9s.<\/p>\n<p>Utilisez <a href=\"https:\/\/pytest-cov.readthedocs.io\/\">pytest-cov<\/a> pour g\u00e9n\u00e9rer des rapports de couverture&nbsp;:<\/p>\n<pre><code class=\"language-bash\">pytest --cov=src\/ --cov-report=xml --cov-report=html\n<\/code><\/pre>\n<p>Int\u00e9grer avec <a href=\"https:\/\/codecov.io\/\">codecov<\/a> ou <a href=\"https:\/\/coveralls.io\/\">coveralls<\/a> pour suivre la couverture dans le temps et imposer des seuils minimums dans CI.<\/p>\n<p>Le <a href=\"https:\/\/learn.scientific-python.org\/development\/guides\/coverage\/\">guide de d\u00e9veloppement de python scientifique<\/a> fournit des exemples de configuration de couverture d\u00e9taill\u00e9s.<\/p>\n<h3>Analyse statique et peluche<\/h3>\n<p>Les outils d&rsquo;analyse statique r\u00e9cup\u00e8rent les bogues et appliquent la coh\u00e9rence du style avant la fusion du code&nbsp;:<\/p>\n<ul>\n<li><strong>Flake8<\/strong>&nbsp;: application du guide de style PEP&nbsp;8 et v\u00e9rification des erreurs de base.<\/li>\n<li><strong>MyPy<\/strong>&nbsp;: v\u00e9rification du type statique (le typage progressif est pr\u00e9cieux, m\u00eame dans le code de recherche).<\/li>\n<li><strong>Black<\/strong>&nbsp;: formatage automatique du code (\u00e9limine les d\u00e9bats de style).<\/li>\n<li><strong>Pylint<\/strong>&nbsp;: analyse plus approfondie de la qualit\u00e9 du code (utilisez prudemment&nbsp;; certaines r\u00e8gles peuvent \u00eatre trop strictes pour le code de recherche).<\/li>\n<\/ul>\n<p>Ex\u00e9cutez-les en tant que travaux CI distincts afin que les \u00e9checs ne bloquent pas les it\u00e9rations de test rapides.<\/p>\n<h3>Coh\u00e9rence de l&rsquo;environnement avec Docker ou Conda<\/h3>\n<p>L&rsquo;un des plus grands d\u00e9fis de reproductibilit\u00e9 est la d\u00e9pendance de l&rsquo;enfer &#8211; diff\u00e9rentes versions des biblioth\u00e8ques produisent des r\u00e9sultats diff\u00e9rents. CI \u00e9limine cela en installant des d\u00e9pendances dans un environnement propre et contr\u00f4l\u00e9.<\/p>\n<p><strong>Option A&nbsp;: Docker<\/strong> (recommand\u00e9 pour CI)<\/p>\n<p>Docker fournit une conteneurisation compl\u00e8te au niveau du syst\u00e8me. A <code>Dockerfile<\/code> d\u00e9finit l&rsquo;environnement exact&nbsp;:<\/p>\n<pre><code class=\"language-dockerfile\">FROM python:3.11-slim\n\nWORKDIR \/app\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY . .\n<\/code><\/pre>\n<p><a href=\"https:\/\/polaris.imag.fr\/arnaud.legrand\/research\/readings\/acm_sigops_si_rsea\/p71-boettiger.pdf\">boettiger (2015)<\/a> soutient que Docker \u00ab\u00a0est la meilleure chose qui soit jamais arriv\u00e9e \u00e0 la reproductibilit\u00e9 scientifique\u00a0\u00bb car il verrouille toute la pile de logiciels, du syst\u00e8me d&rsquo;exploitation aux biblioth\u00e8ques.<\/p>\n<p><strong>Option B&nbsp;: Environnements Conda<\/strong><\/p>\n<p>Si votre projet repose sur des d\u00e9pendances non-Python (par exemple, HDF5, MPI), utilisez Conda&nbsp;:<\/p>\n<pre><code class=\"language-yaml\"># environment.yml\nname: research-ci\ndependencies:\n  - python=3.11\n  - numpy&gt;=1.24\n  - scipy\n  - pip:\n    - pytest\n    - pytest-cov\n<\/code><\/pre>\n<p>Les syst\u00e8mes CI peuvent cr\u00e9er et activer cet environnement avec <code>conda env create -f environment.yml<\/code>.<\/p>\n<p><strong>Important<\/strong>&nbsp;: <a href=\"https:\/\/arxiv.org\/html\/2601.12811v1\">Docker ne garantit pas la reproductibilit\u00e9<\/a> avertit que m\u00eame les conteneurs peuvent avoir des diff\u00e9rences subtiles (horodatages, graines al\u00e9atoires). Pour une reproductibilit\u00e9 maximale, corrigez \u00e9galement les versions et les graines de la biblioth\u00e8que.<\/p>\n<h3>Cr\u00e9ation de documentation<\/h3>\n<p>Incluez une \u00e9tape pour cr\u00e9er de la documentation (Sphinx, MkDocs) et le d\u00e9ployer \u00e9ventuellement. Documentation-as-code garantit que les documents restent synchronis\u00e9s avec le code. Le projet de meilleures pratiques de documentation pour les packages scientifiques Python en d\u00e9taille.<\/p>\n<h3>R\u00e9f\u00e9rences de performance<\/h3>\n<p>Pour les logiciels de recherche intensifs en calculs, surveillez les performances pour d\u00e9tecter les r\u00e9gressions. Des outils tels que <a href=\"https:\/\/asv.readthedocs.io\/\">asv (v\u00e9locit\u00e9 airspeed)<\/a> ex\u00e9cutent automatiquement des benchmarks et se comparent aux essais pr\u00e9c\u00e9dents.<\/p>\n<p>Waller et al. (2015) d\u00e9crivent <a href=\"https:\/\/oceanrep.geomar.de\/28433\/1\/SEN2015.pdf\">y compris les benchmarks de performance dans CI<\/a> pour d\u00e9tecter rapidement les d\u00e9gradations des performances. Ceci est particuli\u00e8rement important pour les solveurs PDE o\u00f9 les modifications algorithmiques peuvent affecter consid\u00e9rablement le temps d&rsquo;ex\u00e9cution.<\/p>\n<h2>Comparaison de plateformes&nbsp;: actions GitHub vs Gitlab CI<\/h2>\n<p>Deux plates-formes CI dominantes existent&nbsp;: les actions GitHub et Gitlab CI. Les deux sont matures et pr\u00eats \u00e0 la production. Le choix d\u00e9pend souvent de l&rsquo;endroit o\u00f9 votre code est h\u00e9berg\u00e9.<\/p>\n<h3>Actions GitHub<\/h3>\n<p><strong>Forences<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Int\u00e9gration approfondie avec GitHub (v\u00e9rification des demandes d&rsquo;extraction, Marketplace des actions).<\/li>\n<li>Syntaxe de configuration plus simple pour les flux de travail courants.<\/li>\n<li>une plus grande communaut\u00e9 et plus d&rsquo;actions de tiers.<\/li>\n<li>gratuit pour les r\u00e9f\u00e9rentiels publics&nbsp;; G\u00e9n\u00e9reux niveau gratuit pour les d\u00e9p\u00f4ts priv\u00e9s.<\/li>\n<\/ul>\n<p><strong>faiblesses<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Moins puissant pour les flux de travail complexes par rapport \u00e0 GitLab.<\/li>\n<li>Fonctionnalit\u00e9s int\u00e9gr\u00e9es limit\u00e9es pour la mise en cache des d\u00e9pendances dans les premi\u00e8res versions (maintenant am\u00e9lior\u00e9e).<\/li>\n<li>Li\u00e9 \u00e0 l&rsquo;\u00e9cosyst\u00e8me GitHub.<\/li>\n<\/ul>\n<p><strong>Adoption<\/strong>&nbsp;: 33&nbsp;% des organisations utilisent des actions GitHub (JetBrains, 2026).<\/p>\n<h3>Gitlab CI<\/h3>\n<p><strong>Forences<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Plus riche en fonctionnalit\u00e9s pr\u00eates \u00e0 l&#8217;emploi (tout sur une seule plate-forme).<\/li>\n<li>Strat\u00e9gies matricielles puissantes et pipelines parent-enfant.<\/li>\n<li>Un meilleur soutien pour Monorepos.<\/li>\n<li>Option d&rsquo;auto-h\u00e9bergement pour les environnements de recherche \u00e0 \u00e9cartement a\u00e9rien.<\/li>\n<\/ul>\n<p><strong>faiblesses<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Courbe d&rsquo;apprentissage plus raide.<\/li>\n<li>Communaut\u00e9 plus petite que les actions GitHub.<\/li>\n<li>L&rsquo;interface peut sembler moins raffin\u00e9e.<\/li>\n<\/ul>\n<p><strong>Adoption<\/strong>&nbsp;: 19&nbsp;% des organisations (JetBrains, 2026).<\/p>\n<h3>Recommandation<\/h3>\n<p>Si votre code est sur GitHub, utilisez <strong>Actions GitHub<\/strong> pour la simplicit\u00e9 et l&rsquo;int\u00e9gration des \u00e9cosyst\u00e8mes. Si vous \u00eates sur Gitlab ou si vous avez besoin de fonctionnalit\u00e9s avanc\u00e9es de pipeline, choisissez <strong>Gitlab CI<\/strong>. Pour les environnements HPC \u00e0 \u00e9cart d&rsquo;air, envisagez GitLab auto-h\u00e9berg\u00e9.<\/p>\n<p>Les deux plates-formes peuvent obtenir les m\u00eames r\u00e9sultats ; Les diff\u00e9rences sont principalement une pr\u00e9f\u00e9rence de workflow. Les exemples ci-dessous utilisent des actions GitHub en raison de sa popularit\u00e9, mais les \u00e9quivalents Gitlab CI sont simples \u00e0 construire.<\/p>\n<h2>Configuration de CI&nbsp;: un flux de travail complet des actions GitHub<\/h2>\n<p>Cette section fournit un workflow d&rsquo;actions GitHub pr\u00eat pour la production pour un package scientifique Python. Adaptez-le \u00e0 la structure de votre projet.<\/p>\n<h3>Les pr\u00e9requis<\/h3>\n<ol>\n<li><strong>Les tests existent<\/strong> (<code>tests\/<\/code> r\u00e9pertoire).<\/li>\n<li><strong>Les exigences sont \u00e9pingl\u00e9es<\/strong> (<code>requirements.txt<\/code> ou <code>environment.yml<\/code>).<\/li>\n<li><strong>Facultatif mais recommand\u00e9<\/strong>&nbsp;: <code>Dockerfile<\/code> pour la reproductibilit\u00e9 de l&rsquo;environnement.<\/li>\n<li>Le r\u00e9f\u00e9rentiel de code est sur GitHub.<\/li>\n<\/ol>\n<h3>Flux de travail de base<\/h3>\n<p>Cr\u00e9er <code>.github\/workflows\/ci.yml<\/code>&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">name: CI\n\non:\n  push:\n    branches: [main, develop]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        python-version: [\"3.9\", \"3.10\", \"3.11\", \"3.12\"]\n\n    steps:\n    - uses: actions\/checkout@v4\n\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions\/setup-python@v5\n      with:\n        python-version: ${{ matrix.python-version }}\n        cache: 'pip'\n        cache-dependency-path: 'requirements.txt'\n\n    - name: Install dependencies\n      run: |\n        pip install --upgrade pip\n        pip install -r requirements.txt\n        pip install pytest pytest-cov\n\n    - name: Run tests with coverage\n      run: |\n        pytest --cov=src\/ --cov-report=xml --cov-report=term-missing --junitxml=test-results.xml\n\n    - name: Upload coverage to Codecov\n      uses: codecov\/codecov-action@v4\n      with:\n        file: .\/coverage.xml\n        flags: unittests\n        name: codecov-umbrella\n\n    - name: Upload test results\n      if: always()\n      uses: actions\/upload-artifact@v4\n      with:\n        name: test-results-${{ matrix.python-version }}\n        path: test-results.xml\n<\/code><\/pre>\n<p><strong>Caract\u00e9ristiques principales<\/strong>&nbsp;:<\/p>\n<ul>\n<li><strong>Strat\u00e9gie de la matrice<\/strong>&nbsp;: les tests s&rsquo;ex\u00e9cutent en parall\u00e8le sur Python&nbsp;3,9 \u00e0&nbsp;3,12, ce qui r\u00e9cup\u00e8re les probl\u00e8mes de compatibilit\u00e9.<\/li>\n<li><strong>Caching<\/strong>&nbsp;: <code>actions\/setup-python<\/code> met en cache les packages PIP, r\u00e9duisant consid\u00e9rablement le temps d&rsquo;installation.<\/li>\n<li><strong>Couverture<\/strong>&nbsp;: sortie de terminal et XML pour CodeCoV.<\/li>\n<li><strong>Artifacts<\/strong>&nbsp;: les r\u00e9sultats des tests sont t\u00e9l\u00e9charg\u00e9s m\u00eame si les tests \u00e9chouent, pr\u00e9servant les preuves.<\/li>\n<\/ul>\n<h3>Utilisation de Docker dans CI<\/h3>\n<p>Si vous avez un <code>Dockerfile<\/code>, utilisez-le pour assurer la coh\u00e9rence de l&rsquo;environnement&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Build Docker image\n      run: docker build -t myproject-ci -f Dockerfile.ci .\n\n    - name: Run tests in Docker\n      run: |\n        docker run --rm \n          -v ${{ github.workspace }}:\/app \n          myproject-ci \n          pytest --cov=src\/ --cov-report=xml\n<\/code><\/pre>\n<h3>G\u00e9rer les tests de longue dur\u00e9e<\/h3>\n<p>Les simulations scientifiques peuvent prendre des heures. Les coureurs CI ont des limites de temps (souvent 6 heures). Strat\u00e9gies :<\/p>\n<ol>\n<li><strong>S\u00e9parez les tests rapides et lents<\/strong>&nbsp;: utilisez des marqueurs PyTest.<\/li>\n<\/ol>\n<pre><code class=\"language-python\"># In test file\nimport pytest\n\n@pytest.mark.slow\ndef test_large_simulation():\n    # Takes &gt;5 minutes\n    pass\n<\/code><\/pre>\n<p>Dans CI&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Run quick tests\n      run: pytest -m \"not slow\"\n\n    - name: Run slow tests (optional, separate job)\n      if: github.event_name == 'schedule'  # Only on schedule, not on every PR\n      run: pytest -m slow\n<\/code><\/pre>\n<ol start=\"2\">\n<li><strong>S\u00e9lection du test<\/strong>&nbsp;: Ex\u00e9cutez uniquement les tests affect\u00e9s par le changement de code \u00e0 l&rsquo;aide de <code>pytest --last-failed<\/code> ou <code>pytest -k \"test_name\"<\/code>.<\/li>\n<li><strong>PARALLELIZE<\/strong>&nbsp;: r\u00e9partissez les tests entre plusieurs travaux CI en utilisant <code>pytest-xdist<\/code>.<\/li>\n<\/ol>\n<h3>D\u00e9pendances de mise en cache<\/h3>\n<p>Au-del\u00e0 de la mise en cache des packages Python, des extensions compil\u00e9es en cache et des fichiers de donn\u00e9es volumineux&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Cache pip packages\n      uses: actions\/cache@v4\n      with:\n        path: ~\/.cache\/pip\n        key: ${{ runner.os }}-pip-${{ hashFiles('**\/requirements.txt') }}\n        restore-keys: |\n          ${{ runner.os }}-pip-\n\n    - name: Cache pytest\n      uses: actions\/cache@v4\n      with:\n        path: .pytest_cache\n        key: ${{ runner.os }}-pytest-${{ hashFiles('**\/*.py') }}\n<\/code><\/pre>\n<h3>Ajout de peluche<\/h3>\n<p>Ajoutez un travail distinct afin que les probl\u00e8mes de style ne bloquent pas l&rsquo;ex\u00e9cution du test&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">  lint:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions\/checkout@v4\n    - uses: actions\/setup-python@v5\n      with:\n        python-version: \"3.11\"\n    - run: pip install flake8 black mypy\n    - run: flake8 src\/ tests\/\n    - run: black --check src\/ tests\/\n    - run: mypy src\/\n<\/code><\/pre>\n<h2>Des pi\u00e8ges courants et comment les \u00e9viter<\/h2>\n<p>Sur la base des d\u00e9fis CI\/CD identifi\u00e9s dans les logiciels de recherche (<a href=\"https:\/\/www.testmuai.com\/blog\/cicd-pipeline-challenges\/\">testMu, 2026<\/a>), voici des erreurs et des solutions fr\u00e9quentes.<\/p>\n<h3>Pitfall 1 : tests qui s&rsquo;\u00e9panouissent<\/h3>\n<p>Les tests floconneux r\u00e9ussissent parfois et \u00e9chouent les autres, \u00e9rodant la confiance dans CI. Ils sont particuli\u00e8rement fr\u00e9quents avec :<\/p>\n<ul>\n<li><strong>Conditions de course<\/strong> dans des tests parall\u00e8les.<\/li>\n<li><strong>Assomptions temporelles<\/strong> (par exemple, \u00ab\u00a0attendre 1 seconde\u00a0\u00bb).<\/li>\n<li><strong>al\u00e9atoire<\/strong> sans graines fixes.<\/li>\n<\/ul>\n<p><strong>Solution<\/strong>&nbsp;: tout d\u00e9terminer. Utilisez <code>pytest<\/code> les luminaires avec <code>scope=\"session\"<\/code> pour les ressources partag\u00e9es. D\u00e9finissez des graines al\u00e9atoires au d\u00e9but de chaque test&nbsp;:<\/p>\n<pre><code class=\"language-python\">import random\nimport numpy as np\n\ndef setup_function():\n    random.seed(42)\n    np.random.seed(42)\n<\/code><\/pre>\n<h3>Pitfall 2 : CI qui prend trop de temps<\/h3>\n<p>Si votre pipeline prend des heures, les d\u00e9veloppeurs le contourneront.<\/p>\n<p><strong>Solution<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Diviser en travaux rapides (sur chaque commit) et lents (nuit).<\/li>\n<li>Cache de mani\u00e8re agressive (PIP, couches Docker, donn\u00e9es de test).<\/li>\n<li>Parall\u00e9liser \u00e0 l&rsquo;aide de strat\u00e9gies matricielles.<\/li>\n<li>Marquez les tests lents connus avec <code>@pytest.mark.slow<\/code> et ex\u00e9cutez-les s\u00e9par\u00e9ment.<\/li>\n<\/ul>\n<h3>Pitfall 3 : D\u00e9rive environnementale entre CI et d\u00e9veloppement<\/h3>\n<p>Les tests r\u00e9ussissent dans CI mais \u00e9chouent localement car les environnements diff\u00e8rent.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: utilisez partout la m\u00eame d\u00e9finition d&rsquo;environnement. Docker est id\u00e9al&nbsp;: les d\u00e9veloppeurs ex\u00e9cutent <code>docker-compose run test<\/code> localement et CI utilise le m\u00eame Dockerfile. Vous pouvez \u00e9galement utiliser <code>tox<\/code> pour g\u00e9rer plusieurs environnements de mani\u00e8re coh\u00e9rente.<\/p>\n<h3>Pitfall&nbsp;4&nbsp;: d\u00e9pendances manquantes ou obsol\u00e8tes<\/h3>\n<p>CI \u00e9choue car une d\u00e9pendance a \u00e9t\u00e9 mise \u00e0 niveau en amont et a rompu la compatibilit\u00e9.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: d\u00e9pendances de broches exactement dans <code>requirements.txt<\/code> (<code>package==1.2.3<\/code>), pas avec des plages (<code>&gt;=1.0<\/code>). Utilisez un fichier de verrouillage de d\u00e9pendance (<code>pip freeze &gt; requirements.txt<\/code>). Mettez r\u00e9guli\u00e8rement \u00e0 jour les d\u00e9pendances de mani\u00e8re contr\u00f4l\u00e9e (p. ex., hebdomadaire <code>dependabot<\/code> PR).<\/p>\n<h3>Pitfall 5 : Pas de surveillance des performances<\/h3>\n<p>Le code devient plus lent au fil du temps, mais vous ne remarquez que lorsqu&rsquo;il est catastrophique.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: ajoutez des r\u00e9f\u00e9rences \u00e0 CI avec <a href=\"https:\/\/asv.readthedocs.io\/\">asv<\/a>. Configurez-le pour qu&rsquo;il \u00e9choue si les performances se d\u00e9gradent au-del\u00e0 d&rsquo;un seuil (par exemple, 5&nbsp;% plus lents). Voir <a href=\"https:\/\/pythonspeed.com\/articles\/speed-unit-tests\/\">guide de la vitesse de Python<\/a> pour la mise en \u0153uvre.<\/p>\n<h3>Pitfall 6 : Ignorer la validation num\u00e9rique<\/h3>\n<p>Les tests utilisent <code>==<\/code> sur les flotteurs et \u00e9chouent par intermittence, ou pire, r\u00e9ussissent de mani\u00e8re incorrecte.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: utilisez <code>pytest.approx<\/code> et <code>numpy.testing.assert_allclose<\/code> partout. Choisissez des tol\u00e9rances bas\u00e9es sur l&rsquo;analyse num\u00e9rique (par exemple, l&rsquo;erreur de discr\u00e9tisation doit \u00eatre O(H\u00b2) pour les m\u00e9thodes du second ordre). Documentation de tol\u00e9rance de document dans Test DocStrings.<\/p>\n<h2>Guide de d\u00e9cision : quand utiliser quoi<\/h2>\n<h3>S\u00e9lection de la plateforme<\/h3>\n<table>\n<thead>\n<tr>\n<th>Situation<\/th>\n<th>Plateforme recommand\u00e9e<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Code h\u00e9berg\u00e9 sur GitHub<\/td>\n<td>Actions GitHub<\/td>\n<\/tr>\n<tr>\n<td>Code h\u00e9berg\u00e9 sur Gitlab<\/td>\n<td>Gitlab CI<\/td>\n<\/tr>\n<tr>\n<td>Besoin de coureurs auto-h\u00e9berg\u00e9s<\/td>\n<td>Gitlab CI (auto-h\u00e9berg\u00e9)<\/td>\n<\/tr>\n<tr>\n<td>Vous voulez une configuration la plus simple<\/td>\n<td>Actions GitHub<\/td>\n<\/tr>\n<tr>\n<td>Pipelines complexes multi-projets<\/td>\n<td>Gitlab CI (pipelines parent-enfant)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>strat\u00e9gie de test<\/h3>\n<table>\n<thead>\n<tr>\n<th>Type de code<\/th>\n<th>Approche recommand\u00e9e<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Fonctions Pure Python<\/td>\n<td>Tests unitaires avec Pytest, cible de couverture \u00e9lev\u00e9e (+90%)<\/td>\n<\/tr>\n<tr>\n<td>Solveurs d&rsquo;EDP<\/td>\n<td>Tests de r\u00e9gression contre des solutions de r\u00e9f\u00e9rence, tests bas\u00e9s sur des propri\u00e9t\u00e9s<\/td>\n<\/tr>\n<tr>\n<td>Algorithmes stochastiques<\/td>\n<td>Correction des graines al\u00e9atoires + tests statistiques (moyenne, variance)<\/td>\n<\/tr>\n<tr>\n<td>Grandes simulations (&gt;5 min)<\/td>\n<td>S\u00e9parez les tests lents, ex\u00e9cutez la nuit&nbsp;; Utiliser <code>@pytest.mark.slow<\/code><\/td>\n<\/tr>\n<tr>\n<td>Couplage multi-composants<\/td>\n<td>Tests d&rsquo;int\u00e9gration avec de petits cas de test, valider l&rsquo;exactitude du couplage<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Choix de conteneurs<\/h3>\n<table>\n<thead>\n<tr>\n<th>Besoin<\/th>\n<th>Recommandation<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Reproductibilit\u00e9 maximale, inclut les DEP de niveau OS<\/td>\n<td>Docker<\/td>\n<\/tr>\n<tr>\n<td>Une gestion plus simple et plus simple<\/td>\n<td>Environnement Conda<\/td>\n<\/tr>\n<tr>\n<td>HPC avec biblioth\u00e8ques MPI<\/td>\n<td>Conda (ou Docker avec <code>--network=host<\/code> et <code>--ipc=host<\/code>)<\/td>\n<\/tr>\n<tr>\n<td>Environnement \u00e0 combles<\/td>\n<td>Conda Pack ou Docker Enregistrer\/charger<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Int\u00e9gration de CI avec les flux de travail de recherche<\/h2>\n<p>CI n&rsquo;existe pas isol\u00e9ment. Il se connecte avec d&rsquo;autres outils et pratiques.<\/p>\n<h3>Int\u00e9gration du suivi des probl\u00e8mes<\/h3>\n<p>Le statut CI appara\u00eet automatiquement sur les demandes d&rsquo;extraction GitHub\/GitLab. Configurez les r\u00e8gles de protection des branches pour exiger le passage de CI avant la fusion. Cela garantit que seul le code valid\u00e9 entre la branche principale.<\/p>\n<p>Messages existants de Matforge sur <a href=\"https:\/\/matforge.org\/why-issue-tracking-is-critical-in-scientific-projects\/\">Suivi des probl\u00e8mes<\/a> et <a href=\"https:\/\/matforge.org\/tracking-long-term-technical-debt-in-research-software\/\">dette technique<\/a> compl\u00e8te en d\u00e9finissant la mani\u00e8re dont les probl\u00e8mes sont g\u00e9r\u00e9s. CI fournit une v\u00e9rification automatique que les probl\u00e8mes sont correctement r\u00e9solus.<\/p>\n<h3>Connexion de reproductibilit\u00e9<\/h3>\n<p>Comme indiqu\u00e9 dans <a href=\"https:\/\/matforge.org\/reproducibility-and-its-role-in-debugging\/\">reproductibilit\u00e9 et son r\u00f4le dans le d\u00e9bogage<\/a>, CI est une pierre angulaire de la recherche reproductible. Chaque commit qui passe CI peut \u00eatre approuv\u00e9 pour produire les m\u00eames r\u00e9sultats sur n&rsquo;importe quelle machine avec le m\u00eame environnement. Ceci est essentiel pour :<\/p>\n<ul>\n<li><strong>Reproductibilit\u00e9 papier<\/strong>&nbsp;: lorsque les examinateurs demandent du code, vous pouvez pointer vers un commit sp\u00e9cifique qui a r\u00e9ussi CI et produit les chiffres.<\/li>\n<li><strong>Collaboration<\/strong>&nbsp;: les contributeurs externes peuvent ex\u00e9cuter les m\u00eames tests localement.<\/li>\n<li><strong>Entretien \u00e0 long terme<\/strong>&nbsp;: des ann\u00e9es plus tard, vous pouvez toujours reconstruire les r\u00e9sultats d&rsquo;un commit valid\u00e9 par CI.<\/li>\n<\/ul>\n<h3>Flux de travail de r\u00e9vision de code<\/h3>\n<p>Associez CI \u00e0 une r\u00e9vision de code obligatoire&nbsp;:<\/p>\n<ol>\n<li>Le d\u00e9veloppeur pousse la branche, CI s&rsquo;ex\u00e9cute.<\/li>\n<li>Si CI r\u00e9ussit, ouvrez une demande d&rsquo;extraction.<\/li>\n<li>Les examinateurs v\u00e9rifient la logique du code et s&rsquo;assurent que les tests sont ad\u00e9quats.<\/li>\n<li>Fusionner uniquement apr\u00e8s les passages de CI et l&rsquo;examen approuv\u00e9.<\/li>\n<\/ol>\n<p>Ce flux de travail est standard dans l&rsquo;industrie mais encore rare dans la recherche. La mise en \u0153uvre augmente consid\u00e9rablement la qualit\u00e9 des logiciels.<\/p>\n<h2>Sujets avanc\u00e9s<\/h2>\n<h3>Test de matrice pour plusieurs d\u00e9pendances<\/h3>\n<p>Les packages scientifiques d\u00e9pendent souvent de NumPy\/Scipy avec un comportement sp\u00e9cifique \u00e0 la version. Testez une matrice de versions Python et de d\u00e9pendance&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">strategy:\n  matrix:\n    python-version: [\"3.9\", \"3.10\", \"3.11\"]\n    numpy-version: [\"1.24\", \"1.25\", \"1.26\"]\n<\/code><\/pre>\n<p>Installez la version sp\u00e9cifique de NumPy \u00e0 l&rsquo;\u00e9tape <code>Install dependencies<\/code>&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - run: |\n        pip install \"numpy==${{ matrix.numpy-version }}\" scipy\n<\/code><\/pre>\n<p>Cela permet de d\u00e9tecter les probl\u00e8mes de compatibilit\u00e9 plus t\u00f4t.<\/p>\n<h3>D\u00e9tection de la r\u00e9gression des performances<\/h3>\n<p>Utilisez <a href=\"https:\/\/asv.readthedocs.io\/\">asv<\/a> pour suivre les performances dans le temps&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Run benchmarks\n      run: |\n        asv run --quick --show-stderr\n      # asv compares against previous commits and reports regressions\n<\/code><\/pre>\n<p>Configurez ASV pour \u00e9chouer au travail CI si une r\u00e9f\u00e9rence est de 10&nbsp;% plus lente que l&rsquo;ex\u00e9cution pr\u00e9c\u00e9dente. Voir <a href=\"https:\/\/pythonspeed.com\/articles\/speed-unit-tests\/\">article de PythonSpeed<\/a> pour plus de d\u00e9tails.<\/p>\n<h3>D\u00e9ploiement continu de la documentation<\/h3>\n<p>CI peut d\u00e9ployer automatiquement la documentation sur les pages GitHub&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">  deploy-docs:\n    needs: test  # Only run after tests pass\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions\/checkout@v4\n    - run: pip install -r requirements-docs.txt\n    - run: sphinx-build -b html docs\/ public\/\n    - uses: peaceiris\/actions-gh-pages@v3\n      with:\n        github_token: ${{ secrets.GITHUB_TOKEN }}\n        publish_dir: .\/public\n<\/code><\/pre>\n<p>Cela maintient la documentation synchronis\u00e9e avec les modifications de code.<\/p>\n<h2>Guides connexes<\/h2>\n<ul>\n<li><strong><a href=\"https:\/\/matforge.org\/reproducibility-and-its-role-in-debugging\/\">La reproductibilit\u00e9 et son r\u00f4le dans le d\u00e9bogage<\/a><\/strong> \u2013 comment les pratiques de reproductibilit\u00e9 am\u00e9liorent l&rsquo;efficacit\u00e9 du d\u00e9bogage.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/tracking-long-term-technical-debt-in-research-software\/\">Suivi de la dette technique \u00e0 long terme dans les logiciels de recherche<\/a><\/strong> \u2013 g\u00e9rer la qualit\u00e9 du code dans le temps&nbsp;; CI aide \u00e0 pr\u00e9venir de nouvelles dettes.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/managing-research-software-through-tickets\/\">Gestion des logiciels de recherche via des tickets<\/a><\/strong> &#8211; Int\u00e9gration de CI avec les workflows de suivi des probl\u00e8mes.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/why-issue-tracking-is-critical-in-scientific-projects\/\">Pourquoi le suivi des probl\u00e8mes est essentiel dans les projets scientifiques<\/a><\/strong> \u2013 Comprendre l&rsquo;importance du suivi des probl\u00e8mes dans le d\u00e9veloppement de logiciels scientifiques.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/collaboration-between-developers-and-researchers-turning-innovation-into-scalable-impact\/\">Collaboration entre d\u00e9veloppeurs et chercheurs<\/a><\/strong> \u2013 Transformer l&rsquo;innovation en impact \u00e9volutif gr\u00e2ce \u00e0 un travail d&rsquo;\u00e9quipe efficace.<\/li>\n<\/ul>\n<h2>R\u00e9sum\u00e9 et \u00e9tapes suivantes<\/h2>\n<p>L&rsquo;int\u00e9gration continue transforme les logiciels de recherche \u00e0 partir de scripts fragiles et non document\u00e9s en actifs fiables et maintenables. Les \u00e9tapes essentielles sont :<\/p>\n<ol>\n<li>R\u00e9digez des tests automatis\u00e9s avec PyTest, en utilisant <code>pytest.approx<\/code> pour les comparaisons num\u00e9riques.<\/li>\n<li>Configurez un pipeline CI (actions GitHub ou Gitlab CI) qui s&rsquo;ex\u00e9cute \u00e0 chaque requ\u00eate push et pull.<\/li>\n<li>Utilisez Docker ou Conda pour assurer la coh\u00e9rence de l&rsquo;environnement entre CI et le d\u00e9veloppement.<\/li>\n<li>Ajoutez la cr\u00e9ation de rapports de couverture, de peluchage et de cr\u00e9ation de documentation.<\/li>\n<li>Surveillez les performances avec des benchmarks pour d\u00e9tecter les r\u00e9gressions.<\/li>\n<li>Int\u00e9grez CI \u00e0 vos processus existants de suivi des probl\u00e8mes et de r\u00e9vision de code.<\/li>\n<\/ol>\n<p><strong>Actions imm\u00e9diates<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Si vous n&rsquo;avez pas de tests, commencez par en \u00e9crire quelques-uns pour les fonctions les plus critiques. M\u00eame une couverture de 20 % est meilleure que rien.<\/li>\n<li>Cr\u00e9ez un fichier de configuration CI de base (<code>.github\/workflows\/ci.yml<\/code> comme indiqu\u00e9 ci-dessus) et it\u00e9rez.<\/li>\n<li>R\u00e9parez imm\u00e9diatement les tests floconneux, ils \u00e9rodent la confiance.<\/li>\n<li>Ajoutez un \u00ab\u00a0badge\u00a0\u00bb \u00e0 votre fichier Lisez-moi indiquant le statut CI (par exemple, <img decoding=\"async\" src=\"https:\/\/img.shields.io\/badge\/CI-passing-green\" alt=\"ci\">).<\/li>\n<\/ul>\n<p><strong>Quand rechercher une consultation<\/strong>&nbsp;: si votre projet implique des d\u00e9pendances complexes (MPI, code GPU, biblioth\u00e8ques propri\u00e9taires) ou poss\u00e8de 10&nbsp;000&nbsp;lignes de code, envisagez un examen professionnel de votre configuration CI. Nous proposons <a href=\"\/category\/issue-tracking-tickets-technical-requests\/\">services de mise en \u0153uvre CI\/CD personnalis\u00e9s<\/a> pour les \u00e9quipes de recherche.<\/p>\n<h2>R\u00e9f\u00e9rences et lectures compl\u00e9mentaires<\/h2>\n<ul>\n<li>Wilson, G., et al. (2012). <a href=\"https:\/\/www.ee.columbia.edu\/~dpwe\/e6891\/resources\/1210.0530v3.pdf\">Meilleures pratiques pour le calcul scientifique<\/a>. <em>biologie PLOS<\/em>.<\/li>\n<li>Boettiger, C. (2015). <a href=\"https:\/\/polaris.imag.fr\/arnaud.legrand\/research\/readings\/acm_sigops_si_rsea\/p71-boettiger.pdf\">Une introduction \u00e0 Docker pour la reproductibilit\u00e9 Recherche<\/a>. <em>sigops ACM<\/em>.<\/li>\n<li>Waller, J., et al. (2015). <a\u00a00>Inclure des indices de performance dans l&rsquo;int\u00e9gration continue. <em>sean<\/em>.<\/a\u00a00><\/li>\n<li><a href=\"https:\/\/imperialcollegelondon.github.io\/ci-best-practice\/\">Int\u00e9gration continue pour les logiciels de recherche<\/a> \u2013 Guide des meilleures pratiques de l&rsquo;Imperial College London.<\/li>\n<li><a href=\"https:\/\/docs.github.com\/actions\/guides\/building-and-testing-python\">Actions GitHub&nbsp;: Construire et tester Python<\/a> \u2013 Documentation officielle.<\/li>\n<li><a href=\"https:\/\/github.com\/swcarpentry\/good-enough-practices-in-scientific-computing\">assez bonnes pratiques en informatique scientifique<\/a> \u2013 menuiseries logicielles.<\/li>\n<\/ul>\n<hr>\n<p><strong>Compte de mots<\/strong>&nbsp;: ~2&nbsp;200<br \/> <strong>Temps de lecture<\/strong>&nbsp;: ~10&nbsp;minutes<br \/> <strong>Audience cible<\/strong>&nbsp;: chercheurs, \u00e9tudiants dipl\u00f4m\u00e9s et d\u00e9veloppeurs travaillant sur des projets Python scientifiques qui ont besoin d&rsquo;\u00e9tablir une qualit\u00e9 fiable et automatis\u00e9e assurance.<\/p>\n","protected":false,"raw":"<p>L'int\u00e9gration continue (CI) construit, teste et valide automatiquement le code de recherche \u00e0 chaque validation. Pour les logiciels scientifiques, CI est essentiel pour la reproductibilit\u00e9, la d\u00e9tection pr\u00e9coce des bogues et le maintien de la qualit\u00e9 dans le temps. Impl\u00e9mentez CI en&nbsp;: (1) la r\u00e9daction de tests automatis\u00e9s avec PyTest, (2) la configuration d'un pipeline CI \u00e0 l'aide d'actions GitHub ou GitLab CI, (3) \u00e0 l'aide de Docker\/CONDA pour la coh\u00e9rence de l'environnement, (4) l'ajout de rapports de couverture et (5) l'int\u00e9gration de benchmarks de performance. G\u00e9rez les tests num\u00e9riques avec <code>pytest.approx<\/code>, utilisez des strat\u00e9gies matricielles pour tester les versions Python et les d\u00e9pendances de cache afin de r\u00e9duire le temps d'ex\u00e9cution. CI transforme le code de recherche de scripts fragiles en logiciels fiables et maintenables.<\/p>\n<h2>Introduction&nbsp;: Pourquoi l'int\u00e9gration continue est-elle importante pour la recherche&nbsp;?<\/h2>\n<p>Les logiciels de recherche sont connus pour leur rupture silencieuse. Un petit changement dans une partie du code peut produire des r\u00e9sultats subtilement diff\u00e9rents en aval, en invalidant les r\u00e9sultats publi\u00e9s ou en perdant des mois de temps de calcul. Les tests manuels traditionnels, en ex\u00e9cutant quelques exemples \u00e0 la main, ne sont pas \u00e9tendus \u00e0 des codes de simulation complexes avec des dizaines de modules interd\u00e9pendants.<\/p>\n<p>L'int\u00e9gration continue (CI) r\u00e9sout ce probl\u00e8me en ex\u00e9cutant automatiquement une suite de tests compl\u00e8te \u00e0 chaque time code. Mais CI est plus qu'une simple automatisation ; C'est une discipline de qualit\u00e9 qui renforce la reproductibilit\u00e9 et valide l'exactitude en permanence. Comme l'indique le papier <a href=\"https:\/\/www.ee.columbia.edu\/~dpwe\/e6891\/resources\/1210.0530v3.pdf\">meilleures pratiques pour le calcul scientifique<\/a> n'est pas n\u00e9gociable pour les logiciels scientifiques fiables\" (Wilson et al., 2012).<\/p>\n<p>Pour les \u00e9quipes de recherche, CI offre des avantages concrets :<\/p>\n<ul>\n<li><strong>Reproductibilit\u00e9<\/strong>&nbsp;: CI v\u00e9rifie que le code produit des r\u00e9sultats coh\u00e9rents dans les environnements et dans le temps.<\/li>\n<li><strong>D\u00e9tection pr\u00e9coce des d\u00e9fauts<\/strong>&nbsp;: les bogues sont d\u00e9tect\u00e9s quelques minutes apr\u00e8s leur introduction, pas des semaines plus tard lors de la pr\u00e9paration du manuscrit.<\/li>\n<li><strong>Confiance \u00e0 Refactor<\/strong>&nbsp;: Avec un filet de s\u00e9curit\u00e9 de tests, vous pouvez am\u00e9liorer la structure du code sans craindre de casser quelque chose.<\/li>\n<li><strong>Activation de la collaboration<\/strong>&nbsp;: plusieurs contributeurs peuvent fonctionner sur la m\u00eame base de code avec des v\u00e9rifications automatis\u00e9es emp\u00eachant les r\u00e9gressions.<\/li>\n<li><strong>Documentation des attentes<\/strong>&nbsp;: les tests servent de sp\u00e9cifications ex\u00e9cutables qui documentent le comportement du code.<\/li>\n<\/ul>\n<p>Malgr\u00e9 ces avantages, de nombreux projets de recherche n'ont toujours pas de CI. Les excuses courantes incluent \"notre code est trop complexe pour \u00eatre test\u00e9\", \"les tests prennent trop de temps\" ou \"nous n'avons pas le temps de configurer CI\". Ce guide d\u00e9mant\u00e8le ces objections et fournit une approche pratique, \u00e9tape par \u00e9tape, \u00e0 CI adapt\u00e9 aux logiciels scientifiques.<\/p>\n<h2>Qu'est-ce que l'int\u00e9gration continue, vraiment ?<\/h2>\n<p>L'int\u00e9gration continue consiste \u00e0 fusionner fr\u00e9quemment des modifications de code dans un r\u00e9f\u00e9rentiel partag\u00e9, id\u00e9alement plusieurs fois par jour, et \u00e0 v\u00e9rifier automatiquement chaque fusion avec un pipeline de construction et de test automatis\u00e9. La partie \"continue\" signifie que la r\u00e9troaction est rapide&nbsp;; Les d\u00e9veloppeurs savent en quelques minutes si leur changement a cass\u00e9 quelque chose.<\/p>\n<p>Un pipeline CI comprend g\u00e9n\u00e9ralement :<\/p>\n<ol>\n<li><strong>Checkout<\/strong>&nbsp;: le syst\u00e8me CI r\u00e9cup\u00e8re le dernier code.<\/li>\n<li><strong>Configuration de l'environnement<\/strong>&nbsp;: les d\u00e9pendances sont install\u00e9es (souvent dans un conteneur).<\/li>\n<li><strong>Analyse statique<\/strong>&nbsp;: le code est li\u00e9 aux probl\u00e8mes de style et aux bogues potentiels.<\/li>\n<li><strong>Tests unitaires<\/strong>&nbsp;: les fonctions et les modules individuels sont test\u00e9s isol\u00e9ment.<\/li>\n<li><strong>Tests d'int\u00e9gration<\/strong>&nbsp;: plusieurs composants sont test\u00e9s ensemble.<\/li>\n<li><strong>Rapport de couverture<\/strong>&nbsp;: la fraction du code exerc\u00e9 par les tests est mesur\u00e9e.<\/li>\n<li><strong>Construction d'artefacts<\/strong>&nbsp;: une documentation, des packages ou des fichiers binaires sont g\u00e9n\u00e9r\u00e9s.<\/li>\n<li><strong>Marques de performances<\/strong> (facultatif)&nbsp;: la vitesse d'ex\u00e9cution et l'utilisation de la m\u00e9moire sont suivies.<\/li>\n<\/ol>\n<p>Pour les logiciels de recherche, nous ajoutons :<\/p>\n<ul>\n<li><strong>Validation num\u00e9rique<\/strong>&nbsp;: tests qui tiennent compte des tol\u00e9rances en virgule flottante et des variations stochastiques.<\/li>\n<li><strong>V\u00e9rifications de reproductibilit\u00e9<\/strong>&nbsp;: v\u00e9rification des r\u00e9sultats correspondant aux r\u00e9sultats de r\u00e9f\u00e9rence dans des limites acceptables.<\/li>\n<li><strong>Validation des donn\u00e9es<\/strong>&nbsp;: Assurer l'int\u00e9grit\u00e9 des donn\u00e9es d'entr\u00e9e et de sortie.<\/li>\n<\/ul>\n<h2>Composants de base&nbsp;: cr\u00e9ation d'un pipeline CI pr\u00eat pour la recherche<\/h2>\n<p>Un pipeline CI robuste pour les projets scientifiques Python devrait inclure ces composants, chacun traitant d'un aspect de qualit\u00e9 sp\u00e9cifique.<\/p>\n<h3>Tests automatis\u00e9s avec PyTest<\/h3>\n<p>La fondation est une suite de tests compl\u00e8te utilisant <a href=\"https:\/\/docs.pytest.org\/\">pytest<\/a>. PyTest est la norme de facto pour les tests Python en raison de sa simplicit\u00e9, de ses appareils puissants et de son \u00e9cosyst\u00e8me riche.<\/p>\n<p>Pour le code scientifique, concentrez-vous sur :<\/p>\n<ul>\n<li><strong>Tests unitaires<\/strong> pour les fonctions individuelles (par exemple, un solveur de diffusion calcule-t-il correctement sur un simple maillage&nbsp;?).<\/li>\n<li><strong>Tests de r\u00e9gression<\/strong> qui comparent les r\u00e9sultats aux r\u00e9sultats connus de bons (essentiel pour les solveurs PDE).<\/li>\n<li><strong>Tests bas\u00e9s sur la propri\u00e9t\u00e9<\/strong> en utilisant <a href=\"https:\/\/hypothesis.readthedocs.io\/\">hypoth\u00e8se<\/a> pour g\u00e9n\u00e9rer des entr\u00e9es al\u00e9atoires et v\u00e9rifier les invariants.<\/li>\n<\/ul>\n<p>Les tests unitaires pour le brouillon de code scientifique (en cours) couvrent en profondeur les strat\u00e9gies Pytest, notamment la gestion de la pr\u00e9cision num\u00e9rique.<\/p>\n<h3>Gestion des comparaisons num\u00e9riques<\/h3>\n<p>Le code scientifique traite de l'arithm\u00e9tique \u00e0 virgule flottante, o\u00f9 l'\u00e9galit\u00e9 exacte est souvent impossible en raison d'erreurs d'arrondissement. PyTest fournit <code>pytest.approx<\/code> pour les comparaisons approximatives&nbsp;:<\/p>\n<pre><code class=\"language-python\">def test_diffusion_result():\n    result = run_simulation()\n    expected = 0.123456\n    assert result == pytest.approx(expected, rel=1e-6)  # 0.1% tolerance\n<\/code><\/pre>\n<p>Pour les tableaux, utilisez <code>numpy.testing.assert_allclose<\/code>&nbsp;:<\/p>\n<pre><code class=\"language-python\">import numpy.testing as npt\n\ndef test_field_solution():\n    computed = solve_pde()\n    reference = load_reference_solution()\n    npt.assert_allclose(computed, reference, rtol=1e-5, atol=1e-10)\n<\/code><\/pre>\n<p>Choisissez des tol\u00e9rances en fonction de la physique et de la pr\u00e9cision de la discr\u00e9tisation. Documentez la raison pour laquelle des tol\u00e9rances sp\u00e9cifiques ont \u00e9t\u00e9 choisies.<\/p>\n<h3>Mesure de couverture de code<\/h3>\n<p>La couverture du code mesure la quantit\u00e9 de votre base de code ex\u00e9cut\u00e9e lors des tests. Bien que la couverture \u00e0 100 % n'est pas toujours n\u00e9cessaire (ou r\u00e9alisable), le suivi de la couverture permet d'identifier les chemins de code non test\u00e9s.<\/p>\n<p>Utilisez <a href=\"https:\/\/pytest-cov.readthedocs.io\/\">pytest-cov<\/a> pour g\u00e9n\u00e9rer des rapports de couverture&nbsp;:<\/p>\n<pre><code class=\"language-bash\">pytest --cov=src\/ --cov-report=xml --cov-report=html\n<\/code><\/pre>\n<p>Int\u00e9grer avec <a href=\"https:\/\/codecov.io\/\">codecov<\/a> ou <a href=\"https:\/\/coveralls.io\/\">coveralls<\/a> pour suivre la couverture dans le temps et imposer des seuils minimums dans CI.<\/p>\n<p>Le <a href=\"https:\/\/learn.scientific-python.org\/development\/guides\/coverage\/\">guide de d\u00e9veloppement de python scientifique<\/a> fournit des exemples de configuration de couverture d\u00e9taill\u00e9s.<\/p>\n<h3>Analyse statique et peluche<\/h3>\n<p>Les outils d'analyse statique r\u00e9cup\u00e8rent les bogues et appliquent la coh\u00e9rence du style avant la fusion du code&nbsp;:<\/p>\n<ul>\n<li><strong>Flake8<\/strong>&nbsp;: application du guide de style PEP&nbsp;8 et v\u00e9rification des erreurs de base.<\/li>\n<li><strong>MyPy<\/strong>&nbsp;: v\u00e9rification du type statique (le typage progressif est pr\u00e9cieux, m\u00eame dans le code de recherche).<\/li>\n<li><strong>Black<\/strong>&nbsp;: formatage automatique du code (\u00e9limine les d\u00e9bats de style).<\/li>\n<li><strong>Pylint<\/strong>&nbsp;: analyse plus approfondie de la qualit\u00e9 du code (utilisez prudemment&nbsp;; certaines r\u00e8gles peuvent \u00eatre trop strictes pour le code de recherche).<\/li>\n<\/ul>\n<p>Ex\u00e9cutez-les en tant que travaux CI distincts afin que les \u00e9checs ne bloquent pas les it\u00e9rations de test rapides.<\/p>\n<h3>Coh\u00e9rence de l'environnement avec Docker ou Conda<\/h3>\n<p>L'un des plus grands d\u00e9fis de reproductibilit\u00e9 est la d\u00e9pendance de l'enfer - diff\u00e9rentes versions des biblioth\u00e8ques produisent des r\u00e9sultats diff\u00e9rents. CI \u00e9limine cela en installant des d\u00e9pendances dans un environnement propre et contr\u00f4l\u00e9.<\/p>\n<p><strong>Option A&nbsp;: Docker<\/strong> (recommand\u00e9 pour CI)<\/p>\n<p>Docker fournit une conteneurisation compl\u00e8te au niveau du syst\u00e8me. A <code>Dockerfile<\/code> d\u00e9finit l'environnement exact&nbsp;:<\/p>\n<pre><code class=\"language-dockerfile\">FROM python:3.11-slim\n\nWORKDIR \/app\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY . .\n<\/code><\/pre>\n<p><a href=\"https:\/\/polaris.imag.fr\/arnaud.legrand\/research\/readings\/acm_sigops_si_rsea\/p71-boettiger.pdf\">boettiger (2015)<\/a> soutient que Docker \"est la meilleure chose qui soit jamais arriv\u00e9e \u00e0 la reproductibilit\u00e9 scientifique\" car il verrouille toute la pile de logiciels, du syst\u00e8me d'exploitation aux biblioth\u00e8ques.<\/p>\n<p><strong>Option B&nbsp;: Environnements Conda<\/strong><\/p>\n<p>Si votre projet repose sur des d\u00e9pendances non-Python (par exemple, HDF5, MPI), utilisez Conda&nbsp;:<\/p>\n<pre><code class=\"language-yaml\"># environment.yml\nname: research-ci\ndependencies:\n  - python=3.11\n  - numpy&gt;=1.24\n  - scipy\n  - pip:\n    - pytest\n    - pytest-cov\n<\/code><\/pre>\n<p>Les syst\u00e8mes CI peuvent cr\u00e9er et activer cet environnement avec <code>conda env create -f environment.yml<\/code>.<\/p>\n<p><strong>Important<\/strong>&nbsp;: <a href=\"https:\/\/arxiv.org\/html\/2601.12811v1\">Docker ne garantit pas la reproductibilit\u00e9<\/a> avertit que m\u00eame les conteneurs peuvent avoir des diff\u00e9rences subtiles (horodatages, graines al\u00e9atoires). Pour une reproductibilit\u00e9 maximale, corrigez \u00e9galement les versions et les graines de la biblioth\u00e8que.<\/p>\n<h3>Cr\u00e9ation de documentation<\/h3>\n<p>Incluez une \u00e9tape pour cr\u00e9er de la documentation (Sphinx, MkDocs) et le d\u00e9ployer \u00e9ventuellement. Documentation-as-code garantit que les documents restent synchronis\u00e9s avec le code. Le projet de meilleures pratiques de documentation pour les packages scientifiques Python en d\u00e9taille.<\/p>\n<h3>R\u00e9f\u00e9rences de performance<\/h3>\n<p>Pour les logiciels de recherche intensifs en calculs, surveillez les performances pour d\u00e9tecter les r\u00e9gressions. Des outils tels que <a href=\"https:\/\/asv.readthedocs.io\/\">asv (v\u00e9locit\u00e9 airspeed)<\/a> ex\u00e9cutent automatiquement des benchmarks et se comparent aux essais pr\u00e9c\u00e9dents.<\/p>\n<p>Waller et al. (2015) d\u00e9crivent <a href=\"https:\/\/oceanrep.geomar.de\/28433\/1\/SEN2015.pdf\">y compris les benchmarks de performance dans CI<\/a> pour d\u00e9tecter rapidement les d\u00e9gradations des performances. Ceci est particuli\u00e8rement important pour les solveurs PDE o\u00f9 les modifications algorithmiques peuvent affecter consid\u00e9rablement le temps d'ex\u00e9cution.<\/p>\n<h2>Comparaison de plateformes&nbsp;: actions GitHub vs Gitlab CI<\/h2>\n<p>Deux plates-formes CI dominantes existent&nbsp;: les actions GitHub et Gitlab CI. Les deux sont matures et pr\u00eats \u00e0 la production. Le choix d\u00e9pend souvent de l'endroit o\u00f9 votre code est h\u00e9berg\u00e9.<\/p>\n<h3>Actions GitHub<\/h3>\n<p><strong>Forences<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Int\u00e9gration approfondie avec GitHub (v\u00e9rification des demandes d'extraction, Marketplace des actions).<\/li>\n<li>Syntaxe de configuration plus simple pour les flux de travail courants.<\/li>\n<li>une plus grande communaut\u00e9 et plus d'actions de tiers.<\/li>\n<li>gratuit pour les r\u00e9f\u00e9rentiels publics&nbsp;; G\u00e9n\u00e9reux niveau gratuit pour les d\u00e9p\u00f4ts priv\u00e9s.<\/li>\n<\/ul>\n<p><strong>faiblesses<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Moins puissant pour les flux de travail complexes par rapport \u00e0 GitLab.<\/li>\n<li>Fonctionnalit\u00e9s int\u00e9gr\u00e9es limit\u00e9es pour la mise en cache des d\u00e9pendances dans les premi\u00e8res versions (maintenant am\u00e9lior\u00e9e).<\/li>\n<li>Li\u00e9 \u00e0 l'\u00e9cosyst\u00e8me GitHub.<\/li>\n<\/ul>\n<p><strong>Adoption<\/strong>&nbsp;: 33&nbsp;% des organisations utilisent des actions GitHub (JetBrains, 2026).<\/p>\n<h3>Gitlab CI<\/h3>\n<p><strong>Forences<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Plus riche en fonctionnalit\u00e9s pr\u00eates \u00e0 l'emploi (tout sur une seule plate-forme).<\/li>\n<li>Strat\u00e9gies matricielles puissantes et pipelines parent-enfant.<\/li>\n<li>Un meilleur soutien pour Monorepos.<\/li>\n<li>Option d'auto-h\u00e9bergement pour les environnements de recherche \u00e0 \u00e9cartement a\u00e9rien.<\/li>\n<\/ul>\n<p><strong>faiblesses<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Courbe d'apprentissage plus raide.<\/li>\n<li>Communaut\u00e9 plus petite que les actions GitHub.<\/li>\n<li>L'interface peut sembler moins raffin\u00e9e.<\/li>\n<\/ul>\n<p><strong>Adoption<\/strong>&nbsp;: 19&nbsp;% des organisations (JetBrains, 2026).<\/p>\n<h3>Recommandation<\/h3>\n<p>Si votre code est sur GitHub, utilisez <strong>Actions GitHub<\/strong> pour la simplicit\u00e9 et l'int\u00e9gration des \u00e9cosyst\u00e8mes. Si vous \u00eates sur Gitlab ou si vous avez besoin de fonctionnalit\u00e9s avanc\u00e9es de pipeline, choisissez <strong>Gitlab CI<\/strong>. Pour les environnements HPC \u00e0 \u00e9cart d'air, envisagez GitLab auto-h\u00e9berg\u00e9.<\/p>\n<p>Les deux plates-formes peuvent obtenir les m\u00eames r\u00e9sultats ; Les diff\u00e9rences sont principalement une pr\u00e9f\u00e9rence de workflow. Les exemples ci-dessous utilisent des actions GitHub en raison de sa popularit\u00e9, mais les \u00e9quivalents Gitlab CI sont simples \u00e0 construire.<\/p>\n<h2>Configuration de CI&nbsp;: un flux de travail complet des actions GitHub<\/h2>\n<p>Cette section fournit un workflow d'actions GitHub pr\u00eat pour la production pour un package scientifique Python. Adaptez-le \u00e0 la structure de votre projet.<\/p>\n<h3>Les pr\u00e9requis<\/h3>\n<ol>\n<li><strong>Les tests existent<\/strong> (<code>tests\/<\/code> r\u00e9pertoire).<\/li>\n<li><strong>Les exigences sont \u00e9pingl\u00e9es<\/strong> (<code>requirements.txt<\/code> ou <code>environment.yml<\/code>).<\/li>\n<li><strong>Facultatif mais recommand\u00e9<\/strong>&nbsp;: <code>Dockerfile<\/code> pour la reproductibilit\u00e9 de l'environnement.<\/li>\n<li>Le r\u00e9f\u00e9rentiel de code est sur GitHub.<\/li>\n<\/ol>\n<h3>Flux de travail de base<\/h3>\n<p>Cr\u00e9er <code>.github\/workflows\/ci.yml<\/code>&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">name: CI\n\non:\n  push:\n    branches: [main, develop]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        python-version: [\"3.9\", \"3.10\", \"3.11\", \"3.12\"]\n\n    steps:\n    - uses: actions\/checkout@v4\n\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions\/setup-python@v5\n      with:\n        python-version: ${{ matrix.python-version }}\n        cache: 'pip'\n        cache-dependency-path: 'requirements.txt'\n\n    - name: Install dependencies\n      run: |\n        pip install --upgrade pip\n        pip install -r requirements.txt\n        pip install pytest pytest-cov\n\n    - name: Run tests with coverage\n      run: |\n        pytest --cov=src\/ --cov-report=xml --cov-report=term-missing --junitxml=test-results.xml\n\n    - name: Upload coverage to Codecov\n      uses: codecov\/codecov-action@v4\n      with:\n        file: .\/coverage.xml\n        flags: unittests\n        name: codecov-umbrella\n\n    - name: Upload test results\n      if: always()\n      uses: actions\/upload-artifact@v4\n      with:\n        name: test-results-${{ matrix.python-version }}\n        path: test-results.xml\n<\/code><\/pre>\n<p><strong>Caract\u00e9ristiques principales<\/strong>&nbsp;:<\/p>\n<ul>\n<li><strong>Strat\u00e9gie de la matrice<\/strong>&nbsp;: les tests s'ex\u00e9cutent en parall\u00e8le sur Python&nbsp;3,9 \u00e0&nbsp;3,12, ce qui r\u00e9cup\u00e8re les probl\u00e8mes de compatibilit\u00e9.<\/li>\n<li><strong>Caching<\/strong>&nbsp;: <code>actions\/setup-python<\/code> met en cache les packages PIP, r\u00e9duisant consid\u00e9rablement le temps d'installation.<\/li>\n<li><strong>Couverture<\/strong>&nbsp;: sortie de terminal et XML pour CodeCoV.<\/li>\n<li><strong>Artifacts<\/strong>&nbsp;: les r\u00e9sultats des tests sont t\u00e9l\u00e9charg\u00e9s m\u00eame si les tests \u00e9chouent, pr\u00e9servant les preuves.<\/li>\n<\/ul>\n<h3>Utilisation de Docker dans CI<\/h3>\n<p>Si vous avez un <code>Dockerfile<\/code>, utilisez-le pour assurer la coh\u00e9rence de l'environnement&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Build Docker image\n      run: docker build -t myproject-ci -f Dockerfile.ci .\n\n    - name: Run tests in Docker\n      run: |\n        docker run --rm \n          -v ${{ github.workspace }}:\/app \n          myproject-ci \n          pytest --cov=src\/ --cov-report=xml\n<\/code><\/pre>\n<h3>G\u00e9rer les tests de longue dur\u00e9e<\/h3>\n<p>Les simulations scientifiques peuvent prendre des heures. Les coureurs CI ont des limites de temps (souvent 6 heures). Strat\u00e9gies :<\/p>\n<ol>\n<li><strong>S\u00e9parez les tests rapides et lents<\/strong>&nbsp;: utilisez des marqueurs PyTest.<\/li>\n<\/ol>\n<pre><code class=\"language-python\"># In test file\nimport pytest\n\n@pytest.mark.slow\ndef test_large_simulation():\n    # Takes &gt;5 minutes\n    pass\n<\/code><\/pre>\n<p>Dans CI&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Run quick tests\n      run: pytest -m \"not slow\"\n\n    - name: Run slow tests (optional, separate job)\n      if: github.event_name == 'schedule'  # Only on schedule, not on every PR\n      run: pytest -m slow\n<\/code><\/pre>\n<ol start=\"2\">\n<li><strong>S\u00e9lection du test<\/strong>&nbsp;: Ex\u00e9cutez uniquement les tests affect\u00e9s par le changement de code \u00e0 l'aide de <code>pytest --last-failed<\/code> ou <code>pytest -k \"test_name\"<\/code>.<\/li>\n<li><strong>PARALLELIZE<\/strong>&nbsp;: r\u00e9partissez les tests entre plusieurs travaux CI en utilisant <code>pytest-xdist<\/code>.<\/li>\n<\/ol>\n<h3>D\u00e9pendances de mise en cache<\/h3>\n<p>Au-del\u00e0 de la mise en cache des packages Python, des extensions compil\u00e9es en cache et des fichiers de donn\u00e9es volumineux&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Cache pip packages\n      uses: actions\/cache@v4\n      with:\n        path: ~\/.cache\/pip\n        key: ${{ runner.os }}-pip-${{ hashFiles('**\/requirements.txt') }}\n        restore-keys: |\n          ${{ runner.os }}-pip-\n\n    - name: Cache pytest\n      uses: actions\/cache@v4\n      with:\n        path: .pytest_cache\n        key: ${{ runner.os }}-pytest-${{ hashFiles('**\/*.py') }}\n<\/code><\/pre>\n<h3>Ajout de peluche<\/h3>\n<p>Ajoutez un travail distinct afin que les probl\u00e8mes de style ne bloquent pas l'ex\u00e9cution du test&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">  lint:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions\/checkout@v4\n    - uses: actions\/setup-python@v5\n      with:\n        python-version: \"3.11\"\n    - run: pip install flake8 black mypy\n    - run: flake8 src\/ tests\/\n    - run: black --check src\/ tests\/\n    - run: mypy src\/\n<\/code><\/pre>\n<h2>Des pi\u00e8ges courants et comment les \u00e9viter<\/h2>\n<p>Sur la base des d\u00e9fis CI\/CD identifi\u00e9s dans les logiciels de recherche (<a href=\"https:\/\/www.testmuai.com\/blog\/cicd-pipeline-challenges\/\">testMu, 2026<\/a>), voici des erreurs et des solutions fr\u00e9quentes.<\/p>\n<h3>Pitfall 1 : tests qui s'\u00e9panouissent<\/h3>\n<p>Les tests floconneux r\u00e9ussissent parfois et \u00e9chouent les autres, \u00e9rodant la confiance dans CI. Ils sont particuli\u00e8rement fr\u00e9quents avec :<\/p>\n<ul>\n<li><strong>Conditions de course<\/strong> dans des tests parall\u00e8les.<\/li>\n<li><strong>Assomptions temporelles<\/strong> (par exemple, \"attendre 1 seconde\").<\/li>\n<li><strong>al\u00e9atoire<\/strong> sans graines fixes.<\/li>\n<\/ul>\n<p><strong>Solution<\/strong>&nbsp;: tout d\u00e9terminer. Utilisez <code>pytest<\/code> les luminaires avec <code>scope=\"session\"<\/code> pour les ressources partag\u00e9es. D\u00e9finissez des graines al\u00e9atoires au d\u00e9but de chaque test&nbsp;:<\/p>\n<pre><code class=\"language-python\">import random\nimport numpy as np\n\ndef setup_function():\n    random.seed(42)\n    np.random.seed(42)\n<\/code><\/pre>\n<h3>Pitfall 2 : CI qui prend trop de temps<\/h3>\n<p>Si votre pipeline prend des heures, les d\u00e9veloppeurs le contourneront.<\/p>\n<p><strong>Solution<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Diviser en travaux rapides (sur chaque commit) et lents (nuit).<\/li>\n<li>Cache de mani\u00e8re agressive (PIP, couches Docker, donn\u00e9es de test).<\/li>\n<li>Parall\u00e9liser \u00e0 l'aide de strat\u00e9gies matricielles.<\/li>\n<li>Marquez les tests lents connus avec <code>@pytest.mark.slow<\/code> et ex\u00e9cutez-les s\u00e9par\u00e9ment.<\/li>\n<\/ul>\n<h3>Pitfall 3 : D\u00e9rive environnementale entre CI et d\u00e9veloppement<\/h3>\n<p>Les tests r\u00e9ussissent dans CI mais \u00e9chouent localement car les environnements diff\u00e8rent.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: utilisez partout la m\u00eame d\u00e9finition d'environnement. Docker est id\u00e9al&nbsp;: les d\u00e9veloppeurs ex\u00e9cutent <code>docker-compose run test<\/code> localement et CI utilise le m\u00eame Dockerfile. Vous pouvez \u00e9galement utiliser <code>tox<\/code> pour g\u00e9rer plusieurs environnements de mani\u00e8re coh\u00e9rente.<\/p>\n<h3>Pitfall&nbsp;4&nbsp;: d\u00e9pendances manquantes ou obsol\u00e8tes<\/h3>\n<p>CI \u00e9choue car une d\u00e9pendance a \u00e9t\u00e9 mise \u00e0 niveau en amont et a rompu la compatibilit\u00e9.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: d\u00e9pendances de broches exactement dans <code>requirements.txt<\/code> (<code>package==1.2.3<\/code>), pas avec des plages (<code>&gt;=1.0<\/code>). Utilisez un fichier de verrouillage de d\u00e9pendance (<code>pip freeze &gt; requirements.txt<\/code>). Mettez r\u00e9guli\u00e8rement \u00e0 jour les d\u00e9pendances de mani\u00e8re contr\u00f4l\u00e9e (p. ex., hebdomadaire <code>dependabot<\/code> PR).<\/p>\n<h3>Pitfall 5 : Pas de surveillance des performances<\/h3>\n<p>Le code devient plus lent au fil du temps, mais vous ne remarquez que lorsqu'il est catastrophique.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: ajoutez des r\u00e9f\u00e9rences \u00e0 CI avec <a href=\"https:\/\/asv.readthedocs.io\/\">asv<\/a>. Configurez-le pour qu'il \u00e9choue si les performances se d\u00e9gradent au-del\u00e0 d'un seuil (par exemple, 5&nbsp;% plus lents). Voir <a href=\"https:\/\/pythonspeed.com\/articles\/speed-unit-tests\/\">guide de la vitesse de Python<\/a> pour la mise en \u0153uvre.<\/p>\n<h3>Pitfall 6 : Ignorer la validation num\u00e9rique<\/h3>\n<p>Les tests utilisent <code>==<\/code> sur les flotteurs et \u00e9chouent par intermittence, ou pire, r\u00e9ussissent de mani\u00e8re incorrecte.<\/p>\n<p><strong>Solution<\/strong>&nbsp;: utilisez <code>pytest.approx<\/code> et <code>numpy.testing.assert_allclose<\/code> partout. Choisissez des tol\u00e9rances bas\u00e9es sur l'analyse num\u00e9rique (par exemple, l'erreur de discr\u00e9tisation doit \u00eatre O(H\u00b2) pour les m\u00e9thodes du second ordre). Documentation de tol\u00e9rance de document dans Test DocStrings.<\/p>\n<h2>Guide de d\u00e9cision : quand utiliser quoi<\/h2>\n<h3>S\u00e9lection de la plateforme<\/h3>\n<table>\n<thead>\n<tr>\n<th>Situation<\/th>\n<th>Plateforme recommand\u00e9e<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Code h\u00e9berg\u00e9 sur GitHub<\/td>\n<td>Actions GitHub<\/td>\n<\/tr>\n<tr>\n<td>Code h\u00e9berg\u00e9 sur Gitlab<\/td>\n<td>Gitlab CI<\/td>\n<\/tr>\n<tr>\n<td>Besoin de coureurs auto-h\u00e9berg\u00e9s<\/td>\n<td>Gitlab CI (auto-h\u00e9berg\u00e9)<\/td>\n<\/tr>\n<tr>\n<td>Vous voulez une configuration la plus simple<\/td>\n<td>Actions GitHub<\/td>\n<\/tr>\n<tr>\n<td>Pipelines complexes multi-projets<\/td>\n<td>Gitlab CI (pipelines parent-enfant)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>strat\u00e9gie de test<\/h3>\n<table>\n<thead>\n<tr>\n<th>Type de code<\/th>\n<th>Approche recommand\u00e9e<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Fonctions Pure Python<\/td>\n<td>Tests unitaires avec Pytest, cible de couverture \u00e9lev\u00e9e (+90%)<\/td>\n<\/tr>\n<tr>\n<td>Solveurs d'EDP<\/td>\n<td>Tests de r\u00e9gression contre des solutions de r\u00e9f\u00e9rence, tests bas\u00e9s sur des propri\u00e9t\u00e9s<\/td>\n<\/tr>\n<tr>\n<td>Algorithmes stochastiques<\/td>\n<td>Correction des graines al\u00e9atoires + tests statistiques (moyenne, variance)<\/td>\n<\/tr>\n<tr>\n<td>Grandes simulations (&gt;5 min)<\/td>\n<td>S\u00e9parez les tests lents, ex\u00e9cutez la nuit&nbsp;; Utiliser <code>@pytest.mark.slow<\/code><\/td>\n<\/tr>\n<tr>\n<td>Couplage multi-composants<\/td>\n<td>Tests d'int\u00e9gration avec de petits cas de test, valider l'exactitude du couplage<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Choix de conteneurs<\/h3>\n<table>\n<thead>\n<tr>\n<th>Besoin<\/th>\n<th>Recommandation<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Reproductibilit\u00e9 maximale, inclut les DEP de niveau OS<\/td>\n<td>Docker<\/td>\n<\/tr>\n<tr>\n<td>Une gestion plus simple et plus simple<\/td>\n<td>Environnement Conda<\/td>\n<\/tr>\n<tr>\n<td>HPC avec biblioth\u00e8ques MPI<\/td>\n<td>Conda (ou Docker avec <code>--network=host<\/code> et <code>--ipc=host<\/code>)<\/td>\n<\/tr>\n<tr>\n<td>Environnement \u00e0 combles<\/td>\n<td>Conda Pack ou Docker Enregistrer\/charger<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Int\u00e9gration de CI avec les flux de travail de recherche<\/h2>\n<p>CI n'existe pas isol\u00e9ment. Il se connecte avec d'autres outils et pratiques.<\/p>\n<h3>Int\u00e9gration du suivi des probl\u00e8mes<\/h3>\n<p>Le statut CI appara\u00eet automatiquement sur les demandes d'extraction GitHub\/GitLab. Configurez les r\u00e8gles de protection des branches pour exiger le passage de CI avant la fusion. Cela garantit que seul le code valid\u00e9 entre la branche principale.<\/p>\n<p>Messages existants de Matforge sur <a href=\"https:\/\/matforge.org\/why-issue-tracking-is-critical-in-scientific-projects\/\">Suivi des probl\u00e8mes<\/a> et <a href=\"https:\/\/matforge.org\/tracking-long-term-technical-debt-in-research-software\/\">dette technique<\/a> compl\u00e8te en d\u00e9finissant la mani\u00e8re dont les probl\u00e8mes sont g\u00e9r\u00e9s. CI fournit une v\u00e9rification automatique que les probl\u00e8mes sont correctement r\u00e9solus.<\/p>\n<h3>Connexion de reproductibilit\u00e9<\/h3>\n<p>Comme indiqu\u00e9 dans <a href=\"https:\/\/matforge.org\/reproducibility-and-its-role-in-debugging\/\">reproductibilit\u00e9 et son r\u00f4le dans le d\u00e9bogage<\/a>, CI est une pierre angulaire de la recherche reproductible. Chaque commit qui passe CI peut \u00eatre approuv\u00e9 pour produire les m\u00eames r\u00e9sultats sur n'importe quelle machine avec le m\u00eame environnement. Ceci est essentiel pour :<\/p>\n<ul>\n<li><strong>Reproductibilit\u00e9 papier<\/strong>&nbsp;: lorsque les examinateurs demandent du code, vous pouvez pointer vers un commit sp\u00e9cifique qui a r\u00e9ussi CI et produit les chiffres.<\/li>\n<li><strong>Collaboration<\/strong>&nbsp;: les contributeurs externes peuvent ex\u00e9cuter les m\u00eames tests localement.<\/li>\n<li><strong>Entretien \u00e0 long terme<\/strong>&nbsp;: des ann\u00e9es plus tard, vous pouvez toujours reconstruire les r\u00e9sultats d'un commit valid\u00e9 par CI.<\/li>\n<\/ul>\n<h3>Flux de travail de r\u00e9vision de code<\/h3>\n<p>Associez CI \u00e0 une r\u00e9vision de code obligatoire&nbsp;:<\/p>\n<ol>\n<li>Le d\u00e9veloppeur pousse la branche, CI s'ex\u00e9cute.<\/li>\n<li>Si CI r\u00e9ussit, ouvrez une demande d'extraction.<\/li>\n<li>Les examinateurs v\u00e9rifient la logique du code et s'assurent que les tests sont ad\u00e9quats.<\/li>\n<li>Fusionner uniquement apr\u00e8s les passages de CI et l'examen approuv\u00e9.<\/li>\n<\/ol>\n<p>Ce flux de travail est standard dans l'industrie mais encore rare dans la recherche. La mise en \u0153uvre augmente consid\u00e9rablement la qualit\u00e9 des logiciels.<\/p>\n<h2>Sujets avanc\u00e9s<\/h2>\n<h3>Test de matrice pour plusieurs d\u00e9pendances<\/h3>\n<p>Les packages scientifiques d\u00e9pendent souvent de NumPy\/Scipy avec un comportement sp\u00e9cifique \u00e0 la version. Testez une matrice de versions Python et de d\u00e9pendance&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">strategy:\n  matrix:\n    python-version: [\"3.9\", \"3.10\", \"3.11\"]\n    numpy-version: [\"1.24\", \"1.25\", \"1.26\"]\n<\/code><\/pre>\n<p>Installez la version sp\u00e9cifique de NumPy \u00e0 l'\u00e9tape <code>Install dependencies<\/code>&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - run: |\n        pip install \"numpy==${{ matrix.numpy-version }}\" scipy\n<\/code><\/pre>\n<p>Cela permet de d\u00e9tecter les probl\u00e8mes de compatibilit\u00e9 plus t\u00f4t.<\/p>\n<h3>D\u00e9tection de la r\u00e9gression des performances<\/h3>\n<p>Utilisez <a href=\"https:\/\/asv.readthedocs.io\/\">asv<\/a> pour suivre les performances dans le temps&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">    - name: Run benchmarks\n      run: |\n        asv run --quick --show-stderr\n      # asv compares against previous commits and reports regressions\n<\/code><\/pre>\n<p>Configurez ASV pour \u00e9chouer au travail CI si une r\u00e9f\u00e9rence est de 10&nbsp;% plus lente que l'ex\u00e9cution pr\u00e9c\u00e9dente. Voir <a href=\"https:\/\/pythonspeed.com\/articles\/speed-unit-tests\/\">article de PythonSpeed<\/a> pour plus de d\u00e9tails.<\/p>\n<h3>D\u00e9ploiement continu de la documentation<\/h3>\n<p>CI peut d\u00e9ployer automatiquement la documentation sur les pages GitHub&nbsp;:<\/p>\n<pre><code class=\"language-yaml\">  deploy-docs:\n    needs: test  # Only run after tests pass\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions\/checkout@v4\n    - run: pip install -r requirements-docs.txt\n    - run: sphinx-build -b html docs\/ public\/\n    - uses: peaceiris\/actions-gh-pages@v3\n      with:\n        github_token: ${{ secrets.GITHUB_TOKEN }}\n        publish_dir: .\/public\n<\/code><\/pre>\n<p>Cela maintient la documentation synchronis\u00e9e avec les modifications de code.<\/p>\n<h2>Guides connexes<\/h2>\n<ul>\n<li><strong><a href=\"https:\/\/matforge.org\/reproducibility-and-its-role-in-debugging\/\">La reproductibilit\u00e9 et son r\u00f4le dans le d\u00e9bogage<\/a><\/strong> \u2013 comment les pratiques de reproductibilit\u00e9 am\u00e9liorent l'efficacit\u00e9 du d\u00e9bogage.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/tracking-long-term-technical-debt-in-research-software\/\">Suivi de la dette technique \u00e0 long terme dans les logiciels de recherche<\/a><\/strong> \u2013 g\u00e9rer la qualit\u00e9 du code dans le temps&nbsp;; CI aide \u00e0 pr\u00e9venir de nouvelles dettes.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/managing-research-software-through-tickets\/\">Gestion des logiciels de recherche via des tickets<\/a><\/strong> - Int\u00e9gration de CI avec les workflows de suivi des probl\u00e8mes.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/why-issue-tracking-is-critical-in-scientific-projects\/\">Pourquoi le suivi des probl\u00e8mes est essentiel dans les projets scientifiques<\/a><\/strong> \u2013 Comprendre l'importance du suivi des probl\u00e8mes dans le d\u00e9veloppement de logiciels scientifiques.<\/li>\n<li><strong><a href=\"https:\/\/matforge.org\/collaboration-between-developers-and-researchers-turning-innovation-into-scalable-impact\/\">Collaboration entre d\u00e9veloppeurs et chercheurs<\/a><\/strong> \u2013 Transformer l'innovation en impact \u00e9volutif gr\u00e2ce \u00e0 un travail d'\u00e9quipe efficace.<\/li>\n<\/ul>\n<h2>R\u00e9sum\u00e9 et \u00e9tapes suivantes<\/h2>\n<p>L'int\u00e9gration continue transforme les logiciels de recherche \u00e0 partir de scripts fragiles et non document\u00e9s en actifs fiables et maintenables. Les \u00e9tapes essentielles sont :<\/p>\n<ol>\n<li>R\u00e9digez des tests automatis\u00e9s avec PyTest, en utilisant <code>pytest.approx<\/code> pour les comparaisons num\u00e9riques.<\/li>\n<li>Configurez un pipeline CI (actions GitHub ou Gitlab CI) qui s'ex\u00e9cute \u00e0 chaque requ\u00eate push et pull.<\/li>\n<li>Utilisez Docker ou Conda pour assurer la coh\u00e9rence de l'environnement entre CI et le d\u00e9veloppement.<\/li>\n<li>Ajoutez la cr\u00e9ation de rapports de couverture, de peluchage et de cr\u00e9ation de documentation.<\/li>\n<li>Surveillez les performances avec des benchmarks pour d\u00e9tecter les r\u00e9gressions.<\/li>\n<li>Int\u00e9grez CI \u00e0 vos processus existants de suivi des probl\u00e8mes et de r\u00e9vision de code.<\/li>\n<\/ol>\n<p><strong>Actions imm\u00e9diates<\/strong>&nbsp;:<\/p>\n<ul>\n<li>Si vous n'avez pas de tests, commencez par en \u00e9crire quelques-uns pour les fonctions les plus critiques. M\u00eame une couverture de 20 % est meilleure que rien.<\/li>\n<li>Cr\u00e9ez un fichier de configuration CI de base (<code>.github\/workflows\/ci.yml<\/code> comme indiqu\u00e9 ci-dessus) et it\u00e9rez.<\/li>\n<li>R\u00e9parez imm\u00e9diatement les tests floconneux, ils \u00e9rodent la confiance.<\/li>\n<li>Ajoutez un \"badge\" \u00e0 votre fichier Lisez-moi indiquant le statut CI (par exemple, <img src=\"https:\/\/img.shields.io\/badge\/CI-passing-green\" alt=\"ci\">).<\/li>\n<\/ul>\n<p><strong>Quand rechercher une consultation<\/strong>&nbsp;: si votre projet implique des d\u00e9pendances complexes (MPI, code GPU, biblioth\u00e8ques propri\u00e9taires) ou poss\u00e8de 10&nbsp;000&nbsp;lignes de code, envisagez un examen professionnel de votre configuration CI. Nous proposons <a href=\"\/category\/issue-tracking-tickets-technical-requests\/\">services de mise en \u0153uvre CI\/CD personnalis\u00e9s<\/a> pour les \u00e9quipes de recherche.<\/p>\n<h2>R\u00e9f\u00e9rences et lectures compl\u00e9mentaires<\/h2>\n<ul>\n<li>Wilson, G., et al. (2012). <a href=\"https:\/\/www.ee.columbia.edu\/~dpwe\/e6891\/resources\/1210.0530v3.pdf\">Meilleures pratiques pour le calcul scientifique<\/a>. <em>biologie PLOS<\/em>.<\/li>\n<li>Boettiger, C. (2015). <a href=\"https:\/\/polaris.imag.fr\/arnaud.legrand\/research\/readings\/acm_sigops_si_rsea\/p71-boettiger.pdf\">Une introduction \u00e0 Docker pour la reproductibilit\u00e9 Recherche<\/a>. <em>sigops ACM<\/em>.<\/li>\n<li>Waller, J., et al. (2015). <a\u00a00>Inclure des indices de performance dans l'int\u00e9gration continue. <em>sean<\/em>.<\/a\u00a00><\/li>\n<li><a href=\"https:\/\/imperialcollegelondon.github.io\/ci-best-practice\/\">Int\u00e9gration continue pour les logiciels de recherche<\/a> \u2013 Guide des meilleures pratiques de l'Imperial College London.<\/li>\n<li><a href=\"https:\/\/docs.github.com\/actions\/guides\/building-and-testing-python\">Actions GitHub&nbsp;: Construire et tester Python<\/a> \u2013 Documentation officielle.<\/li>\n<li><a href=\"https:\/\/github.com\/swcarpentry\/good-enough-practices-in-scientific-computing\">assez bonnes pratiques en informatique scientifique<\/a> \u2013 menuiseries logicielles.<\/li>\n<\/ul>\n<hr>\n<p><strong>Compte de mots<\/strong>&nbsp;: ~2&nbsp;200<br> <strong>Temps de lecture<\/strong>&nbsp;: ~10&nbsp;minutes<br> <strong>Audience cible<\/strong>&nbsp;: chercheurs, \u00e9tudiants dipl\u00f4m\u00e9s et d\u00e9veloppeurs travaillant sur des projets Python scientifiques qui ont besoin d'\u00e9tablir une qualit\u00e9 fiable et automatis\u00e9e assurance.<\/p>\n"},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 13<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span>L&rsquo;int\u00e9gration continue (CI) construit, teste et valide automatiquement le code de recherche \u00e0 chaque validation. Pour les logiciels scientifiques, CI est essentiel pour la reproductibilit\u00e9, la d\u00e9tection pr\u00e9coce des bogues et le maintien de la qualit\u00e9 dans le temps. Impl\u00e9mentez CI en&nbsp;: (1) la r\u00e9daction de tests automatis\u00e9s avec PyTest, (2) la configuration d&rsquo;un pipeline [&hellip;]<\/p>\n","protected":false,"raw":""},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"fr_FR","_original_post":"https:\/\/matforge.org\/?p=240","iawp_total_views":1,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1226","post","type-post","status-publish","format-standard","hentry","category-issue-tracking-tickets-technical-requests","fr-FR"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s - matforge.org<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s - matforge.org\" \/>\n<meta property=\"og:description\" content=\"Reading Time:  13 minutesL&rsquo;int\u00e9gration continue (CI) construit, teste et valide automatiquement le code de recherche \u00e0 chaque validation. Pour les logiciels scientifiques, CI est essentiel pour la reproductibilit\u00e9, la d\u00e9tection pr\u00e9coce des bogues et le maintien de la qualit\u00e9 dans le temps. Impl\u00e9mentez CI en&nbsp;: (1) la r\u00e9daction de tests automatis\u00e9s avec PyTest, (2) la configuration d&rsquo;un pipeline [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/\" \/>\n<meta property=\"og:site_name\" content=\"matforge.org\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-21T14:28:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/img.shields.io\/badge\/CI-passing-green\" \/>\n<meta name=\"author\" content=\"Priya Nair\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"Priya Nair\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/\"},\"author\":{\"name\":\"Priya Nair\",\"@id\":\"https:\\\/\\\/matforge.org\\\/#\\\/schema\\\/person\\\/2effd7bc155a5e6357f31dac970c5795\"},\"headline\":\"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s\",\"datePublished\":\"2026-08-21T14:28:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/\"},\"wordCount\":3731,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/img.shields.io\\\/badge\\\/CI-passing-green\",\"articleSection\":[\"Suivi des probl\u00e8mes, billets &amp; Demandes techniques\"],\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/\",\"url\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/\",\"name\":\"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s - matforge.org\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/img.shields.io\\\/badge\\\/CI-passing-green\",\"datePublished\":\"2026-08-21T14:28:41+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/#\\\/schema\\\/person\\\/2effd7bc155a5e6357f31dac970c5795\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#primaryimage\",\"url\":\"https:\\\/\\\/img.shields.io\\\/badge\\\/CI-passing-green\",\"contentUrl\":\"https:\\\/\\\/img.shields.io\\\/badge\\\/CI-passing-green\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/matforge.org\\\/fr\\\/continuous-integration-research-software-automated-testing-validation\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/matforge.org\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/matforge.org\\\/#website\",\"url\":\"https:\\\/\\\/matforge.org\\\/\",\"name\":\"matforge.org\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/matforge.org\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/matforge.org\\\/#\\\/schema\\\/person\\\/2effd7bc155a5e6357f31dac970c5795\",\"name\":\"Priya Nair\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f11e168d4cd2f1eff83cbb851d6cff42d81d88bb59d8831ee77468aa4a5eea88?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f11e168d4cd2f1eff83cbb851d6cff42d81d88bb59d8831ee77468aa4a5eea88?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f11e168d4cd2f1eff83cbb851d6cff42d81d88bb59d8831ee77468aa4a5eea88?s=96&d=mm&r=g\",\"caption\":\"Priya Nair\"},\"sameAs\":[\"http:\\\/\\\/matforge.org\"],\"url\":\"https:\\\/\\\/matforge.org\\\/author\\\/priya-nair\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s - matforge.org","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/","og_locale":"fr_FR","og_type":"article","og_title":"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s - matforge.org","og_description":"Reading Time:  13 minutesL&rsquo;int\u00e9gration continue (CI) construit, teste et valide automatiquement le code de recherche \u00e0 chaque validation. Pour les logiciels scientifiques, CI est essentiel pour la reproductibilit\u00e9, la d\u00e9tection pr\u00e9coce des bogues et le maintien de la qualit\u00e9 dans le temps. Impl\u00e9mentez CI en&nbsp;: (1) la r\u00e9daction de tests automatis\u00e9s avec PyTest, (2) la configuration d&rsquo;un pipeline [&hellip;]","og_url":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/","og_site_name":"matforge.org","article_published_time":"2026-08-21T14:28:41+00:00","og_image":[{"url":"https:\/\/img.shields.io\/badge\/CI-passing-green","type":"","width":"","height":""}],"author":"Priya Nair","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"Priya Nair","Dur\u00e9e de lecture estim\u00e9e":"21 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#article","isPartOf":{"@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/"},"author":{"name":"Priya Nair","@id":"https:\/\/matforge.org\/#\/schema\/person\/2effd7bc155a5e6357f31dac970c5795"},"headline":"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s","datePublished":"2026-08-21T14:28:41+00:00","mainEntityOfPage":{"@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/"},"wordCount":3731,"commentCount":0,"image":{"@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#primaryimage"},"thumbnailUrl":"https:\/\/img.shields.io\/badge\/CI-passing-green","articleSection":["Suivi des probl\u00e8mes, billets &amp; Demandes techniques"],"inLanguage":"fr-FR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/","url":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/","name":"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s - matforge.org","isPartOf":{"@id":"https:\/\/matforge.org\/#website"},"primaryImageOfPage":{"@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#primaryimage"},"image":{"@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#primaryimage"},"thumbnailUrl":"https:\/\/img.shields.io\/badge\/CI-passing-green","datePublished":"2026-08-21T14:28:41+00:00","author":{"@id":"https:\/\/matforge.org\/#\/schema\/person\/2effd7bc155a5e6357f31dac970c5795"},"breadcrumb":{"@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#primaryimage","url":"https:\/\/img.shields.io\/badge\/CI-passing-green","contentUrl":"https:\/\/img.shields.io\/badge\/CI-passing-green"},{"@type":"BreadcrumbList","@id":"https:\/\/matforge.org\/fr\/continuous-integration-research-software-automated-testing-validation\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/matforge.org\/"},{"@type":"ListItem","position":2,"name":"Int\u00e9gration continue pour les logiciels de recherche : tests et validation automatis\u00e9s"}]},{"@type":"WebSite","@id":"https:\/\/matforge.org\/#website","url":"https:\/\/matforge.org\/","name":"matforge.org","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/matforge.org\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Person","@id":"https:\/\/matforge.org\/#\/schema\/person\/2effd7bc155a5e6357f31dac970c5795","name":"Priya Nair","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/secure.gravatar.com\/avatar\/f11e168d4cd2f1eff83cbb851d6cff42d81d88bb59d8831ee77468aa4a5eea88?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f11e168d4cd2f1eff83cbb851d6cff42d81d88bb59d8831ee77468aa4a5eea88?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f11e168d4cd2f1eff83cbb851d6cff42d81d88bb59d8831ee77468aa4a5eea88?s=96&d=mm&r=g","caption":"Priya Nair"},"sameAs":["http:\/\/matforge.org"],"url":"https:\/\/matforge.org\/author\/priya-nair\/"}]}},"_links":{"self":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts\/1226","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/comments?post=1226"}],"version-history":[{"count":1,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts\/1226\/revisions"}],"predecessor-version":[{"id":1364,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts\/1226\/revisions\/1364"}],"wp:attachment":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/media?parent=1226"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/categories?post=1226"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/tags?post=1226"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}