Skip to content

Implements initial version of the test parser #314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions testparser.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import std/[tables, options]
import compiler/[ast, idents, msgs, syntaxes, options, pathutils, lineinfos]
# import compiler/[renderer, astalgo]

type
TestInfo* = object
name*: string
line*: uint

SuiteInfo* = object
name*: string #empty means global suite
tests*: seq[TestInfo]
line*: uint

TestFileInfo* = object
testFile*: string
suites*: Table[string, SuiteInfo]
hasErrors*: bool

proc extractTest(n: PNode, conf: ConfigRef): Option[TestInfo] =
if n.kind in nkCallKinds and
n[0].kind == nkIdent and
n[0].ident.s == "test":
if n.len >= 2 and n[1].kind in {nkStrLit .. nkTripleStrLit}:
return some(TestInfo(
name: n[1].strVal,
line: n.info.line
))
else:
localError(conf, n.info, "'test' requires a string literal name")
return none(TestInfo)

proc extract(n: PNode, conf: ConfigRef, result: var TestFileInfo) =
case n.kind
of nkStmtList, nkStmtListExpr:
for child in n:
extract(child, conf, result)
of nkCallKinds:
if n[0].kind == nkIdent:
case n[0].ident.s
of "suite":
if n.len >= 2 and n[1].kind in {nkStrLit .. nkTripleStrLit}:
var suite = SuiteInfo(
name: n[1].strVal,
tests: @[],
line: n.info.line
)
# Extract tests within the suite's body
if n.len > 2 and n[2].kind == nkStmtList:
for testNode in n[2]:
let testInfo = extractTest(testNode, conf)
if testInfo.isSome:
suite.tests.add(testInfo.get)

result.suites[suite.name] = suite
else:
localError(conf, n.info, "'suite' requires a string literal name")
result.hasErrors = true
of "test":
# Handle top-level tests (not in a suite)
let testInfo = extractTest(n, conf)
if testInfo.isSome:
result.suites.mgetOrPut("", SuiteInfo(
name: "",
tests: @[],
line: 0
)).tests.add(testInfo.get)
else:
discard
else:
discard

proc extractTestInfo*(testFile: string): TestFileInfo =
## Extract test information from a test file. This parses the test file
## and extracts suite and test names.
result.testFile = testFile
var conf = newConfigRef()
conf.foreignPackageNotes = {}
conf.notes = {}
conf.mainPackageNotes = {}
conf.errorMax = high(int)
conf.structuredErrorHook = proc(
config: ConfigRef, info: TLineInfo, msg: string, severity: Severity
) {.gcsafe.} =
localError(config, info, warnUser, msg)

let fileIdx = fileInfoIdx(conf, AbsoluteFile testFile)
var parser: Parser
if setupParser(parser, fileIdx, newIdentCache(), conf):
extract(parseAll(parser), conf, result)
closeParser(parser)
result.hasErrors = result.hasErrors or conf.errorCounter > 0

3 changes: 2 additions & 1 deletion tests/all.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import
tnimlangserver,
tprojectsetup,
textensions,
tmisc
tmisc,
ttestrunner
1 change: 1 addition & 0 deletions tests/projects/nonimbleproject.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
echo "hello"
24 changes: 24 additions & 0 deletions tests/projects/tasks/tests/testwithsuites.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import unittest

import testproject


suite "test suite":
test "can add":
check add(5, 5) == 10

test "can add 2":
check add(5, 5) == 10

test "can add 3":
check add(5, 5) == 10

suite "test suite 2":
test "can add 4":
check add(5, 5) == 10

test "can add 5":
check add(5, 5) == 10

test "can add 6":
check add(5, 5) == 10
7 changes: 7 additions & 0 deletions tests/projects/testproject/src/testproject.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This is just an example to get you started. A typical library package
# exports the main API in this file. Note that you cannot rename this file
# but you can remove it if you wish.

proc add*(x, y: int): int =
## Adds two numbers together.
return x + y
12 changes: 12 additions & 0 deletions tests/projects/testproject/src/testproject/submodule.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This is just an example to get you started. Users of your library will
# import this file by writing ``import testproject/submodule``. Feel free to rename or
# remove this file altogether. You may create additional modules alongside
# this file as required.

type
Submodule* = object
name*: string

proc initSubmodule*(): Submodule =
## Initialises a new ``Submodule`` object.
Submodule(name: "Anonymous")
12 changes: 12 additions & 0 deletions tests/projects/testproject/testproject.nimble
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Package

version = "0.1.0"
author = "jmgomez"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"


# Dependencies

requires "nim >= 2.0.8"
1 change: 1 addition & 0 deletions tests/projects/testproject/tests/config.nims
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
switch("path", "$projectDir/../src")
12 changes: 12 additions & 0 deletions tests/projects/testproject/tests/test1.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This is just an example to get you started. You may wish to put all of your
# tests into a single file, or separate them into multiple `test1`, `test2`
# etc. files (better names are recommended, just make sure the name starts with
# the letter 't').
#
# To run these tests, simply execute `nimble test`.

import unittest

import testproject
test "can add":
check add(5, 5) == 10
23 changes: 23 additions & 0 deletions tests/ttestrunner.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import unittest
import std/[os, tables]
import testparser

suite "Test Parser":
test "should be able to retrieve a test from a file":
let file = getCurrentDir() / "tests" / "projects" / "testproject" / "tests" / "test1.nim"
let testInfo = extractTestInfo(file)
# echo testInfo
check testInfo.suites.len == 1
check testInfo.suites[""].tests.len == 1
check testInfo.suites[""].tests[0].name == "can add"
check testInfo.suites[""].tests[0].line == 11

test "should be able to retrieve suites and tests from a file":
let file = getCurrentDir() / "tests" / "projects" / "tasks" / "tests" / "testwithsuites.nim"
let testInfo = extractTestInfo(file)
# echo testInfo
check testInfo.suites.len == 3 # 2 suites and 1 test global
check testInfo.suites["test suite"].tests.len == 3
check testInfo.suites["test suite 2"].tests.len == 2
check testInfo.suites[""].tests.len == 1