Unit Tests - KidneyThief/TinScript1.0 GitHub Wiki
There are two purposes to the unit tests included with TinScript:
- First, to ensure stability of the language as features are added, and issues are fixed.
- Second, they also provide "how to" examples of many of the language features, and are a good reference when just starting out.
All unit tests are implemented between two files:
- unittest.cpp, found in the source directory for TinScript
- unittest.ts, the script complement file found in the scripts directory.
All unit tests instantiate an instance of this class, which contains:
- A unique name, so an individual unit test can be specified.
- A brief description.
- A script command to be executed.
- A string containing the expected result of that script command.
- A function pointer, so tests involving code can be performed.
- A string containing the expected result of executing the code function.
- A bool to allow some tests to execute the code *after* the script command (by default, code functions are used to initialize a test, and the script command is executed second.)
All unit tests are created from within this function. The creation of a unit test can be invalid if, for example, it is not given a unique name. You can look through the implementation of this, and note the number and categorization of unit tests that currently exist:
- All types have unit tests, testing every operation valid for that type. This includes:
- Math operations (e.g. float addition, integer bit shifts)
- Comparison operations (e.g. boolean AND, float 'less than')
- Conversion operations (e.g. assigning a float to an int variable, assigning an integer to a bool variable)
- POD tests for the registered type vector3f - see the External Type Registration for more details.
- Language element tests
- hashtable is a unique construct within TinScript and has some functional tests
- Flow control functional tests, for if, for, while statements
- A recursive scripted function (calculating fibonacci numbers) has been added.
- Integration tests:
- Script access to registered variables.
- Code access to scripted variables.
- Script access to registered functions - one for every return type.
- Code access to scripted functions - also one for every return type.
- class registration and namespace tests:
- Ensuring registered classes can be instantiated.
- Ensuring instantiated objects have correct access to the registered hierarchy.
- Ensuring an instantiated object with its own namespace correctly extends and has access to the hierarchy
- Ensuring this same scripted namespace extension can be access from code.
- There are over a hundred unit tests currently implemented, and more are being added as features are added and the language matures.
- Note: All unit tests are completely independent of each other, as unit tests should be. The result of one has no correlation to a previous test result, or whether the previous test had even been executed.
This function is the entry point for executing the unit tests. Called as is, it will spam the output with each test, and it's result. Any unit test that fails will generate an assert.
There are two parameters provided for convenience in executing the unit tests:
-
BeginUnitTests(true/false);
- Passing a bool as the first parameter will allow only the results to be displayed (eliminating the excessive spam of 100+ tests.
- By default, all unit test descriptions and results are displayed - specify 'true' to display only the failure asserts and final result.
-
BeginUnitTests(false, <unit test name>);
- The second parameter can be used to specify a single specific test - useful especially if a unit test has uncovered a problem to be fixed.
- e.g. BeginUnitTests(false, "script_return_v3f");
- The second parameter can be used to specify a single specific test - useful especially if a unit test has uncovered a problem to be fixed.
It is too early to guarantee that TinScript is 100% thread safe, however, a thread test has been implemented to demonstrate the complete encapsulation of each CScriptContext.
- This test is platform specific, and only implemented under WIN32 - however, as script contexts are are easily created and wholly encapsulated, specific platform thread tests should be easily implemented.
- A new thread is spawned, creating its own script context.
- Each thread executes the following:
- Executes the unit tests.
- Create a named object named for the thread.
- ListObjects() is executed from each thread.
- A script global (string) variable is set to the name of the thread.
- The value of the script global for each thread is printed.
- The mult thread test is considered successful if:
- Unit tests complete successfully on each thread.
- ListObjects() only shows the object(s) created by that thread.
- The printed value of the global is either 'MainThread' or 'AltThread'
- In a multi threaded environment there are two things to note:
- The threads must must not create their context in parallel - ensure that one thread is initialized before the next, as all threads access a single registration list upon creation.
- All threads create their own copies of registration dictionaries, the string table, etc... it wouldn't be much work to define a set of "registration functions", allowing separation of which classes/functions/variables are custom registered for each thread, but this has not yet been implemented.