Add initial documentation to test suite

This commit is contained in:
Mattia Giambirtone 2024-02-19 17:48:27 +01:00
parent b2efb1c9b5
commit 41abf59395
Signed by: nocturn9x
GPG Key ID: 8270F9F467971E59
1 changed files with 50 additions and 27 deletions

View File

@ -25,33 +25,47 @@ import util/symbols
type
TestStatus* = enum
## Test status enumeration
Init, Running, Success,
Failed, Crashed,
TimedOut, Skipped
TestKind* = enum
## Test type enumeration
Tokenizer, Parser, TypeChecker,
Runtime
TestRunner = proc (suite: TestSuite, test: Test)
# Represents a test outcome. The exc field contains
# the exception raised during the test, if any. The
# error field indicates whether the test errored out
# or not. If exc is non-null and error is false, this
# means the error was expected behavior
TestOutcome = tuple[error: bool, exc: ref Exception]
Test* {.inheritable.} = ref object
skip*: bool
name*: string
kind*: TestKind
source*: string
status*: TestStatus
expected*: TestStatus
outcome*: TestOutcome
runnerFunc: TestRunner
## A generic test object
skip*: bool # Skip running this test if true
name*: string # Test name. Only useful for displaying purposes
kind*: TestKind # Test kind (tokenizer, parser, compiler, etc.)
source*: string # The source input of the test. Usually peon code
status*: TestStatus # The test's current state
expected*: TestStatus # The test's expected final state after run()
outcome*: TestOutcome # The test's outcome
runnerFunc: TestRunner # The test's internal runner function
TokenizerTest* = ref object of Test
## A tokenization test. Allows to specify
## a desired error message and error location
## upon tokenization failure
message: string
location: tuple[start, stop: int]
TestSuite* = ref object
## A suite of tests
tests*: seq[Test]
@ -80,21 +94,15 @@ proc `$`*(self: Test): string =
return ""
proc getTestDetails(self: Test): string =
doAssert self.status != Init
case self.kind:
of Tokenizer:
var self = TokenizerTest(self)
result = &"expecting "
else:
# TODO
discard
proc createLexer: Lexer =
result = newLexer()
result.fillSymbolTable()
proc tokenizeSucceedsRunner(suite: TestSuite, test: Test) =
## Runs a tokenitazion test that is expected to succeed
try:
var tokenizer = newLexer()
tokenizer.fillSymbolTable()
var tokenizer = createLexer()
discard tokenizer.lex(test.source, "<string>")
except LexingError:
test.status = Failed
@ -110,10 +118,11 @@ proc tokenizeSucceedsRunner(suite: TestSuite, test: Test) =
proc tokenizeFailsRunner(suite: TestSuite, test: Test) =
## Runs a tokenitazion test that is expected to fail
## and checks that it fails in the way we expect
var test = TokenizerTest(test)
try:
var tokenizer = newLexer()
tokenizer.fillSymbolTable()
var tokenizer = createLexer()
discard tokenizer.lex(test.source, "<string>")
except LexingError:
var exc = LexingError(getCurrentException())
@ -132,54 +141,64 @@ proc tokenizeFailsRunner(suite: TestSuite, test: Test) =
test.status = Failed
proc newTestSuite*: TestSuite = new(result)
proc newTestSuite*: TestSuite =
## Creates a new test suite
new(result)
proc addTest*(self: TestSuite, test: Test) =
## Adds a test to the test suite
self.tests.add(test)
proc addTests*(self: TestSuite, tests: openarray[Test]) =
## Adds the given tests to the test suite
for test in tests:
self.addTest(test)
proc removeTest*(self: TestSuite, test: Test) =
## Removes the given test from the test suite
self.tests.delete(self.tests.find(test))
proc removeTests*(self: TestSuite, tests: openarray[Test]) =
## Removes the given tests from the test suite
for test in tests:
self.removeTest(test)
proc newTokenizeTest(name, source: string): TokenizerTest =
proc newTokenizeTest(name, source: string, skip = false): TokenizerTest =
new(result)
result.name = name
result.kind = Tokenizer
result.status = Init
result.source = source
result.skip = skip
proc testTokenizeSucceeds*(name, source: string, skip = false): Test =
var test = newTokenizeTest(name, source)
## Creates a new tokenizer test that is expected to succeed
var test = newTokenizeTest(name, source, skip)
test.runnerFunc = tokenizeSucceedsRunner
test.message = ""
test.location = (-1 , -1)
result = Test(test)
result.skip = skip
proc testTokenizeFails*(name, source: string, message: string, location: tuple[start, stop: int], skip = false): Test =
var test = newTokenizeTest(name, source)
## Creates a new tokenizer test that is expected to fail with the
## given error message and at the given location
var test = newTokenizeTest(name, source, skip)
test.runnerFunc = tokenizeFailsRunner
test.message = message
test.location = location
result = Test(test)
result.skip = skip
proc run*(self: TestSuite) =
## Runs the test suite to completion,
## sequentially
for test in self.tests:
if test.skip:
test.status = Skipped
@ -188,6 +207,10 @@ proc run*(self: TestSuite) =
proc successful*(self: TestSuite): bool =
## Returns whether the test suite completed
## successfully or not. If called before run(),
## this function returns false. Skipped tests
## do not affect the outcome of this function
result = true
for test in self.tests:
if test.status in [Skipped, Success]: