stdlib test runner: implement setup and teardown commands to unit tests (#8776)

# Description

As in other testing frameworks, the `setup` runs before every test case,
and the `teardown` after that. A context can be created in `setup`,
which will be in the `$in` variable in the test cases, and in the
`teardown`. The `teardown` is called regardless of the test is passed,
skipped, or failed.

For example:

```nushell
use std.nu *

export def setup [] {
    log debug "Setup is running"
    {msg: "This is the context"}
}

export def teardown [] {
    log debug $"Teardown is running. Context: ($in)"
}

export def test_assert_pass [] {
    log debug $"Assert is running. Context: ($in)"
}

export def test_assert_skip [] {
    log debug $"Assert is running. Context: ($in)"
    assert skip
}

export def test_assert_fail_skipped_by_default [] {
    log debug $"Assert is running. Context: ($in)"
    assert false
}
```


![image](https://user-images.githubusercontent.com/282320/230466359-9908cc72-edbd-4150-9aff-d15fe42c0cc7.png)

# After Submitting

I'll update the documentation.

---------

Co-authored-by: Mate Farkas <Mate.Farkas@oneidentity.com>
This commit is contained in:
Máté FARKAS 2023-04-10 22:42:11 +02:00 committed by GitHub
parent 9bb2c8faf5
commit c3678764b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 62 deletions

View File

@ -79,13 +79,16 @@ def main [
let tests = ( let tests = (
ls ($path | path join $module_search_pattern) ls ($path | path join $module_search_pattern)
| each {|row| {file: $row.name name: ($row.name | path parse | get stem)}} | each {|row| {file: $row.name name: ($row.name | path parse | get stem)}}
| upsert test {|module| | upsert commands {|module|
nu -c $'use ($module.file) *; $nu.scope.commands | select name module_name | to nuon' nu -c $'use `($module.file)` *; $nu.scope.commands | select name module_name | to nuon'
| from nuon | from nuon
| where module_name == $module.name | where module_name == $module.name
| where ($it.name | str starts-with "test_")
| get name | get name
} }
| upsert test {|module| $module.commands | where ($it | str starts-with "test_") }
| upsert setup {|module| "setup" in $module.commands }
| upsert teardown {|module| "teardown" in $module.commands }
| reject commands
| flatten | flatten
| rename file module name | rename file module name
) )
@ -114,11 +117,27 @@ def main [
log info $"Running tests in ($module.name)" log info $"Running tests in ($module.name)"
$module.tests | each {|test| $module.tests | each {|test|
log debug $"Running test ($test.name)" log debug $"Running test ($test.name)"
nu -c $'
use ($test.file) ($test.name) let context_setup = if $test.setup {
$"use `($test.file)` setup; let context = \(setup\)"
} else {
"let context = {}"
}
let context_teardown = if $test.teardown {
$"use `($test.file)` teardown; $context | teardown"
} else {
""
}
let nu_script = $'
($context_setup)
use `($test.file)` ($test.name)
try { try {
($test.name) $context | ($test.name)
($context_teardown)
} catch { |err| } catch { |err|
($context_teardown)
if $err.msg == "ASSERT:SKIP" { if $err.msg == "ASSERT:SKIP" {
exit 2 exit 2
} else { } else {
@ -126,6 +145,8 @@ def main [
} }
} }
' '
nu -c $nu_script
let result = match $env.LAST_EXIT_CODE { let result = match $env.LAST_EXIT_CODE {
0 => "pass", 0 => "pass",
2 => "skip", 2 => "skip",

View File

@ -1,74 +1,55 @@
use std "assert length" use std "assert length"
use std "assert equal" use std "assert equal"
def clean [path: path] { export def setup [] {
cd $path {base_path: ($nu.temp-path | path join $"test_dirs_(random uuid)")}
}
export def teardown [] {
let base_path = $in.base_path
cd $base_path
cd .. cd ..
rm -r $path rm -r $base_path
} }
export def test_dirs_command [] { export def test_dirs_command [] {
# need some directories to play with # need some directories to play with
let base_path = ($nu.temp-path | path join $"test_dirs_(random uuid)") let base_path = $in.base_path
let path_a = ($base_path | path join "a") let path_a = ($base_path | path join "a")
let path_b = ($base_path | path join "b") let path_b = ($base_path | path join "b")
try { mkdir $base_path $path_a $path_b
mkdir $base_path $path_a $path_b
cd $base_path cd $base_path
use std "dirs next" use std "dirs next"
use std "dirs prev" use std "dirs prev"
use std "dirs add" use std "dirs add"
use std "dirs drop" use std "dirs drop"
use std "dirs show" use std "dirs show"
assert length $env.DIRS_LIST 1 "list is just pwd after initialization" assert length $env.DIRS_LIST 1 "list is just pwd after initialization"
assert equal $base_path $env.DIRS_LIST.0 "list is just pwd after initialization" assert equal $base_path $env.DIRS_LIST.0 "list is just pwd after initialization"
dirs next dirs next
assert equal $base_path $env.DIRS_LIST.0 "next wraps at end of list" assert equal $base_path $env.DIRS_LIST.0 "next wraps at end of list"
dirs prev dirs prev
assert equal $base_path $env.DIRS_LIST.0 "prev wraps at top of list" assert equal $base_path $env.DIRS_LIST.0 "prev wraps at top of list"
dirs add $path_b $path_a dirs add $path_b $path_a
assert equal $path_b $env.PWD "add changes PWD to first added dir" assert equal $path_b $env.PWD "add changes PWD to first added dir"
assert length $env.DIRS_LIST 3 "add in fact adds to list" assert length $env.DIRS_LIST 3 "add in fact adds to list"
assert equal $path_a $env.DIRS_LIST.2 "add in fact adds to list" assert equal $path_a $env.DIRS_LIST.2 "add in fact adds to list"
dirs next 2 dirs next 2
assert equal $base_path $env.PWD "next wraps at end of list" assert equal $base_path $env.PWD "next wraps at end of list"
dirs prev 1 dirs prev 1
assert equal $path_a $env.PWD "prev wraps at start of list" assert equal $path_a $env.PWD "prev wraps at start of list"
dirs drop dirs drop
assert length $env.DIRS_LIST 2 "drop removes from list" assert length $env.DIRS_LIST 2 "drop removes from list"
assert equal $base_path $env.PWD "drop changes PWD to next in list (after dropped element)" assert equal $base_path $env.PWD "drop changes PWD to next in list (after dropped element)"
assert equal (dirs show) [[active path]; [true $base_path] [false $path_b]] "show table contains expected information" assert equal (dirs show) [[active path]; [true $base_path] [false $path_b]] "show table contains expected information"
} catch { |error|
clean $base_path
let error = (
$error
| get debug
| str replace "{" "("
| str replace "}" ")"
| parse 'GenericError("{msg}", "{text}", Some(Span ( start: {start}, end: {end} )), {rest})'
| reject rest
| get 0
)
error make {
msg: $error.msg
label: {
text: $error.text
start: ($error.start | into int)
end: ($error.end | into int)
}
}
}
try { clean $base_path }
} }

View File

@ -0,0 +1,32 @@
use std "log debug"
use std "log error"
use std "assert"
use std "assert skip"
export def setup [] {
log debug "Setup is running"
{msg: "This is the context"}
}
export def teardown [] {
log debug $"Teardown is running. Context: ($in)"
}
export def test_assert_pass [] {
log debug $"Assert is running. Context: ($in)"
}
export def test_assert_skip [] {
log debug $"Assert is running. Context: ($in)"
assert skip
}
export def test_assert_fail_skipped_by_default [] {
assert skip # Comment this line if you want to see what happens if a test fails
log debug $"Assert is running. Context: ($in)"
assert false
}
export def unrelated [] {
log error "This should not run"
}

View File

@ -3,8 +3,23 @@ use std "xupdate"
use std "xinsert" use std "xinsert"
use std "assert equal" use std "assert equal"
export def setup [] {
{sample_xml: ('
<a>
<b>
<c a="b"></c>
</b>
<c></c>
<d>
<e>z</e>
<e>x</e>
</d>
</a>' | from xml)
}
}
export def test_xml_xaccess [] { export def test_xml_xaccess [] {
let sample_xml = ('<a><b><c a="b"></c></b><c></c><d><e>z</e><e>x</e></d></a>' | from xml) let sample_xml = $in.sample_xml
assert equal ($sample_xml | xaccess [a]) [$sample_xml] assert equal ($sample_xml | xaccess [a]) [$sample_xml]
assert equal ($sample_xml | xaccess [*]) [$sample_xml] assert equal ($sample_xml | xaccess [*]) [$sample_xml]
@ -14,7 +29,7 @@ export def test_xml_xaccess [] {
} }
export def test_xml_xupdate [] { export def test_xml_xupdate [] {
let sample_xml = ('<a><b><c a="b"></c></b><c></c><d><e>z</e><e>x</e></d></a>' | from xml) let sample_xml = $in.sample_xml
assert equal ($sample_xml | xupdate [*] {|x| $x | update attributes {i: j}}) ('<a i="j"><b><c a="b"></c></b><c></c><d><e>z</e><e>x</e></d></a>' | from xml) assert equal ($sample_xml | xupdate [*] {|x| $x | update attributes {i: j}}) ('<a i="j"><b><c a="b"></c></b><c></c><d><e>z</e><e>x</e></d></a>' | from xml)
assert equal ($sample_xml | xupdate [* d e *] {|x| $x | update content 'nushell'}) ('<a><b><c a="b"></c></b><c></c><d><e>nushell</e><e>nushell</e></d></a>' | from xml) assert equal ($sample_xml | xupdate [* d e *] {|x| $x | update content 'nushell'}) ('<a><b><c a="b"></c></b><c></c><d><e>nushell</e><e>nushell</e></d></a>' | from xml)
@ -22,7 +37,7 @@ export def test_xml_xupdate [] {
} }
export def test_xml_xinsert [] { export def test_xml_xinsert [] {
let sample_xml = ('<a><b><c a="b"></c></b><c></c><d><e>z</e><e>x</e></d></a>' | from xml) let sample_xml = $in.sample_xml
assert equal ($sample_xml | xinsert [a] {tag: b attributes:{} content: []}) ('<a><b><c a="b"></c></b><c></c><d><e>z</e><e>x</e></d><b></b></a>' | from xml) assert equal ($sample_xml | xinsert [a] {tag: b attributes:{} content: []}) ('<a><b><c a="b"></c></b><c></c><d><e>z</e><e>x</e></d><b></b></a>' | from xml)
assert equal ($sample_xml | xinsert [a d *] {tag: null attributes: null content: 'n'} | to xml) '<a><b><c a="b"></c></b><c></c><d><e>zn</e><e>xn</e></d></a>' assert equal ($sample_xml | xinsert [a d *] {tag: null attributes: null content: 'n'} | to xml) '<a><b><c a="b"></c></b><c></c><d><e>zn</e><e>xn</e></d></a>'