Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 95e53a8

Browse files
committed
Initial contribution of the cmd2 external test plugin
0 parents  commit 95e53a8

14 files changed

+664
-0
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6+
7+
## 1.0.0 (2020-03-09)
8+
9+
### Added
10+
- Initial contribution
11+
12+

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Jared Crapo
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# cmd2 External Test Plugin
2+
3+
## Table of Contents
4+
5+
- [Overview](#overview)
6+
- [Example cmd2 Application](#example-cmd2-application)
7+
- [Defining the test fixture](#defining-the-test-fixture)
8+
- [Writing Tests](#writing-tests)
9+
- [License](#license)
10+
11+
12+
## Overview
13+
14+
This plugin supports testing of a cmd2 application by exposing access cmd2 commands with the same context
15+
as from within a cmd2 pyscript. This allows for verification of an application's support for pyscripts.
16+
17+
18+
## Example cmd2 Application
19+
20+
The following short example shows how to mix in the external test plugin to create a fixture for testing
21+
your cmd2 application.
22+
23+
Define your cmd2 application
24+
25+
```python
26+
import cmd2
27+
class ExampleApp(cmd2.Cmd):
28+
"""An class to show how to use a plugin"""
29+
def __init__(self, *args, **kwargs):
30+
# gotta have this or neither the plugin or cmd2 will initialize
31+
super().__init__(*args, **kwargs)
32+
33+
def do_something(self, arg):
34+
self.last_result = 5
35+
self.poutput('this is the something command')
36+
```
37+
38+
## Defining the test fixture
39+
40+
In your test, define a fixture for your cmd2 application
41+
42+
```python
43+
import cmd2_ext_test
44+
import pytest
45+
46+
class ExampleAppTester(cmd2_ext_test.ExternalTestMixin, ExampleApp):
47+
def __init__(self, *args, **kwargs):
48+
# gotta have this or neither the plugin or cmd2 will initialize
49+
super().__init__(*args, **kwargs)
50+
51+
@pytest.fixture
52+
def example_app():
53+
app = ExampleAppTester()
54+
return app
55+
```
56+
57+
## Writing Tests
58+
59+
Now write your tests that validate your application using the `app_cmd` function to access
60+
the cmd2 application's commands. This allows invocation of the application's commands in the
61+
same format as a user would type. The results from calling a command matches what is returned
62+
from running an python script with cmd2's pyscript command, which provides stdout, stderr, and
63+
the command's result data.
64+
65+
```python
66+
from cmd2 import CommandResult
67+
68+
def test_something(example_app):
69+
# execute a command
70+
out = example_app.app_cmd("something")
71+
72+
# validate the command output and result data
73+
assert isinstance(out, CommandResult)
74+
assert str(out.stdout).strip() == 'this is the something command'
75+
assert out.data == 5
76+
```
77+
78+
## License
79+
80+
cmd2 [uses the very liberal MIT license](https://github.com/python-cmd2/cmd2/blob/master/LICENSE).
81+
We invite plugin authors to consider doing the same.

build-pyenvs.sh

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env bash
2+
#
3+
4+
# create pyenv environments for each minor version of python
5+
# supported by this project
6+
#
7+
# this script uses terms from Semantic Versioning https://semver.org/
8+
# version numbers are: major.minor.patch
9+
#
10+
# this script will delete and recreate existing virtualenvs named
11+
# cmd2-3.7, etc. It will also create a .python-version
12+
#
13+
# Prerequisites:
14+
# - *nix-ish environment like macOS or Linux
15+
# - pyenv installed
16+
# - pyenv-virtualenv installed
17+
# - readline and openssl libraries installed so pyenv can
18+
# build pythons
19+
#
20+
21+
# Make a array of the python minor versions we want to install.
22+
# Order matters in this list, because it's the order that the
23+
# virtualenvs will be added to '.python-version'. Feel free to modify
24+
# this list, but note that this script intentionally won't install
25+
# dev, rc, or beta python releases
26+
declare -a pythons=("3.7" "3.6" "3.5" "3.4")
27+
28+
# function to find the latest patch of a minor version of python
29+
function find_latest_version {
30+
pyenv install -l | \
31+
sed -En -e "s/^ *//g" -e "/(dev|b|rc)/d" -e "/^$1/p" | \
32+
tail -1
33+
}
34+
35+
# empty out '.python-version'
36+
> .python-version
37+
38+
# loop through the pythons
39+
for minor_version in "${pythons[@]}"
40+
do
41+
patch_version=$( find_latest_version "$minor_version" )
42+
# use pyenv to install the latest versions of python
43+
# if it's already installed don't install it again
44+
pyenv install -s "$patch_version"
45+
46+
envname="cmd2-$minor_version"
47+
# remove the associated virtualenv
48+
pyenv uninstall -f "$envname"
49+
# create a new virtualenv
50+
pyenv virtualenv -p "python$minor_version" "$patch_version" "$envname"
51+
# append the virtualenv to .python-version
52+
echo "$envname" >> .python-version
53+
done

cmd2_ext_test/__init__.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#
2+
# coding=utf-8
3+
"""Description of myplugin
4+
5+
An overview of what myplugin does.
6+
"""
7+
8+
from pkg_resources import get_distribution, DistributionNotFound
9+
10+
from .cmd2_ext_test import ExternalTestMixin
11+
12+
try:
13+
__version__ = get_distribution(__name__).version
14+
except DistributionNotFound:
15+
__version__ = 'unknown'

cmd2_ext_test/cmd2_ext_test.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# coding=utf-8
3+
"""External test interface plugin"""
4+
5+
from typing import Optional
6+
7+
import cmd2
8+
9+
10+
class ExternalTestMixin:
11+
"""A cmd2 plugin (mixin class) that exposes an interface to execute application commands from python"""
12+
13+
def __init__(self, *args, **kwargs):
14+
# code placed here runs before cmd2 initializes
15+
super().__init__(*args, **kwargs)
16+
# code placed here runs after cmd2 initializes
17+
self._pybridge = cmd2.py_bridge.PyBridge(self)
18+
19+
def app_cmd(self, command: str, echo: Optional[bool] = None) -> cmd2.CommandResult:
20+
"""
21+
Run the application command
22+
:param command: The application command as it would be written on the cmd2 application prompt
23+
:param echo: Flag whether the command's output should be echoed to stdout/stderr
24+
:return: A CommandResult object that captures stdout, stderr, and the command's result object
25+
"""
26+
try:
27+
self._in_py = True
28+
29+
return self._pybridge(command, echo)
30+
31+
finally:
32+
self._in_py = False

cmd2_ext_test/pylintrc

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# pylint configuration
3+
#
4+
# $ pylint --rcfile=cmd2_myplugin/pylintrc cmd2_myplugin
5+
#
6+
7+
[messages control]
8+
# too-few-public-methods pylint expects a class to have at
9+
# least two public methods
10+
disable=too-few-public-methods

examples/example.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# coding=utf-8
3+
# import cmd2
4+
import cmd2
5+
import cmd2_ext_test
6+
import cmd2.py_bridge
7+
8+
9+
class Example(cmd2.Cmd):
10+
"""An class to show how to use a plugin"""
11+
def __init__(self, *args, **kwargs):
12+
# gotta have this or neither the plugin or cmd2 will initialize
13+
super().__init__(*args, **kwargs)
14+
15+
def do_something(self, arg):
16+
self.last_result = 5
17+
self.poutput('this is the something command')
18+
19+
20+
class ExampleTester(cmd2_ext_test.ExternalTestMixin, Example):
21+
def __init__(self, *args, **kwargs):
22+
# gotta have this or neither the plugin or cmd2 will initialize
23+
super().__init__(*args, **kwargs)
24+
25+
26+
if __name__ == '__main__':
27+
app = ExampleTester()
28+
29+
out = app.app_cmd("something")
30+
assert isinstance(out, cmd2.CommandResult)
31+
32+
assert out.data == 5

setup.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#
2+
# coding=utf-8
3+
4+
import os
5+
import setuptools
6+
7+
#
8+
# get the long description from the README file
9+
here = os.path.abspath(os.path.dirname(__file__))
10+
with open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
11+
long_description = f.read()
12+
13+
setuptools.setup(
14+
name='cmd2-ext-test',
15+
use_scm_version=True,
16+
17+
description='External test plugin for cmd2. Allows for external invocation of commands as if from a cmd2 pyscript',
18+
long_description=long_description,
19+
long_description_content_type='text/markdown',
20+
keywords='cmd2 test plugin',
21+
22+
author='Eric Lin',
23+
author_email='[email protected]',
24+
url='https://github.com/python-cmd2/cmd2-ext-test',
25+
license='MIT',
26+
27+
packages=['cmd2_ext_test'],
28+
29+
python_requires='>=3.4',
30+
install_requires=['cmd2 >= 0.9.4, <=2'],
31+
setup_requires=['setuptools_scm'],
32+
33+
classifiers=[
34+
'Development Status :: 4 - Beta',
35+
'Environment :: Console',
36+
'Operating System :: OS Independent',
37+
'Topic :: Software Development :: Libraries :: Python Modules',
38+
'Intended Audience :: Developers',
39+
'License :: OSI Approved :: MIT License',
40+
'Programming Language :: Python :: 3.4',
41+
'Programming Language :: Python :: 3.5',
42+
'Programming Language :: Python :: 3.6',
43+
'Programming Language :: Python :: 3.7',
44+
],
45+
46+
# dependencies for development and testing
47+
# $ pip install -e .[dev]
48+
extras_require={
49+
'dev': ['setuptools_scm', 'pytest', 'codecov', 'pytest-cov',
50+
'pylint', 'invoke', 'wheel', 'twine']
51+
},
52+
)

0 commit comments

Comments
 (0)