Converted under_scores to CamelCase.
This commit is contained in:
parent
210290b38c
commit
8a9ab60118
3 changed files with 198 additions and 198 deletions
42
README.md
42
README.md
|
|
@ -7,7 +7,7 @@ Einheit is a Nim unit testing library inspired by Python's unit tests. Nim's uni
|
||||||
The benefit of the macro style I chose means that you can document your tests nicely as well :)
|
The benefit of the macro style I chose means that you can document your tests nicely as well :)
|
||||||
|
|
||||||
### Description
|
### Description
|
||||||
test_suite is a compile-time macro that allows a user to easily define tests and run them.
|
testSuite is a compile-time macro that allows a user to easily define tests and run them.
|
||||||
|
|
||||||
Methods are used for inheritance, so if you want to derive a test suite, then you have to make sure the base suite uses methods for the tests that you want to derive.
|
Methods are used for inheritance, so if you want to derive a test suite, then you have to make sure the base suite uses methods for the tests that you want to derive.
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ A special proc/method is called setup(). The macro will inject this method/proc
|
||||||
|
|
||||||
Test methods/procs to be run are prefixed with "test" in the method/proc name. This is so that you can write tests that call procs that do other things and won't be run as a test.
|
Test methods/procs to be run are prefixed with "test" in the method/proc name. This is so that you can write tests that call procs that do other things and won't be run as a test.
|
||||||
|
|
||||||
For each suite method/proc, an implicit variable called "self" is added. This lets you access the test_suite in an OO kind of way.
|
For each suite method/proc, an implicit variable called "self" is added. This lets you access the testSuite in an OO kind of way.
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
|
|
@ -32,41 +32,41 @@ nimble install einheit
|
||||||
```nim
|
```nim
|
||||||
import einheit
|
import einheit
|
||||||
|
|
||||||
test_suite SuiteName of TestSuite:
|
testSuite SuiteName of TestSuite:
|
||||||
|
|
||||||
var
|
var
|
||||||
suite_var: string
|
suiteVar: string
|
||||||
test_obj: int
|
testObj: int
|
||||||
|
|
||||||
method setup()=
|
method setup()=
|
||||||
## do setup code here
|
## do setup code here
|
||||||
self.suite_var = "Testing"
|
self.suiteVar = "Testing"
|
||||||
self.test_obj = 90
|
self.testObj = 90
|
||||||
|
|
||||||
method test_adding_string()=
|
method testAddingString()=
|
||||||
## adds a string to the suite_var
|
## adds a string to the suiteVar
|
||||||
self.suite_var &= " 123"
|
self.suiteVar &= " 123"
|
||||||
self.assert_equal(self.suite_var, "Testing 123")
|
self.assertEqual(self.suiteVar, "Testing 123")
|
||||||
|
|
||||||
proc raises_os()=
|
proc raisesOs()=
|
||||||
# This proc won't be invoked as a test, it must begin with "test" in lowercase
|
# This proc won't be invoked as a test, it must begin with "test" in lowercase
|
||||||
raise newException(OSError, "Oh no! OS malfunction!")
|
raise newException(OSError, "Oh no! OS malfunction!")
|
||||||
|
|
||||||
method test_raises()=
|
method testRaises()=
|
||||||
# Two ways of asserting
|
# Two ways of asserting
|
||||||
self.assert_raises OSError:
|
self.assertRaises OSError:
|
||||||
self.raises_os()
|
self.raisesOs()
|
||||||
|
|
||||||
self.assert_raises(OSError, self.raises_os())
|
self.assertRaises(OSError, self.raisesOs())
|
||||||
|
|
||||||
method test_test_obj()=
|
method testTestObj()=
|
||||||
self.assert_true(self.test_obj == 90)
|
self.assertTrue(self.testObj == 90)
|
||||||
|
|
||||||
method test_more_more()=
|
method testMoreMore()=
|
||||||
self.assert_false("String" != "String")
|
self.assertFalse("String" != "String")
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
einheit.run_tests()
|
einheit.runTests()
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also find examples in the [test.nim](test.nim) file, including inheritance.
|
You can also find examples in the [test.nim](test.nim) file, including inheritance.
|
||||||
|
|
|
||||||
278
einheit.nim
278
einheit.nim
|
|
@ -7,12 +7,12 @@
|
||||||
##
|
##
|
||||||
## .. code:: nim
|
## .. code:: nim
|
||||||
##
|
##
|
||||||
## test_suite UnitTests:
|
## testSuite UnitTests:
|
||||||
## proc this_is_a_test()=
|
## proc thisIsATest()=
|
||||||
## self.assert_equals(1, 1)
|
## self.assertEquals(1, 1)
|
||||||
## self.assert_true(2 != 3)
|
## self.assertTrue(2 != 3)
|
||||||
## self.assert_false(3 == 4)
|
## self.assertFalse(3 == 4)
|
||||||
## self.assert_raises(OSError, newException(OSError, "OS is exploding!"))
|
## self.assertRaises(OSError, newException(OSError, "OS is exploding!"))
|
||||||
##
|
##
|
||||||
import macros
|
import macros
|
||||||
import strutils
|
import strutils
|
||||||
|
|
@ -24,17 +24,17 @@ type
|
||||||
TestSuite = ref object of RootObj
|
TestSuite = ref object of RootObj
|
||||||
## The base TestSuite
|
## The base TestSuite
|
||||||
name: string
|
name: string
|
||||||
current_test_name: string
|
currentTestName: string
|
||||||
tests_passed: int
|
testsPassed: int
|
||||||
num_tests: int
|
numTests: int
|
||||||
|
|
||||||
TestAssertError = object of Exception
|
TestAssertError = object of Exception
|
||||||
## assert_true and other assert_* statements will raise
|
## assertTrue and other assert_* statements will raise
|
||||||
## this exception when the condition fails
|
## this exception when the condition fails
|
||||||
line_number: int
|
lineNumber: int
|
||||||
file_name: string
|
fileName: string
|
||||||
code_snip: string
|
codeSnip: string
|
||||||
test_name: string
|
testName: string
|
||||||
|
|
||||||
# -- Methods for the TestSuite base --
|
# -- Methods for the TestSuite base --
|
||||||
|
|
||||||
|
|
@ -42,19 +42,19 @@ method setup*(suite: TestSuite)=
|
||||||
## Base method for setup code
|
## Base method for setup code
|
||||||
discard
|
discard
|
||||||
|
|
||||||
method run_tests*(suite: TestSuite)=
|
method runTests*(suite: TestSuite)=
|
||||||
## Base method for running tests
|
## Base method for running tests
|
||||||
discard
|
discard
|
||||||
|
|
||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
|
|
||||||
|
|
||||||
template return_exception(name, test_name, snip, vals)=
|
template returnException(name, testName, snip, vals)=
|
||||||
## private template for raising an exception
|
## private template for raising an exception
|
||||||
let pos = instantiationInfo(fullpaths=true)
|
let pos = instantiationInfo(fullpaths=true)
|
||||||
let pos_rel = instantiationInfo()
|
let posRel = instantiationInfo()
|
||||||
var
|
var
|
||||||
filename = pos_rel.filename
|
filename = posRel.filename
|
||||||
line = pos.line
|
line = pos.line
|
||||||
var message = "\n"
|
var message = "\n"
|
||||||
message &= " Condition: $2($1)\n".format(snip.replace("\n","").strip(), name)
|
message &= " Condition: $2($1)\n".format(snip.replace("\n","").strip(), name)
|
||||||
|
|
@ -62,49 +62,49 @@ template return_exception(name, test_name, snip, vals)=
|
||||||
message &= " Location: $1; line $2".format(filename, line)
|
message &= " Location: $1; line $2".format(filename, line)
|
||||||
|
|
||||||
var exc = newException(TestAssertError, message)
|
var exc = newException(TestAssertError, message)
|
||||||
exc.file_name = filename
|
exc.fileName = filename
|
||||||
exc.line_number = line
|
exc.lineNumber = line
|
||||||
exc.code_snip = snip
|
exc.codeSnip = snip
|
||||||
exc.test_name = test_name
|
exc.testName = testName
|
||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
# --------------------------- Templates for assertion --------------------------------------
|
# --------------------------- Templates for assertion --------------------------------------
|
||||||
|
|
||||||
template assert_equal*(self: TestSuite, lhs: untyped, rhs: untyped): untyped {.immediate.}=
|
template assertEqual*(self: TestSuite, lhs: untyped, rhs: untyped): untyped {.immediate.}=
|
||||||
## Raises a TestAssertError when the lhs and the rhs are not equal.
|
## Raises a TestAssertError when the lhs and the rhs are not equal.
|
||||||
if (lhs) != (rhs):
|
if (lhs) != (rhs):
|
||||||
var snip = astToStr(lhs) & ", " & astToStr(rhs)
|
var snip = astToStr(lhs) & ", " & astToStr(rhs)
|
||||||
|
|
||||||
var
|
var
|
||||||
vals = "$3 == $1; $1 != $2".format(lhs, rhs, astToStr(lhs))
|
vals = "$3 == $1; $1 != $2".format(lhs, rhs, astToStr(lhs))
|
||||||
test_name = self.current_test_name
|
testName = self.currentTestName
|
||||||
|
|
||||||
return_exception("assert_true", test_name, snip, vals)
|
returnException("assertTrue", testName, snip, vals)
|
||||||
|
|
||||||
template assert_true*(self: TestSuite, code: untyped): untyped {.immediate.}=
|
template assertTrue*(self: TestSuite, code: untyped): untyped {.immediate.}=
|
||||||
## Raises a TestAssertError when the code is false.
|
## Raises a TestAssertError when the code is false.
|
||||||
if not code:
|
if not code:
|
||||||
var snip = astToStr(code)
|
var snip = astToStr(code)
|
||||||
|
|
||||||
var
|
var
|
||||||
vals = "($1) == $2".format(snip, code)
|
vals = "($1) == $2".format(snip, code)
|
||||||
test_name = self.current_test_name
|
testName = self.currentTestName
|
||||||
|
|
||||||
return_exception("assert_true", test_name, snip, vals)
|
returnException("assertTrue", testName, snip, vals)
|
||||||
|
|
||||||
template assert_false*(self: TestSuite, code: untyped): untyped {.immediate.}=
|
template assertFalse*(self: TestSuite, code: untyped): untyped {.immediate.}=
|
||||||
## Raises a TestAssertError when the code is true.
|
## Raises a TestAssertError when the code is true.
|
||||||
if code:
|
if code:
|
||||||
var snip = astToStr(code)
|
var snip = astToStr(code)
|
||||||
|
|
||||||
var
|
var
|
||||||
vals = "($1) == $2".format(snip, code)
|
vals = "($1) == $2".format(snip, code)
|
||||||
test_name = self.current_test_name
|
testName = self.currentTestName
|
||||||
|
|
||||||
return_exception("assert_false", test_name, snip, vals)
|
returnException("assertFalse", testName, snip, vals)
|
||||||
|
|
||||||
|
|
||||||
template assert_raises*(self: TestSuite, error: untyped, code: untyped): untyped {.immediate.}=
|
template assertRaises*(self: TestSuite, error: Exception, code: untyped): untyped {.immediate.}=
|
||||||
## Raises a TestAssertError when the exception "error" is
|
## Raises a TestAssertError when the exception "error" is
|
||||||
## not thrown in the code
|
## not thrown in the code
|
||||||
try:
|
try:
|
||||||
|
|
@ -112,9 +112,9 @@ template assert_raises*(self: TestSuite, error: untyped, code: untyped): untyped
|
||||||
var
|
var
|
||||||
snip = astToStr(code)
|
snip = astToStr(code)
|
||||||
vals = "No Exception Raised"
|
vals = "No Exception Raised"
|
||||||
test_name = self.current_test_name
|
testName = self.currentTestName
|
||||||
|
|
||||||
return_exception("assert_raises", test_name, snip, vals)
|
returnException("assertRaises", testName, snip, vals)
|
||||||
|
|
||||||
except error:
|
except error:
|
||||||
discard
|
discard
|
||||||
|
|
@ -124,9 +124,9 @@ template assert_raises*(self: TestSuite, error: untyped, code: untyped): untyped
|
||||||
var
|
var
|
||||||
snip = astToStr(code)
|
snip = astToStr(code)
|
||||||
vals = "Exception != $1".format(astToStr(error))
|
vals = "Exception != $1".format(astToStr(error))
|
||||||
test_name = self.current_test_name
|
testName = self.currentTestName
|
||||||
|
|
||||||
return_exception("assert_raises", test_name, snip, vals)
|
returnException("assertRaises", testName, snip, vals)
|
||||||
|
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
@ -134,9 +134,9 @@ template assert_raises*(self: TestSuite, error: untyped, code: untyped): untyped
|
||||||
|
|
||||||
|
|
||||||
# A list to hold all test suites that are created
|
# A list to hold all test suites that are created
|
||||||
var test_suites: seq[TestSuite] = @[]
|
var testSuites: seq[TestSuite] = @[]
|
||||||
|
|
||||||
macro test_suite*(head: untyped, body: untyped): untyped =
|
macro testSuite*(head: untyped, body: untyped): untyped =
|
||||||
## Compile-time macro that allows a user to define tests and run them
|
## Compile-time macro that allows a user to define tests and run them
|
||||||
##
|
##
|
||||||
## Methods are used for inheritance, so if you want to derive a test
|
## Methods are used for inheritance, so if you want to derive a test
|
||||||
|
|
@ -154,36 +154,36 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
## procs that do other things and won't be run as a test.
|
## procs that do other things and won't be run as a test.
|
||||||
##
|
##
|
||||||
## For each suite method/proc, an implicit variable called "self"
|
## For each suite method/proc, an implicit variable called "self"
|
||||||
## is added. This lets you access the test_suite in an OO kind
|
## is added. This lets you access the testSuite in an OO kind
|
||||||
## of way.
|
## of way.
|
||||||
##
|
##
|
||||||
## Usage:
|
## Usage:
|
||||||
##
|
##
|
||||||
## .. code:: nim
|
## .. code:: nim
|
||||||
##
|
##
|
||||||
## test_suite SuiteName of TestSuite:
|
## testSuite SuiteName of TestSuite:
|
||||||
##
|
##
|
||||||
## var
|
## var
|
||||||
## suite_var: string
|
## suiteVar: string
|
||||||
##
|
##
|
||||||
## method setup()=
|
## method setup()=
|
||||||
## ## do setup code here
|
## ## do setup code here
|
||||||
## self.suite_var = "Testing"
|
## self.suiteVar = "Testing"
|
||||||
##
|
##
|
||||||
## method test_adding_string()=
|
## method testAddingString()=
|
||||||
## ## adds a string to the suite_var
|
## ## adds a string to the suiteVar
|
||||||
## self.suite_var &= " 123"
|
## self.suiteVar &= " 123"
|
||||||
## self.assert_equal(self.suite_var, "Testing 123")
|
## self.assertEqual(self.suiteVar, "Testing 123")
|
||||||
##
|
##
|
||||||
## when isMainModule:
|
## when isMainModule:
|
||||||
## einheit.run_tests()
|
## einheit.runTests()
|
||||||
|
|
||||||
# object reference name inside methods.
|
# object reference name inside methods.
|
||||||
# ie: self, self
|
# ie: self, self
|
||||||
let obj_reference = "self"
|
let objReference = "self"
|
||||||
var export_class: bool = false
|
var exportClass: bool = false
|
||||||
|
|
||||||
template import_required_libs()=
|
template importRequiredLibs()=
|
||||||
import strutils
|
import strutils
|
||||||
when not defined(ECMAScript):
|
when not defined(ECMAScript):
|
||||||
import terminal
|
import terminal
|
||||||
|
|
@ -217,11 +217,11 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
# Prefix
|
# Prefix
|
||||||
# Ident !"of"
|
# Ident !"of"
|
||||||
# Ident !"RootObj"
|
# Ident !"RootObj"
|
||||||
export_class = true
|
exportClass = true
|
||||||
typeName = head[1]
|
typeName = head[1]
|
||||||
baseName = head[2][1]
|
baseName = head[2][1]
|
||||||
elif head.kind == nnkInfix and $head[0] == "*":
|
elif head.kind == nnkInfix and $head[0] == "*":
|
||||||
export_class = true
|
exportClass = true
|
||||||
typeName = head[1]
|
typeName = head[1]
|
||||||
else:
|
else:
|
||||||
quit "Invalid node: " & head.lispRepr
|
quit "Invalid node: " & head.lispRepr
|
||||||
|
|
@ -250,7 +250,7 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
# StmtList
|
# StmtList
|
||||||
# StrLit ...
|
# StrLit ...
|
||||||
# MethodDef
|
# MethodDef
|
||||||
# Ident !"age_human_yrs"
|
# Ident !"ageHumanYrs"
|
||||||
# Empty
|
# Empty
|
||||||
# Empty
|
# Empty
|
||||||
# FormalParams
|
# FormalParams
|
||||||
|
|
@ -276,37 +276,37 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
# return `baseName`(self)
|
# return `baseName`(self)
|
||||||
# result.add(super)
|
# result.add(super)
|
||||||
|
|
||||||
template set_node_name(n2, proc_name, type_name)=
|
template setNodeName(n2, procName, typeName)=
|
||||||
if n2.name.kind == nnkIdent:
|
if n2.name.kind == nnkIdent:
|
||||||
proc_name = $(n2.name.toStrLit())
|
procName = $(n2.name.toStrLit())
|
||||||
n2.name = ident(proc_name & type_name)
|
n2.name = ident(procName & typeName)
|
||||||
elif n2.name.kind == nnkPostFix:
|
elif n2.name.kind == nnkPostFix:
|
||||||
if n2.name[1].kind == nnkIdent:
|
if n2.name[1].kind == nnkIdent:
|
||||||
proc_name = $(n2.name[1].toStrLit())
|
procName = $(n2.name[1].toStrLit())
|
||||||
n2.name[1] = ident(proc_name & type_name)
|
n2.name[1] = ident(procName & typeName)
|
||||||
elif n2.name[1].kind == nnkAccQuoted:
|
elif n2.name[1].kind == nnkAccQuoted:
|
||||||
proc_name = $(n2.name[1][0].toStrLit())
|
procName = $(n2.name[1][0].toStrLit())
|
||||||
n2.name[1][0] = ident(proc_name & type_name)
|
n2.name[1][0] = ident(procName & typeName)
|
||||||
elif n2.name.kind == nnkAccQuoted:
|
elif n2.name.kind == nnkAccQuoted:
|
||||||
proc_name = $(n2.name[0].toStrLit())
|
procName = $(n2.name[0].toStrLit())
|
||||||
n2.name[0] = ident(proc_name & type_name)
|
n2.name[0] = ident(procName & typeName)
|
||||||
result.add(n2)
|
result.add(n2)
|
||||||
|
|
||||||
|
|
||||||
template run_tests_proc(self, typeName, base_method, type_method)=
|
template runTestsProc(self, typeName, baseMethod, typeMethod)=
|
||||||
method type_method(self: typeName)=
|
method typeMethod(self: typeName)=
|
||||||
when compiles(self.base_method()):
|
when compiles(self.baseMethod()):
|
||||||
self.base_method()
|
self.baseMethod()
|
||||||
|
|
||||||
method run_tests(self: typeName)=
|
method runTests(self: typeName)=
|
||||||
self.type_method()
|
self.typeMethod()
|
||||||
|
|
||||||
var base_method_name = ident("run_tests" & $baseName.toStrLit())
|
var baseMethodName = ident("runTests" & $baseName.toStrLit())
|
||||||
var type_method_name = ident("run_tests" & $typeName.toStrLit())
|
var typeMethodName = ident("runTests" & $typeName.toStrLit())
|
||||||
|
|
||||||
var run_tests = getAst(run_tests_proc(ident(obj_reference), typeName, base_method_name, type_method_name))
|
var runTests = getAst(runTestsProc(ident(objReference), typeName, baseMethodName, typeMethodName))
|
||||||
|
|
||||||
var found_setup = false
|
var foundSetup = false
|
||||||
|
|
||||||
# Make forward declarations so that function order
|
# Make forward declarations so that function order
|
||||||
# does not matter, just like in real OOP!
|
# does not matter, just like in real OOP!
|
||||||
|
|
@ -315,7 +315,7 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
of nnkMethodDef, nnkProcDef:
|
of nnkMethodDef, nnkProcDef:
|
||||||
# inject `self: T` into the arguments
|
# inject `self: T` into the arguments
|
||||||
let n = copyNimTree(node)
|
let n = copyNimTree(node)
|
||||||
n.params.insert(1, newIdentDefs(ident(obj_reference), typeName))
|
n.params.insert(1, newIdentDefs(ident(objReference), typeName))
|
||||||
# clear the body so we only get a
|
# clear the body so we only get a
|
||||||
# declaration
|
# declaration
|
||||||
n.body = newEmptyNode()
|
n.body = newEmptyNode()
|
||||||
|
|
@ -323,30 +323,30 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
|
|
||||||
# forward declare the inheritable method
|
# forward declare the inheritable method
|
||||||
let n2 = copyNimTree(n)
|
let n2 = copyNimTree(n)
|
||||||
let type_name = $(typeName.toStrLit())
|
let typeName = $(typeName.toStrLit())
|
||||||
var proc_name = ""
|
var procName = ""
|
||||||
|
|
||||||
set_node_name(n2, proc_name, type_name)
|
setNodeName(n2, procName, typeName)
|
||||||
|
|
||||||
if proc_name == "setup":
|
if procName == "setup":
|
||||||
found_setup = true
|
foundSetup = true
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
if not found_setup:
|
if not foundSetup:
|
||||||
template setup_proc(self, typeName, setup_proc)=
|
template setupProc(self, typeName, setupProc)=
|
||||||
method setup(self: typeName)
|
method setup(self: typeName)
|
||||||
method setup_proc(self: typeName)
|
method setupProc(self: typeName)
|
||||||
|
|
||||||
template setup_decl(self, base_method)=
|
template setupDecl(self, baseMethod)=
|
||||||
method setup()=
|
method setup()=
|
||||||
self.base_method()
|
self.baseMethod()
|
||||||
discard
|
discard
|
||||||
|
|
||||||
var setup_proc_typename = ident("setup" & $typeName.toStrLit())
|
var setupProcTypename = ident("setup" & $typeName.toStrLit())
|
||||||
var base_method_name = ident("setup" & $baseName.toStrLit())
|
var baseMethodName = ident("setup" & $baseName.toStrLit())
|
||||||
result.add(getAst(setup_proc(ident(obj_reference), typeName, setup_proc_typename)))
|
result.add(getAst(setupProc(ident(objReference), typeName, setupProcTypename)))
|
||||||
body.add(getAst(setup_decl(ident(obj_reference), base_method_name))[0])
|
body.add(getAst(setupDecl(ident(objReference), baseMethodName))[0])
|
||||||
|
|
||||||
# Iterate over the statements, adding `self: T`
|
# Iterate over the statements, adding `self: T`
|
||||||
# to the parameters of functions
|
# to the parameters of functions
|
||||||
|
|
@ -355,45 +355,45 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
of nnkMethodDef, nnkProcDef:
|
of nnkMethodDef, nnkProcDef:
|
||||||
# inject `self: T` into the arguments
|
# inject `self: T` into the arguments
|
||||||
let n = copyNimTree(node)
|
let n = copyNimTree(node)
|
||||||
n.params.insert(1, newIdentDefs(ident(obj_reference), typeName))
|
n.params.insert(1, newIdentDefs(ident(objReference), typeName))
|
||||||
|
|
||||||
# Copy the proc or method for inheritance
|
# Copy the proc or method for inheritance
|
||||||
# ie: procName_ClassName()
|
# ie: procName_ClassName()
|
||||||
let n2 = copyNimTree(node)
|
let n2 = copyNimTree(node)
|
||||||
n2.params.insert(1, newIdentDefs(ident(obj_reference), typeName))
|
n2.params.insert(1, newIdentDefs(ident(objReference), typeName))
|
||||||
|
|
||||||
let type_name = $(typeName.toStrLit())
|
let typeName = $(typeName.toStrLit())
|
||||||
var proc_name = $(n2.name.toStrLit())
|
var procName = $(n2.name.toStrLit())
|
||||||
var is_assignment = proc_name.contains("=")
|
var isAssignment = procName.contains("=")
|
||||||
|
|
||||||
set_node_name(n2, proc_name, type_name)
|
setNodeName(n2, procName, typeName)
|
||||||
|
|
||||||
if proc_name == "setup":
|
if procName == "setup":
|
||||||
let dot_name = newDotExpr(ident(obj_reference), ident("name"))
|
let dotName = newDotExpr(ident(objReference), ident("name"))
|
||||||
let set_name = newAssignment(dot_name, newLit(typeName))
|
let setName = newAssignment(dotName, newLit(typeName))
|
||||||
n2.body.add(set_name)
|
n2.body.add(setName)
|
||||||
elif proc_name.startswith("test"):
|
elif procName.startswith("test"):
|
||||||
let proc_call = newDotExpr(ident(obj_reference),
|
let procCall = newDotExpr(ident(objReference),
|
||||||
ident(proc_name & type_name))
|
ident(procName & typeName))
|
||||||
|
|
||||||
template set_test_name(self, proc_name)=
|
template setTestName(self, procName)=
|
||||||
self.current_test_name = proc_name
|
self.currentTestName = procName
|
||||||
|
|
||||||
template try_block(self, test_call)=
|
template tryBlock(self, testCall)=
|
||||||
self.num_tests += 1
|
self.numTests += 1
|
||||||
try:
|
try:
|
||||||
test_call
|
testCall
|
||||||
styled_echo(styleBright, fgGreen, "[OK]",
|
styledEcho(styleBright, fgGreen, "[OK]",
|
||||||
fgWhite, " ", self.current_test_name)
|
fgWhite, " ", self.currentTestName)
|
||||||
self.tests_passed += 1
|
self.testsPassed += 1
|
||||||
except TestAssertError:
|
except TestAssertError:
|
||||||
let e = (ref TestAssertError)(getCurrentException())
|
let e = (ref TestAssertError)(getCurrentException())
|
||||||
styled_echo(styleBright,
|
styledEcho(styleBright,
|
||||||
fgRed, "[Failed]",
|
fgRed, "[Failed]",
|
||||||
fgWhite, " ", self.current_test_name, e.msg)
|
fgWhite, " ", self.currentTestName, e.msg)
|
||||||
|
|
||||||
run_tests[0][6].add(getAst(set_test_name(ident(obj_reference), proc_name)))
|
runTests[0][6].add(getAst(setTestName(ident(objReference), procName)))
|
||||||
run_tests[0][6].add(getAst(try_block(ident(obj_reference), proc_call)))
|
runTests[0][6].add(getAst(tryBlock(ident(objReference), procCall)))
|
||||||
|
|
||||||
# simply call the class method from here
|
# simply call the class method from here
|
||||||
# proc procName=
|
# proc procName=
|
||||||
|
|
@ -401,11 +401,11 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
var p: seq[NimNode] = @[]
|
var p: seq[NimNode] = @[]
|
||||||
for i in 1..n.params.len-1:
|
for i in 1..n.params.len-1:
|
||||||
p.add(n.params[i][0])
|
p.add(n.params[i][0])
|
||||||
if is_assignment:
|
if isAssignment:
|
||||||
let dot = newDotExpr(ident(obj_reference), ident(proc_name & type_name))
|
let dot = newDotExpr(ident(objReference), ident(procName & typeName))
|
||||||
n.body = newStmtList(newAssignment(dot, p[1]))
|
n.body = newStmtList(newAssignment(dot, p[1]))
|
||||||
else:
|
else:
|
||||||
n.body = newStmtList(newCall(proc_name & type_name, p))
|
n.body = newStmtList(newCall(procName & typeName, p))
|
||||||
|
|
||||||
result.add(n)
|
result.add(n)
|
||||||
|
|
||||||
|
|
@ -438,27 +438,27 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
# Ident !"int"
|
# Ident !"int"
|
||||||
# Empty
|
# Empty
|
||||||
|
|
||||||
var type_decl: NimNode
|
var typeDecl: NimNode
|
||||||
|
|
||||||
template declare_type_export(tname, bname)=
|
template declareTypeExport(tname, bname)=
|
||||||
type tname* = ref object of bname
|
type tname* = ref object of bname
|
||||||
template declare_type(tname, bname)=
|
template declareType(tname, bname)=
|
||||||
type tname = ref object of bname
|
type tname = ref object of bname
|
||||||
|
|
||||||
if baseName == nil:
|
if baseName == nil:
|
||||||
if export_class:
|
if exportClass:
|
||||||
type_decl = getAst(declare_type_export(typeName, TestSuite))
|
typeDecl = getAst(declareTypeExport(typeName, TestSuite))
|
||||||
else:
|
else:
|
||||||
type_decl = getAst(declare_type(typeName, TestSuite))
|
typeDecl = getAst(declareType(typeName, TestSuite))
|
||||||
else:
|
else:
|
||||||
if export_class:
|
if exportClass:
|
||||||
type_decl = getAst(declare_type_export(typeName, baseName))
|
typeDecl = getAst(declareTypeExport(typeName, baseName))
|
||||||
else:
|
else:
|
||||||
type_decl = getAst(declare_type(typeName, baseName))
|
typeDecl = getAst(declareType(typeName, baseName))
|
||||||
|
|
||||||
# Inspect the tree structure:
|
# Inspect the tree structure:
|
||||||
#
|
#
|
||||||
# echo type_decl.treeRepr
|
# echo typeDecl.treeRepr
|
||||||
# --------------------
|
# --------------------
|
||||||
# StmtList
|
# StmtList
|
||||||
# TypeSection
|
# TypeSection
|
||||||
|
|
@ -471,40 +471,40 @@ macro test_suite*(head: untyped, body: untyped): untyped =
|
||||||
# OfInherit
|
# OfInherit
|
||||||
# Ident !"RootObj"
|
# Ident !"RootObj"
|
||||||
# Empty <= We want to replace this
|
# Empty <= We want to replace this
|
||||||
type_decl[0][0][2][0][2] = recList
|
typeDecl[0][0][2][0][2] = recList
|
||||||
|
|
||||||
# insert the type declaration
|
# insert the type declaration
|
||||||
result.insert(0, type_decl)
|
result.insert(0, typeDecl)
|
||||||
|
|
||||||
# insert libs needed
|
# insert libs needed
|
||||||
result.insert(0, getAst(import_required_libs()))
|
result.insert(0, getAst(importRequiredLibs()))
|
||||||
|
|
||||||
result.add(run_tests)
|
result.add(runTests)
|
||||||
|
|
||||||
template add_test_suite(typeName)=
|
template addTestSuite(typeName)=
|
||||||
test_suites.add(typeName())
|
testSuites.add(typeName())
|
||||||
|
|
||||||
result.add(getAst(add_test_suite(typeName)))
|
result.add(getAst(addTestSuite(typeName)))
|
||||||
|
|
||||||
|
|
||||||
proc run_tests*()=
|
proc runTests*()=
|
||||||
## The method that runs the tests. Invoke
|
## The method that runs the tests. Invoke
|
||||||
## after setting up all of the tests and
|
## after setting up all of the tests and
|
||||||
## usually inside a "when isMainModule" block
|
## usually inside a "when isMainModule" block
|
||||||
for suite in test_suites:
|
for suite in testSuites:
|
||||||
suite.setup()
|
suite.setup()
|
||||||
|
|
||||||
styled_echo(styleBright,
|
styledEcho(styleBright,
|
||||||
fgYellow, "\n[Running]",
|
fgYellow, "\n[Running]",
|
||||||
fgWhite, " $1\n".format(suite.name))
|
fgWhite, " $1\n".format(suite.name))
|
||||||
suite.run_tests()
|
suite.runTests()
|
||||||
|
|
||||||
# Output red if tests didn't pass, green otherwise
|
# Output red if tests didn't pass, green otherwise
|
||||||
var color = fgGreen
|
var color = fgGreen
|
||||||
if suite.tests_passed != suite.num_tests:
|
if suite.testsPassed != suite.numTests:
|
||||||
color = fgRed
|
color = fgRed
|
||||||
|
|
||||||
styled_echo(styleBright, color,
|
styledEcho(styleBright, color,
|
||||||
"\n[", $suite.tests_passed, "/", $suite.num_tests, "]",
|
"\n[", $suite.testsPassed, "/", $suite.numTests, "]",
|
||||||
fgWhite, " tests passed.\n")
|
fgWhite, " tests passed.\n")
|
||||||
|
|
||||||
|
|
|
||||||
76
test.nim
76
test.nim
|
|
@ -1,69 +1,69 @@
|
||||||
import einheit
|
import einheit
|
||||||
|
|
||||||
test_suite UnitTests:
|
testSuite UnitTests:
|
||||||
var
|
var
|
||||||
test_obj: int
|
testObj: int
|
||||||
|
|
||||||
proc do_things()=
|
proc doThings()=
|
||||||
# This proc won't be invoked as a test
|
# This proc won't be invoked as a test
|
||||||
self.test_obj = 400
|
self.testObj = 400
|
||||||
self.assert_true(self.test_obj == 400)
|
self.assertTrue(self.testObj == 400)
|
||||||
|
|
||||||
method setup()=
|
method setup()=
|
||||||
self.test_obj = 5
|
self.testObj = 5
|
||||||
self.test_obj = 90
|
self.testObj = 90
|
||||||
|
|
||||||
method test_for_b()=
|
method testForB()=
|
||||||
var b = 0
|
var b = 0
|
||||||
self.do_things()
|
self.doThings()
|
||||||
self.assert_true(4 == 4)
|
self.assertTrue(4 == 4)
|
||||||
|
|
||||||
method test_for_c()=
|
method testForC()=
|
||||||
var c = 0
|
var c = 0
|
||||||
# supposed to fail
|
# supposed to fail
|
||||||
self.assert_equal(c, 1)
|
self.assertEqual(c, 1)
|
||||||
|
|
||||||
|
|
||||||
test_suite UnitTestsNew:
|
testSuite UnitTestsNew:
|
||||||
var
|
var
|
||||||
test_obj: int
|
testObj: int
|
||||||
|
|
||||||
method setup()=
|
method setup()=
|
||||||
self.test_obj = 5
|
self.testObj = 5
|
||||||
self.test_obj = 90
|
self.testObj = 90
|
||||||
|
|
||||||
method test_test_obj()=
|
method testTestObj()=
|
||||||
self.assert_true(self.test_obj == 90)
|
self.assertTrue(self.testObj == 90)
|
||||||
|
|
||||||
method test_stuff()=
|
method testStuff()=
|
||||||
self.assert_equal("Stuff", "Stuff")
|
self.assertEqual("Stuff", "Stuff")
|
||||||
|
|
||||||
method test_more()=
|
method testMore()=
|
||||||
self.assert_equal("String", "String")
|
self.assertEqual("String", "String")
|
||||||
|
|
||||||
method test_more_more()=
|
method testMoreMore()=
|
||||||
self.assert_false("String" != "String")
|
self.assertFalse("String" != "String")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Inheritance!
|
# Inheritance!
|
||||||
test_suite TestInherit of UnitTestsNew:
|
testSuite TestInherit of UnitTestsNew:
|
||||||
## This will call every test defined in UnitTestsNew
|
## This will call every test defined in UnitTestsNew
|
||||||
|
|
||||||
proc raises_os()=
|
proc raisesOs()=
|
||||||
# This proc won't be invoked as a test
|
# This proc won't be invoked as a test
|
||||||
raise newException(OSError, "Oh no! OS malfunction!")
|
raise newException(OSError, "Oh no! OS malfunction!")
|
||||||
|
|
||||||
method test_raises()=
|
method testRaises()=
|
||||||
|
|
||||||
# Two ways of asserting
|
# Two ways of asserting
|
||||||
self.assert_raises OSError:
|
self.assertRaises OSError:
|
||||||
self.raises_os()
|
self.raisesOs()
|
||||||
|
|
||||||
self.assert_raises(OSError, self.raises_os())
|
self.assertRaises(OSError, self.raisesOs())
|
||||||
|
|
||||||
|
|
||||||
test_suite MoreInheritance of TestInherit:
|
testSuite MoreInheritance of TestInherit:
|
||||||
|
|
||||||
method setup()=
|
method setup()=
|
||||||
# This must be called if overriding setup if you want
|
# This must be called if overriding setup if you want
|
||||||
|
|
@ -74,20 +74,20 @@ test_suite MoreInheritance of TestInherit:
|
||||||
|
|
||||||
# This will make one of the tests inherited from UnitTestsNew
|
# This will make one of the tests inherited from UnitTestsNew
|
||||||
# fail. This is expected.
|
# fail. This is expected.
|
||||||
self.test_obj = 12345
|
self.testObj = 12345
|
||||||
|
|
||||||
method test_test_obj()=
|
method testTestObj()=
|
||||||
# This method is overwritten. To call the base method,
|
# This method is overwritten. To call the base method,
|
||||||
# simply use
|
# simply use
|
||||||
# self.test_test_obj_UnitTestsNew()
|
# self.testTestObj_UnitTestsNew()
|
||||||
# However, currently this method will be run
|
# However, currently this method will be run
|
||||||
# IN ADDITION to the base class's method.
|
# IN ADDITION to the base class's method.
|
||||||
# This one will pass, the other will fail
|
# This one will pass, the other will fail
|
||||||
self.assert_true(self.test_obj == 12345)
|
self.assertTrue(self.testObj == 12345)
|
||||||
|
|
||||||
method test_new_obj()=
|
method testNewObj()=
|
||||||
self.assert_equal(self.test_obj, 12345)
|
self.assertEqual(self.testObj, 12345)
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
run_tests()
|
runTests()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue