Split testing into unit and functional tests.
* Split the `test` nimble task into `unittest` and `functest`, with corresponding test directories and test runners. * Added documentation in README regarding building and testing StrawBoss. * Created a small, simple test project for use in the functional tests. * Added a `keepEnv` template in the server unit test code to make it easy to preserve the working environment for a single unit test to invistigate failures manually.
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "test-project-1",
|
||||
"name": "dummy-project",
|
||||
"versionCmd": "git describe --all --always",
|
||||
"steps": {
|
||||
"build": {
|
@ -8,12 +8,12 @@
|
||||
],
|
||||
"pwdCost": 11,
|
||||
"projects": [
|
||||
{ "name": "test-project-1",
|
||||
{ "name": "dummy-project",
|
||||
"repo": "/non-existent/dir",
|
||||
"cfgFilePath": "strawhat.json",
|
||||
"defaultBranch": "deploy",
|
||||
"envVars": { "VAR1": "value" }
|
||||
},
|
||||
{ "name": "test-strawboss",
|
||||
"repo": "https://git.jdb-labs.com:jdb/test-strawboss.git" } ]
|
||||
{ "name": "test-project",
|
||||
"repo": "" } ]
|
||||
}
|
||||
|
100
src/test/nim/functional/tserver.nim
Normal file
100
src/test/nim/functional/tserver.nim
Normal file
@ -0,0 +1,100 @@
|
||||
import httpclient, json, os, osproc, sequtils, strutils, tempfile, unittest, untar
|
||||
|
||||
from langutils import sameContents
|
||||
|
||||
import ../testutil
|
||||
import ../../../main/nim/strawbosspkg/configuration
|
||||
import ../../../main/nim/strawbosspkg/private/util
|
||||
|
||||
let apiBase = "http://localhost:8180/api"
|
||||
let cfgFilePath = "src/test/json/strawboss.config.json"
|
||||
let cfg = loadStrawBossConfig(cfgFilePath)
|
||||
|
||||
# Util template intended for use to manually review test case.
|
||||
# Inserting into a test case will prevent the test case from cleaning up it's
|
||||
# working files and echo the command to start StrawBoss using that test's
|
||||
# configuration and working files.
|
||||
template keepEnv(): untyped =
|
||||
preserveEnv = true
|
||||
echo "artifacts dir: " & tempArtifactsDir
|
||||
echo "strawboss serve -c " & tempCfgPath
|
||||
|
||||
suite "strawboss server":
|
||||
|
||||
# Suite setup: extract test project
|
||||
let testProjTempDir = mkdtemp()
|
||||
let testProjTarFile = newTarFile("src/test/test-project.tar.gz")
|
||||
let testProjName = "test-project"
|
||||
testProjTarFile.extract(testProjTempDir)
|
||||
|
||||
# per-test setup: spin up a fresh strawboss instance
|
||||
setup:
|
||||
let tempArtifactsDir = mkdtemp()
|
||||
let (_, tempCfgPath) = mkstemp()
|
||||
var preserveEnv = false
|
||||
|
||||
# copy our test config
|
||||
var newCfg = cfg
|
||||
newCfg.artifactsRepo = tempArtifactsDir
|
||||
|
||||
# update the repo string for the extracted test project
|
||||
var testProjDef = newCfg.findProject(testProjName)
|
||||
testProjDef.repo = testProjTempDir & "/" & testProjName
|
||||
newCfg.setProject(testProjName, testProjDef)
|
||||
|
||||
# save the updated config and start the strawboss instance using it
|
||||
writeFile(tempCfgPath, $newCfg)
|
||||
let serverProcess = startProcess("./strawboss", ".",
|
||||
@["serve", "-c", tempCfgPath], loadEnv(), {poUsePath})
|
||||
|
||||
# give the server time to spin up
|
||||
sleep(100)
|
||||
|
||||
teardown:
|
||||
discard newAsyncHttpClient().post(apiBase & "/service/debug/stop")
|
||||
|
||||
if not preserveEnv:
|
||||
removeDir(tempArtifactsDir)
|
||||
removeFile(tempCfgPath)
|
||||
|
||||
# give the server time to spin down but kill it after that
|
||||
sleep(100)
|
||||
if serverProcess.running: kill(serverProcess)
|
||||
|
||||
test "handle missing project configuration":
|
||||
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
||||
let resp = http.get(apiBase & "/projects/" & cfg.projects[0].name)
|
||||
check resp.status.startsWith("404")
|
||||
|
||||
test "gives 404 when no versions built":
|
||||
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
||||
let resp = http.get(apiBase & "/projects/" & testProjName & "/versions")
|
||||
check resp.status.startsWith("404")
|
||||
|
||||
test "GET /api/project/@projectName/versions":
|
||||
let projArtifactsDir = tempArtifactsDir & "/" & testProjName
|
||||
let expectedVersions = @["alpha", "beta", "1.0.0", "1.0.1"]
|
||||
|
||||
# Touch configuration files
|
||||
createDir(projArtifactsDir)
|
||||
for v in expectedVersions:
|
||||
var f: File
|
||||
check open(f, projArtifactsDir & "/configuration." & v & ".json", fmWrite)
|
||||
close(f)
|
||||
|
||||
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
||||
let resp = http.get(apiBase & "/project/" & testProjName & "/versions")
|
||||
let returnedVersions = parseJson(resp.body).getElems.mapIt(it.getStr)
|
||||
check sameContents(expectedVersions, returnedVersions)
|
||||
|
||||
#test "enqueue a build":
|
||||
# let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
||||
# let resp = http.get(apiBase & "/project/" & testProjName & "
|
||||
|
||||
# Last-chance catch to kill the server in case some test err'ed and didn't
|
||||
# reach it's teardown handler
|
||||
discard newAsyncHttpClient().post(apiBase & "/service/debug/stop")
|
||||
|
||||
# Also, delete the extracted test project "source" repo
|
||||
removeDir(testProjTempDir)
|
||||
|
3
src/test/nim/run_functional_tests.nim
Normal file
3
src/test/nim/run_functional_tests.nim
Normal file
@ -0,0 +1,3 @@
|
||||
import unittest
|
||||
|
||||
import ./functional/tserver.nim
|
4
src/test/nim/run_unit_tests.nim
Normal file
4
src/test/nim/run_unit_tests.nim
Normal file
@ -0,0 +1,4 @@
|
||||
import unittest
|
||||
|
||||
import ./unit/tserver.nim
|
||||
import ./unit/tconfiguration.nim
|
@ -1,4 +0,0 @@
|
||||
import unittest
|
||||
|
||||
import ./tserver.nim
|
||||
import ./tconfiguration.nim
|
9
src/test/nim/testutil.nim
Normal file
9
src/test/nim/testutil.nim
Normal file
@ -0,0 +1,9 @@
|
||||
import httpclient, json, strutils
|
||||
|
||||
proc newAuthenticatedHttpClient*(apiBase, uname, pwd: string): HttpClient =
|
||||
result = newHttpClient()
|
||||
let authResp = result.post(apiBase & "/auth-token", $(%*{"username": uname, "password": pwd}))
|
||||
assert authResp.status.startsWith("200")
|
||||
result.headers = newHttpHeaders({"Authorization": "Bearer " & parseJson(authResp.body).getStr})
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import json, strtabs, tables, unittest
|
||||
from langutils import sameContents
|
||||
import ../../main/nim/strawbosspkg/configuration
|
||||
import ../../../main/nim/strawbosspkg/configuration
|
||||
|
||||
suite "load and save configuration objects":
|
||||
|
@ -1,18 +1,12 @@
|
||||
import asyncdispatch, httpclient, json, os, osproc, sequtils, strutils,
|
||||
tempfile, times, unittest
|
||||
times, unittest
|
||||
|
||||
from langutils import sameContents
|
||||
|
||||
import ../../main/nim/strawbosspkg/configuration
|
||||
import ../../main/nim/strawbosspkg/server
|
||||
import ../../main/nim/strawbosspkg/private/util
|
||||
|
||||
# test helpers
|
||||
proc newAuthenticatedHttpClient(apiBase, uname, pwd: string): HttpClient =
|
||||
result = newHttpClient()
|
||||
let authResp = result.post(apiBase & "/auth-token", $(%*{"username": uname, "password": pwd}))
|
||||
assert authResp.status.startsWith("200")
|
||||
result.headers = newHttpHeaders({"Authorization": "Bearer " & parseJson(authResp.body).getStr})
|
||||
import ../testutil
|
||||
import ../../../main/nim/strawbosspkg/configuration
|
||||
import ../../../main/nim/strawbosspkg/server
|
||||
import ../../../main/nim/strawbosspkg/private/util
|
||||
|
||||
let apiBase = "http://localhost:8180/api"
|
||||
let cfgFilePath = "src/test/json/strawboss.config.json"
|
||||
@ -98,56 +92,3 @@ suite "strawboss server":
|
||||
sleep(100)
|
||||
if serverProcess.running: kill(serverProcess)
|
||||
|
||||
suite "strawboss server continued":
|
||||
|
||||
setup:
|
||||
let tmpArtifactsDir = mkdtemp()
|
||||
let (_, tmpCfgPath) = mkstemp()
|
||||
var newCfg = cfg
|
||||
newCfg.artifactsRepo = tmpArtifactsDir
|
||||
writeFile(tmpCfgPath, $newCfg)
|
||||
let serverProcess = startProcess("./strawboss", ".",
|
||||
@["serve", "-c", tmpCfgPath], loadEnv(), {poUsePath})
|
||||
|
||||
# give the server time to spin up
|
||||
sleep(100)
|
||||
|
||||
teardown:
|
||||
discard newAsyncHttpClient().post(apiBase & "/service/debug/stop")
|
||||
removeDir(tmpArtifactsDir)
|
||||
removeFile(tmpCfgPath)
|
||||
|
||||
# give the server time to spin down but kill it after that
|
||||
sleep(100)
|
||||
if serverProcess.running: kill(serverProcess)
|
||||
|
||||
test "handle missing project configuration":
|
||||
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
||||
let resp = http.get(apiBase & "/projects/" & cfg.projects[0].name)
|
||||
check resp.status.startsWith("404")
|
||||
|
||||
test "gives 404 when no versions built":
|
||||
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
||||
let resp = http.get(apiBase & "/projects/" & cfg.projects[0].name & "/versions")
|
||||
check resp.status.startsWith("404")
|
||||
|
||||
test "GET /api/project/@projectName/versions":
|
||||
let projArtifactsDir = tmpArtifactsDir & "/" & cfg.projects[0].name
|
||||
let expectedVersions = @["alpha", "beta", "1.0.0", "1.0.1"]
|
||||
|
||||
# Touch configuration files
|
||||
createDir(projArtifactsDir)
|
||||
for v in expectedVersions:
|
||||
var f: File
|
||||
check open(f, projArtifactsDir & "/configuration." & v & ".json", fmWrite)
|
||||
close(f)
|
||||
|
||||
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
||||
let resp = http.get(apiBase & "/project/" & cfg.projects[0].name & "/versions")
|
||||
let returnedVersions = parseJson(resp.body).getElems.mapIt(it.getStr)
|
||||
check sameContents(expectedVersions, returnedVersions)
|
||||
|
||||
# Last-chance catch to kill the server in case some test err'ed and didn't
|
||||
# reach it's teardown handler
|
||||
discard newAsyncHttpClient().post(apiBase & "/service/debug/stop")
|
||||
|
BIN
src/test/test-project.tar.gz
Normal file
BIN
src/test/test-project.tar.gz
Normal file
Binary file not shown.
Reference in New Issue
Block a user