Tests en C++ : aperçu des frameworks et outils (Google Test, Catch2, doctest)

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Tests en C++ : frameworks et outils



Les tests de qualité sont une partie essentielle du développement en C++. Contrairement aux langages dynamiques, le C++ nécessite une attention particulière à la gestion de la mémoire, à la durée de vie des objets et aux performances. Dans cet article, nous analyserons les trois frameworks les plus populaires pour les tests unitaires : Google Test, Catch2 et doctest, et aborderons également des outils supplémentaires.



Pourquoi les tests en C++ sont-ils nécessaires ?

Le C++ est un langage avec gestion manuelle de la mémoire et une puissante magie des templates. Sans tests, il est facile de commettre :

  • Des fuites mémoire et des doubles libérations
  • Un comportement indéfini (UB) lors de l'utilisation de pointeurs
  • Des erreurs dans la surcharge des opérateurs et les constructeurs de copie
  • Des régressions lors du refactoring de code legacy

Les frameworks de test automatisent la vérification et aident à trouver rapidement les problèmes.



Google Test (gtest)

Le framework le plus répandu de Google. Il prend en charge toutes les fonctionnalités principales : les macros ASSERT_* et EXPECT_*, les tests paramétrés, les fixtures (test fixtures), les death-tests.



Installation (via CMake FetchContent)

include(FetchContent)FetchContent_Declare(  googletest  GIT_REPOSITORY https://github.com/google/googletest.git  GIT_TAG release-1.14.0)FetchContent_MakeAvailable(googletest)


Exemple de test simple

#include <gtest/gtest.h>

int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n - 1);}

TEST(FactorialTest, HandlesZeroInput) { EXPECT_EQ(factorial(0), 1);}

TEST(FactorialTest, HandlesPositiveInput) { EXPECT_EQ(factorial(5), 120); EXPECT_EQ(factorial(3), 6);}

int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}


Fixtures et tests paramétrés

class MathFixture : public ::testing::Test {protected:    void SetUp() override { /* initialisation */ }    void TearDown() override { /* nettoyage */ }};

// Test paramétréclass SumTest : public ::testing::TestWithParam<std::tuple<int, int, int>> {};TEST_P(SumTest, CheckSum) { auto [a, b, expected] = GetParam(); EXPECT_EQ(a + b, expected);}INSTANTIATE_TEST_SUITE_P(SumParams, SumTest, ::testing::Values( std::make_tuple(1, 1, 2), std::make_tuple(0, 0, 0) ));


Avantages : immense communauté, intégration avec CI/CD, macros puissantes, support des death-tests.
Inconvénients : compilation relativement lente, taille importante du fichier exécutable.



Catch2

Un framework moderne mettant l'accent sur la lisibilité des tests. Il utilise le style BDD (Behaviour-Driven Development) et prend en charge les sections.



Installation (header-only)

Catch2 est distribué comme un seul fichier d'en-tête. Il suffit de télécharger catch_amalgamated.hpp et de l'inclure.



Exemple avec sections

#define CATCH_CONFIG_MAIN#include <catch2/catch.hpp>

int divide(int a, int b) { if (b == 0) throw std::invalid_argument("division par zéro"); return a / b;}

TEST_CASE("Tests de division", "[math]") { SECTION("Division normale") { REQUIRE(divide(10, 2) == 5); } SECTION("Division par zéro") { REQUIRE_THROWS_AS(divide(5, 0), std::invalid_argument); }}


Style BDD (Given-When-Then)

SCENARIO("Opération push_back sur un vecteur", "[conteneur]") {    GIVEN("Un vecteur vide") {        std::vector<int> v;        WHEN("Nous ajoutons un élément") {            v.push_back(42);            THEN("La taille devient 1") {                REQUIRE(v.size() == 1);            }            AND_THEN("L'élément est correct") {                REQUIRE(v[0] == 42);                    

Recommendations