Adds cpp-utils as a dependency.
Uses PrettyPrint from cpp-utils instead of the local copies.
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,8 +1,9 @@
|
|||||||
/.vscode/
|
/.vscode/
|
||||||
/bazel-*
|
/bazel-*
|
||||||
/build/
|
/build/
|
||||||
/tmp/
|
|
||||||
/docs/
|
/docs/
|
||||||
|
/external
|
||||||
|
/tmp/
|
||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
|
|||||||
1
BUILD
1
BUILD
@@ -35,6 +35,7 @@ cc_library(
|
|||||||
hdrs = ["tinytest.h"],
|
hdrs = ["tinytest.h"],
|
||||||
includes = ["*.h"],
|
includes = ["*.h"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
deps = ["@cpputils//:pretty_print"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_test(
|
cc_test(
|
||||||
|
|||||||
15
WORKSPACE
15
WORKSPACE
@@ -52,20 +52,9 @@ http_archive(
|
|||||||
urls = ["https://github.com/google/googletest/archive/ccdeec888ebb740a7ea4e07d3e84a1b7ee32b315.zip"],
|
urls = ["https://github.com/google/googletest/archive/ccdeec888ebb740a7ea4e07d3e84a1b7ee32b315.zip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "com_google_absl",
|
|
||||||
strip_prefix = "abseil-cpp-b971ac5250ea8de900eae9f95e06548d14cd95fe",
|
|
||||||
urls = ["https://github.com/abseil/abseil-cpp/archive/b971ac5250ea8de900eae9f95e06548d14cd95fe.zip"],
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "bazel_skylib",
|
|
||||||
sha256 = "f7be3474d42aae265405a592bb7da8e171919d74c16f082a5457840f06054728",
|
|
||||||
urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz"],
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "cpputils",
|
name = "cpputils",
|
||||||
|
sha256 = "2d1f0904640706ad9b88bfc2acf03225af6d9cf9aca0863b6cff8ceeb976aca6",
|
||||||
strip_prefix = "cpp-utils-52de4b8bc2f6d8118dba94ade47f70522ba87b56",
|
strip_prefix = "cpp-utils-52de4b8bc2f6d8118dba94ade47f70522ba87b56",
|
||||||
urls = ["https://github.com/headhunter45/TinyTest/archive/460c9492d927689b9db7f28d8742705dc0bbee62.zip"],
|
urls = ["https://github.com/headhunter45/cpp-utils/archive/52de4b8bc2f6d8118dba94ade47f70522ba87b56.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|||||||
625
tinytest.h
625
tinytest.h
@@ -1,5 +1,5 @@
|
|||||||
#ifndef TEST_H__
|
#ifndef TinyTest__tinytest_h__
|
||||||
#define TEST_H__
|
#define TinyTest__tinytest_h__
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
* @file tinytest.h *
|
* @file tinytest.h *
|
||||||
* *
|
* *
|
||||||
@@ -21,144 +21,208 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "pretty_print.h"
|
||||||
|
|
||||||
namespace TinyTest {
|
namespace TinyTest {
|
||||||
// Begin EscapeForPrinting
|
|
||||||
template <typename TChar, typename TTraits>
|
|
||||||
std::basic_string_view<TChar, TTraits> EscapeForPrinting(const std::basic_string_view<TChar, TTraits>& text) {
|
|
||||||
return std::regex_replace(text, std::regex("\033"), "\\033");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TChar, typename TTraits>
|
/// @defgroup tests Tests
|
||||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string<TChar, TTraits>& text) {
|
/// @defgroup test_suites Test Suites
|
||||||
return std::regex_replace(text, std::regex("\033"), "\\033");
|
/// @defgroup test_results Test Results
|
||||||
}
|
/// @defgroup test_execution Test Execution
|
||||||
|
/// @defgroup configure_functions Configure Functions
|
||||||
|
/// @defgroup compare_functions Compare Functions
|
||||||
|
/// @defgroup helpers Helpers
|
||||||
|
|
||||||
template <typename TChar>
|
/// @addtogroup configure_functions
|
||||||
std::basic_string<TChar> EscapeForPrinting(const TChar* text) {
|
/// @{
|
||||||
return std::regex_replace(text, std::regex("\033"), "\\033");
|
|
||||||
}
|
|
||||||
|
|
||||||
// End EscapeForPrinting
|
/// @brief This is a type that represents a setup or teardown function for tests.
|
||||||
|
using TestConfigureFunction = std::function<void()>;
|
||||||
|
|
||||||
// Begin PrettyPrint
|
/// @brief This is a type that represents an optional setup or teardown function for tests.
|
||||||
// std::string_view.
|
using MaybeTestConfigureFunction = std::optional<TestConfigureFunction>;
|
||||||
template <typename TChar, typename TTraits>
|
|
||||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string_view<TChar, TTraits>& item) {
|
|
||||||
os << "\"" << EscapeForPrinting(item) << "\"";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::string.
|
/// @brief This is the default configure function.
|
||||||
template <typename TChar, typename TTraits>
|
/// @return The default configure function. This is currently std::nullopt.
|
||||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string<TChar, TTraits>& item) {
|
MaybeTestConfigureFunction DefaultTestConfigureFunction();
|
||||||
os << "\"" << EscapeForPrinting(item) << "\"";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// const char*.
|
/// @brief Combines multiple test configure functions into a single one.
|
||||||
template <typename TChar, typename TTraits>
|
/// @param first The first setup function if this is nullopt it is ignored.
|
||||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const TChar* item) {
|
/// @param second The second setup function if this is nullopt it is ignored.
|
||||||
os << "\"" << EscapeForPrinting(item) << "\"";
|
/// @return The resulting setup function or nullopt if both first and second are nullopt.
|
||||||
return os;
|
MaybeTestConfigureFunction Coalesce(MaybeTestConfigureFunction first, MaybeTestConfigureFunction second);
|
||||||
}
|
/// @}
|
||||||
|
|
||||||
// tuple<...>
|
/// @addtogroup compare_functions
|
||||||
template <typename TChar, typename TTraits, typename... TArgs>
|
/// @{
|
||||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits> os, const std::tuple<TArgs...>& tuple) {
|
|
||||||
std::apply(
|
|
||||||
[&os](auto&&... args) {
|
|
||||||
if (sizeof...(TArgs) == 0) {
|
|
||||||
os << "[]";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t n = 0;
|
|
||||||
os << "[ ";
|
|
||||||
((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? ", " : "")), ...);
|
|
||||||
os << " ]";
|
|
||||||
},
|
|
||||||
tuple);
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// containers
|
/// @brief This is a type that represents a compare function for types of TResult.
|
||||||
template <typename TChar,
|
///
|
||||||
typename TTraits,
|
/// It should return true if the parameters are equal and false otherwise.
|
||||||
typename TContainer,
|
/// @tparam TResult The type of the parameters. This is the return type of the function being tested.
|
||||||
typename = std::enable_if_t<
|
template <typename TResult>
|
||||||
std::is_same_v<decltype(std::declval<TContainer>().begin()), decltype(std::declval<TContainer>().end())>>,
|
using TestCompareFunction = std::function<bool(const TResult& expected, const TResult& actual)>;
|
||||||
typename = std::enable_if_t<std::is_base_of_v<
|
|
||||||
std::input_iterator_tag,
|
|
||||||
typename std::iterator_traits<decltype(std::declval<TContainer>().begin())>::iterator_category>>>
|
|
||||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TContainer container) {
|
|
||||||
os << "[ ";
|
|
||||||
for (auto it = container.begin(); it != container.end(); it++) {
|
|
||||||
if (it != container.begin()) {
|
|
||||||
os << ", ";
|
|
||||||
}
|
|
||||||
PrettyPrint(os, *it);
|
|
||||||
}
|
|
||||||
os << " ]";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch-all for everything else.
|
/// @brief This is a type that represents an optional compare function for types of TResult.
|
||||||
template <typename TChar, typename TTraits, typename TItem>
|
/// @tparam TResult The type of the parameters. This is the return type of the function being tested.
|
||||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TItem item) {
|
template <typename TResult>
|
||||||
os << item;
|
using MaybeTestCompareFunction = std::optional<TestCompareFunction<TResult>>;
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// End PrettyPrint
|
/// @brief This is the default compare function.
|
||||||
|
/// @tparam TResult The return type of the test function.
|
||||||
|
/// @return The default compare function. Currently this is std::nullopt.
|
||||||
|
template <typename TResult>
|
||||||
|
MaybeTestCompareFunction<TResult> DefaultTestCompareFunction();
|
||||||
|
/// @}
|
||||||
|
|
||||||
// Begin PrettyPrintWithSeparator
|
// TODO: For some reason all hell breaks loose if test_name or expected output
|
||||||
// Prints args with separator between them. std::string_view separator.
|
// are const&. Figure out why. Probably need to use decay and make const& where we want it explicitly.
|
||||||
template <typename TChar, typename TTraits, typename... TArgs>
|
/// @addtogroup tests
|
||||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> os,
|
/// @{
|
||||||
std::basic_string_view<TChar, TTraits> separator,
|
|
||||||
TArgs&&... args) {
|
|
||||||
(((PrettyPrint(os, args), os), EscapeForPrinting(separator)), ...);
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints args with separator between them. std::string separator.
|
/// @brief This is a type that represents an individual test.
|
||||||
template <typename TChar, typename TTraits, typename... TArgs>
|
/// @tparam TResult The return type of the test function.
|
||||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> os,
|
/// @tparam ...TInputParams The parameters to pass to the test function
|
||||||
std::basic_string<TChar, TTraits> separator,
|
template <typename TResult, typename... TInputParams>
|
||||||
TArgs&&... args) {
|
using TestTuple = std::tuple<
|
||||||
(((PrettyPrint_item(os, args), os), EscapeForPrinting(separator)), ...);
|
/// test_name
|
||||||
return os;
|
std::string,
|
||||||
}
|
/// expected_output
|
||||||
|
TResult,
|
||||||
|
/// input_params - The input parameters for this test. These will be used when calling std::apply with
|
||||||
|
/// function_to_test to execute the test.
|
||||||
|
std::tuple<TInputParams...>,
|
||||||
|
/// test_compare_function - If this is not nullptr then this function will be called instead of
|
||||||
|
/// suite_compare_function to determine if the test passes. Use this to check for side effects of the test. Return
|
||||||
|
/// true if the test passes and false otherwise.
|
||||||
|
MaybeTestCompareFunction<TResult>,
|
||||||
|
/// test_setup_function - If this is not nullptr this function is called before each test to setup the environment.
|
||||||
|
/// It is called with std::apply and input_params so you can use them to mock records with specific IDs or calculate
|
||||||
|
/// an expected result.
|
||||||
|
MaybeTestConfigureFunction,
|
||||||
|
/// test_teardown_function - If this is not nullptr this function is called after each test to cleanup any
|
||||||
|
/// allocated/shared resources.
|
||||||
|
MaybeTestConfigureFunction,
|
||||||
|
/// is_enabled - If this is false the test, setup, and teardown functions are not run.
|
||||||
|
bool>;
|
||||||
|
|
||||||
// Prints args with separator between them. const char* separator.
|
/// @brief Executes a TestSuite.
|
||||||
template <typename TChar, typename TTraits, typename... Args>
|
/// @tparam TResult The result type of the test.
|
||||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> os, const TChar* separator, Args&&... args) {
|
/// @tparam ...TInputParams The types of parameters sent to the test function.
|
||||||
((os << args << EscapeForPrinting(separator)), ...);
|
/// @param test_name The label for this test. For example "should calculate the
|
||||||
return os;
|
/// interest".
|
||||||
}
|
/// @param expected The expected output of calling the test function with these
|
||||||
|
/// input parameters.
|
||||||
|
/// @param input_params The input parameters to use when calling the test
|
||||||
|
/// function.
|
||||||
|
/// @param test_compare_function An optional function that can be used to Compare the
|
||||||
|
/// expected and actual return values. This is good for when you only care about
|
||||||
|
/// certain fields being equal.
|
||||||
|
/// @param before_each This is called to setup the environment before running
|
||||||
|
/// the test. This is where you should build mocks, setup spies, and set any
|
||||||
|
/// other values you need before calling the test function.
|
||||||
|
/// @param after_each This is called after each test run to cleanup anything
|
||||||
|
/// allocated in before_each.
|
||||||
|
/// @param is_enabled If false this test run is not executed and considered
|
||||||
|
/// skipped for reporting purposes.
|
||||||
|
/// @return A TestTuple suitable for use as a test run when calling test_fn.
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
TestTuple<TResult, TInputParams...> MakeTest(const std::string& test_name,
|
||||||
|
const TResult& expected,
|
||||||
|
std::tuple<TInputParams...> input_params,
|
||||||
|
MaybeTestCompareFunction<TResult> test_compare_function = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction before_each = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction after_each = std::nullopt,
|
||||||
|
bool is_enabled = true);
|
||||||
|
/// @}
|
||||||
|
|
||||||
// End PrettyPrintWithSeparator
|
/// @addtogroup test_suites
|
||||||
|
/// @{
|
||||||
|
|
||||||
////////////////////
|
/// @brief This type represents a test suite.
|
||||||
|
/// @tparam TResult The return type of the function to test.
|
||||||
|
/// @tparam TFunctionToTest The type of the function to test.
|
||||||
|
/// @tparam ...TInputParams The types of the input parameters to the function to test.
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
using TestSuite = std::tuple<
|
||||||
|
/// test_name - The name of the test.
|
||||||
|
std::string,
|
||||||
|
/// function_to_test - The function to test. It will be executed once for each item in the tests initializer_list.
|
||||||
|
std::function<TResult(TInputParams...)>,
|
||||||
|
/// tests - This is an initializer list of @link TestTuple @endlink that represent the test runs to execute.
|
||||||
|
std::initializer_list<TestTuple<TResult, TInputParams...>>,
|
||||||
|
/// test_compare_function - This is an optional function that overrides how test results are compared.
|
||||||
|
MaybeTestCompareFunction<TResult>,
|
||||||
|
/// before_each - This is an optional function that is executed before each test.
|
||||||
|
MaybeTestConfigureFunction,
|
||||||
|
/// after_each - This is an optional function that is executed after each test.
|
||||||
|
MaybeTestConfigureFunction,
|
||||||
|
// is_enabled - If true the suite is executed. If false all test runs are reported as skipped and none are run.
|
||||||
|
bool>;
|
||||||
|
|
||||||
// TODO: Document this.
|
/// @brief Makes a TestSuite tuple from the given parameters.
|
||||||
|
/// @tparam TResult The return type of function_to_test.
|
||||||
|
/// @tparam TFunctionToTest The type of function_to_test.
|
||||||
|
/// @tparam ...TInputParams The parameter types of function_to_test.
|
||||||
|
/// @param suite_name The label for this test suite.
|
||||||
|
/// @param function_to_test The function to test.
|
||||||
|
/// @param test_data The configuration for the test runs.
|
||||||
|
/// @param compare An optional compare function to use when evaluating test results.
|
||||||
|
/// @param before_each An optional function to run before each test.
|
||||||
|
/// @param after_each An optional function to run after each test.
|
||||||
|
/// @param is_enabled If false the test suite is skipped. All tests in the suite will be reported as skipped.
|
||||||
|
/// @return The results of the test suite.
|
||||||
|
template <typename TResult, typename TFunctionToTest, typename... TInputParams>
|
||||||
|
TestSuite<TResult, TInputParams...> MakeTestSuite(const std::string& suite_name,
|
||||||
|
TFunctionToTest function_to_test,
|
||||||
|
std::initializer_list<TestTuple<TResult, TInputParams...>> test_data,
|
||||||
|
MaybeTestCompareFunction<TResult> compare = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction before_each = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction after_each = std::nullopt,
|
||||||
|
bool is_enabled = true);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// @addtogroup helpers
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// @brief Intercepts cout, executes the function and returns a string with all tesxt sent to cout while running the
|
||||||
|
/// function.
|
||||||
|
/// @tparam TResult The return type of function_to_execute.
|
||||||
|
/// @tparam ...TParameters The parameter types of function_to_execute.
|
||||||
|
/// @param function_to_execute The function to execute.
|
||||||
|
/// @param maybe_args The args to call function_to_execute with or nullopt if it takes no parameters.
|
||||||
|
/// @return A string containing all text written to cout by function_to_execute.
|
||||||
template <typename TResult, typename... TParameters>
|
template <typename TResult, typename... TParameters>
|
||||||
std::string InterceptCout(std::function<TResult(TParameters...)> fnToExecute,
|
std::string InterceptCout(std::function<TResult(TParameters...)> function_to_execute,
|
||||||
std::optional<std::tuple<TParameters...>> maybe_args = std::nullopt) {
|
std::optional<std::tuple<TParameters...>> maybe_args = std::nullopt);
|
||||||
std::ostringstream os;
|
|
||||||
auto saved_buffer = std::cout.rdbuf();
|
|
||||||
std::cout.rdbuf(os.rdbuf());
|
|
||||||
// TODO: run the function
|
|
||||||
|
|
||||||
if (maybe_args.has_value()) {
|
/// @brief This function compares two vectors.
|
||||||
std::apply(fnToExecute, maybe_args.value());
|
/// @tparam TChar The character type of the stream to write to.
|
||||||
} else {
|
/// @tparam TTraits The character_traits type of the stream to write to.
|
||||||
std::invoke(fnToExecute);
|
/// @tparam TItem The type of item in the vectors.
|
||||||
}
|
/// @param error_message The stream to write error messages to.
|
||||||
std::cout.rdbuf(saved_buffer);
|
/// @param expected The expected vector.
|
||||||
return os.str();
|
/// @param actual The actual vector.
|
||||||
}
|
/// @return The error_message stream.
|
||||||
|
template <typename TChar, typename TTraits, typename TItem>
|
||||||
|
auto& Compare(std::basic_ostream<TChar, TTraits>& error_message,
|
||||||
|
std::vector<TItem> expected,
|
||||||
|
std::vector<TItem> actual);
|
||||||
|
|
||||||
/// @brief
|
/// @}
|
||||||
|
|
||||||
|
/// @addtogroup test_results
|
||||||
|
|
||||||
|
/// @brief Represents the results of running some number of tests.
|
||||||
|
///
|
||||||
|
/// This type may evolve over time, but currently it tracks:
|
||||||
|
/// * The total number of tests run.
|
||||||
|
/// * The number of failures and any messages sent with the failures.
|
||||||
|
/// * The number of tests skipped and any messages sent with the skips.
|
||||||
|
/// * The number of tests with errors and any error messages sent with the errors.
|
||||||
|
/// * __Note:__ Errors do not count as test runs. Errored tests will be recorded as a passed/failed/skipped test
|
||||||
|
/// separately.
|
||||||
|
/// * The number of passed tests.
|
||||||
class TestResults {
|
class TestResults {
|
||||||
public:
|
public:
|
||||||
/// @brief Creates an empty TestResults instance representing no tests run.
|
/// @brief Creates an empty TestResults instance representing no tests run.
|
||||||
@@ -173,8 +237,7 @@ class TestResults {
|
|||||||
/// @param failed The number of failed tests.
|
/// @param failed The number of failed tests.
|
||||||
/// @param passed The number of passed tests.
|
/// @param passed The number of passed tests.
|
||||||
/// @param skipped The number of skipped tests.
|
/// @param skipped The number of skipped tests.
|
||||||
/// @param total The total number of tests run. This should equal the sum of
|
/// @param total The total number of tests run. This should equal the sum of failed, passed, and skipped tests.
|
||||||
/// failed, passed, and skipped tests.
|
|
||||||
/// @param error_messages The list of error messages.
|
/// @param error_messages The list of error messages.
|
||||||
/// @param failure_messages The list of failure messages.
|
/// @param failure_messages The list of failure messages.
|
||||||
/// @param skip_messages The list of skip messages.
|
/// @param skip_messages The list of skip messages.
|
||||||
@@ -275,82 +338,33 @@ class TestResults {
|
|||||||
uint32_t total_;
|
uint32_t total_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief
|
/// @brief Writes a friendly version of results to the provided stream.
|
||||||
/// @tparam TResult
|
/// @param os The stream to write to.
|
||||||
template <typename TResult>
|
/// @param results The TestResults to write.
|
||||||
using TestCompareFunction = std::function<bool(const TResult& expected, const TResult& actual)>;
|
void PrintResults(std::ostream& os, TestResults results);
|
||||||
|
|
||||||
/// @brief
|
/// @addtogroup test_execution
|
||||||
/// @tparam TResult
|
/// @{
|
||||||
template <typename TResult>
|
|
||||||
using MaybeTestCompareFunction = std::optional<TestCompareFunction<TResult>>;
|
|
||||||
|
|
||||||
// TODO: Document this.
|
|
||||||
template <typename TResult>
|
|
||||||
MaybeTestCompareFunction<TResult> DefaultTestCompareFunction() {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Document this.
|
|
||||||
using TestConfigureFunction = std::function<void()>;
|
|
||||||
// TODO: Document this.
|
|
||||||
using MaybeTestConfigureFunction = std::optional<TestConfigureFunction>;
|
|
||||||
// TOD: Document this.
|
|
||||||
MaybeTestConfigureFunction DefaultTestConfigureFunction();
|
|
||||||
|
|
||||||
// TODO: For some reason all hell breaks loose if test_name or expected output
|
|
||||||
// are const&. Figure out why. Probably need to use decay and make const& where we want it explicitly.
|
|
||||||
/// @brief
|
|
||||||
/// @tparam TResult
|
|
||||||
/// @tparam ...TInputParams
|
|
||||||
template <typename TResult, typename... TInputParams>
|
|
||||||
using TestTuple =
|
|
||||||
std::tuple<std::string /* test_name */,
|
|
||||||
TResult /* expected_output */,
|
|
||||||
std::tuple<TInputParams...> /* input_params - The input parameters for this test. These will be used when
|
|
||||||
calling std::apply with function_to_test to execute the test. */
|
|
||||||
,
|
|
||||||
MaybeTestCompareFunction<TResult> /* test_Compare_function - If this is not nullprt then this function
|
|
||||||
will be called instead of suite_Compare_function to determine if the
|
|
||||||
test passes. Use this to check for side effects of the test. Return
|
|
||||||
true if the test passes and false otherwise. */
|
|
||||||
,
|
|
||||||
MaybeTestConfigureFunction /* test_setup_function - If this is not nullptr this function is called before
|
|
||||||
each test to setup the environment. It is called with std::apply and
|
|
||||||
input_params so you can use them to mock records with specific IDs or
|
|
||||||
calculate an expected result. */
|
|
||||||
,
|
|
||||||
MaybeTestConfigureFunction /* test_teardown_function If this is not nullptr this function is called after
|
|
||||||
each test to cleanup any allocated/shared resources. */
|
|
||||||
,
|
|
||||||
bool /* is_enabled If this is false the test, setup, and teardown functions are not run. */>;
|
|
||||||
|
|
||||||
/// @brief
|
|
||||||
/// @tparam TResult
|
|
||||||
/// @tparam TFunctionToTest
|
|
||||||
/// @tparam ...TInputParams
|
|
||||||
template <typename TResult, typename... TInputParams>
|
|
||||||
using TestSuite = std::tuple<std::string,
|
|
||||||
std::function<TResult(TInputParams...)>,
|
|
||||||
std::initializer_list<TestTuple<TResult, TInputParams...>>,
|
|
||||||
MaybeTestCompareFunction<TResult>,
|
|
||||||
MaybeTestConfigureFunction,
|
|
||||||
MaybeTestConfigureFunction,
|
|
||||||
bool>;
|
|
||||||
|
|
||||||
|
/// @brief This function marks a test as skipped with an optional reason.
|
||||||
|
/// @param results The TestResults to update.
|
||||||
|
/// @param suite_label The label for the test suite.
|
||||||
|
/// @param test_label The label for the test.
|
||||||
|
/// @param reason The optional reason the test is being skipped.
|
||||||
|
/// @return The TestResults for chaining.
|
||||||
TestResults& SkipTest(TestResults& results,
|
TestResults& SkipTest(TestResults& results,
|
||||||
const std::string& suite_label,
|
const std::string& suite_label,
|
||||||
const std::string& test_label,
|
const std::string& test_label,
|
||||||
std::optional<const std::string> reason = std::nullopt);
|
std::optional<const std::string> reason = std::nullopt);
|
||||||
|
|
||||||
/// @brief
|
/// @brief Executes a TestSuite.
|
||||||
/// @tparam TResult The result type of the test.
|
/// @tparam TResult The result type of the test.
|
||||||
/// @tparam TInputParams... The types of parameters sent to the test function.
|
/// @tparam TInputParams... The types of parameters sent to the test function.
|
||||||
/// @param suite_label The label for this test suite. For example a class name
|
/// @param suite_label The label for this test suite. For example a class name
|
||||||
/// such as "MortgageCalculator".
|
/// such as "MortgageCalculator".
|
||||||
/// @param function_to_test The function to be tested. It will be called with
|
/// @param function_to_test The function to be tested. It will be called with
|
||||||
/// std::apply and a std::tuple<TInputParams...> made from each item in tests.
|
/// std::apply and a std::tuple<TInputParams...> made from each item in tests.
|
||||||
/// @param tests A std::vector of test runs.
|
/// @param tests An std::initializer_list of test runs.
|
||||||
/// @param suite_Compare A function used to Compare the expected and actual test
|
/// @param suite_Compare A function used to Compare the expected and actual test
|
||||||
/// results. This can be overridden per test by setting test_Compare.
|
/// results. This can be overridden per test by setting test_Compare.
|
||||||
/// @param after_all This is called before each suite is started to setup the
|
/// @param after_all This is called before each suite is started to setup the
|
||||||
@@ -367,7 +381,90 @@ TestResults ExecuteSuite(std::string suite_label,
|
|||||||
MaybeTestCompareFunction<TResult> suite_Compare = std::nullopt,
|
MaybeTestCompareFunction<TResult> suite_Compare = std::nullopt,
|
||||||
MaybeTestConfigureFunction before_all = std::nullopt,
|
MaybeTestConfigureFunction before_all = std::nullopt,
|
||||||
MaybeTestConfigureFunction after_all = std::nullopt,
|
MaybeTestConfigureFunction after_all = std::nullopt,
|
||||||
bool is_enabled = true) {
|
bool is_enabled = true);
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult The result type of the test.
|
||||||
|
/// @tparam TInputParams... The types of parameters sent to the test function.
|
||||||
|
/// @param test_suite A tuple representing the test suite configuration.
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
TestResults ExecuteSuite(const TestSuite<TResult, TInputParams...>& test_suite);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
template <typename TResult>
|
||||||
|
MaybeTestCompareFunction<TResult> DefaultTestCompareFunction() {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
TestTuple<TResult, TInputParams...> MakeTest(const std::string& test_name,
|
||||||
|
const TResult& expected,
|
||||||
|
std::tuple<TInputParams...> input_params,
|
||||||
|
MaybeTestCompareFunction<TResult> test_compare_function,
|
||||||
|
MaybeTestConfigureFunction before_each,
|
||||||
|
MaybeTestConfigureFunction after_each,
|
||||||
|
bool is_enabled) {
|
||||||
|
return make_tuple(test_name, expected, input_params, test_compare_function, before_each, after_each, is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TResult, typename TFunctionToTest, typename... TInputParams>
|
||||||
|
TestSuite<TResult, TInputParams...> MakeTestSuite(const std::string& suite_name,
|
||||||
|
TFunctionToTest function_to_test,
|
||||||
|
std::initializer_list<TestTuple<TResult, TInputParams...>> test_data,
|
||||||
|
MaybeTestCompareFunction<TResult> compare,
|
||||||
|
MaybeTestConfigureFunction before_each,
|
||||||
|
MaybeTestConfigureFunction after_each,
|
||||||
|
bool is_enabled) {
|
||||||
|
return make_tuple(suite_name, function_to_test, test_data, compare, before_each, after_each, is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TResult, typename... TParameters>
|
||||||
|
std::string InterceptCout(std::function<TResult(TParameters...)> function_to_execute,
|
||||||
|
std::optional<std::tuple<TParameters...>> maybe_args) {
|
||||||
|
std::ostringstream os;
|
||||||
|
auto saved_buffer = std::cout.rdbuf();
|
||||||
|
std::cout.rdbuf(os.rdbuf());
|
||||||
|
|
||||||
|
if (maybe_args.has_value()) {
|
||||||
|
std::apply(function_to_execute, maybe_args.value());
|
||||||
|
} else {
|
||||||
|
std::invoke(function_to_execute);
|
||||||
|
}
|
||||||
|
std::cout.rdbuf(saved_buffer);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TChar, typename TTraits, typename TItem>
|
||||||
|
auto& Compare(std::basic_ostream<TChar, TTraits>& error_message,
|
||||||
|
std::vector<TItem> expected,
|
||||||
|
std::vector<TItem> actual) {
|
||||||
|
if (expected.size() != actual.size()) {
|
||||||
|
error_message << "size mismatch expected: " << expected.size() << ", actual: " << actual.size();
|
||||||
|
return error_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t index = 0; index < expected.size(); index++) {
|
||||||
|
if (expected[index] != actual[index]) {
|
||||||
|
error_message << "vectors differ at index " << index << ", ";
|
||||||
|
CPPUtils::PrettyPrint(error_message, expected[index]) << " != ";
|
||||||
|
CPPUtils::PrettyPrint(error_message, actual[index]) << ", expected: ";
|
||||||
|
CPPUtils::PrettyPrint(error_message, expected) << ", actual: ";
|
||||||
|
CPPUtils::PrettyPrint(error_message, actual);
|
||||||
|
return error_message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
TestResults ExecuteSuite(std::string suite_label,
|
||||||
|
std::function<TResult(TInputParams...)> function_to_test,
|
||||||
|
std::initializer_list<TestTuple<TResult, TInputParams...>> tests,
|
||||||
|
MaybeTestCompareFunction<TResult> suite_Compare,
|
||||||
|
MaybeTestConfigureFunction before_all,
|
||||||
|
MaybeTestConfigureFunction after_all,
|
||||||
|
bool is_enabled) {
|
||||||
TestResults results;
|
TestResults results;
|
||||||
if (!is_enabled) {
|
if (!is_enabled) {
|
||||||
std::cout << "🚧Skipping suite: " << suite_label << " because it is disabled." << std::endl;
|
std::cout << "🚧Skipping suite: " << suite_label << " because it is disabled." << std::endl;
|
||||||
@@ -451,7 +548,9 @@ TestResults ExecuteSuite(std::string suite_label,
|
|||||||
std::cout << " ✅PASSED" << std::endl;
|
std::cout << " ✅PASSED" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "expected: \"" << expected_output << "\", actual: \"" << actual << "\"";
|
os << "expected: ";
|
||||||
|
CPPUtils::PrettyPrint(os, expected_output) << ", actual: ";
|
||||||
|
CPPUtils::PrettyPrint(os, actual);
|
||||||
results.Fail(qualified_test_label + " " + os.str());
|
results.Fail(qualified_test_label + " " + os.str());
|
||||||
std::cout << " ❌FAILED: " << os.str() << std::endl;
|
std::cout << " ❌FAILED: " << os.str() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -471,10 +570,6 @@ TestResults ExecuteSuite(std::string suite_label,
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief
|
|
||||||
/// @tparam TResult The result type of the test.
|
|
||||||
/// @tparam TInputParams... The types of parameters sent to the test function.
|
|
||||||
/// @param test_suite A tuple representing the test suite configuration.
|
|
||||||
template <typename TResult, typename... TInputParams>
|
template <typename TResult, typename... TInputParams>
|
||||||
TestResults ExecuteSuite(const TestSuite<TResult, TInputParams...>& test_suite) {
|
TestResults ExecuteSuite(const TestSuite<TResult, TInputParams...>& test_suite) {
|
||||||
std::string suite_label = std::get<0>(test_suite);
|
std::string suite_label = std::get<0>(test_suite);
|
||||||
@@ -487,152 +582,6 @@ TestResults ExecuteSuite(const TestSuite<TResult, TInputParams...>& test_suite)
|
|||||||
return ExecuteSuite(suite_label, function_to_test, tests, suite_Compare, before_all, after_all, is_enabled);
|
return ExecuteSuite(suite_label, function_to_test, tests, suite_Compare, before_all, after_all, is_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief
|
|
||||||
/// @tparam TResult The result type of the test.
|
|
||||||
/// @tparam ...TInputParams The types of parameters sent to the test function.
|
|
||||||
/// @param test_name The label for this test. For example "should calculate the
|
|
||||||
/// interest".
|
|
||||||
/// @param expected The expected output of calling the test function with these
|
|
||||||
/// input parameters.
|
|
||||||
/// @param input_params The input parameters to use when calling the test
|
|
||||||
/// function.
|
|
||||||
/// @param test_Compare_fn An optional function that can be used to Compare the
|
|
||||||
/// expected and actual return values. This is good for when you only care about
|
|
||||||
/// certain fields being equal.
|
|
||||||
/// @param before_each This is called to setup the environment before running
|
|
||||||
/// the test. This is where you should build mocks, setup spies, and set any
|
|
||||||
/// other values you need before calling the test function.
|
|
||||||
/// @param after_each This is called after each test run to cleanup anything
|
|
||||||
/// allocated in before_each.
|
|
||||||
/// @param is_enabled If false this test run is not executed and considered
|
|
||||||
/// skipped for reporting purposes.
|
|
||||||
/// @return A TestTuple suitable for use as a test run when calling test_fn.
|
|
||||||
template <typename TResult, typename... TInputParams>
|
|
||||||
TestTuple<TResult, TInputParams...> MakeTest(const std::string& test_name,
|
|
||||||
const TResult& expected,
|
|
||||||
std::tuple<TInputParams...> input_params,
|
|
||||||
MaybeTestCompareFunction<TResult> test_Compare_fn = std::nullopt,
|
|
||||||
MaybeTestConfigureFunction before_each = std::nullopt,
|
|
||||||
MaybeTestConfigureFunction after_each = std::nullopt,
|
|
||||||
bool is_enabled = true) {
|
|
||||||
return make_tuple(test_name, expected, input_params, test_Compare_fn, before_each, after_each, is_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief
|
|
||||||
/// @tparam TResult
|
|
||||||
/// @tparam TFunctionToTest
|
|
||||||
/// @tparam ...TInputParams
|
|
||||||
/// @param suite_name
|
|
||||||
/// @param function_to_test
|
|
||||||
/// @param test_data
|
|
||||||
/// @param Compare
|
|
||||||
/// @param before_each
|
|
||||||
/// @param after_each
|
|
||||||
/// @param is_enabled
|
|
||||||
/// @return
|
|
||||||
template <typename TResult, typename TFunctionToTest, typename... TInputParams>
|
|
||||||
TestSuite<TResult, TInputParams...> MakeTestSuite(const std::string& suite_name,
|
|
||||||
TFunctionToTest function_to_test,
|
|
||||||
std::initializer_list<TestTuple<TResult, TInputParams...>> test_data,
|
|
||||||
MaybeTestCompareFunction<TResult> Compare = std::nullopt,
|
|
||||||
MaybeTestConfigureFunction before_each = std::nullopt,
|
|
||||||
MaybeTestConfigureFunction after_each = std::nullopt,
|
|
||||||
bool is_enabled = true) {
|
|
||||||
return make_tuple(suite_name, function_to_test, test_data, Compare, before_each, after_each, is_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Writes a friendly version of results to the provided stream.
|
|
||||||
/// @param os The stream to write to.
|
|
||||||
/// @param results The TestResults to write.
|
|
||||||
void PrintResults(std::ostream& os, TestResults results);
|
|
||||||
|
|
||||||
/// @brief
|
|
||||||
/// @param first
|
|
||||||
/// @param second
|
|
||||||
/// @return
|
|
||||||
MaybeTestConfigureFunction Coalesce(MaybeTestConfigureFunction first, MaybeTestConfigureFunction second);
|
|
||||||
|
|
||||||
// TODO: Document this.
|
|
||||||
// Tuple printer based on code from:
|
|
||||||
// https://stackoverflow.com/questions/6245735/pretty-print-stdtuple/31116392#58417285
|
|
||||||
template <typename TChar, typename TTraits, typename... TArgs>
|
|
||||||
auto& operator<<(std::basic_ostream<TChar, TTraits>& os, std::tuple<TArgs...> const& t) {
|
|
||||||
std::apply(
|
|
||||||
[&os](auto&&... args) {
|
|
||||||
if (sizeof...(TArgs) == 0) {
|
|
||||||
os << "[]";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t n = 0;
|
|
||||||
os << "[ ";
|
|
||||||
((TinyTest::PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? ", " : "")), ...);
|
|
||||||
os << " ]";
|
|
||||||
},
|
|
||||||
t);
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Document this.
|
|
||||||
template <typename TChar, typename TTraits>
|
|
||||||
auto& operator<<(std::basic_ostream<TChar, TTraits>& os, const void* pointer) {
|
|
||||||
os << pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Simplify this.
|
|
||||||
template <typename TChar,
|
|
||||||
typename TTraits,
|
|
||||||
typename TContainer,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
std::is_same_v<decltype(std::declval<TContainer>().begin()), decltype(std::declval<TContainer>().end())>>,
|
|
||||||
typename = std::enable_if_t<std::is_base_of_v<
|
|
||||||
std::input_iterator_tag,
|
|
||||||
typename std::iterator_traits<decltype(std::declval<TContainer>().begin())>::iterator_category>>>
|
|
||||||
auto& operator<<(std::basic_ostream<TChar, TTraits>& os, TContainer container) {
|
|
||||||
os << "[ ";
|
|
||||||
for (auto it = container.begin(); it != container.end(); it++) {
|
|
||||||
if (it != container.begin()) {
|
|
||||||
os << ", ";
|
|
||||||
}
|
|
||||||
TinyTest::PrettyPrint(os, *it);
|
|
||||||
}
|
|
||||||
os << " ]";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Document this.
|
|
||||||
template <typename TChar, typename TTraits, typename TItem>
|
|
||||||
auto& operator<<(std::basic_ostream<TChar, TTraits>& os, std::initializer_list<TItem> container) {
|
|
||||||
os << "[ ";
|
|
||||||
for (auto it = container.begin(); it != container.end(); it++) {
|
|
||||||
if (it != container.begin()) {
|
|
||||||
os << ", ";
|
|
||||||
}
|
|
||||||
TinyTest::PrettyPrint(os, *it);
|
|
||||||
}
|
|
||||||
os << " ]";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Document this.
|
|
||||||
template <typename TChar, typename TTraits, typename TItem>
|
|
||||||
auto& Compare(std::basic_ostream<TChar, TTraits>& error_message,
|
|
||||||
std::vector<TItem> expected,
|
|
||||||
std::vector<TItem> actual) {
|
|
||||||
if (expected.size() != actual.size()) {
|
|
||||||
error_message << "size mismatch expected: " << expected.size() << ", actual: " << actual.size();
|
|
||||||
return error_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t index = 0; index < expected.size(); index++) {
|
|
||||||
if (expected[index] != actual[index]) {
|
|
||||||
error_message << "vectors differ at index " << index << ", \"" << expected[index] << "\" != \"" << actual[index]
|
|
||||||
<< "\", expected: \"" << expected << "\", actual: \"" << actual << "\"";
|
|
||||||
return error_message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return error_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End namespace TinyTest
|
} // End namespace TinyTest
|
||||||
|
|
||||||
#endif // End !defined TEST_H__
|
#endif // End !defined(TinyTest__tinytest_h__)
|
||||||
|
|||||||
@@ -42,74 +42,6 @@ using TinyTest::PrintResults;
|
|||||||
using TinyTest::TestResults;
|
using TinyTest::TestResults;
|
||||||
using TinyTest::TestSuite;
|
using TinyTest::TestSuite;
|
||||||
using TinyTest::TestTuple;
|
using TinyTest::TestTuple;
|
||||||
using TinyTest::operator<<;
|
|
||||||
|
|
||||||
TEST(TuplePrinter, ShouldPrintAnEmptyTuple) {
|
|
||||||
ostringstream os;
|
|
||||||
auto tuple = make_tuple();
|
|
||||||
os << tuple;
|
|
||||||
// Ideally something like "[]" or "Tuple: []"
|
|
||||||
EXPECT_THAT(os.str(), Eq("[]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TuplePrinter, ShouldPrintATupleOfOneString) {
|
|
||||||
ostringstream os;
|
|
||||||
auto tuple = make_tuple("asdf");
|
|
||||||
os << tuple;
|
|
||||||
// Ideally this wouldn't have a space at the end.
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ \"asdf\" ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TuplePrinter, ShouldPrintATupleOfTwoIntegers) {
|
|
||||||
ostringstream os;
|
|
||||||
auto tuple = make_tuple(69, 420);
|
|
||||||
os << tuple;
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ 69, 420 ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TuplePrinter, ShouldPrintATupleOfTwoStrings) {
|
|
||||||
ostringstream os;
|
|
||||||
auto tuple = make_tuple("first", "second");
|
|
||||||
os << tuple;
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ \"first\", \"second\" ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TuplePrinter, ShouldPrintATupleOfOneStringAndOneInteger) {
|
|
||||||
ostringstream os;
|
|
||||||
auto tuple = make_tuple("this is a string that ends with 69", 420);
|
|
||||||
os << tuple;
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ \"this is a string that ends with 69\", 420 ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TuplePrinter, ShouldPringATupleOfStringsContainingSpaces) {
|
|
||||||
ostringstream os;
|
|
||||||
auto tuple = make_tuple(" ", " ", " ", " ");
|
|
||||||
os << tuple;
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ \" \", \" \", \" \", \" \" ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(VectorPrinter, ShouldPrintAnEmptyVector) {
|
|
||||||
ostringstream os;
|
|
||||||
vector value = vector({1, 2, 3, 4});
|
|
||||||
os << value;
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ 1, 2, 3, 4 ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(VectorPrinter, ShouldPrintAVectorOfCStrings) {
|
|
||||||
ostringstream os;
|
|
||||||
vector value = vector({"asdf", "fdsa", "lemon", "cherry"});
|
|
||||||
os << value;
|
|
||||||
// Ideally "[ \"asdf\", \"fdsa\", \"lemon\", \"cherry\" ]"
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ \"asdf\", \"fdsa\", \"lemon\", \"cherry\" ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(VectorPrinter, ShouldPrintAVectorOfStrings) {
|
|
||||||
ostringstream os;
|
|
||||||
vector value = vector<string>({"asdf", "fdsa", "lemon", "cherry"});
|
|
||||||
os << value;
|
|
||||||
// Ideally "[ \"asdf\", \"fdsa\", \"lemon\", \"cherry\" ]"
|
|
||||||
EXPECT_THAT(os.str(), Eq("[ \"asdf\", \"fdsa\", \"lemon\", \"cherry\" ]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(VectorCompare, ShouldPrintSizeMismatch) {
|
TEST(VectorCompare, ShouldPrintSizeMismatch) {
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
@@ -124,9 +56,8 @@ TEST(VectorCompare, ShouldPrintVectorsDifferAtIndexZero) {
|
|||||||
vector first = vector({1, 2, 3, 4});
|
vector first = vector({1, 2, 3, 4});
|
||||||
vector second = vector({0, 1, 2, 3});
|
vector second = vector({0, 1, 2, 3});
|
||||||
Compare(os, first, second);
|
Compare(os, first, second);
|
||||||
EXPECT_THAT(
|
EXPECT_THAT(os.str(),
|
||||||
os.str(),
|
Eq((string) "vectors differ at index 0, 1 != 0, expected: [ 1, 2, 3, 4 ], actual: [ 0, 1, 2, 3 ]"));
|
||||||
Eq("vectors differ at index 0, \"1\" != \"0\", expected: \"[ 1, 2, 3, 4 ]\", actual: \"[ 0, 1, 2, 3 ]\""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VectorCompare, ShouldPrintVectorsDifferAtEnd) {
|
TEST(VectorCompare, ShouldPrintVectorsDifferAtEnd) {
|
||||||
@@ -134,9 +65,7 @@ TEST(VectorCompare, ShouldPrintVectorsDifferAtEnd) {
|
|||||||
vector first = vector({1, 2, 3, 4});
|
vector first = vector({1, 2, 3, 4});
|
||||||
vector second = vector({1, 2, 3, 0});
|
vector second = vector({1, 2, 3, 0});
|
||||||
Compare(os, first, second);
|
Compare(os, first, second);
|
||||||
EXPECT_THAT(
|
EXPECT_THAT(os.str(), Eq("vectors differ at index 3, 4 != 0, expected: [ 1, 2, 3, 4 ], actual: [ 1, 2, 3, 0 ]"));
|
||||||
os.str(),
|
|
||||||
Eq("vectors differ at index 3, \"4\" != \"0\", expected: \"[ 1, 2, 3, 4 ]\", actual: \"[ 1, 2, 3, 0 ]\""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VectorCompare, ShouldPrintNothingWhenVectorsAreEqual) {
|
TEST(VectorCompare, ShouldPrintNothingWhenVectorsAreEqual) {
|
||||||
@@ -881,7 +810,7 @@ TEST(ExecuteSuiteWithParams, ShouldExecuteASuiteWithASingleFailure) {
|
|||||||
Eq(
|
Eq(
|
||||||
R"test(🚀Beginning Suite: My Suite
|
R"test(🚀Beginning Suite: My Suite
|
||||||
Beginning Test: Test Name
|
Beginning Test: Test Name
|
||||||
❌FAILED: expected: "0", actual: "1"
|
❌FAILED: expected: 0, actual: 1
|
||||||
Ending Test: Test Name
|
Ending Test: Test Name
|
||||||
Ending Suite: My Suite
|
Ending Suite: My Suite
|
||||||
)test"));
|
)test"));
|
||||||
@@ -1053,7 +982,7 @@ TEST(ExecuteSuiteWithParams, ShouldCatchAnExceptionThrownByATest) {
|
|||||||
R"test(🚀Beginning Suite: My Suite
|
R"test(🚀Beginning Suite: My Suite
|
||||||
Beginning Test: Test Name
|
Beginning Test: Test Name
|
||||||
🔥ERROR: Caught exception "std::exception".
|
🔥ERROR: Caught exception "std::exception".
|
||||||
❌FAILED: expected: "1", actual: "0"
|
❌FAILED: expected: 1, actual: 0
|
||||||
Ending Test: Test Name
|
Ending Test: Test Name
|
||||||
Ending Suite: My Suite
|
Ending Suite: My Suite
|
||||||
)test"));
|
)test"));
|
||||||
@@ -1113,7 +1042,7 @@ TEST(ExecuteSuiteWithParams, ShouldCatchAStringThrownByATest) {
|
|||||||
R"test(🚀Beginning Suite: My Suite
|
R"test(🚀Beginning Suite: My Suite
|
||||||
Beginning Test: Test Name
|
Beginning Test: Test Name
|
||||||
🔥ERROR: Caught string "burp".
|
🔥ERROR: Caught string "burp".
|
||||||
❌FAILED: expected: "1", actual: "0"
|
❌FAILED: expected: 1, actual: 0
|
||||||
Ending Test: Test Name
|
Ending Test: Test Name
|
||||||
Ending Suite: My Suite
|
Ending Suite: My Suite
|
||||||
)test"));
|
)test"));
|
||||||
@@ -1173,7 +1102,7 @@ TEST(ExecuteSuiteWithParams, ShouldCatchACStringThrownByATest) {
|
|||||||
R"test(🚀Beginning Suite: My Suite
|
R"test(🚀Beginning Suite: My Suite
|
||||||
Beginning Test: Test Name
|
Beginning Test: Test Name
|
||||||
🔥ERROR: Caught c-string "burp".
|
🔥ERROR: Caught c-string "burp".
|
||||||
❌FAILED: expected: "1", actual: "0"
|
❌FAILED: expected: 1, actual: 0
|
||||||
Ending Test: Test Name
|
Ending Test: Test Name
|
||||||
Ending Suite: My Suite
|
Ending Suite: My Suite
|
||||||
)test"));
|
)test"));
|
||||||
@@ -1233,7 +1162,7 @@ TEST(ExecuteSuiteWithParams, ShouldCatchSomethingElseThrownByATest) {
|
|||||||
R"test(🚀Beginning Suite: My Suite
|
R"test(🚀Beginning Suite: My Suite
|
||||||
Beginning Test: Test Name
|
Beginning Test: Test Name
|
||||||
🔥ERROR: Caught something that is neither an std::exception nor an std::string.
|
🔥ERROR: Caught something that is neither an std::exception nor an std::string.
|
||||||
❌FAILED: expected: "1", actual: "0"
|
❌FAILED: expected: 1, actual: 0
|
||||||
Ending Test: Test Name
|
Ending Test: Test Name
|
||||||
Ending Suite: My Suite
|
Ending Suite: My Suite
|
||||||
)test"));
|
)test"));
|
||||||
|
|||||||
Reference in New Issue
Block a user