Hegel 0.11.4
Property-based testing for C++
Loading...
Searching...
No Matches
hegel::TestCase Class Reference

Handle to the currently-executing test case. More...

#include <test_case.h>

Public Member Functions

 TestCase (const TestCase &)=delete
TestCase & operator= (const TestCase &)=delete
 TestCase (TestCase &&) noexcept
 Move-constructs, transferring ownership of the underlying handle.
TestCase & operator= (TestCase &&) noexcept
 Move-assigns, transferring ownership of the underlying handle.
template<typename T>
draw (const generators::Generator< T > &gen) const
 Draw a random value from a generator.
template<typename T>
draw (std::string_view name, const generators::Generator< T > &gen, bool repeatable=false) const
 Draw a random value from a generator, printed under name.
void assume (bool condition) const
 Reject the current test case if condition is false.
void reject () const
 Reject the current test case unconditionally.
void target (double score, std::string_view label="") const
 Record a score for the engine's targeted-search phase to maximize.
void repeat (const std::function< void()> &body) const
 Run body in an engine-managed loop.
void note (std::string_view message) const
 Record a message that will be printed on the final replay of a failing test case.
TestCase clone () const
 Creates a clone of this test case with an independent choice sequence forked from this test case.
template<typename F>
auto spawn (F fn) const
 Run fn on a clone of this test case in a new thread.

Detailed Description

Handle to the currently-executing test case.

A TestCase is passed as the sole argument to the callback given to hegel::test(). It is the main way a test definition interacts with Hegel.

TestCase owns its underlying libhegel handle and is move-only (not copyable). The callback receives it by reference; a clone() returns a fresh owning TestCase. It must not outlive the test-case callback.

HEGEL_TEST(example)(hegel::TestCase& tc) {
namespace gs = hegel::generators;
auto x = tc.draw("x", gs::integers<int>({.min_value = 0}));
tc.assume(x != 0);
tc.note("x = " + std::to_string(x));
}
Handle to the currently-executing test case.
Definition test_case.h:40
#define HEGEL_TEST(name,...)
Define a Hegel property test.
Definition hegel.h:575
Hegel generators.
Definition core.h:17

Member Function Documentation

◆ assume()

void hegel::TestCase::assume ( bool condition) const

Reject the current test case if condition is false.

auto age = tc.draw(gs::integers<int>());
tc.assume(age >= 18);
Parameters
conditionValue that must be true for the test case to continue. If false, the current test case is rejected.

◆ clone()

TestCase hegel::TestCase::clone ( ) const

Creates a clone of this test case with an independent choice sequence forked from this test case.

The returned TestCase draws from its own choice sequence but shares this case's outcome and budget. A single test case must not be drawn from concurrently, so give each thread its own clone.

Returns
A TestCase.
auto worker = tc.clone();
auto a = worker.draw(gs::integers<int>());
auto b = tc.draw(gs::integers<int>());

◆ draw() [1/2]

template<typename T>
T hegel::TestCase::draw ( const generators::Generator< T > & gen) const

Draw a random value from a generator.

Each draw is printed as a C++ declaration, auto <name> = <value>;, on the final replay of a failing test case and on every case at Verbosity::Verbose and above. Draws made through this overload print as draw_1, draw_2, ... in draw order. Use the named overload to print under a variable name.

Template Parameters
TThe value type produced by gen
Parameters
genThe generator to draw from
Returns
A generated value of type T

◆ draw() [2/2]

template<typename T>
T hegel::TestCase::draw ( std::string_view name,
const generators::Generator< T > & gen,
bool repeatable = false ) const

Draw a random value from a generator, printed under name.

Template Parameters
TThe value type produced by gen
Parameters
nameVariable name for the printed declaration.
genThe generator to draw from
repeatablePass true to print name with a 1-based suffix per use (x_1, x_2, ...). Useful when the same draw runs in a loop. A non-repeatable name prints bare on every use.
Returns
A freshly generated value of type T

◆ note()

void hegel::TestCase::note ( std::string_view message) const

Record a message that will be printed on the final replay of a failing test case.

Parameters
messageThe message to record.

◆ operator=()

TestCase & hegel::TestCase::operator= ( TestCase && )
noexcept

Move-assigns, transferring ownership of the underlying handle.

Returns
Reference to this test case.

◆ reject()

void hegel::TestCase::reject ( ) const

Reject the current test case unconditionally.

Equivalent to assume(false), but marked [[noreturn]] so code after the call is statically known to be unreachable.

auto n = tc.draw(gs::integers<int>());
unsigned u = n >= 0 ? static_cast<unsigned>(n) : tc.reject();
void reject() const
Reject the current test case unconditionally.

◆ repeat()

void hegel::TestCase::repeat ( const std::function< void()> & body) const

Run body in an engine-managed loop.

The engine decides how many iterations to run, exploring and shrinking the count like any other drawn quantity. Control returns to the caller once the loop completes. A rejected iteration (via assume / reject) is discarded and the loop continues; any other exception propagates out as a failure.

Parameters
bodyCallable invoked once per iteration.
int total = 0;
tc.repeat([&] {
total += tc.draw(gs::integers<int>({.min_value = 0}));
if (total < 0) throw std::runtime_error("overflow");
});

◆ spawn()

template<typename F>
auto hegel::TestCase::spawn ( F fn) const

Run fn on a clone of this test case in a new thread.

Clones this test case on the calling thread, then invokes fn with the clone (as a TestCase&) on a std::thread. The returned Worker awaits it. Worker::join() returns fn's result and re-raises any exception it threw. Join every worker before the test body returns.

Template Parameters
FCallable invocable as fn(TestCase&).
Parameters
fnThe work to run on the cloned stream.
Returns
A Worker handle to the running thread.
auto w = tc.spawn([](hegel::TestCase& c) {
return c.draw(gs::integers<int>());
});
auto mine = tc.draw(gs::integers<int>());
auto theirs = w.join();
T draw(const generators::Generator< T > &gen) const
Draw a random value from a generator.
Definition core.h:264

◆ target()

void hegel::TestCase::target ( double score,
std::string_view label = "" ) const

Record a score for the engine's targeted-search phase to maximize.

Higher scores are treated as "more interesting." The engine biases later test cases toward inputs that produced higher scores under the same label. Has no effect unless the Target phase is enabled.

Parameters
scoreThe observation to maximize. Must be finite.
labelDistinguishes independent targeting goals. Each label may be recorded at most once per test case.
auto n = tc.draw(gs::integers<int>({.min_value = 0}));
tc.target(static_cast<double>(n));

The documentation for this class was generated from the following files: