Outils pour utilisateurs

Outils du site


lib:catch2

Site Web

Catch2 permet de créer des tests unitaires.

Exemples

Test de base

#include <catch2/catch_test_macros.hpp>
 
#include <cstdint>
 
uint32_t factorial( uint32_t number ) {
  return number <= 1 ? number : factorial(number-1) * number;
}
 
TEST_CASE("Factorials are computed", "[factorial]") {
  REQUIRE(factorial( 1) == 1);
  REQUIRE(factorial( 2) == 2);
  REQUIRE(factorial( 3) == 6);
  REQUIRE(factorial(10) == 3628800);
 
  SECTION("section1") {
    std::vector<int> v(5);
    v.resize(10);
 
    REQUIRE(v.size() == 10);
    REQUIRE(v.capacity() >= 10);
  }}

L'usage de SECTION permet de créer des sous cas tests qui peuvent être désactivés via --section <section name> lors de l'appel du programme tests en ligne de commande.

Pour les cas courants, il n'y a pas besoin d'avoir une méthode main. Si suffit de se lier avec la target CMake Catch2WithMain.

Toutes les macros de tests REQUIRE et autres ne s'utilisent qu'à l'intérieur d'un TEST_CASE et donc le main de Catch2.

Benchmark

TEST_CASE("Benchmark Fibonacci", "[!benchmark]") {
  REQUIRE(fibonacci(5) == 5);
 
  REQUIRE(fibonacci(20) == 6765);
  BENCHMARK("fibonacci 20") {
    return fibonacci(20);
  };
 
  REQUIRE(fibonacci(25) == 75025);
  BENCHMARK("fibonacci 25") {
    return fibonacci(25);
  };
 
  BENCHMARK_ADVANCED("Warmup")
  (Catch::Benchmark::Chronometer meter) {
    warm_up_each_execution();
 
    meter.measure(
      [] {
        ....
        }
      });
  };
}

Il faut passer par BENCHMARK_ADVANCED pour ne mesurer que certaines parties du code qui doit être exécutées.

Nombre d'exécutions

Les benchmarks sont exécutés 100 fois par défaut.

Tous les benchmarks vont être exécutés le même nombre de fois. Ce n'est pas personnalisable individuellement Github 1711.

C'est modifiable en passant --benchmark-samples 10 en ligne de commande.

Ou encore, c'est modifiable dans le code:

class ConfigDataSession : public Catch::Session {
 public:
  ConfigDataSession() {
    auto& config_data = configData();
    config_data.benchmarkSamples = 10;
  }
};
 
int main(int argc, char* argv[]) {
  ConfigDataSession session;
  return session.run(argc, argv);
}

Dans ce dernier cas, le binaire doit se lier avec Catch2 et non plus Catch2WithMain.

Récupérer les résultats des tests

Il faut ajouter un Listener.

namespace {
size_t byte_count = 0;
}
 
class ComputeBandwidthReporter : public Catch::EventListenerBase {
 public:
  using Catch::EventListenerBase::EventListenerBase;
 
  void benchmarkEnded(Catch::BenchmarkStats<> const& benchmark_stats) override {
    std::cout << "\n[speed] "
              << byte_count / (benchmark_stats.mean.point.count() / 1000000000) / 1024 / 1024
              << "Mo/s\n";
  }
};
 
CATCH_REGISTER_LISTENER(ComputeBandwidthReporter)

Le listener étant un objet global, il n'est pas possible de lui passer des paramètres. Dans mon cas, je passe par un objet global.

Les temps du benchmark sont en nanosecondes.

Intégration

CMake

find_package(Catch2 REQUIRED)
 
target_link_libraries(target_test PRIVATE Catch2::Catch2WithMain)
lib/catch2.txt · Dernière modification : de root