aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack <66967891+ASpoonPlaysGames@users.noreply.github.com>2024-04-12 00:52:53 +0100
committerGitHub <noreply@github.com>2024-04-12 01:52:53 +0200
commitf427583ec497f80aa2f80ac4d34dc44b7e23643f (patch)
tree094de71101c670b8f13fabe60d40901033d6d2c2
parent11787b3896b8242ac8f7e583d72cabf68f9161a9 (diff)
downloadNorthstarMods-f427583ec497f80aa2f80ac4d34dc44b7e23643f.tar.gz
NorthstarMods-f427583ec497f80aa2f80ac4d34dc44b7e23643f.zip
Add initial unit testing logic (#708)
Adds initial logic to allow for some form of basic unit testing.
-rw-r--r--Northstar.Custom/mod.json13
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/_testing.nut302
2 files changed, 315 insertions, 0 deletions
diff --git a/Northstar.Custom/mod.json b/Northstar.Custom/mod.json
index 399311e4..69432f49 100644
--- a/Northstar.Custom/mod.json
+++ b/Northstar.Custom/mod.json
@@ -441,6 +441,19 @@
"RunOn": "CLIENT || SERVER || UI"
},
{
+ "Path": "_testing.nut",
+ "RunOn": "CLIENT || SERVER || UI",
+ "ClientCallback": {
+ "Before": "Testing_Init"
+ },
+ "ServerCallback": {
+ "Before": "Testing_Init"
+ },
+ "UICallback": {
+ "Before": "Testing_Init"
+ }
+ },
+ {
"Path": "_event_models.gnut",
"RunOn": "SERVER && LOBBY",
"ServerCallback": {
diff --git a/Northstar.Custom/mod/scripts/vscripts/_testing.nut b/Northstar.Custom/mod/scripts/vscripts/_testing.nut
new file mode 100644
index 00000000..15bcf18b
--- /dev/null
+++ b/Northstar.Custom/mod/scripts/vscripts/_testing.nut
@@ -0,0 +1,302 @@
+global function Testing_Init
+global function RunAllTests
+global function RunAllTests_SaveToFile
+global function RunTestsByCategory
+global function RunTestByCategoryAndName
+
+global function AddTest
+
+struct TestInfo
+{
+ string testName
+ var functionref() callback
+ // whether the test completed successfully
+ // if this is true, actualResult is valid
+ bool completed
+ // var not string because then i can just set it to an exception
+ // which print can then handle
+ var error
+ // whether the test is considered successful
+ var expectedResult
+ var actualResult
+ bool passed
+}
+
+struct {
+ table< string, array< TestInfo > > tests = {}
+} file
+
+void function Testing_Init()
+{
+ // tests for the testing functions :)
+ //AddTest( "Example Tests", "example succeeding test", ExampleTest_ReturnsTrue, true )
+ //AddTest( "Example Tests", "example failing test", ExampleTest_ReturnsFalse, true )
+ //AddTest( "Example Tests", "example erroring test", ExampleTest_ThrowsError, true )
+ //AddTest( "Example Tests", "example test with args", var function() {
+ // return ExampleTest_HasArgs_ReturnsNonVar( 2, 3 )
+ //}, 6 )
+}
+
+int function ExampleTest_HasArgs_ReturnsNonVar( int first, int second )
+{
+ return first * second
+}
+
+var function ExampleTest_ReturnsFalse()
+{
+ return false
+}
+
+var function ExampleTest_ReturnsTrue()
+{
+ return true
+}
+
+var function ExampleTest_ThrowsError()
+{
+ throw "Example exception"
+ return null
+}
+
+void function RunAllTests_SaveToFile()
+{
+ RunAllTests()
+
+ #if UI
+ string fileName = "ns-unit-tests-UI.json"
+ #elseif CLIENT
+ string fileName = "ns-unit-tests-CLIENT.json"
+ #elseif SERVER
+ string fileName = "ns-unit-tests-SERVER.json"
+ #endif
+
+ // cant encode structs so have to reconstruct a table manually from the structs
+ table out = {}
+ foreach ( category, tests in file.tests )
+ {
+ array categoryResults = []
+ foreach ( test in tests )
+ {
+ table testTable = {}
+ testTable[ "name" ] <- test.testName
+ testTable[ "completed" ] <- test.completed
+ testTable[ "passed" ] <- test.passed
+ if ( !test.completed )
+ testTable[ "error" ] <- test.error
+ else if ( !test.passed )
+ {
+ testTable[ "expectedResult" ] <- test.expectedResult
+ testTable[ "actualResult" ] <- test.actualResult
+ }
+
+ categoryResults.append( testTable )
+ }
+ out[ category ] <- categoryResults
+ }
+
+ NSSaveJSONFile( fileName, out )
+}
+
+void function RunAllTests()
+{
+ printt( "Running all tests!" )
+
+ foreach ( category, categoryTests in file.tests )
+ {
+ foreach ( test in categoryTests )
+ {
+ RunTest( test )
+ }
+ }
+
+ PrintAllTestResults()
+}
+
+void function RunTestsByCategory( string category )
+{
+ if ( !( category in file.tests ) )
+ {
+ printt( format( "Category '%s' has no tests registered", category ) )
+ return
+ }
+
+ foreach ( categoryTest in file.tests[ category ] )
+ {
+ RunTest( categoryTest )
+ }
+}
+
+void function RunTestByCategoryAndName( string category, string testName )
+{
+ // find test
+ if ( !( category in file.tests ) )
+ {
+ printt( format( "Category '%s' has no tests registered", category ) )
+ return
+ }
+
+ TestInfo ornull foundTest = null
+ foreach ( categoryTest in file.tests[ category ] )
+ {
+ if ( categoryTest.testName == testName )
+ {
+ foundTest = categoryTest
+ break
+ }
+ }
+
+ if ( !foundTest )
+ {
+ printt( format( "Category '%s' does not contain a test with name '%s'", category, testName ) )
+ return
+ }
+
+ expect TestInfo( foundTest )
+
+ printt( "Running test!" )
+ // run test
+ RunTest( foundTest )
+ // print result
+ PrintTestResult( foundTest )
+}
+
+void function RunTest( TestInfo test )
+{
+ test.completed = false
+ test.passed = false
+ test.actualResult = null
+ test.error = ""
+
+ try
+ {
+ test.actualResult = test.callback()
+ test.completed = true
+ test.passed = test.actualResult == test.expectedResult
+ }
+ catch ( exception )
+ {
+ test.completed = false
+ test.error = exception
+ }
+}
+
+void function PrintAllTestResults()
+{
+ int totalSucceeded = 0
+ int totalFailed = 0
+ int totalErrored = 0
+
+ foreach ( category, categoryTests in file.tests )
+ {
+ int categorySucceeded = 0
+ int categoryFailed = 0
+ int categoryErrored = 0
+
+ printt( format( "Results for category: '%s'", category ) )
+ foreach ( test in categoryTests )
+ {
+ if ( test.completed )
+ {
+ if ( test.passed )
+ {
+ printt( "\t", test.testName, "- Passed!" )
+ categorySucceeded++
+ }
+ else
+ {
+ printt( "\t", test.testName, "- Failed!" )
+ printt( "\t\tExpected:", test.expectedResult )
+ printt( "\t\tActual: ", test.actualResult )
+ categoryFailed++
+ }
+ }
+ else
+ {
+ printt( "\t", test.testName, "- Errored!" )
+ printt( "\t\tError:", test.error )
+ categoryErrored++
+ }
+ }
+
+ printt( "Succeeded:", categorySucceeded, "Failed:", categoryFailed, "Errored:", categoryErrored )
+
+ totalSucceeded += categorySucceeded
+ totalFailed += categoryFailed
+ totalErrored += categoryErrored
+ }
+
+ printt( "TOTAL SUCCEEDED:", totalSucceeded, "TOTAL FAILED:", totalFailed, "TOTAL ERRORED:", totalErrored )
+}
+
+void function PrintCategoryResults( string category )
+{
+ int categorySucceeded = 0
+ int categoryFailed = 0
+ int categoryErrored = 0
+
+ printt( format( "Results for category: '%s'", category ) )
+ foreach ( test in file.tests[ category ] )
+ {
+ if ( test.completed )
+ {
+ if ( test.passed )
+ {
+ printt( "\t", test.testName, "- Passed!" )
+ categorySucceeded++
+ }
+ else
+ {
+ printt( "\t", test.testName, "- Failed!" )
+ printt( "\t\tExpected:", test.expectedResult )
+ printt( "\t\tActual: ", test.actualResult )
+ categoryFailed++
+ }
+ }
+ else
+ {
+ printt( "\t", test.testName, "- Errored!" )
+ printt( "\t\tError:", test.error )
+ categoryErrored++
+ }
+ }
+
+ printt( "Succeeded:", categorySucceeded, "Failed:", categoryFailed, "Errored:", categoryErrored )
+}
+
+void function PrintTestResult( TestInfo test )
+{
+ string resultString = test.testName
+
+ if ( test.completed )
+ {
+ if ( test.passed )
+ resultString += " - Passed!"
+ else
+ {
+ resultString += " - Failed!"
+ resultString += "\n\tExpected: " + test.expectedResult
+ resultString += "\n\tActual: " + test.actualResult
+ }
+ }
+ else
+ {
+ resultString += " - Not completed!"
+ resultString += "\n\tError: " + test.error
+ }
+
+ printt( resultString )
+}
+
+void function AddTest( string testCategory, string testName, var functionref() testFunc, var expectedResult )
+{
+ TestInfo newTest
+ newTest.testName = testName
+ newTest.callback = testFunc
+ newTest.expectedResult = expectedResult
+
+ // create the test category if it doesn't exist
+ if ( !( testCategory in file.tests ) )
+ file.tests[ testCategory ] <- [ newTest ]
+ else
+ file.tests[ testCategory ].append( newTest )
+}