Skip to content

Instantly share code, notes, and snippets.

@ognis1205
Last active November 28, 2020 20:48
Show Gist options
  • Save ognis1205/9dacba657d5701f90d50e8f02a45ccdb to your computer and use it in GitHub Desktop.
Save ognis1205/9dacba657d5701f90d50e8f02a45ccdb to your computer and use it in GitHub Desktop.
PoC Implementation of Boost.Test-Like Test Suite Hook Mechanism.
#include <iostream>
#include <list>
using namespace std;
// |
// | Start of Boost.Test Header.
// v
using Invoker = void (*)();
class TestCaseBase {
public:
virtual void DoTest()=0;
};
class Framework {
public:
void Traverse() {
for (auto& t : test_cases_) {
t();
};
}
void Register(Invoker test_case) {
test_cases_.push_back(test_case);
};
private:
list<Invoker> test_cases_;
};
Framework framework;
class Registerar {
public:
Registerar(Invoker test_case) {
framework.Register(test_case);
}
};
struct has_setup {
template<typename T>
static auto check(T&& t) -> decltype(t.setup(), true_type {});
template<typename T>
static auto check(...) -> false_type;
};
template<typename T>
struct is_setup_fixture : public decltype(has_setup::check<T>(declval<T>())) {};
template<typename T, typename enable_if<is_setup_fixture<T>::value, nullptr_t>::type=nullptr>
void unit_test_setup_conditional(T&& t) {
t.setup();
}
template<typename T, typename enable_if<!is_setup_fixture<T>::value, nullptr_t>::type=nullptr>
void unit_test_setup_conditional(T&& t) {}
struct has_teardown {
template<typename T>
static auto check(T&& t) -> decltype(t.teardown(), true_type {});
template<typename T>
static auto check(...) -> false_type;
};
template<typename T>
struct is_teardown_fixture : public decltype(has_teardown::check<T>(declval<T>())) {};
template<typename T, typename enable_if<is_teardown_fixture<T>::value, nullptr_t>::type=nullptr>
void unit_test_teardown_conditional(T&& t) {
t.teardown();
}
template<typename T, typename enable_if<!is_setup_fixture<T>::value, nullptr_t>::type=nullptr>
void unit_test_teardown_conditional(T&& t) {}
int main(int argc, char* argv[]) {
framework.Traverse();
return 0;
}
// ^
// | End of Boost.Test Header.
// |
// |
// | Lines below are macro-expanded user defined code.
// v
class TestFixture {
public:
TestFixture() { cout << "setup " << endl; }
~TestFixture() { cout << "teardown" << endl; }
void setup() { cout << "optional setup" << endl; }
void teardown() { cout << "optional teardown" << endl; }
};
class TestCase : public TestCaseBase, public TestFixture {
public:
void DoTest();
};
static void invoke() {
cout << "fixture ctor" << endl;
TestCase test_case;
cout << "fixture setup" << endl;
unit_test_setup_conditional(test_case);
cout << "test entry" << endl;
test_case.DoTest();
cout << "fixture teardown" << endl;
unit_test_teardown_conditional(test_case);
cout << "fixture dtor" << endl;
}
Registerar registerar(&invoke);
void TestCase::DoTest() {
cout << "Do test." << endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment