summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Ceratto <federico.ceratto@gmail.com>2016-02-23 23:55:58 +0000
committerFederico Ceratto <federico.ceratto@gmail.com>2016-02-23 23:55:58 +0000
commit24e841d5e002442115e3d7a045742fbd8a05477f (patch)
tree45e47959e46168def43e5eda4c83dd0a9da70071
parentd37d349a1a0319f9735af9ffdf6bd976f6f41ee9 (diff)
downloadcmd2-git-24e841d5e002442115e3d7a045742fbd8a05477f.tar.gz
Add unit tests
-rw-r--r--tests/conftest.py45
-rw-r--r--tests/test_cmd2.py187
-rw-r--r--tests/test_transcript.py167
-rw-r--r--tox.ini7
4 files changed, 405 insertions, 1 deletions
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 00000000..55700914
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,45 @@
+#
+# Cmd2 unit/functional testing
+#
+# Copyright 2016 Federico Ceratto <federico.ceratto@gmail.com>
+# Released under MIT license, see LICENSE file
+
+from pytest import fixture
+
+import cmd2
+
+
+class StdOut(object):
+ def __init__(self):
+ self.clear()
+
+ def write(self, s):
+ self.buffer += s
+
+ def read(self):
+ raise NotImplementedError
+
+ def clear(self):
+ self.buffer = ''
+
+
+def _normalize(block):
+ # normalize a block of text to perform comparison
+ assert isinstance(block, str)
+ block = block.strip('\n')
+ return [line.rstrip() for line in block.splitlines()]
+
+
+def run_cmd(app, cmd):
+ app.stdout.clear()
+ app.onecmd_plus_hooks(cmd)
+ out = app.stdout.buffer
+ app.stdout.clear()
+ return _normalize(out)
+
+
+@fixture
+def base_app():
+ c = cmd2.Cmd()
+ c.stdout = StdOut()
+ return c
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
new file mode 100644
index 00000000..8435ac1a
--- /dev/null
+++ b/tests/test_cmd2.py
@@ -0,0 +1,187 @@
+#
+# Cmd2 unit/functional testing
+#
+# Copyright 2016 Federico Ceratto <federico.ceratto@gmail.com>
+# Released under MIT license, see LICENSE file
+
+import mock
+import pytest
+
+from conftest import run_cmd, _normalize
+import cmd2
+
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+
+def test_ver():
+ assert cmd2.__version__ == '0.6.9a'
+
+
+def test_base_help(base_app):
+ out = run_cmd(base_app, 'help')
+ expected = _normalize("""
+Documented commands (type help <topic>):
+========================================
+_load ed history list py save shortcuts
+_relative_load edit l load r set show
+cmdenvironment hi li pause run shell
+
+Undocumented commands:
+======================
+EOF eof exit help q quit
+""")
+ assert out == expected
+
+
+def test_base_help_history(base_app):
+ out = run_cmd(base_app, 'help history')
+ expected = _normalize("""
+history [arg]: lists past commands issued
+
+ | no arg: list all
+ | arg is integer: list one history item, by index
+ | arg is string: string search
+ | arg is /enclosed in forward-slashes/: regular expression search
+
+Usage: history [options] (limit on which commands to include)
+
+Options:
+ -h, --help show this help message and exit
+ -s, --script Script format; no separation lines
+""")
+ assert out == expected
+
+
+def test_base_shortcuts(base_app):
+ out = run_cmd(base_app, 'shortcuts')
+ expected = _normalize("""
+Single-key shortcuts for other commands:
+!: shell
+?: help
+@: load
+@@: _relative_load
+""")
+ assert out == expected
+
+
+def notest_base_(base_app):
+ out = run_cmd(base_app, 'shortcuts')
+ expected = _normalize("""
+""")
+ assert out == expected
+
+
+def test_base_show(base_app):
+ out = run_cmd(base_app, 'show')
+ expected = _normalize("""
+abbrev: True
+case_insensitive: True
+colors: True
+continuation_prompt: >
+debug: False
+default_file_name: command.txt
+echo: False
+feedback_to_output: False
+prompt: (Cmd)
+quiet: False
+timing: False
+""")
+ # ignore "editor: vi" (could be others)
+ out = [l for l in out if not l.startswith('editor: ')]
+ assert out == expected
+
+
+def test_base_set(base_app):
+ out = run_cmd(base_app, 'set quiet True')
+ expected = _normalize("""
+quiet - was: False
+now: True
+""")
+ assert out == expected
+
+ out = run_cmd(base_app, 'show quiet')
+ assert out == ['quiet: True']
+
+
+def test_base_set_not_supported(base_app):
+ out = run_cmd(base_app, 'set qqq True')
+ assert out == []
+ # TODO: check stderr
+
+
+def test_base_shell(base_app, monkeypatch):
+ m = mock.Mock()
+ monkeypatch.setattr("os.system", m)
+ out = run_cmd(base_app, 'shell echo a')
+ assert out == []
+ assert m.called
+ m.assert_called_with('echo a')
+
+
+def test_base_py(base_app):
+ out = run_cmd(base_app, 'py qqq=3')
+ assert out == []
+ out = run_cmd(base_app, 'py print qqq')
+ assert out == []
+ # TODO: check stderr
+
+
+def test_base_error(base_app):
+ out = run_cmd(base_app, 'meow')
+ assert out == ["*** Unknown syntax: meow"]
+
+
+def test_base_history(base_app):
+ run_cmd(base_app, 'help')
+ run_cmd(base_app, 'shortcuts')
+ out = run_cmd(base_app, 'history')
+ expected = _normalize("""
+-------------------------[1]
+help
+-------------------------[2]
+shortcuts
+""")
+ assert out == expected
+
+ out = run_cmd(base_app, 'history he')
+ expected = _normalize("""
+-------------------------[1]
+help
+""")
+ assert out == expected
+
+ out = run_cmd(base_app, 'history sh')
+ expected = _normalize("""
+-------------------------[2]
+shortcuts
+""")
+ assert out == expected
+
+
+def test_base_list(base_app):
+ run_cmd(base_app, 'help')
+ run_cmd(base_app, 'shortcuts')
+ out = run_cmd(base_app, 'list')
+ expected = _normalize("""
+-------------------------[2]
+shortcuts
+""")
+ assert out == expected
+
+
+@pytest.mark.xfail
+def test_base_load(base_app):
+ base_app.read_file_or_url = mock.Mock(
+ return_value=StringIO('set quiet True\n')
+ )
+ out = run_cmd(base_app, 'load myfname')
+ expected = _normalize("""
+quiet - was: False
+now: True
+""")
+ assert out == expected
+
+
diff --git a/tests/test_transcript.py b/tests/test_transcript.py
new file mode 100644
index 00000000..06cf50b6
--- /dev/null
+++ b/tests/test_transcript.py
@@ -0,0 +1,167 @@
+#
+# Cmd2 functional testing based on transcript
+#
+# Copyright 2016 Federico Ceratto <federico.ceratto@gmail.com>
+# Released under MIT license, see LICENSE file
+
+import pytest
+
+from cmd2 import Cmd, make_option, options
+from conftest import run_cmd, StdOut, _normalize
+
+
+class CmdLineApp(Cmd):
+ multilineCommands = ['orate']
+ maxrepeats = 3
+ redirector = '->'
+
+ opts = [
+ make_option('-p', '--piglatin', action="store_true", help="atinLay"),
+ make_option('-s', '--shout', action="store_true",
+ help="N00B EMULATION MODE"),
+ make_option('-r', '--repeat', type="int", help="output [n] times")
+ ]
+
+ @options(opts, arg_desc='(text to say)')
+ def do_speak(self, arg, opts=None):
+ """Repeats what you tell me to."""
+ arg = ''.join(arg)
+ if opts.piglatin:
+ arg = '%s%say' % (arg[1:].rstrip(), arg[0])
+ if opts.shout:
+ arg = arg.upper()
+ repetitions = opts.repeat or 1
+ for i in range(min(repetitions, self.maxrepeats)):
+ self.stdout.write(arg)
+ self.stdout.write('\n')
+ # self.stdout.write is better than "print", because Cmd can be
+ # initialized with a non-standard output destination
+
+ do_say = do_speak # now "say" is a synonym for "speak"
+ do_orate = do_speak # another synonym, but this one takes multi-line input
+
+
+@pytest.fixture
+def _cmdline_app():
+ c = CmdLineApp()
+ c.stdout = StdOut()
+ #c.shortcuts.update({'&': 'speak', 'h': 'hello'})
+ c.settable.append('maxrepeats Max number of `--repeat`s allowed')
+ return c
+
+
+def _get_transcript_blocks(transcript):
+ cmd = None
+ expected = ''
+ for line in transcript.splitlines():
+ if line.startswith('(Cmd) '):
+ if cmd is not None:
+ yield cmd, _normalize(expected)
+
+ cmd = line[6:]
+ expected = ''
+ else:
+ expected += line + '\n'
+ yield cmd, _normalize(expected)
+
+
+@pytest.mark.xfail
+def test_base_with_transcript(_cmdline_app):
+ app = _cmdline_app
+ transcript = """
+(Cmd) help
+
+Documented commands (type help <topic>):
+========================================
+_load ed history list pause run set show
+_relative_load edit l load py save shell speak
+cmdenvironment hi li orate r say shortcuts
+
+Undocumented commands:
+======================
+EOF eof exit help q quit
+
+(Cmd) help say
+Repeats what you tell me to.
+Usage: speak [options] (text to say)
+
+Options:
+ -h, --help show this help message and exit
+ -p, --piglatin atinLay
+ -s, --shout N00B EMULATION MODE
+ -r REPEAT, --repeat=REPEAT
+ output [n] times
+
+(Cmd) say goodnight, Gracie
+goodnight, Gracie
+(Cmd) say -ps --repeat=5 goodnight, Gracie
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+(Cmd) set
+abbrev: True
+case_insensitive: True
+colors: True
+continuation_prompt: >
+debug: False
+default_file_name: command.txt
+echo: False
+editor: /\w*/
+feedback_to_output: False
+maxrepeats: 3
+prompt: (Cmd)
+quiet: False
+timing: False
+(Cmd) set maxrepeats 5
+maxrepeats - was: 3
+now: 5
+(Cmd) say -ps --repeat=5 goodnight, Gracie
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+(Cmd) hi
+-------------------------[1]
+help
+-------------------------[2]
+help say
+-------------------------[3]
+say goodnight, Gracie
+-------------------------[4]
+say -ps --repeat=5 goodnight, Gracie
+-------------------------[5]
+set
+-------------------------[6]
+set maxrepeats 5
+-------------------------[7]
+say -ps --repeat=5 goodnight, Gracie
+(Cmd) run 4
+say -ps --repeat=5 goodnight, Gracie
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+OODNIGHT, GRACIEGAY
+(Cmd) orate Four score and
+> seven releases ago
+> our BDFL
+>
+Four score and
+seven releases ago
+our BDFL
+(Cmd) & look, a shortcut!
+look, a shortcut!
+(Cmd) say put this in a file > myfile.txt
+(Cmd) say < myfile.txt
+put this in a file
+(Cmd) set prompt "---> "
+prompt - was: (Cmd)
+now: --->
+---> say goodbye
+goodbye
+"""
+
+ for cmd, expected in _get_transcript_blocks(transcript):
+ out = run_cmd(app, 'help')
+ assert out == expected
diff --git a/tox.ini b/tox.ini
index 2801d30c..ed2d2e12 100644
--- a/tox.ini
+++ b/tox.ini
@@ -2,7 +2,12 @@
envlist = py27,py34,py35,jython,pypy
[testenv]
-deps=pyparsing
+deps =
+ mock
+ pyparsing
+ pytest
commands=
+ py.test -v --basetemp={envtmpdir} {posargs}
{envpython} cmd2.py
{envpython} example/example.py --test example/exampleSession.txt
+