1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "Prerequisites/BsPrerequisitesUtil.h"
6
7
8
9namespace bs
10{
11 /** @addtogroup Testing
12 * @{
13 */
14
15/** Tests if condition is true, and reports unit test failure if it fails. */
16#define BS_TEST_ASSERT(expr) assertment((expr), __FUNCTION__, __FILE__, __LINE__);
17
18/** Tests if condition is true, and reports unit test failure with a message if it fails. */
19#define BS_TEST_ASSERT_MSG(expr, msg) assertment((expr), msg, __FILE__, __LINE__);
20
21 /**
22 * Primary class for unit testing. Override and register unit tests in constructor then run the tests using the
23 * desired method of output.
24 */
25 class BS_UTILITY_EXPORT TestSuite
26 {
27 public:
28 typedef void(TestSuite::*Func)();
29
30 private:
31 /** Contains data about a single unit test. */
32 struct TestEntry
33 {
34 TestEntry(Func test, const String& name);
35
36 Func test;
37 String name;
38 };
39
40 public:
41 virtual ~TestSuite() = default;
42
43 /** Runs all the tests in the suite (and sub-suites). Tests results are reported to the provided output class. */
44 void run(TestOutput& output);
45
46 /** Adds a new child suite to this suite. This method allows you to group suites and execute them all at once. */
47 void add(const SPtr<TestSuite>& suite);
48
49 /** Creates a new suite of a particular type. */
50 template <class T>
51 static SPtr<TestSuite> create()
52 {
53 static_assert((std::is_base_of<TestSuite, T>::value), "Invalid test suite type. It needs to derive from bs::TestSuite.");
54
55 return std::static_pointer_cast<TestSuite>(bs_shared_ptr_new<T>());
56 }
57
58 protected:
59 TestSuite() = default;
60
61 /** Called right before any tests are ran. */
62 virtual void startUp() {}
63
64 /** Called after all tests and child suite's tests are ran. */
65 virtual void shutDown() {}
66
67 /**
68 * Register a new unit test.
69 *
70 * @param[in] test Function to call in order to execute the test.
71 * @param[in] name Name of the test we can use for referencing it later.
72 */
73 void addTest(Func test, const String& name);
74
75 /**
76 * Reports success or failure depending on the result of an expression.
77 *
78 * @param[in] success If true success is reported, otherwise failure.
79 * @param[in] desc Message describing the nature of the failure.
80 * @param[in] file Name of the source code file the assertment originates from.
81 * @param[in] line Line number at which the assertment was triggered at.
82 */
83 void assertment(bool success, const String& desc, const String& file, long line);
84
85 Vector<TestEntry> mTests;
86 Vector<SPtr<TestSuite>> mSuites;
87
88 // Transient
89 TestOutput* mOutput = nullptr;
90 String mActiveTestName;
91 };
92
93/** Registers a new unit test within an implementation of TestSuite. */
94#define BS_ADD_TEST(func) addTest(static_cast<Func>(&func), #func);
95
96 /** @} */
97}
98