summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Lin <anselor@gmail.com>2020-07-21 16:36:31 -0400
committeranselor <anselor@gmail.com>2020-08-04 13:38:08 -0400
commit372676d479dff8bb07f9361deddd63b17ce7c9d3 (patch)
tree6e10d6de68c693928c045a57f369c65aac6014e5
parent65136e9222ada9485f1313fc7bb3e189f060b8d5 (diff)
downloadcmd2-git-372676d479dff8bb07f9361deddd63b17ce7c9d3.tar.gz
Moved commandset tests into an isolated test
-rw-r--r--isolated_tests/test_commandset/__init__.py3
-rw-r--r--isolated_tests/test_commandset/conftest.py196
-rw-r--r--isolated_tests/test_commandset/test_commandset.py (renamed from tests/test_commandset.py)0
-rw-r--r--tasks.py11
4 files changed, 208 insertions, 2 deletions
diff --git a/isolated_tests/test_commandset/__init__.py b/isolated_tests/test_commandset/__init__.py
new file mode 100644
index 00000000..037f3866
--- /dev/null
+++ b/isolated_tests/test_commandset/__init__.py
@@ -0,0 +1,3 @@
+#
+# -*- coding: utf-8 -*-
+#
diff --git a/isolated_tests/test_commandset/conftest.py b/isolated_tests/test_commandset/conftest.py
new file mode 100644
index 00000000..5b1a6f05
--- /dev/null
+++ b/isolated_tests/test_commandset/conftest.py
@@ -0,0 +1,196 @@
+# coding=utf-8
+"""
+Cmd2 unit/functional testing
+"""
+import sys
+from contextlib import redirect_stderr, redirect_stdout
+from typing import List, Optional, Union
+from unittest import mock
+
+from pytest import fixture
+
+import cmd2
+from cmd2.utils import StdSim
+
+# Prefer statically linked gnureadline if available (for macOS compatibility due to issues with libedit)
+try:
+ import gnureadline as readline
+except ImportError:
+ # Try to import readline, but allow failure for convenience in Windows unit testing
+ # Note: If this actually fails, you should install readline on Linux or Mac or pyreadline on Windows
+ try:
+ # noinspection PyUnresolvedReferences
+ import readline
+ except ImportError:
+ pass
+
+
+def verify_help_text(cmd2_app: cmd2.Cmd,
+ help_output: Union[str, List[str]],
+ verbose_strings: Optional[List[str]] = None) -> None:
+ """This function verifies that all expected commands are present in the help text.
+
+ :param cmd2_app: instance of cmd2.Cmd
+ :param help_output: output of help, either as a string or list of strings
+ :param verbose_strings: optional list of verbose strings to search for
+ """
+ if isinstance(help_output, str):
+ help_text = help_output
+ else:
+ help_text = ''.join(help_output)
+ commands = cmd2_app.get_visible_commands()
+ for command in commands:
+ assert command in help_text
+
+ if verbose_strings:
+ for verbose_string in verbose_strings:
+ assert verbose_string in help_text
+
+
+# Help text for the history command
+HELP_HISTORY = """Usage: history [-h] [-r | -e | -o FILE | -t TRANSCRIPT_FILE | -c] [-s] [-x]
+ [-v] [-a]
+ [arg]
+
+View, run, edit, save, or clear previously entered commands
+
+positional arguments:
+ arg empty all history items
+ a one history item by number
+ a..b, a:b, a:, ..b items by indices (inclusive)
+ string items containing string
+ /regex/ items matching regular expression
+
+optional arguments:
+ -h, --help show this help message and exit
+ -r, --run run selected history items
+ -e, --edit edit and then run selected history items
+ -o, --output_file FILE
+ output commands to a script file, implies -s
+ -t, --transcript TRANSCRIPT_FILE
+ output commands and results to a transcript file,
+ implies -s
+ -c, --clear clear all history
+
+formatting:
+ -s, --script output commands in script format, i.e. without command
+ numbers
+ -x, --expanded output fully parsed commands with any aliases and
+ macros expanded, instead of typed commands
+ -v, --verbose display history and include expanded commands if they
+ differ from the typed command
+ -a, --all display all commands, including ones persisted from
+ previous sessions
+"""
+
+# Output from the shortcuts command with default built-in shortcuts
+SHORTCUTS_TXT = """Shortcuts for other commands:
+!: shell
+?: help
+@: run_script
+@@: _relative_run_script
+"""
+
+# Output from the show command with default settings
+SHOW_TXT = """allow_style: 'Terminal'
+debug: False
+echo: False
+editor: 'vim'
+feedback_to_output: False
+max_completion_items: 50
+quiet: False
+timing: False
+"""
+
+SHOW_LONG = """
+allow_style: 'Terminal' # Allow ANSI text style sequences in output (valid values: Terminal, Always, Never)
+debug: False # Show full traceback on exception
+echo: False # Echo command issued into output
+editor: 'vim' # Program used by 'edit'
+feedback_to_output: False # Include nonessentials in '|', '>' results
+max_completion_items: 50 # Maximum number of CompletionItems to display during tab completion
+quiet: False # Don't print nonessential feedback
+timing: False # Report execution times
+"""
+
+
+def normalize(block):
+ """ Normalize a block of text to perform comparison.
+
+ Strip newlines from the very beginning and very end Then split into separate lines and strip trailing whitespace
+ from each line.
+ """
+ assert isinstance(block, str)
+ block = block.strip('\n')
+ return [line.rstrip() for line in block.splitlines()]
+
+
+def run_cmd(app, cmd):
+ """ Clear out and err StdSim buffers, run the command, and return out and err """
+ saved_sysout = sys.stdout
+ sys.stdout = app.stdout
+
+ # This will be used to capture app.stdout and sys.stdout
+ copy_cmd_stdout = StdSim(app.stdout)
+
+ # This will be used to capture sys.stderr
+ copy_stderr = StdSim(sys.stderr)
+
+ try:
+ app.stdout = copy_cmd_stdout
+ with redirect_stdout(copy_cmd_stdout):
+ with redirect_stderr(copy_stderr):
+ app.onecmd_plus_hooks(cmd)
+ finally:
+ app.stdout = copy_cmd_stdout.inner_stream
+ sys.stdout = saved_sysout
+
+ out = copy_cmd_stdout.getvalue()
+ err = copy_stderr.getvalue()
+ return normalize(out), normalize(err)
+
+
+@fixture
+def base_app():
+ return cmd2.Cmd()
+
+
+# These are odd file names for testing quoting of them
+odd_file_names = [
+ 'nothingweird',
+ 'has spaces',
+ '"is_double_quoted"',
+ "'is_single_quoted'"
+]
+
+
+def complete_tester(text: str, line: str, begidx: int, endidx: int, app) -> Optional[str]:
+ """
+ This is a convenience function to test cmd2.complete() since
+ in a unit test environment there is no actual console readline
+ is monitoring. Therefore we use mock to provide readline data
+ to complete().
+
+ :param text: the string prefix we are attempting to match
+ :param line: the current input line with leading whitespace removed
+ :param begidx: the beginning index of the prefix text
+ :param endidx: the ending index of the prefix text
+ :param app: the cmd2 app that will run completions
+ :return: The first matched string or None if there are no matches
+ Matches are stored in app.completion_matches
+ These matches also have been sorted by complete()
+ """
+ def get_line():
+ return line
+
+ def get_begidx():
+ return begidx
+
+ def get_endidx():
+ return endidx
+
+ # Run the readline tab completion function with readline mocks in place
+ with mock.patch.object(readline, 'get_line_buffer', get_line):
+ with mock.patch.object(readline, 'get_begidx', get_begidx):
+ with mock.patch.object(readline, 'get_endidx', get_endidx):
+ return app.complete(text, 0)
diff --git a/tests/test_commandset.py b/isolated_tests/test_commandset/test_commandset.py
index eedf51de..eedf51de 100644
--- a/tests/test_commandset.py
+++ b/isolated_tests/test_commandset/test_commandset.py
diff --git a/tasks.py b/tasks.py
index e5f6e7cb..811e3245 100644
--- a/tasks.py
+++ b/tasks.py
@@ -58,8 +58,15 @@ def pytest(context, junit=False, pty=True):
command_str = 'pytest --cov=cmd2 --cov-report=term --cov-report=html '
if junit:
command_str += ' --junitxml=junit/test-results.xml '
- command_str += ' tests'
- context.run(command_str, pty=pty)
+ tests_cmd = command_str + ' tests'
+ context.run(tests_cmd, pty=pty)
+
+ command_str += ' --cov-append'
+
+ for root, dirnames, _ in os.walk(TASK_ROOT/'isolated_tests'):
+ for dir in dirnames:
+ if dir.startswith('test_'):
+ context.run(command_str + ' isolated_tests/' + dir)
namespace.add_task(pytest)