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 | |
9 | namespace 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 | |