123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /*!
- \defgroup ScriptTestingFramework Script Testing Framework
- \addtogroup ScriptTestingFramework
- @{
- \page Page_System_ScriptTestingFramework Script Testing Framework
- \tableofcontents
- \section Introduction Introduction
- - Provides a unified and simple interface that emphasizes the smallest amount
- of boiler plate code possible.
- - The collection and instantiation of its primitives is performed right after
- the script compilation.
- - Within the framework a SINGLE test harness derived class can exist. The
- harness runs the tests and contains API to access them.
- - The test units are compiled to Suites. These provide additional API for
- environmental control.
- \section SimpleTests Simple tests
- Can be perfomed in form of annotated <b>free functions</b>.
- <em>Note: Notice the Suite name in the attribute.</em>
- @code
- [Test("MyFirstTestSuite")]
- TestResultBase MyFooBarTest() { return TestBoolResult(5 > 3); }
- @endcode
- \section StatefulTests Stateful tests
- More elaborate tests that need some state and will run for several ticks have
- to be defined as TestBase derived classes. Your logic has to be ran through
- __step methods__.
- \subsection StepMethods Step methods
- - You can name your step methods however you like.
- - They have to be annotated by the [Step(Stage)] attribute which pairs the step
- with a stage.
- \subsection Stages Stages
- - They divide the steps into groups that express the initialization and
- finalization process.
- - Stages are executed in order Setup -> Main -> TearDown.
- - Methods in stages are executed in order of definition.
- \subsection ReturnValues Return values
- - void -> Will get executed only once.
- - bool -> Will get executed every tick until true is returned.
- \subsection Result Result
- - Result is set via API member method of TestBase `SetResult(TestResultBase)`.
- - Setting a result which evaluates to failure will terminate the stage.
- \subsection FailureUnwind Failure unwind
- - If the Setup stage fails the test only terminates and TearDown is not called.
- - Main stage failure will trigger the TearDown.
- - TearDown failure will do nothing.
- \subsection Timeout Timeout
- - The tests won't timeout by default. The value may be specified via Test
- attribute.
- - The timeout counter resets for every stage method.
- - If the stage method times out the TimeoutResult is set (it evaluates to
- failure and the failure unwind process starts).
- @code
- [Test("MyFirstTestSuite", timeoutS: 2, timeoutMs: 250)]
- class MyAsyncTest : TestBase
- {
- // Simple blocking initialization.
- [Step(EStage.Setup)]
- void Initialize() { ... }
- // Async test which is waiting for result for several frames.
- [Step(EStage.Main)]
- bool Pool() { ... }
- // Finalization process waiting for result for several frames.
- [Step(EStage.TearDown)]
- bool FinalizeA() { ... }
- // Simple blocking finalization call.
- [Step(EStage.TearDown)]
- void FinalizeB() { ... }
- }
- @endcode
- */
- //-----------------------------------------------------------------------------
- //! Attribute used for tests annotation and assignment to Suites.
- class Test
- {
- string Suite;
- int TimeoutS;
- int TimeoutMs;
- int SortOrder;
- //! Defines a suite the test belongs to, its timeout value and order within the suite.
- void Test(string suite, int timeoutS = 0, int timeoutMs = 0, int sortOrder = 0)
- {
- Suite = suite;
- TimeoutS = timeoutS;
- TimeoutMs = timeoutMs;
- SortOrder = sortOrder;
- }
- }
- //-----------------------------------------------------------------------------
- //! Stage definition used in conjunction with Step attribute.
- enum EStage
- {
- Setup,
- Main,
- TearDown
- }
- //-----------------------------------------------------------------------------
- //! Attribute which marks a method as part of the testing process.
- class Step
- {
- EStage Stage;
- void Step(EStage stage = EStage.Main)
- {
- Stage = stage;
- }
- }
- //-----------------------------------------------------------------------------
- //! Collection and main interface of the Testing framework.
- class TestHarness : Managed
- {
- //! Starts the testing process. Returns true when all tests have finished. If
- //! some of them are still in progress false is reported.
- proto native static bool Run();
- //! Generates a xml report.
- proto static string Report();
- //! Returns number of test suites.
- proto native static int GetNSuites();
- //! Returns a test suite.
- proto native static TestSuite GetSuite(int handle);
- //! Returns currently active TestSuite or null when none is active.
- proto native static TestSuite ActiveSuite();
- //! Returns true when all tests and suites finished.
- proto native static bool Finished();
- //! Starts up the testing process and initializes the structures.
- proto native static void Begin();
- //! Finalizes the testing process.
- proto native static void End();
- }
- //-----------------------------------------------------------------------------
- //! Collection of tests.
- class TestSuite : Managed
- {
- //! Sets the suite result. Failure can result in specialized behavior described
- //! in TestResultBase.
- proto native void SetResult(TestResultBase res);
- //! Returns the number for tests within this suite.
- proto native int GetNTests();
- //! Returns a test.
- proto native TestBase GetTest(int handle);
- //! Enables/Disables the suites. Disabled suites won't run at all.
- proto native void SetEnabled(bool val);
- //! Enabled flag getter.
- proto native bool IsEnabled();
- //! Suite class name getter. Strictly for UI porposes!
- proto string GetName();
- //! Callback for user defined initialization. Called for all suites during TestHarness.Begin().
- protected void OnInit();
- }
- //-----------------------------------------------------------------------------
- //! Test base class.
- class TestBase : Managed
- {
- //! Sets the test result. Failure can result in specialized behavior described
- //! in TestResultBase.
- proto native void SetResult(TestResultBase res);
- //! Result getter.
- proto native TestResultBase GetResult();
- //! Enables/Disables the test. Disabled tests won't run at all.
- proto native void SetEnabled(bool val);
- //! Enabled flag getter.
- proto native bool IsEnabled();
- //! Test name getter. Strictly for UI porposes!
- proto string GetName();
- }
- //-----------------------------------------------------------------------------
- //! Base class for test results. This way you report back to the system.
- //! More complex failure types with descriptions can be reported by
- //! implementation of FailureText in format of junit
- //! [https://llg.cubic.org/docs/junit/].
- class TestResultBase : Managed
- {
- //! Return true of the result means failure.
- bool Failure() { return NativeFailure(); }
- //! Text used for xml report output.
- string FailureText() { return NativeFailureText(); }
- // Script forwarding to cpp. Otherwise the script overloading wouldn't be able
- // to call the native base implementation.
- // ----------------- vvv -----------------
- proto native bool NativeFailure();
- proto native string NativeFailureText();
- // ----------------- ^^^ -----------------
- }
- /*!
- * @}
- */
- //-----------------------------------------------------------------------------
- // EXAMPLES
- //-----------------------------------------------------------------------------
- /*
- //-----------------------------------------------------------------------------
- //! Basic test result.
- class TestBoolResult : TestResultBase
- {
- bool Value;
- void TestBoolResult(bool val) { Value = val; }
- override bool Failure() { return !Value; }
- override string FailureText()
- {
- // junit kind of error report. (simple)
- return "<failure type=\"BoolResult\">Failed</failure>";
- }
- }
- //-----------------------------------------------------------------------------
- class MyHarness : TestHarness
- {
- }
- //-----------------------------------------------------------------------------
- class MyTestSuite : TestSuite
- {
- int cnt;
- [Step(EStage.Setup)]
- void Prep()
- {
- Print("MyTestSuite::Prep");
- cnt = 3;
- }
- [Step(EStage.Setup)]
- bool Count()
- {
- --cnt;
- Print("MyTestSuite::Count: cnt=" + cnt);
- return cnt == 0;
- }
- [Step(EStage.TearDown)]
- bool CountUp()
- {
- ++cnt;
- Print("MyTestSuite::CountUp: cnt=" + cnt);
- return cnt == 10;
- }
- }
- //-----------------------------------------------------------------------------
- [Test("MyTestSuite")]
- TestResultBase MyTest()
- {
- Print("MyFuncTest");
- return new TestBoolResult(true);
- }
- //-----------------------------------------------------------------------------
- [Test("MyTestSuite")]
- class MyAsyncTest : TestBase
- {
- int counter;
- [Step(EStage.Main)]
- void Set()
- {
- counter = 10;
- }
- [Step(EStage.Main)]
- bool Pool()
- {
- Print("AsyncTest::Pool::counter=" + counter);
- if(counter == 0)
- {
- Print("AsyncTest::Pool::Result");
- SetResult(new TestBoolResult(false));
- return true;
- }
- Print("AsyncTest::Pool::Progress");
- counter--;
- return false;
- }
- }
- */
|