简而言之
构造一foo::list
和一std::list
,然后在对它们执行操作时比较它们。真正与普通单元测试的唯一区别是您有两个容器,而不是直接对您正在测试的类型使用REQUIRE()
每个操作,而是对您正在测试的类型和引用类型执行操作,然后比较它们。为此,我们假设它std::list
或任何东西都没有错误。然后,我们将其用作不失败的参考点。换句话说,如果操作成功std::list
和 成功foo::list
,并且它们比较相等,则操作成功。
一个例子
你知道可以用来比较状态的操作子集是什么,而我不知道,所以这里有一个模拟比较函数
template <class T, class U>
bool compare_types(const T &t, const U &u)
{
bool equivalent = true;
//Generic comparisons here, like iterating over the elements to compare their values.
//Of course update equal or just return false if the comparison fails.
//If your types are not containers, perform whatever is needed to test equivalent state.
return equivalent;
}
正如 Jarod42 指出的那样,这会变得更有趣和更通用,特别是如果Op f
以下是 lambda(通用 lambda 需要 C++14):
template <class ValueT, class RefT, class TestT, class Op>
bool compare_op_with_value(RefT &t, TestT &u, Op f, const ValueT &value)
{
if (!compare_types(t, u))
return false;
f(t, value);
f(u, value);
return compare_types(t, u);
}
您的函数可能会返回一个值:
template <class ValueT, class RefT, class TestT, class Op>
bool compare_op_with_ret(RefT &t, TestT &u, Op f)
{
if (!compare_types(t, u))
return false;
ValueT ret1 = f(t);
ValueT ret2 = f(u);
return ret1 == ret2 && compare_types(t, u);
}
...对于可取消引用的返回类型等等。您需要为每种测试编写一个新的比较函数,但这很简单。您需要为不同的返回类型(例如迭代器)添加另一个模板参数。
然后你需要你的测试用例(我代替std::vector
了foo::list
博览会)......
TEMPLATE_TEST_CASE("StdFooCompare", "[list]", int)
{
using std_type = std::list<TestType>;
using foo_type = std::vector<TestType>;
auto initializer = {0,1,2,3,4};
std_type list1 = initializer;
foo_type list2 = initializer;
//testing insertion, using auto since insert() returns iterators
auto insert_f = [](auto list, TestType value) -> auto {
return list.insert(list.begin(), value);
};
REQUIRE(compare_op_with_value(list1, list2, insert_f, -1));
//testing front(), being explicit about the return type rather than using auto
auto front_f = [](auto list) -> TestType & {
return list.front();
};
REQUIRE(compare_op_with_ret<TestType>(list1, list2, front_f));
//continue testing along these lines
}
我可以在这上面多花几个小时,但我希望你能明白。我在这上面花了更多时间。
注意:我实际上并没有运行此代码,因此将其全部视为伪代码以了解这个想法,例如我可能错过了分号或类似的东西。