Sequoia
|
Free functions for performing checks, together with the 'checker' class template which wraps them. More...
#include "sequoia/TestFramework/CoreInfrastructure.hpp"
#include "sequoia/TestFramework/BinaryRelationships.hpp"
#include "sequoia/TestFramework/Advice.hpp"
#include "sequoia/TestFramework/TestLogger.hpp"
#include "sequoia/Core/Meta/Utilities.hpp"
#include <format>
Go to the source code of this file.
Classes | |
struct | sequoia::testing::equality_check_t |
struct | sequoia::testing::simple_equality_check_t |
struct | sequoia::testing::general_equivalence_check_t< ValueBasedCustomizer > |
struct | sequoia::testing::general_equivalence_check_t< ValueBasedCustomizer > |
struct | sequoia::testing::general_weak_equivalence_check_t< ValueBasedCustomizer > |
struct | sequoia::testing::general_weak_equivalence_check_t< ValueBasedCustomizer > |
struct | sequoia::testing::with_best_available_check_t< MinimalReporting > |
struct | sequoia::testing::exception_message_extractor< E > |
struct | sequoia::testing::default_exception_message_postprocessor |
struct | sequoia::testing::supports_range_check< CheckType, Mode, T, U, Advisor > |
struct | sequoia::testing::supports_range_check< CheckType, Mode, T, U, Advisor > |
class | sequoia::testing::checker< Mode, Extender > |
Exposes elementary check methods, with the option to plug in arbitrary Extenders to compose functionality. More... | |
Namespaces | |
namespace | sequoia::testing::impl |
Condition for applying a container check. | |
Concepts | |
concept | sequoia::testing::tests_against |
concept | sequoia::testing::tests_against_with_or_without_tutor |
concept | sequoia::testing::checkable_against |
Macros | |
#define | STATIC_CHECK(...) (check("", [](){ static_assert(__VA_ARGS__); return true; }())) |
Typedefs | |
using | sequoia::testing::equivalence_check_t = general_equivalence_check_t< void > |
using | sequoia::testing::weak_equivalence_check_t = general_weak_equivalence_check_t< void > |
Enumerations | |
enum class | minimal_reporting_permitted : bool { no , yes } |
Functions | |
template<class ValueBasedCustomizer > | |
std::string | sequoia::testing::to_string (general_equivalence_check_t< ValueBasedCustomizer >) |
template<class ValueBasedCustomizer > | |
std::string | sequoia::testing::to_string (general_weak_equivalence_check_t< ValueBasedCustomizer >) |
template<class CheckType , test_mode Mode, class T , class U , class Advisor > requires tests_against_with_or_without_tutor<CheckType, Mode, T, U, tutor<Advisor>> | |
void | sequoia::testing::select_test (CheckType flavour, test_logger< Mode > &logger, const T &obtained, const U &prediction, tutor< Advisor > advisor) |
template<class CheckType , test_mode Mode, class T , class U , class Advisor > requires is_general_equivalence_check<CheckType> && tests_against_with_or_without_tutor<CheckType, Mode, T, U, tutor<Advisor>> | |
bool | sequoia::testing::general_equivalence_check (CheckType flavour, std::string description, test_logger< Mode > &logger, const T &obtained, const U &predicted, tutor< Advisor > advisor) |
generic function that generates a check from any class providing a static check method. | |
template<bool IsFinalMessage, test_mode Mode, class Compare , class T , class Advisor > requires std::is_invocable_r_v<bool, Compare, T, T> && (!IsFinalMessage || reportable<T>) | |
void | sequoia::testing::binary_comparison (final_message_constant< IsFinalMessage >, sentinel< Mode > &sentry, Compare compare, const T &obtained, const T &prediction, tutor< Advisor > advisor) |
template<class E , test_mode Mode, class Fn , invocable_r< std::string, project_paths, std::string > Postprocessor = default_exception_message_postprocessor> | |
bool | sequoia::testing::check_exception_thrown (std::string description, test_logger< Mode > &logger, Fn &&function, const project_paths &projPaths, Postprocessor postprocessor={}) |
template<class CheckType , test_mode Mode, std::input_or_output_iterator Iter, std::sentinel_for< Iter > Sentinel, std::input_or_output_iterator PredictionIter, std::sentinel_for< PredictionIter > PredictionSentinel, class Advisor = null_advisor> requires supports_iterator_range_check<CheckType, Mode, Iter, PredictionIter, Advisor> | |
bool | sequoia::testing::check (CheckType flavour, std::string description, test_logger< Mode > &logger, Iter first, Sentinel last, PredictionIter predictionFirst, PredictionSentinel predictionLast, tutor< Advisor > advisor={}) |
The workhorse for comparing the contents of ranges. | |
template<class Compare , test_mode Mode, class T , class Advisor = null_advisor> requires potential_comparator_for<Compare, T> | |
bool | sequoia::testing::check (Compare compare, std::string description, test_logger< Mode > &logger, const T &obtained, const T &prediction, tutor< Advisor > advisor={}) |
The workhorse for performing a check with respect to a user-specified binary operator. | |
template<test_mode Mode, class T , class Advisor = null_advisor> requires supports_equality_check<Mode, T, Advisor> | |
bool | sequoia::testing::check (equality_check_t, std::string description, test_logger< Mode > &logger, const T &obtained, const T &prediction, tutor< Advisor > advisor={}) |
The workhorse of equality checking, which takes responsibility for reflecting upon types and then dispatching, appropriately. | |
template<test_mode Mode, class T , class Advisor = null_advisor> requires supports_simple_equality_check<Mode, T, Advisor> | |
bool | sequoia::testing::check (simple_equality_check_t, std::string description, test_logger< Mode > &logger, const T &obtained, const T &prediction, tutor< Advisor > advisor={}) |
The workhorse for checking simple equality. | |
template<class CheckType , test_mode Mode, class T , class U , class Advisor = null_advisor> requires supports_generalized_equivalence_check<CheckType, Mode, T, U, Advisor> | |
bool | sequoia::testing::check (CheckType flavour, std::string description, test_logger< Mode > &logger, const T &obtained, const U &prediction, tutor< Advisor > advisor={}) |
template<minimal_reporting_permitted MinimalReporting, test_mode Mode, class T , class U , class Advisor = null_advisor> requires supports_best_available_check<MinimalReporting, Mode, T, U, Advisor> | |
bool | sequoia::testing::check (with_best_available_check_t< MinimalReporting >, std::string description, test_logger< Mode > &logger, const T &obtained, const U &prediction, tutor< Advisor > advisor={}) |
The workhorse for dispatching to the strongest available type of check. | |
template<test_mode Mode, class Advisor = null_advisor> | |
bool | sequoia::testing::check (std::string description, test_logger< Mode > &logger, const bool obtained, tutor< Advisor > advisor={}) |
Variables | |
constexpr equality_check_t | sequoia::testing::equality {} |
constexpr simple_equality_check_t | sequoia::testing::simple_equality {} |
constexpr equivalence_check_t | sequoia::testing::equivalence {} |
constexpr weak_equivalence_check_t | sequoia::testing::weak_equivalence {} |
constexpr with_best_available_check_t< minimal_reporting_permitted::no > | sequoia::testing::with_best_available {} |
template<class T > | |
constexpr bool | sequoia::testing::is_elementary_check |
template<class T > | |
constexpr bool | sequoia::testing::is_best_available_check |
template<class T > | |
constexpr bool | sequoia::testing::is_customized_check |
template<class T > | |
constexpr bool | sequoia::testing::is_general_equivalence_check {is_customized_check<T> || std::is_same_v<T, equivalence_check_t> || std::is_same_v<T, weak_equivalence_check_t>} |
template<class Compare , class T > | |
constexpr bool | sequoia::testing::potential_comparator_for |
template<class CheckType , test_mode Mode, class T , class U , class Tutor > | |
constexpr bool | sequoia::testing::checkable_against_fallback |
template<test_mode Mode, class T , class U , class Tutor > | |
constexpr bool | sequoia::testing::has_elementary_check_against |
template<class CheckType , test_mode Mode, std::input_or_output_iterator Iter, std::input_or_output_iterator PredictionIter, class Advisor > | |
constexpr bool | sequoia::testing::supports_iterator_range_check {checkable_against<CheckType, Mode, std::iter_value_t<Iter>, std::iter_value_t<PredictionIter>, tutor<Advisor>>} |
Condition for applying a check across a range of values. | |
template<class CheckType , test_mode Mode, faithful_range T, faithful_range U, class Advisor > | |
constexpr bool | sequoia::testing::impl::supports_range_check_v |
template<class CheckType , test_mode Mode, class T , class U , class Advisor > | |
constexpr bool | sequoia::testing::supports_range_check_v {supports_range_check<CheckType, Mode, T, U, Advisor>::value} |
template<test_mode Mode, class T , class Advisor > | |
constexpr bool | sequoia::testing::supports_equality_check |
Condition for applying an equality check. | |
template<test_mode Mode, class T , class Advisor > | |
constexpr bool | sequoia::testing::supports_simple_equality_check |
Condition for applying an equality check. | |
template<class CheckType , test_mode Mode, class T , class U , class Advisor > | |
constexpr bool | sequoia::testing::supports_generalized_equivalence_check |
The workhorse for (weak) equivalence checking. | |
template<minimal_reporting_permitted MinimalReporting, test_mode Mode, class T , class U , class Advisor > | |
constexpr bool | sequoia::testing::supports_best_available_check |
Condition for applying the best available check. | |
Free functions for performing checks, together with the 'checker' class template which wraps them.
Given a type, T
, any reasonable testing framework must provide a mechanism for checking whether or not two instances of T
are, in some sense, the same. If the type implements operator==
then it is natural to utilize this. However, there is much more to the story. First of all, if this check fails then, in order to be useful, there must be some way of serializing the state of T
. This may be done by specializing the class template serializer for cases where operator<<
is not appropriately overloaded.
However, there is an alternative which may be superior. Consider trying to implement vector
. This class has various const accessors suggesting that, if operator==
returns false
, then the accessors can be used to probe the exact nature of the inequality. To this end, a class template value_tester is defined. Specializations that provide an implementation for the static method void test(equality_check_t, ...)
perform a detailed check of the equality of the state of two supposedly equal instance of a class. Note that there is no need for the value_tester to include checks of operator==
or operator!=
, since these will be done, regardless. Indeed, the value_tester will be triggered independently of whether operator==
fails since either the latter or the accessors may have bugs, and introducing unnecessary dependencies would reduce the fidelity of the testing framework.
If a value_tester is supplied, clients may typically expect a notification that operator==
has returned false
. There will then be a series of subsequent checks which will reveal the precise nature of the failure. For example, for vectors, one will be told whether the sizes differ and, if not, the element which is causing the difference between the two supposedly equal instances. If the vector holds a user-defined type then, so long as this has its own value_tester, the process will continue until a type is reached without a value_tester; typically this will be a sufficiently simple type that serialization is the appropriate solution (as is the case for may built-in types).
Suppose a client wishes to compare instances of some_container<T>
. If some_container<T>
has a specialization of value_tester then this will be used; if it does not then reflection is used to determine if some_container
overloads begin
and end
. If so, then it is treated as a range and all that is required is to implement a value_tester
for T
(unless serialization is prefered). If some_container
is user-defined, it is wisest to provide an overload of the value_tester. However, if the container is part of std, it is probably safe to assume it works correctly and so instead effort can be directed focused on T.
With this in mind, imagine creating a container, C
. One of the first things one may wish to do is to check that it is correctly initialized. It would be a mistake to use value_tester<C>::test(equality_check_t, ...)
for this since, to do so, a second, identical instance would need to be created. This is circular and prone to false positives. However, one may instead furnish value_tester<C>
with methods test(equivalence_check_t, ...)
and/or test(weak_equivalence_check_t, ...)
.
We may consider a value for e.g. std::vector<int>
to be equivalent to an initializer_list<int>
in the sense that they hold (at the relevant point of the program) the same elements. Thus, an appropriate defintion of test(equivalence_check_t, ...)
is supplied. Of course, there is more to a vector than the values it holds: there is the entire allocator framework too. In this case, however, it is not part of the logical structure and, indeed, the state of the allocator is not considered in vector<T>::operator==
. Thus it is philosophically reasonable to consider equivalence of vector
and initializer_list
. However, sometimes is is useful to check the equivalence of the state of an instance of T
to a proper subset of the logical state of an instance of some S. For this purpose, an appropriate defintion of test(weak_equivalence_check_t, ...)
.
bool sequoia::testing::check | ( | CheckType | flavour, |
std::string | description, | ||
test_logger< Mode > & | logger, | ||
Iter | first, | ||
Sentinel | last, | ||
PredictionIter | predictionFirst, | ||
PredictionSentinel | predictionLast, | ||
tutor< Advisor > | advisor = {} |
||
) |
The workhorse for comparing the contents of ranges.
bool sequoia::testing::check | ( | Compare | compare, |
std::string | description, | ||
test_logger< Mode > & | logger, | ||
const T & | obtained, | ||
const T & | prediction, | ||
tutor< Advisor > | advisor = {} |
||
) |
The workhorse for performing a check with respect to a user-specified binary operator.
The comparison object either implements binary comparison for T or it is fed into the overload for ranges.
bool sequoia::testing::check | ( | equality_check_t | , |
std::string | description, | ||
test_logger< Mode > & | logger, | ||
const T & | obtained, | ||
const T & | prediction, | ||
tutor< Advisor > | advisor = {} |
||
) |
The workhorse of equality checking, which takes responsibility for reflecting upon types and then dispatching, appropriately.
The input type, T, must either
If this constraint is not satisfied there are several possible remedies:
check(equivalence_check_t,...)
or check(weak_equivalence_check_t,...)
then consider furnishing either of these with an implementation. bool sequoia::testing::general_equivalence_check | ( | CheckType | flavour, |
std::string | description, | ||
test_logger< Mode > & | logger, | ||
const T & | obtained, | ||
const U & | predicted, | ||
tutor< Advisor > | advisor | ||
) |
generic function that generates a check from any class providing a static check method.
This employs a sentinel and so can be used naively.
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
Condition for applying the best available check.
|
inlineconstexpr |
Condition for applying an equality check.
|
inlineconstexpr |
The workhorse for (weak) equivalence checking.
This function will reflect on whether an appropriate invocation of check(equivalence_check_t,...)
or check(weak_equivalence_check_t,...)
exists. If so, it will be used and if not the method will attempt to interpret T as a range. If both of these fail then:
Condition for applying a generalized equivalance check
|
inlineconstexpr |
Condition for applying an equality check.