Add testing context as test case argument & support simple profiling in tests
This commit is contained in:
parent
bc18b03a53
commit
91faa2423e
2 changed files with 61 additions and 6 deletions
|
|
@ -1,13 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
||||
#include <psemek/util/to_string.hpp>
|
||||
|
||||
namespace psemek::test
|
||||
{
|
||||
|
||||
void add_test_case(char const * name, void(*f)());
|
||||
struct context
|
||||
{
|
||||
struct profile_data
|
||||
{
|
||||
std::string name;
|
||||
std::chrono::high_resolution_clock::duration duration;
|
||||
bool ended_with_exception;
|
||||
};
|
||||
|
||||
std::vector<profile_data> profile;
|
||||
};
|
||||
|
||||
void add_test_case(char const * name, void(*f)(context &));
|
||||
|
||||
struct failure
|
||||
: std::exception
|
||||
|
|
@ -27,12 +41,35 @@ namespace psemek::test
|
|||
std::string location_;
|
||||
};
|
||||
|
||||
struct profiler
|
||||
{
|
||||
using clock = std::chrono::high_resolution_clock;
|
||||
|
||||
profiler(std::string name, context & ctx)
|
||||
: name_{std::move(name)}
|
||||
, ctx_{ctx}
|
||||
{
|
||||
start_ = clock::now();
|
||||
}
|
||||
|
||||
~profiler()
|
||||
{
|
||||
auto end = clock::now();
|
||||
ctx_.profile.push_back({name_, end - start_, std::uncaught_exceptions() > 0});
|
||||
}
|
||||
|
||||
private:
|
||||
clock::time_point start_;
|
||||
std::string name_;
|
||||
context & ctx_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define test_case(name) \
|
||||
void name ## _test_case (); \
|
||||
void name ## _test_case (::psemek::test::context &); \
|
||||
static const auto name ## _test_case_registrator = []{ ::psemek::test::add_test_case(#name, &(name ## _test_case)); return 0; }(); \
|
||||
void name ## _test_case ()
|
||||
void name ## _test_case ([[maybe_unused]] ::psemek::test::context & _ctx)
|
||||
|
||||
#define fail(...) throw ::psemek::test::failure(::psemek::util::to_string(__VA_ARGS__), ::psemek::util::to_string(__FILE__, ":", __LINE__))
|
||||
|
||||
|
|
@ -52,3 +89,6 @@ void name ## _test_case ()
|
|||
#define expect_gequal(expr1, expr2) if ((expr1) < (expr2)) fail(#expr1, " (", (expr1), ") < ", #expr2, " (", (expr2), ")")
|
||||
|
||||
#define expect_throw(expr, type) do { bool thrown = false; try { (void)(expr); } catch (type const &) { thrown = true; } if (!thrown) fail(#expr, " didn't throw ", #type); } while (false)
|
||||
|
||||
#define test_profile(name) \
|
||||
if (::psemek::test::profiler name ## _profiler(#name, _ctx); true)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
namespace psemek::test
|
||||
{
|
||||
|
||||
static std::map<std::string, void(*)()> tests;
|
||||
static std::map<std::string, void(*)(context &)> tests;
|
||||
|
||||
static std::string normalize(std::string name)
|
||||
{
|
||||
|
|
@ -31,7 +31,7 @@ namespace psemek::test
|
|||
return name;
|
||||
}
|
||||
|
||||
void add_test_case(char const * name, void(*f)())
|
||||
void add_test_case(char const * name, void(*f)(context &))
|
||||
{
|
||||
std::string pname = normalize(name);
|
||||
|
||||
|
|
@ -99,10 +99,12 @@ int main(int argc, char ** argv)
|
|||
<< '[' << std::setfill(' ') << std::setw(test_index_len) << std::right << i << '/' << test_count << "] "
|
||||
<< std::left << std::setfill('.') << std::setw(max_name_length + 5) << name;
|
||||
|
||||
psemek::test::context ctx;
|
||||
|
||||
try
|
||||
{
|
||||
auto start = clock::now();
|
||||
psemek::test::tests[name]();
|
||||
psemek::test::tests[name](ctx);
|
||||
auto end = clock::now();
|
||||
std::cout << "ok (" << psemek::util::pretty(end - start, std::chrono::milliseconds{1}) << ")" << std::endl;
|
||||
++success;
|
||||
|
|
@ -121,6 +123,19 @@ int main(int argc, char ** argv)
|
|||
{
|
||||
std::cout << "failure: (unknown exception)" << std::endl;
|
||||
}
|
||||
|
||||
std::size_t max_profile_name_len = 0;
|
||||
for (auto const & p : ctx.profile)
|
||||
max_profile_name_len = std::max(max_profile_name_len, p.name.size());
|
||||
|
||||
for (auto const & p : ctx.profile)
|
||||
{
|
||||
std::cout << indent
|
||||
<< std::setfill(' ') << std::setw(max_profile_name_len + 5) << p.name
|
||||
<< psemek::util::pretty(p.duration, std::chrono::milliseconds{1})
|
||||
<< (p.ended_with_exception ? " (exception)" : "")
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
auto all_end = clock::now();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue