[[https://github.com/catchorg/Catch2|Site Web]]
Catch2 permet de créer des tests unitaires.
=====Exemples=====
====Test de base====
#include
#include
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 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 %%'' 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 [[https://github.com/catchorg/Catch2/issues/1711|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)