From 40034d73156885f9ce46707a4cb3b65355cc2628 Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Sat, 14 Nov 2015 19:20:00 -0800 Subject: [PATCH] Replace run_tests bash script with xsh script. This replaces the bash script I originally proposed as a way to safely invoke unit tests with a xonsh script (we need to eat our own dog food). This also udpates the documentation. --- Makefile | 9 ++++-- docs/devguide.rst | 65 ++++++++++++++++++++++++++++++++++------ docs/index.rst | 3 +- scripts/run_tests.sh | 25 ---------------- scripts/run_tests.xsh | 70 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 38 deletions(-) delete mode 100755 scripts/run_tests.sh create mode 100755 scripts/run_tests.xsh diff --git a/Makefile b/Makefile index 53d86aac2..d627223c3 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ SHELL = /bin/sh +which = edited # which tests to run + all: @echo "You must specifiy a make target." @echo "Targets are:" @@ -32,13 +34,14 @@ lint-all: # Test just the changed python files. It doesn't matter if "git add" has # already been done but obviously if you've already done "git commit" then # they're no longer consider changed. This should be run (along with "make -# lint") before commiting a set of changes. +# lint") before commiting a set of changes. You can also pass a list of test +# names via a "which=name1 name2..." argument. test: - scripts/run_tests.sh -e + scripts/run_tests.xsh $(which) # Test all the python files. test-all: - scripts/run_tests.sh + scripts/run_tests.xsh all # Build the parser_table.py module. This is normally done by setup.py at # install time. This just makes it easy to create the parser module on the fly diff --git a/docs/devguide.rst b/docs/devguide.rst index 31fea0a87..aab2293ad 100644 --- a/docs/devguide.rst +++ b/docs/devguide.rst @@ -61,22 +61,66 @@ is open to interpretation. unittest directly or write tests in an object-oriented style. * Test generators make more dots and the dots must flow! +You can easily check for style issues, including some outright bugs such +as mispelled variable names, using pylint. If you're using Anaconda you'll +need to run "conda install pylint" once. You can easily run pylint on +the edited files in your uncommited git change: + + $ make lint + +If you want to lint the entire code base run: + + $ make lint-all + How to Test ================ -First, install nose: http://nose.readthedocs.org/en/latest/ +First, install nose: http://nose.readthedocs.org/en/latest/. Second, ensure +your cwd is the root directory of the project (i.e., the one containing the +.git directory). To perform all unit tests:: - $ cd tests/ - $ nosetests + $ make test-all -This will recursively look through the currently directory, open up every file -named test_* and run every function (or method) named test_*. +Or, if you want to do it the hard way: -Nosetests can also take file(s) as an argument. For example, to run just the -lexer and parser module tests:: + $ scripts/run-tests.xsh - $ nosetests test_lexer.py test_parser.py +Or, if you want to do it the really hard way: + + $ python3 -c 'import setup; setup.build_tables()' + $ XONSHRC='' nosetests + +If you're working on a change and haven't yet commited it you can run the +associated tests with: + + $ make test + +If you want to run specific tests you can specify the test names. For example +to run test_parser: + + $ python3 -c 'import setup; setup.build_tables()' + $ XONSHRC='' nosetests tests/test_parser.py + +If you want to run specific tests you can pass the test name to the +scripts/run_tests.xsh script. The test name can be the bare test name +(e.g., ``aliases``), include the ``test_`` prefix and ``.py`` suffix +without the directory (e.g., ``test_aliases.py``), or the complete relative +path (e.g., ``tests/test_aliases.py``). For example: + + $ make test which=aliases + +Or by invoking the run_tests script directly: + + $ scripts/run_tests.xsh aliases + +Note that you can pass multiple test names in the above examples: + + $ make test which='aliases environ' + +Or: + + $ scripts/run_tests.xsh aliases environ Happy testing! @@ -247,7 +291,10 @@ When releasing xonsh, make sure to do the following items in order: -------------------- Maintenance Tasks -------------------- -None currently. +You can cleanup your local repository of transient files such as \*.pyc files +created by unit testing by running: + + $ make clean ----------------------- Performing the Release diff --git a/docs/index.rst b/docs/index.rst index 3acf4683e..6e48671e2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -230,7 +230,8 @@ Xonsh currently has the following external dependencies, *Documentation:* - #. Sphinx + #. `Sphinx ` (which uses + `reStructuredText `) #. Numpydoc #. Cloud Sphinx Theme diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh deleted file mode 100755 index 515cff1cb..000000000 --- a/scripts/run_tests.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -# -# Run all the nosetests or just the ones relevant for the edited files. -# -make build-tables # ensure lexer/parser table module is up to date -if [[ $1 == "-e" ]]; then - tmp_file=$(mktemp /tmp/nose_tests_XXXXXX) - git status -s | - awk '/\.py$/ { print $2 }' | - while read f; do - if [[ $f == xonsh/* ]]; then - f="tests/test_$(basename $f)" - if [[ -f $f ]]; then - echo $f - fi - else - echo $f - fi - done | - sort -u > $tmp_file - XONSHRC=/dev/null nosetests -v $(< $tmp_file) - rm $tmp_file -else - XONSHRC=/dev/null nosetests -fi diff --git a/scripts/run_tests.xsh b/scripts/run_tests.xsh new file mode 100755 index 000000000..0f43e8f72 --- /dev/null +++ b/scripts/run_tests.xsh @@ -0,0 +1,70 @@ +#!/usr/bin/env xonsh --no-rc +# +# Run all the nosetests or just the ones relevant for the edited files in the +# current uncommited git change or just the ones named on the command line. +# Your cwd must be the top of the project tree. +# +# Usage: +# run_tests.xsh [edited | all | list of test names] +# +# You can omit the "all" argument if you want all tests run. +# +import os.path +import sys + +if not os.path.isdir('.git'): + print('No .git directory. The cwd must be the top of the project tree.', + file=sys.stderr) + sys.exit(1) + +if len($ARGS) == 1: + # Run all tests. + $[make build-tables] # ensure lexer/parser table module is up to date + $[env XONSHRC='' nosetests] +elif len($ARGS) == 2 and $ARG1 == 'all': + # Run all tests. + $[make build-tables] # ensure lexer/parser table module is up to date + $[env XONSHRC='' nosetests] +elif len($ARGS) == 2 and $ARG1 == 'edited': + # Run just the tests for the files edited in the uncommited change. + tests = set() + for edited_fname in $(git status -s).split(): + if not edited_fname.endswith('.py'): + continue + if edited_fname.startswith('xonsh/'): + test_fname = 'tests/test_' + edited_fname[len('xonsh/')] + if os.path.exists(test_fname): + tests.add(test_fname) + elif edited_fname.startswith('tests/'): + tests.add(test_fname) + else: + print('Ignoring file because I cannot find a test for: {!r}.'. + format(edited_fname), file=sys.stderr) + + if tests: + $[make build-tables] # ensure lexer/parser table module is up to date + $[env XONSHRC='' nosetests -v @(sorted(tests))] + else: + print('Cannot find any tests in the pending changes.', file=sys.stderr) +else: + # Run the named tests. + tests = set() + for test_fname in $ARGS[1:]: + if not test_fname.startswith('tests/'): + if not test_fname.startswith('test_'): + test_fname = 'tests/test_' + test_fname + if not test_fname.endswith('.py'): + test_fname += '.py' + if os.path.exists(test_fname): + tests.add(test_fname) + else: + print('Cannot find test module {!r}; ignoring the argument.'. + format(test_fname), file=sys.stderr) + + if tests: + $[make build-tables] # ensure lexer/parser table module is up to date + $[env XONSHRC='' nosetests -v @(sorted(tests))] + else: + print('Cannot find any tests matching {}.'.format($ARGS[1:]), + file=sys.stderr) + sys.exit(1)