Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

NIGHTMARE

Nightmare Is of Generous Help when Testing; May Arnold be Remembered Eternally

You must really, really love to test!


nightmare is a tool for automatic testing of non-interactive commandline applications.

usage: nightmare-2.0-py2.7.egg [-h] [--bench BENCH] [--suite SUITE]
[--dut DUT] [--test TEST [TEST ...]]
[--timeout TIMEOUT] [--arnold] [--save FILE]
[--limit LIMIT] [--quiet] [--verbose]
[--commands] [--length] [--info-only]
[--pipe-streams] [--output-fails]
[--unify-fails] [--no-color] [--continue]
[--error] [--ignoreEmptyLines] [--relative]
[--cr] [--ln] [--crln] [--gui] [--no-gui]
[--version]
A test tool for non-interactive commandline programms
optional arguments:
-h, --help show this help message and exit
--gui Use the GUI (experimental and unstable).
--no-gui Don't use the GUI.
--version Display version information
Test selection:
--bench BENCH File which contains the testbench.
--suite SUITE Use testsuite SUITE from the testbench.
--dut DUT, --DUT DUT Set the device under test.
--test TEST [TEST ...]
Run only the specified tests
--timeout TIMEOUT Set a global timeout for all tests.
--arnold, -a Use the arnold mode (requires pyparsing module)
--save FILE Save the testsuite as FILE
Output Control:
--limit LIMIT Set a (soft) limit for a number of Bytes, after which
output piping will we stopped. Checks are made after
each line.
--quiet, -q Quiet mode. There will be no output except results.
--verbose, -v Verbose mode. The program gets chatty (default).
--commands, -C Show the command executed for each test.
--length, -l Print only the number of tests in the suite.
--info-only, -i Display only test information, but don't run them.
--pipe-streams, -p Redirect DUT output to their respective streams.
--output-fails, -o Redirect DUT output from failed tests to their
respective streams.
--unify-fails, -u Display the unified diff of output and expectation.
--no-color Don't use any colored output.
Test Flow:
--continue, -c Continuous mode (Don't halt on failed tests).
--error, -e Same as '-c', but will halt if an error occurs.
--ignoreEmptyLines, -L
Ignore empty lines
--relative, -r Use a path relative to the testbench path.
--cr Force the line separation character (Mac OS).
--ln Force the line separation character (Unix / Mac OS-X).
--crln Force the line separation character (Windows).

Additional to the commandline interface there is a GUI using the wxPython. The GUI is limited in its capabilities compared to the CLI, especially when it comes to testbench editing.

Be careful when you save your testbench! You might loose data, if it originates from a handwritten testbench.

Testbench files

A collection of test is called a "testbench". Inside a testbench there are a number of suites grouping tests together.

The testbench files a normal python files, which get evaluated by calling the internal "execfile" function. This might not be the savest approach, but it is definitly one of the easiest ones.

Here is a example for a minimal testbench.

#!/usr/bin/env python
# pyTest - Testsuite
# Saved at 21:12:26
#
# Device Under Test
DUT = "echo"
# Test definitions
suite = [
Test (
name = "Test 1",
description = "A successfull run",
command = "$DUT pyTest",
stdout = "pyTest",
returnCode = 0
),
Test (
name = "Test 2",
description = "Testing output on stderr",
command = "$DUT pyTest 1>&2",
stderr = "pyTest"
)
]

This example contains on testsuite name "suite" with two tests. I hope the syntax is selfexplanatory.

The Pattern $DUT is a substitute for the application that gets tested.

Here's a list of all possible fields in a test definition:

  • name: The (brief) name of the test.
  • description: A longer description, about the purpose of this test.
  • command: The command to be executed.
  • stdout: The expected result on stdout.
  • stderr: The expected result on stderr.
  • returnCode: The expected returncode.
  • timeout: Time in seconds before the process gets automatically killed.

Almost every field in the test is optional expect the command. The reason should be obvious.

One reason for the testfiles to be real python script is the possibility to use lambda functions for testing the output against an expectation.

The following example shows a test using a lambda function:

Test (
name "Lambda",
description = "A test with lambda function",
command = "echo Hello World",
stdout = lambda x : x.find("o") > 0
)

All expectation fields (stdout, stderr, returnCode) may contain lambda a lambda expression.

In addition it is possible to use regular expression as expectation. This is done by a simple "regex:"-prefix followed by the regular expression.

The following example shows a test using a regular expression:

Test (
name "Regex",
description = "A test with regular expression",
command = "echo Hello World",
stdout = "regex:^[a-zA-Z ]+$"
)

In addition nightmare supports so called Expecation-objects as value for stdout and stderr. These classes must have a __call__ method with a single argument, which is the output of the corresponding stream. The method should compare the output with the expectation and return a boolean value.

Another special type are so called Stringifier-objects. They also must implement a __call__ method, but their result is a 2-tuple containing 2 lists of strings, that are passed onto nightmare's internal diff (-u) tool.

There are three predefined Expectations/ Stringifiers:

  • ExpectFile(filename): compares the output byte-wise with a given file.

     Test (
    ...
    stdout = ExpectFile("output.txt")
    )
    
  • Stringifier(object): compares the output with the string-representation of the given object.

     # Assumption: there exists a class Image
    img = Image.read("image.png")
    Test (
    ...
    stdout = Stringifier(img)
    )
    
  • StringifiedFile(filename): loads the contents of a text-file for line by line comparison.

     Test (
    ...
    stdout = StringifiedFile("output.txt")
    )
    

History / Background

The development started in 2012 at FH-Wedel as a addition / replacement to the aging "arnold"-tool, which is a tcl-script. Since I'm a notorious windows user I was annoyed by the fact, that tcl/expect barely works on windows. Being a fan of the python language I decided to develop a new tool which fulfills the same requirements but by using a (in my humble opinion) more modern language.

As part of my job at the FH Wedel it was successfully used as the primary testing tool, to check if the implementation of the programming exercise meet the required specifications. Since "arnold" is an acronym, this tool's name needed to be equally ridiculous. The name "nightmare" was given as a consequence, because most of the students in the exercises absolutely hated the strictness of my tests.

About

nightmare is a tool for automatic testing of non-interactive commandline applications.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages