From 7fdd0b21b980fe529358337c9238bf4b54900196 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 21 Dec 2017 11:31:40 -0700 Subject: [PATCH 1/6] Add a tests package. --- tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/__init__.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b From 58f3a0e5ed49b7f12f4fb9a9472edb09fecc5821 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 19 Dec 2017 13:02:42 -0700 Subject: [PATCH 2/6] Add a __main__ for running the test suite. --- tests/__main__.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/__main__.py diff --git a/tests/__main__.py b/tests/__main__.py new file mode 100644 index 00000000..8df0e6f4 --- /dev/null +++ b/tests/__main__.py @@ -0,0 +1,30 @@ + +import os +import os.path +from unittest.main import main +import sys + + +TEST_ROOT = os.path.dirname(__file__) +PROJECT_ROOT = os.path.dirname(TEST_ROOT) + +executable = 'python3 -m unittest' + +if all(arg.startswith('-') for arg in sys.argv[1:]): + argv = [executable, + 'discover', + '--start-directory', PROJECT_ROOT, + '--top-level-directory', PROJECT_ROOT, + ] + sys.argv[1:] +else: + argv = [executable] + sys.argv[1:] + for i, arg in enumerate(argv[1:], 1): + if arg.startswith('-'): + continue + mod, _, test = arg.partition(':') + mod = mod.rstrip(os.sep) + mod = mod.rstrip('.py') + mod = mod.replace(os.sep, '.') + argv[i] = mod if not test else mod + '.' + test + +main(module=None, argv=argv) From 3d6b05b3ccd2ff9d907bae2eeead07ef64a48128 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jan 2018 19:21:50 +0000 Subject: [PATCH 3/6] Add a make file for dev tasks. --- Makefile | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..89a9908f --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +PYTHON ?= python3 + +.PHONY: help +help: ## Print help about available targets. + @grep -h -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' + +.PHONY: depends +depends: + $(PYTHON) -m pip install flake8 + $(PYTHON) -m pip install coverage + +.PHONY: lint +lint: + $(PYTHON) -m flake8 --ignore E24,E121,E123,E125,E126,E221,E226,E266,E704,E265 $(CURDIR) + +.PHONY: test +test: ## Run the test suite. + $(PYTHON) -m tests + +.PHONY: coverage +coverage: ## Check line coverage. + $(PYTHON) -m coverage run -m tests From e3d1732fccd15d125f5ba768ef6d6fc9f343c35d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jan 2018 19:22:10 +0000 Subject: [PATCH 4/6] Add TravisCI support. --- .travis.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..47775a2b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,25 @@ +language: python +cache: pip +python: + - "2.7" + - "3.6" + +matrix: + include: + - python: 3.6 + env: TARGET=lint + - python: 3.6 + env: TARGET=coverage + after_success: + - if [ $TRAVIS_UPLOAD_COVERAGE == "true" ]; then + bash <(curl -s https://codecov.io/bash); + fi + - python: 2.7 + env: TARGET=test + +install: + - make depends + +script: + #- make $TARGET PYTHON=python$TRAVIS_PYTHON_VERSION + - make $TARGET PYTHON=$TRAVIS_PYTHON_PATH From dc00f36e3ea1f36c66ef82f22292d2e428c3b784 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 9 Jan 2018 16:41:19 +0000 Subject: [PATCH 5/6] Do not hard-code Python 3. --- tests/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/__main__.py b/tests/__main__.py index 8df0e6f4..214121d1 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -8,8 +8,8 @@ import sys TEST_ROOT = os.path.dirname(__file__) PROJECT_ROOT = os.path.dirname(TEST_ROOT) -executable = 'python3 -m unittest' +executable = sys.executable + ' -m unittest' if all(arg.startswith('-') for arg in sys.argv[1:]): argv = [executable, 'discover', From 9a61a4eba622018a6cee0e820f8f4b5d58fd8cd4 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 9 Jan 2018 18:21:51 +0000 Subject: [PATCH 6/6] Factor out convert_argv(). --- tests/__main__.py | 52 +++++++++++++++++++++++++---------------- tests/test_test_main.py | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 tests/test_test_main.py diff --git a/tests/__main__.py b/tests/__main__.py index 214121d1..c61e50ca 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -1,30 +1,42 @@ - import os import os.path -from unittest.main import main import sys +import unittest TEST_ROOT = os.path.dirname(__file__) PROJECT_ROOT = os.path.dirname(TEST_ROOT) -executable = sys.executable + ' -m unittest' -if all(arg.startswith('-') for arg in sys.argv[1:]): - argv = [executable, - 'discover', - '--start-directory', PROJECT_ROOT, - '--top-level-directory', PROJECT_ROOT, - ] + sys.argv[1:] -else: - argv = [executable] + sys.argv[1:] - for i, arg in enumerate(argv[1:], 1): - if arg.startswith('-'): - continue - mod, _, test = arg.partition(':') - mod = mod.rstrip(os.sep) - mod = mod.rstrip('.py') - mod = mod.replace(os.sep, '.') - argv[i] = mod if not test else mod + '.' + test +def convert_argv(argv): + args = [] + modules = set() + for arg in argv: + # Unittest's main has only flags and positional args. + # So we don't worry about options with values. + if not arg.startswith('-'): + # It must be the name of a test, case, module, or file. + # We convert filenames to module names. For filenames + # we support specifying a test name by appending it to + # the filename with a ":" in between. + mod, _, test = arg.partition(':') + if mod.endswith(os.sep): + mod = mod.rsplit(os.sep, 1)[0] + mod = mod.rsplit('.py', 1)[0] + mod = mod.replace(os.sep, '.') + arg = mod if not test else mod + '.' + test + modules.add(mod) + args.append(arg) -main(module=None, argv=argv) + if not modules: + # Do discovery. + args = ['discover', + '--start-directory', PROJECT_ROOT, + ] + args + return [sys.executable + ' -m unittest'] + args + #return [sys.executable, '-m', 'unittest'] + args + + +if __name__ == '__main__': + argv = convert_argv(sys.argv[1:]) + unittest.main(module=None, argv=argv) diff --git a/tests/test_test_main.py b/tests/test_test_main.py new file mode 100644 index 00000000..dc25c4e4 --- /dev/null +++ b/tests/test_test_main.py @@ -0,0 +1,46 @@ +import os +import os.path +import unittest +import sys + +from .__main__ import convert_argv + + +PROJECT_ROOT = os.path.dirname(os.path.dirname(__file__)) + + +class ConvertArgsTests(unittest.TestCase): + + def test_discovery(self): + argv = convert_argv(['-v', '--failfast']) + + self.assertEqual(argv, [ + sys.executable + ' -m unittest', + 'discover', + '--start-directory', PROJECT_ROOT, + '-v', '--failfast', + ]) + + def test_modules(self): + argv = convert_argv(['-v', '--failfast', + 'w', + 'x/y.py:Spam.test_spam'.replace('/', os.sep), + 'z:Eggs', + ]) + + self.assertEqual(argv, [ + sys.executable + ' -m unittest', + '-v', '--failfast', + 'w', + 'x.y.Spam.test_spam', + 'z.Eggs', + ]) + + def test_no_args(self): + argv = convert_argv([]) + + self.assertEqual(argv, [ + sys.executable + ' -m unittest', + 'discover', + '--start-directory', PROJECT_ROOT, + ])