Skip to content

Commit d32a3a4

Browse files
committed
Test parser based on the output of unittest2
1 parent 380e463 commit d32a3a4

File tree

10 files changed

+214
-59
lines changed

10 files changed

+214
-59
lines changed

tests/all.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ import
33
tnimlangserver,
44
tprojectsetup,
55
textensions,
6-
tmisc
6+
tmisc,
7+
ttestrunner

tests/projects/testrunner/config.nims

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# begin Nimble config (version 2)
2+
when withDir(thisDir(), system.fileExists("nimble.paths")):
3+
include "nimble.paths"
4+
# end Nimble config
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# This is just an example to get you started. A typical library package
2+
# exports the main API in this file. Note that you cannot rename this file
3+
# but you can remove it if you wish.
4+
5+
proc add*(x, y: int): int =
6+
## Adds two numbers together.
7+
return x + y
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This is just an example to get you started. Users of your library will
2+
# import this file by writing ``import testrunner/submodule``. Feel free to rename or
3+
# remove this file altogether. You may create additional modules alongside
4+
# this file as required.
5+
6+
type
7+
Submodule* = object
8+
name*: string
9+
10+
proc initSubmodule*(): Submodule =
11+
## Initialises a new ``Submodule`` object.
12+
Submodule(name: "Anonymous")
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Package
2+
3+
version = "0.1.0"
4+
author = "jmgomez"
5+
description = "A new awesome nimble package"
6+
license = "MIT"
7+
srcDir = "src"
8+
9+
10+
# Dependencies
11+
12+
requires "nim", "https://github.com/jmgomez/nim-unittest2#list_tests"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import unittest2
2+
3+
suite "Sample Tests":
4+
test "Sample Test":
5+
check(1 == 1)
6+
7+
test "Global test":
8+
check(1 == 1)
9+
10+
test "Global test 2":
11+
check(1 == 1)
12+
13+
suite "Sample Suite":
14+
test "Sample Test":
15+
check(1 == 1)
16+
17+
test "Sample Test 2":
18+
check(1 == 1)
19+
20+
test "Sample Test 3":
21+
check(1 == 1)
22+
23+
test "Another global test":
24+
check(1 == 1)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This is just an example to get you started. You may wish to put all of your
2+
# tests into a single file, or separate them into multiple `test1`, `test2`
3+
# etc. files (better names are recommended, just make sure the name starts with
4+
# the letter 't').
5+
#
6+
# To run these tests, simply execute `nimble test`.
7+
8+
import unittest2
9+
10+
import testrunner
11+
test "can add":
12+
check add(5, 5) == 10

tests/testhelpers.nim

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import std/[os, osproc, sequtils, strutils, sugar, unittest]
2+
3+
template cd*(dir: string, body: untyped) =
4+
## Sets the current dir to ``dir``, executes ``body`` and restores the
5+
## previous working dir.
6+
let lastDir = getCurrentDir()
7+
setCurrentDir(dir)
8+
block:
9+
defer:
10+
setCurrentDir(lastDir)
11+
body
12+
13+
template createNewDir*(dir: string) =
14+
removeDir dir
15+
createDir dir
16+
17+
template cdNewDir*(dir: string, body: untyped) =
18+
createNewDir dir
19+
cd dir:
20+
body
21+
22+
let
23+
rootDir = getCurrentDir()
24+
nimblePath* = findExe "nimble"
25+
installDir* = rootDir / "tests" / "nimbleDir"
26+
27+
type ProcessOutput* = tuple[output: string, exitCode: int]
28+
29+
proc execNimble*(args: varargs[string]): ProcessOutput =
30+
var quotedArgs = @args
31+
if not args.anyIt("--nimbleDir:" in it or "-l" == it or "--local" == it):
32+
quotedArgs.insert("--nimbleDir:" & installDir)
33+
quotedArgs.insert(nimblePath)
34+
quotedArgs = quotedArgs.map((x: string) => x.quoteShell)
35+
36+
let path {.used.} = getCurrentDir().parentDir() / "src"
37+
38+
var cmd =
39+
when not defined(windows):
40+
"PATH=" & path & ":$PATH " & quotedArgs.join(" ")
41+
else:
42+
quotedArgs.join(" ")
43+
when defined(macosx):
44+
# TODO: Yeah, this is really specific to my machine but for my own sanity...
45+
cmd = "DYLD_LIBRARY_PATH=/usr/local/opt/openssl@1.1/lib " & cmd
46+
47+
result = execCmdEx(cmd)
48+
checkpoint(cmd)
49+
checkpoint(result.output)
50+
51+
proc execNimbleYes*(args: varargs[string]): ProcessOutput =
52+
execNimble(@args & "-y")
53+
54+
proc createNimbleProject*(projectDir: string) =
55+
cdNewDir projectDir:
56+
let (output, exitCode) = execNimbleYes("init")
57+
check exitCode == 0

tests/tprojectsetup.nim

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,68 +3,12 @@ import ../protocol/[enums, types]
33
import
44
std/
55
[
6-
options, unittest, json, os, jsonutils, sequtils, strutils, sugar, strformat,
7-
osproc,
6+
options, unittest, json, os, jsonutils, sequtils, strutils, sugar, strformat
87
]
98
import json_rpc/[rpcclient]
109
import chronicles
1110
import lspsocketclient
12-
13-
template cd*(dir: string, body: untyped) =
14-
## Sets the current dir to ``dir``, executes ``body`` and restores the
15-
## previous working dir.
16-
let lastDir = getCurrentDir()
17-
setCurrentDir(dir)
18-
block:
19-
defer:
20-
setCurrentDir(lastDir)
21-
body
22-
23-
template createNewDir*(dir: string) =
24-
removeDir dir
25-
createDir dir
26-
27-
template cdNewDir*(dir: string, body: untyped) =
28-
createNewDir dir
29-
cd dir:
30-
body
31-
32-
let
33-
rootDir = getCurrentDir()
34-
nimblePath* = findExe "nimble"
35-
installDir* = rootDir / "tests" / "nimbleDir"
36-
37-
type ProcessOutput* = tuple[output: string, exitCode: int]
38-
39-
proc execNimble*(args: varargs[string]): ProcessOutput =
40-
var quotedArgs = @args
41-
if not args.anyIt("--nimbleDir:" in it or "-l" == it or "--local" == it):
42-
quotedArgs.insert("--nimbleDir:" & installDir)
43-
quotedArgs.insert(nimblePath)
44-
quotedArgs = quotedArgs.map((x: string) => x.quoteShell)
45-
46-
let path {.used.} = getCurrentDir().parentDir() / "src"
47-
48-
var cmd =
49-
when not defined(windows):
50-
"PATH=" & path & ":$PATH " & quotedArgs.join(" ")
51-
else:
52-
quotedArgs.join(" ")
53-
when defined(macosx):
54-
# TODO: Yeah, this is really specific to my machine but for my own sanity...
55-
cmd = "DYLD_LIBRARY_PATH=/usr/local/opt/openssl@1.1/lib " & cmd
56-
57-
result = execCmdEx(cmd)
58-
checkpoint(cmd)
59-
checkpoint(result.output)
60-
61-
proc execNimbleYes*(args: varargs[string]): ProcessOutput =
62-
execNimble(@args & "-y")
63-
64-
proc createNimbleProject(projectDir: string) =
65-
cdNewDir projectDir:
66-
let (output, exitCode) = execNimbleYes("init")
67-
check exitCode == 0
11+
import testhelpers
6812

6913
suite "nimble setup":
7014
let cmdParams = CommandLineParams(transport: some socket, port: getNextFreePort())

tests/ttestrunner.nim

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import unittest
2+
import std/[os, osproc, strscans, tables, sequtils, enumerate, strutils]
3+
import testhelpers
4+
5+
type
6+
TestInfo* = object
7+
name*: string
8+
line*: int
9+
file*: string
10+
11+
TestSuiteInfo* = object
12+
name*: string #The suite name, empty if it's a global test
13+
tests*: seq[TestInfo]
14+
15+
TestProjectInfo* = object
16+
entryPoints*: seq[string]
17+
suites*: Table[string, TestSuiteInfo]
18+
19+
20+
21+
22+
proc extractTestInfo*(rawOutput: string): TestProjectInfo =
23+
result.suites = initTable[string, TestSuiteInfo]()
24+
result.suites[""] = TestSuiteInfo(name: "")
25+
let lines = rawOutput.split("\n")
26+
var currentSuite = ""
27+
28+
for i, line in enumerate(lines):
29+
var name, file, ignore: string
30+
var lineNumber: int
31+
32+
if scanf(line, "Suite: $*", name):
33+
currentSuite = name.strip()
34+
result.suites[currentSuite] = TestSuiteInfo(name: currentSuite)
35+
echo "Found suite: ", currentSuite
36+
37+
elif scanf(line, "$*Test: $*", ignore, name):
38+
let insideSuite = line.startsWith("\t")
39+
# Use currentSuite if inside a suite, empty string if not
40+
let suiteName = if insideSuite: currentSuite else: ""
41+
42+
#File is always next line of a test
43+
if scanf(lines[i+1], "$*File:$*:$i", ignore, file, lineNumber):
44+
var testInfo = TestInfo(name: name.strip(), file: file.strip(), line: lineNumber)
45+
echo "Adding test: ", testInfo.name, " to suite: ", suiteName
46+
result.suites[suiteName].tests.add(testInfo)
47+
48+
49+
50+
51+
52+
suite "Test Parser":
53+
test "should be able to list tests from an entry point":
54+
#A project can have multiple entry points for the tests, they are specified in the test runner.
55+
#We first need to install the project, as it uses a custom version of unittest2 (until it get merged).
56+
let projectDir = getCurrentDir() / "tests" / "projects" / "testrunner"
57+
cd projectDir:
58+
let (output, _) = execNimble("install", "-l")
59+
let (listTestsOutput, _) = execCmdEx("nim c -d:listTests ./tests/test1.nim")
60+
let testProjectInfo = extractTestInfo(listTestsOutput)
61+
check testProjectInfo.suites.len == 1
62+
check testProjectInfo.suites[""].tests.len == 1
63+
check testProjectInfo.suites[""].tests[0].name == "can add"
64+
check testProjectInfo.suites[""].tests[0].file == "test1.nim"
65+
check testProjectInfo.suites[""].tests[0].line == 11
66+
67+
test "should be able to list tests and suites":
68+
let projectDir = getCurrentDir() / "tests" / "projects" / "testrunner"
69+
cd projectDir:
70+
let (listTestsOutput, _) = execCmdEx("nim c -d:listTests ./tests/sampletests.nim")
71+
echo "*****"
72+
echo listTestsOutput
73+
echo "*****"
74+
let testProjectInfo = extractTestInfo(listTestsOutput)
75+
echo testProjectInfo
76+
check testProjectInfo.suites.len == 3
77+
check testProjectInfo.suites["Sample Tests"].tests.len == 1
78+
check testProjectInfo.suites["Sample Tests"].tests[0].name == "Sample Test"
79+
check testProjectInfo.suites["Sample Tests"].tests[0].file == "sampletests.nim"
80+
check testProjectInfo.suites["Sample Tests"].tests[0].line == 4
81+
check testProjectInfo.suites["Sample Suite"].tests.len == 3
82+
check testProjectInfo.suites[""].tests.len == 3

0 commit comments

Comments
 (0)