diff options
author | JensDiemer <git@jensdiemer.de> | 2015-06-02 22:00:03 +0200 |
---|---|---|
committer | JensDiemer <git@jensdiemer.de> | 2015-06-02 22:14:41 +0200 |
commit | a7efad51924df90f38a77cbe59aea3a78b0196e5 (patch) | |
tree | 5c19b46dae5b4b92049447736df1d0dc821eb94b | |
parent | 98809541577b9ea2e6161288929f4dcb76038973 (diff) | |
download | creole-a7efad51924df90f38a77cbe59aea3a78b0196e5.tar.gz |
add some tests for setup.py and...
...refactor subprocess code
-rw-r--r-- | creole/tests/test_cli.py | 67 | ||||
-rw-r--r-- | creole/tests/test_setup.py | 47 | ||||
-rw-r--r-- | creole/tests/test_subprocess.py | 69 | ||||
-rw-r--r-- | creole/tests/utils/unittest_subprocess.py | 82 | ||||
-rwxr-xr-x | setup.py | 40 |
5 files changed, 227 insertions, 78 deletions
diff --git a/creole/tests/test_cli.py b/creole/tests/test_cli.py index 5b40529..380428b 100644 --- a/creole/tests/test_cli.py +++ b/creole/tests/test_cli.py @@ -17,77 +17,14 @@ import sys import os import tempfile -from creole.py3compat import PY3 from creole.tests.utils.base_unittest import BaseCreoleTest from creole import VERSION_STRING - +from creole.tests.utils.unittest_subprocess import SubprocessMixin CMDS = ("creole2html", "html2creole", "html2rest", "html2textile") -class CreoleCLITests(BaseCreoleTest): - CMD_PATH = None - - @classmethod - def setUpClass(cls): - # FIXME: How can this be easier?!? - prog = CMDS[0] - cls.CMD_PATH = os.path.abspath(os.path.dirname(sys.executable)) - if not os.path.isfile(os.path.join(cls.CMD_PATH, prog)): - for path in sys.path: - if os.path.isfile(os.path.join(path, prog)): - cls.CMD_PATH = path - break - - def _subprocess(self, popen_args, verbose=True): - assert isinstance(popen_args, list) - - # set absolute path to called cli program - prog = popen_args[0] - prog = os.path.join(self.CMD_PATH, prog) - self.assertTrue(os.path.isfile(prog), "File not found: %r" % prog) - self.assertTrue(os.access(prog, os.X_OK), "File %r is not executeable?!?" % prog) - popen_args[0] = prog - - if verbose: - print("Call:", popen_args) - - process = subprocess.Popen(popen_args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True, - ) - stdout, stderr = process.communicate() - retcode = process.poll() - - if verbose: - print("return code: %r" % retcode) - print("stdout: %r" % stdout) - print("stderr: %r" % stderr) - - stdout = stdout.strip() - return popen_args, retcode, stdout - - def assertSubprocess(self, popen_args, retcode, stdout, verbose=True): - popen_args2, retcode2, stdout2 = self._subprocess(popen_args, verbose) - try: - self.assertEqual(stdout, stdout2, "stdout wrong:") - self.assertEqual(retcode, retcode2, "return code wrong:") - except AssertionError as err: - msg = ( - "Error: %s" - "call via subprocess: %s\n" - "return code........: %r\n" - " ---------- [stdout] ---------- \n" - "%s\n" - "-------------------------------" - ) % ( - err, - repr(popen_args2), retcode2, - stdout2, - ) - self.fail(msg) - +class CreoleCLITests(BaseCreoleTest, SubprocessMixin): def _test_convert(self, source_content, dest_content, cli_str, verbose=True): assert isinstance(source_content, bytes), type(source_content) assert isinstance(dest_content, bytes), type(dest_content) diff --git a/creole/tests/test_setup.py b/creole/tests/test_setup.py new file mode 100644 index 0000000..52524dc --- /dev/null +++ b/creole/tests/test_setup.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# coding: utf-8 + +""" + unittest for CLI + ~~~~~~~~~~~~~~~~ + + :copyleft: 2013-2015 by python-creole team, see AUTHORS for more details. + :license: GNU GPL v3 or above, see LICENSE for more details. +""" + +from __future__ import division, absolute_import, print_function, unicode_literals + +import unittest +import sys +import os + +import creole +from creole.tests.utils.unittest_subprocess import SubprocessMixin + + +class TestSetup(unittest.TestCase, SubprocessMixin): + @classmethod + def setUpClass(cls): + cls.setup_path = os.path.join(os.path.dirname(creole.__file__), "..", "setup.py") + + def test_setup_path(self): + if not os.path.isfile(self.setup_path): + self.fail("Can't find setup.py: %r doesn't exist" % self.setup_path) + + def test_version(self): + self.assertSubprocess( + popen_args=(sys.executable, self.setup_path, "--version"), + retcode=0, + stdout=creole.VERSION_STRING, + verbose=True + ) + + def test_nose_hint(self): + popen_args, retcode, stdout = self.subprocess( + popen_args=(sys.executable, self.setup_path, "test"), + verbose=False, + ) + self.assertIn("Please use 'nosetests'", stdout) + self.assertNotEqual(retcode, 0) + + diff --git a/creole/tests/test_subprocess.py b/creole/tests/test_subprocess.py new file mode 100644 index 0000000..6babded --- /dev/null +++ b/creole/tests/test_subprocess.py @@ -0,0 +1,69 @@ +# coding: utf-8 + +""" + unittest + ~~~~~~~~ + + :copyleft: 2015 by python-creole team, see AUTHORS for more details. + :license: GNU GPL v3 or above, see LICENSE for more details. +""" + +from __future__ import division, absolute_import, print_function, unicode_literals + +import unittest +import sys +import os + +from creole.tests.utils.unittest_subprocess import SubprocessMixin + + +class TestSubprocessMixin(unittest.TestCase, SubprocessMixin): + def test_find_executable(self): + filepath = self.find_executable("python") + if not hasattr(self, "assertRegex"): # New in version 3.1 + self.assertRegex = self.assertRegexpMatches + self.assertRegex(filepath, ".*?python.*?") + + def test_executable_not_exists(self): + with self.assertRaisesRegexp(AssertionError, """Program "doesn't exists!" not found in:.*"""): + self.find_executable("doesn't exists!") + + def test_executable_with_path(self): + msg = "'%s' unexpectedly found in '%s'" % ( + os.sep, sys.executable + ) + with self.assertRaisesRegexp(AssertionError, msg): + self.find_executable(sys.executable) + + def test_subprocess(self): + popen_args, retcode, stdout = self.subprocess( + popen_args=[sys.executable, "-c", "import sys;sys.stdout.write('to stdout')"], + verbose=False + ) + self.assertEqual(stdout, "to stdout") + self.assertEqual(retcode, 0) + + def test_assertSubprocess(self): + code = ( + "import sys;" + "sys.stdout.write('to stdout 1\\n');" + "sys.stdout.flush();" + "sys.stderr.write('to stderr 1\\n');" + "sys.stderr.flush();" + "sys.stdout.write('to stdout 2\\n');" + "sys.stdout.flush();" + "sys.stderr.write('to stderr 2\\n');" + "sys.stderr.flush();" + ) + self.assertSubprocess( + popen_args=(sys.executable, "-c", code), + retcode=0, + stdout=( + "to stdout 1\n" + "to stderr 1\n" + "to stdout 2\n" + "to stderr 2\n" + ), + verbose=True + ) + diff --git a/creole/tests/utils/unittest_subprocess.py b/creole/tests/utils/unittest_subprocess.py new file mode 100644 index 0000000..bca3779 --- /dev/null +++ b/creole/tests/utils/unittest_subprocess.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +""" + unittest subprocess helper + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyleft: 2015 by python-creole team, see AUTHORS for more details. + :license: GNU GPL v3 or above, see LICENSE for more details. +""" + +from __future__ import print_function, unicode_literals + +import json +import os +import subprocess +import sys + + +class SubprocessMixin(object): + # call .../env/bin/python will not add the .../env/bin/ to the PATH + SEARCH_PATH=[os.path.dirname(sys.executable)] + os.environ.get("PATH", "").split(os.pathsep) + + def find_executable(self, program): + self.assertNotIn(os.sep, program) + for path in self.SEARCH_PATH: + filepath = os.path.join(path, program) + if os.path.isfile(filepath): + if not os.access(filepath, os.X_OK): + sys.stderr.write("File %r is not executable?!?\n" % filepath) + else: + return filepath + + self.fail("Program %s not found in:\n\t* %s" % (json.dumps(program), "\n\t* ".join(self.SEARCH_PATH))) + + def subprocess(self, popen_args, verbose=True): + assert isinstance(popen_args, (tuple, list)) + + if verbose: + print("Call:", popen_args) + + try: + process = subprocess.Popen(popen_args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + ) + except Exception as err: + self.fail("Error subprocess call with %r: %s" % (popen_args, err)) + + stdout, stderr = process.communicate() + retcode = process.poll() + + if verbose: + print("return code: %r" % retcode) + print("stdout: %r" % stdout) + print("stderr: %r" % stderr) + + stdout = stdout.strip() + return popen_args, retcode, stdout + + def assertSubprocess(self, popen_args, retcode, stdout, verbose=True): + popen_args2, retcode2, stdout2 = self.subprocess(popen_args, verbose) + stdout = stdout.strip() + try: + self.assertEqual(stdout, stdout2, "stdout wrong:") + self.assertEqual(retcode, retcode2, "return code wrong:") + except AssertionError as err: + msg = ( + "Error: %s" + "call via subprocess: %s\n" + "return code........: %r\n" + " ---------- [stdout] ---------- \n" + "%s\n" + "-------------------------------" + ) % ( + err, + repr(popen_args2), retcode2, + stdout2, + ) + self.fail(msg) + + @@ -21,8 +21,11 @@ from creole.setup_utils import get_long_description PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__)) + if "publish" in sys.argv: try: + # Test if wheel is installed, otherwise the user will only see: + # error: invalid command 'bdist_wheel' import wheel except ImportError as err: print("\nError: %s" % err) @@ -43,20 +46,11 @@ if "publish" in sys.argv: sys.exit() -def get_authors(): - try: - with open(os.path.join(PACKAGE_ROOT, "AUTHORS"), "r") as f: - authors = [l.strip(" *\r\n") for l in f if l.strip().startswith("*")] - except Exception: - evalue = sys.exc_info()[1] - authors = "[Error: %s]" % evalue - return authors - - -if "test" in sys.argv: +if "test" in sys.argv or "nosetests" in sys.argv: """ - nose is a optional dependency, so test import - if user run with: './setup.py test' + nose is a optional dependency, so test import. + Otherwise the user get only the error: + error: invalid command 'nosetests' """ try: import nose @@ -66,7 +60,24 @@ if "test" in sys.argv: print("e.g.:") print(" ~/your/env/$ source bin/activate") print(" ~/your/env/$ pip install nose") + print(" ~/your/env/$ ./setup.py nosetests\n") sys.exit(-1) + else: + if "test" in sys.argv: + print("\nPlease use 'nosetests' instead of 'test' to cover all tests!\n") + print("e.g.:") + print(" $ ./setup.py nosetests\n") + sys.exit(-1) + + +def get_authors(): + try: + with open(os.path.join(PACKAGE_ROOT, "AUTHORS"), "r") as f: + authors = [l.strip(" *\r\n") for l in f if l.strip().startswith("*")] + except Exception: + evalue = sys.exc_info()[1] + authors = "[Error: %s]" % evalue + return authors setup( @@ -89,6 +100,9 @@ setup( "html2textile = creole.cmdline:cli_html2textile", ], }, + tests_require=[ + "nose", # https://pypi.python.org/pypi/nose + ], zip_safe=True, # http://packages.python.org/distribute/setuptools.html#setting-the-zip-safe-flag keywords="creole markup creole2html html2creole rest2html html2rest html2textile", classifiers=[ |