Logo

dev-resources.site

for different kinds of informations.

Tester c'est tricher, compiler c'est douter

Published at
1/10/2025
Categories
ci
clang
c
criterion
Author
mrvym
Categories
4 categories in total
ci
open
clang
open
c
open
criterion
open
Author
5 person written this
mrvym
open
Tester c'est tricher, compiler c'est douter

Dans cet article, nous allons voir le concept de Continuous Integration (CI), son intĂ©rĂȘt et ses inconvĂ©nients et une dĂ©monstration.

Histoire

Mais d'abord, comme Ă  mon habitude, un petit point histoire.

En 1999, Kent Beck a approfondi le sujet dans son premier livre sur l'Extreme Programming. En 2001, CruiseControl, l'un des premiers outils open-source de CI, a vu le jour.

Mais why ?

Le but d'une CI est de faire des tests automatisés à chaque commit. Cela garantit que le code reste fonctionnel en permanence. On appelle cela une Continuous Integration car, à chaque modification, le code est vérifié pour s'assurer qu'il n'y a pas de régressions.

Avantages

  • DĂ©tection prĂ©coce des erreurs : Les problĂšmes sont identifiĂ©s rapidement, ce qui permet de rĂ©agir sans attendre.
  • AmĂ©lioration de la qualitĂ© : En testant systĂ©matiquement, on garantit un code plus robuste.
  • Gain de temps : Les pipelines automatisĂ©s rĂ©duisent la nĂ©cessitĂ© de tests manuels rĂ©pĂ©titifs.

Inconvénients

  • CoĂ»t initial : Mettre en place une CI peut demander des efforts et des compĂ©tences initiales importantes.
  • Temps d’exĂ©cution : Les pipelines complexes peuvent rallonger le temps avant qu'un dĂ©veloppeur puisse valider son code.

Fonctionnement

Avant de voir le fonctionnement, un petit lexique :

  • Jobs : Une instance d'un conteneur (souvent Docker) qui exĂ©cute un script. Cela peut inclure des commandes, des tests ou des actions simples comme un echo.
  • Pipeline : Une sĂ©rie de jobs organisĂ©s de maniĂšre sĂ©quentielle ou parallĂšle. Chaque commit dĂ©clenche cette sĂ©rie pour valider les changements.

Le principe est simple : chaque job retourne un code de statut (succĂšs ou Ă©chec). Si un job Ă©choue, la pipeline s’arrĂȘte ou ignore les Ă©tapes suivantes selon la configuration.

TrĂȘve de blabla

Nous allons utiliser un exemple basé sur GitLab CI. On la configure via un fichier .gitlab-ci.yml.

Basique, simple, simple, basique

image: bookworm-slim:latest

myjobname:
  script:
    - make
Enter fullscreen mode Exit fullscreen mode

Les flags

Pour ajouter des flags de compilation, deux approches sont possibles :

  1. Via une rĂšgle dans le Makefile.
  2. En passant les flags directement dans la commande CI.
myjobname_hard:
  script:
    - CFLAGS="-Wall -Werror" make
    # ou
    - make compile_flags
Enter fullscreen mode Exit fullscreen mode

Tests avec Criterion et flags

Criterion est une bibliothĂšque de tests unitaires en C.

OĂč est passĂ© Criterion ?

Avant d’exĂ©cuter des tests avec Criterion, il est souvent nĂ©cessaire d'installer Criterion, eh oui !

before_script:
  - apt-get update && apt-get install -y libcriterion-dev
script:
  - ./configure
  - make test
Enter fullscreen mode Exit fullscreen mode

Multistaging

Diviser les tests unitaires et fonctionnels en plusieurs stages garantit :

  • une bonne organisation
  • une meilleure visibilitĂ© des rĂ©sultats
stages:
  - build
  - test

build:
  stage: build
  script:
    - make all

test-unit:
  stage: test
  script:
    - make unit-test

test-functional:
  stage: test
  script:
    - make functional-test
Enter fullscreen mode Exit fullscreen mode

Tu t'es fait clang ?

Le formatage du code est super important pour maintenir une base de code propre.

clang_format:
  stage: format
  before_script:
    - apt-get -qq update && apt-get -qq install -y clang-format autotools-dev autoconf-archive gcovr libcriterion-dev
  script:
    - clang-format -i $(find src/ -type f -name "*.c") --dry-run --Werror
Enter fullscreen mode Exit fullscreen mode

Cache

Dans certains cas, c'est utile de mettre en cache des fichiers ou dossiers pour Ă©viter de les recharger Ă  chaque pipeline.

Un exemple courant est le dossier node_modules/ en JavaScript.

cache:
  paths:
    - node_modules/

install:
  script:
    - npm install
Enter fullscreen mode Exit fullscreen mode

Bien entendu, vous pouvez nettoyer le cache au besoin avec une option supplémentaire dans la configuration de pipeline.

Artefacts

Les artefacts sont les fichiers gĂ©nĂ©rĂ©s par la CI qui peuvent ĂȘtre partagĂ©s entre jobs ou tĂ©lĂ©chargĂ©s.

Par exemple, les rapports de tests ou de couverture.

artifacts:
  paths:
    - build/
    - reports/
Enter fullscreen mode Exit fullscreen mode

Coverage de tests

On peut mesurer la couverture de tests en intégrant des outils comme gcovr ou Cobertura dans votre pipeline CI.

test-coverage:
  stage: test
  script:
    - gcovr --html --html-details -o coverage.html
  artifacts:
    paths:
      - coverage.html
Enter fullscreen mode Exit fullscreen mode

Rapporteur

Ce bloc vous permet d'intégrer le coverage report dans votre Merge Request, vous pourrez ainsi voir le code qui n'est pas couvert mais aussi votre pourcentage de coverage.

coverage-report:
  script:
    # do coverage
  coverage: /^TOTAL.*\s+(\d+\%)$/
  artifacts:
    name: coverage.xml
    expire_in: 2 days
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml

Enter fullscreen mode Exit fullscreen mode

Environnement custom

Vous pouvez prĂ©ciser l’environnement de base pour votre CI en sĂ©lectionnant une image Docker spĂ©cifique.

image: gcc:latest
Enter fullscreen mode Exit fullscreen mode

En utilisant un peu ce que l'on vient de voir, ça donnerait quelque chose comme ça :

image: gcc

stages:
  - format
  - build
  - test
  - clean

clang-format:
  stage: format
  script:
    - clang-format -i $(find src/ -type f -name "*.c") --dry-run --Werror

build:
  stage: build
  script:
    - autoreconf --install
    - ./configure
    - make all

test-unit:
  stage: test
  script:
    - autoreconf --install
    - ./configure
    - make unit-test
Enter fullscreen mode Exit fullscreen mode

Attention aux .h et il manque des before_script.

Petit Bonus

On peut aussi vĂ©rifier les trash-files pour s’assurer que le make clean fait bien son travail.

trash-file:
  stage: clean
  needs: []
  before_script:
    - apt-get -qq update && apt-get -qq install -y tree
  script:
    - tree > /tmp/REF
    - make && make clean
    - tree > /tmp/TEST
    - diff /tmp/REF /tmp/TEST
Enter fullscreen mode Exit fullscreen mode

Conclusion

La Continuous Integration est un outil extrĂȘmement puissant. Il peut parfois ĂȘtre difficile Ă  mettre en place, mais les gains sont immenses.

clang Article's
27 articles in total
Favicon
Tester c'est tricher, compiler c'est douter
Favicon
Pointers in Modern C
Favicon
Creating a Robust Logging System in C
Favicon
The unspoken question: "Why do pointers exist?"
Favicon
Pointers : what are they pointing to?
Favicon
Setting up linters in Gitlab CI for C++ and Groovy / Jenkins code
Favicon
SORRY, RUST & DEVS !
Favicon
Cycle don't want to write to the array
Favicon
cĂĄch xá»­ lĂœ lỗi khĂŽng cháșĄy Ä‘Æ°á»Łc code C++ trong Code::Blocks "Tried to run compiler enumerable `C:\MinGW/bin/gcc.exe` but failed"
Favicon
Building an XDP eBPF Program with C and Golang: A Step-by-Step Guide
Favicon
Should I Learn Math First, Then Rust or C, or Can I Learn Mathematics and Rust, C Simultaneously?
Favicon
The C Programming Language by Brian W. Kernighan & Dennis M. Ritchie.
Favicon
The C Programming Language by Brian W. Kernighan & Dennis M. Ritchie.
Favicon
Dynamic Linker Hijacking Experiments - Evasive Techniques (Part 1)
Favicon
How To Include ‘bits/stdc++.h’ Header File With Clang Compiler on macOS
Favicon
How many asterisks can be put?
Favicon
A common pitfall when using sizeof() with pointers
Favicon
Platform detection in C&C++
Favicon
Lint Lint Boom
Favicon
Behind C++ Lambda Functions
Favicon
C++ Levitation: Looking for contributors
Favicon
Type qualifier: register, volatile and restrict - C Programming
Favicon
Configuring Oni as a C / C++ IDE on Ubuntu 18.04
Favicon
Use `bool` in C program
Favicon
Clang vs GCC
Favicon
Working on Object Lifetime Analysis for C++
Favicon
Writing safer C with Clang address sanitizer

Featured ones: