Started implementing execute/describe/it and expect.
This commit is contained in:
		| @@ -97,27 +97,57 @@ namespace JTest { | |||||||
|         return make_testbundle("", {test}); |         return make_testbundle("", {test}); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     testresults_t execute(testbundle_t bundle) { |     testbundle_t xit(const string& label, const test_fn& test_method, optional<testoptions_t> options) { | ||||||
| /* |         // TODO: replace this with a call to it and setting _disabled to true after it and xit are made to return test_t. | ||||||
|         Try to do this in parallel where possible |         test_t test; | ||||||
|  |             test._disabled = true; | ||||||
|         If the bundle is marked as disabled (xdescribe) report all the tests in it and child bundles as SKIPPED. |             test._label = label; | ||||||
|         testresults_t results; |             test._test_method = test_method; | ||||||
|         try { |         return make_testbundle("", {test}); | ||||||
|             bundle.beforeAll(); |     } | ||||||
|             for each child of bundle.children |  | ||||||
|                 results += execute(child) |     testresults_t execute(testbundle_t bundle) { | ||||||
|             for each test of bundle.tests |         testresults_t results; | ||||||
|                 results += execute(test) |  | ||||||
|             bundle.afterAll(); |         if (bundle._disabled) {  | ||||||
|         } catch (...) { |             // TODO: recursively report all tests as skipped. | ||||||
|             Report as much info as possible. This likely means something happened in beforeAll() or afterAll(). |         } else { | ||||||
|  |             try { | ||||||
|  |                 // TODO: Try to do this in parallel where possible | ||||||
|  |                 if (bundle._beforeAll.has_value()) { | ||||||
|  |                     bundle._beforeAll.value()(); | ||||||
|  |                 } | ||||||
|  |                 for_each(bundle._children.begin(), bundle._children.end(), [&results](testbundle_t bundle) { | ||||||
|  |                     // TODO: Find a way to make child tests get our beforeEach and afterEach callbacks. | ||||||
|  |                     results += execute(bundle); | ||||||
|  |                 }); | ||||||
|  |                 // TODO: Consider capturing these callbacks differently. Without the bundle? By value? | ||||||
|  |                 for_each(bundle._tests.begin(), bundle._tests.end(), [&results, &bundle](test_t test) { | ||||||
|  |                     if (bundle._beforeEach.has_value()) { | ||||||
|  |                         bundle._beforeEach.value()(); | ||||||
|  |                     } | ||||||
|  |                     results += execute(test); | ||||||
|  |                     if (bundle._afterEach.has_value()) { | ||||||
|  |                         bundle._afterEach.value()(); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |                 if (bundle._afterAll.has_value()) { | ||||||
|  |                     bundle._afterAll.value()(); | ||||||
|  |                 } | ||||||
|  |             } catch(...) { | ||||||
|  |                 // TODO: Log this and mark the tests as failed. | ||||||
|  |                 //   Report as much info as possible. This likely means something happened in beforeAll() or afterAll(). | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| */ |  | ||||||
|         throw unimplemented_function_error("execute(testbundle_t)"); |         throw unimplemented_function_error("execute(testbundle_t)"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     testresults_t execute(test_t test) { |     testresults_t execute(test_t test) { | ||||||
|  |         int status = 0; | ||||||
|  |         if (test._disabled) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |          | ||||||
| /* | /* | ||||||
|         status = PASSED (PASSED, FAILED, SKIPPED (PENDING | DISABLED), QUEUED, RUNNING) QUEUED and RUNNING might not make sense. |         status = PASSED (PASSED, FAILED, SKIPPED (PENDING | DISABLED), QUEUED, RUNNING) QUEUED and RUNNING might not make sense. | ||||||
|         If the test is marked as disabled (xit) then record it as a skipped test and return. |         If the test is marked as disabled (xit) then record it as a skipped test and return. | ||||||
| @@ -164,9 +194,10 @@ namespace JTest { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     testbundle_t describe(const wstring& label, const make_testbundle_fn& make_tests, optional<describeoptions_t> options) { |     testbundle_t describe(const string& label, const make_testbundle_fn& make_tests, optional<describeoptions_t> options) { | ||||||
|         testbundle_t bundle = make_tests(); |         testbundle_t bundle = make_tests(); | ||||||
|         bundle._label = label; |         bundle._label = label; | ||||||
|  |         bundle._disabled = false; | ||||||
|         if (options.has_value()) { |         if (options.has_value()) { | ||||||
|             describeoptions_t options_v = options.value(); |             describeoptions_t options_v = options.value(); | ||||||
|             bundle._afterAll = combine(options_v.getAfterAll(), bundle._afterAll); |             bundle._afterAll = combine(options_v.getAfterAll(), bundle._afterAll); | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ namespace JTest { | |||||||
|         // vector<testmethod_t> skipped; |         // vector<testmethod_t> skipped; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     struct test_t { | ||||||
|         std::string _label; |         std::string _label; | ||||||
|         test_fn _test_method; |         test_fn _test_method; | ||||||
|         bool _disabled; |         bool _disabled; | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ | |||||||
| #include <vector> | #include <vector> | ||||||
| #include <tuple> | #include <tuple> | ||||||
| #include <stdexcept> | #include <stdexcept> | ||||||
|  | #include <iostream> | ||||||
|  | #include <sstream> | ||||||
|  |  | ||||||
| using namespace JTest; | using namespace JTest; | ||||||
| using namespace MyNS; | using namespace MyNS; | ||||||
| @@ -23,10 +25,6 @@ testresults_t test_ClassToTest_main(const vector<string>& argv) { | |||||||
|                 { |                 { | ||||||
|                     it("should do the thing", [](){ |                     it("should do the thing", [](){ | ||||||
|                         // Throw exception if somethings goes wrong |                         // Throw exception if somethings goes wrong | ||||||
|  |  | ||||||
|  |  | ||||||
|                         // TODO: This unnecessary, by throwing exceptions. |  | ||||||
|                         return (test_t){}; |  | ||||||
|                     }), |                     }), | ||||||
|  |  | ||||||
|                     it("should do the other thing", [](){ |                     it("should do the other thing", [](){ | ||||||
| @@ -95,6 +93,120 @@ testresults_t test_ClassToTest_2(const vector<string>& argv) { | |||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | class Expectable { | ||||||
|  |     public: | ||||||
|  |         Expectable(const T& actual); | ||||||
|  |         virtual ~Expectable(); | ||||||
|  |         virtual void toEqual(const T& value); | ||||||
|  |         virtual void toNotEqual(const T& value); | ||||||
|  |         // Maybe these funcs should return tuple<bool, string> instead. | ||||||
|  |         virtual void toBe(std::function<std::tuple<bool, std::optional<std::string>>(const T& actual)> evaluator); | ||||||
|  |         //virtual void toBeNull(); | ||||||
|  |         //virtual void toNotBeNull(); | ||||||
|  |         //virtual void toThrow(...); | ||||||
|  |     private: | ||||||
|  |         const T& actual_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | Expectable<T>::Expectable(const T& actual) | ||||||
|  | : actual_(actual) {} | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | Expectable<T>::~Expectable() {} | ||||||
|  |  | ||||||
|  | class FailedExpectation: std::runtime_error { | ||||||
|  |     public: | ||||||
|  |         FailedExpectation(const std::string& message); | ||||||
|  |         virtual ~FailedExpectation(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | FailedExpectation::FailedExpectation(const std::string& message) | ||||||
|  | : runtime_error(message) { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | FailedExpectation::~FailedExpectation() {} | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | void Expectable<T>::toEqual(const T& value) { | ||||||
|  |     if (actual_ != value) { | ||||||
|  |         std::ostringstream os; | ||||||
|  |         os << "Expected: " << actual_ << " to be " << value; | ||||||
|  |         throw(FailedExpectation(os.str())); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | void Expectable<T>::toNotEqual(const T& value) { | ||||||
|  |     if (actual_ == value) { | ||||||
|  |         std::ostringstream os; | ||||||
|  |         os << "Expected: " << actual_ << " to not be " << value; | ||||||
|  |         throw(FailedExpectation(os.str())); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | void Expectable<T>::toBe(std::function<std::tuple<bool, std::optional<std::string>>(const T& actual)> evaluator) { | ||||||
|  |     auto result = evaluator(actual_); | ||||||
|  |     if (!std::get<0>(result)) { | ||||||
|  |         std::ostringstream os; | ||||||
|  |         // std::optional<std::string> message = std::get<1>; | ||||||
|  |         std::optional<std::string> message = std::get<1>(result); | ||||||
|  |         if (message.has_value()) { | ||||||
|  |             os << "Expected: " << actual_ << " to pass validation, but " << message.value(); | ||||||
|  |         } else { | ||||||
|  |             os << "Expected: " << actual_ << " to pass validation."; | ||||||
|  |         } | ||||||
|  |         throw(FailedExpectation(os.str())); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // template<typename T> | ||||||
|  | // void Expectable<T>::toBeNull() { | ||||||
|  | //     if (actual_ != nullptr) { | ||||||
|  | //         std::ostringstream os; | ||||||
|  | //         os << "Expected null, but got " << actual_; | ||||||
|  | //         throw(FailedExpectation(os.str())); | ||||||
|  | //     } | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // template<typename T> | ||||||
|  | // void Expectable<T>::toNotBeNull() { | ||||||
|  | //     if (actual_ == nullptr) { | ||||||
|  | //         throw(FailedExpectation("Expected non-null, but got null")); | ||||||
|  | //     } | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // template<typename T> | ||||||
|  | // void Expectable<T>::toThrow(...) {} | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | Expectable<T> expect(const T& actual); | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | Expectable<T> expect(const T& actual) { | ||||||
|  |     return Expectable<T>(actual); | ||||||
|  | } | ||||||
|  |          | ||||||
|  | int MyAddFunction(int a, int b) { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | testresults_t test_BasicExpectable_main(const vector<string>& argv) { | ||||||
|  |     return execute( | ||||||
|  |         describe("MyAddFunction", [](){ | ||||||
|  |             return make_testbundle({ | ||||||
|  |                 it("should add 2 and 2 to get 4", [](){ | ||||||
|  |                     expect(MyAddFunction(2, 2)).toEqual(4); | ||||||
|  |                 }), | ||||||
|  |                 it("should ", [](){ | ||||||
|  |                     // Throw exception if somethings goes wrong | ||||||
|  |                 }), | ||||||
|  |             }, make_describeoptions()); | ||||||
|  |         })); | ||||||
|  | } | ||||||
|  |  | ||||||
| // Dummy test harness | // Dummy test harness | ||||||
| int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||||
|     try { |     try { | ||||||
| @@ -102,6 +214,7 @@ int main(int argc, char* argv[]) { | |||||||
|         testresults_t results; |         testresults_t results; | ||||||
|  |  | ||||||
|         results = add(results, test_ClassToTest_main(args)); |         results = add(results, test_ClassToTest_main(args)); | ||||||
|  |         results = add(results, test_BasicExpectable_main(args)); | ||||||
|  |  | ||||||
|         print_test_results(results, cout); |         print_test_results(results, cout); | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user