Table des matières
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)