diff --git a/README.rst b/README.rst index 491d50ca..e5d417c8 100644 --- a/README.rst +++ b/README.rst @@ -28,6 +28,7 @@ Here's a snippet from `Cram's own test suite`_:: -y, --yes answer yes to all questions -n, --no answer no to all questions -E, --preserve-env don't reset common environment variables + -e, --no-err-files don't write .err files on test failures --keep-tmpdir keep temporary directories --shell=PATH shell to use for running tests (default: /bin/sh) --shell-opts=OPTS arguments to invoke shell with @@ -132,9 +133,10 @@ For example, if we run Cram on `its own example tests`_:: s. # Ran 6 tests, 2 skipped, 1 failed. -Cram will also write the test with its actual output to -``examples/fail.t.err``, allowing you to use other diff tools. This -file is automatically removed the next time the test passes. +Unless run with ``-e`` or ``--no-err-files``, Cram will also write the +test with its actual output to ``examples/fail.t.err``, allowing you to +use other diff tools. This file is automatically removed the next time +the test passes. When you're first writing a test, you might just write the commands and run the test to see what happens. If you run Cram with ``-i`` or diff --git a/cram/_cli.py b/cram/_cli.py index cad8381c..e9afe766 100644 --- a/cram/_cli.py +++ b/cram/_cli.py @@ -53,7 +53,8 @@ def _patch(cmd, diff): out, retcode = execute([cmd, '-p0'], stdin=b''.join(diff)) return retcode == 0 -def runcli(tests, quiet=False, verbose=False, patchcmd=None, answer=None): +def runcli(tests, quiet=False, verbose=False, patchcmd=None, answer=None, + noerrfiles=False): """Run tests with command line interface input/output. tests should be a sequence of 2-tuples containing the following: @@ -101,12 +102,13 @@ def testwrapper(): if not quiet: _log('\n', None, verbose) - errfile = open(errpath, 'wb') - try: - for line in postout: - errfile.write(line) - finally: - errfile.close() + if not noerrfiles: + errfile = open(errpath, 'wb') + try: + for line in postout: + errfile.write(line) + finally: + errfile.close() if not quiet: origdiff = diff @@ -119,7 +121,8 @@ def testwrapper(): _prompt('Accept this change?', 'yN', answer) == 'y'): if _patch(patchcmd, diff): _log(None, path + b': merged output\n', verbose) - os.remove(errpath) + if not noerrfiles: + os.remove(errpath) else: _log(path + b': merge failed\n') diff --git a/cram/_main.py b/cram/_main.py index b6d80edc..d47d21b2 100644 --- a/cram/_main.py +++ b/cram/_main.py @@ -94,6 +94,8 @@ def _parseopts(args): help='answer no to all questions') p.add_option('-E', '--preserve-env', action='store_true', help="don't reset common environment variables") + p.add_option('-e', '--no-err-files', action='store_true', + help="don't write .err files on test failures") p.add_option('--keep-tmpdir', action='store_true', help='keep temporary directories') p.add_option('--shell', action='store', default='/bin/sh', metavar='PATH', @@ -183,10 +185,12 @@ def main(args): os.mkdir(proctmp) try: tests = runtests(paths, tmpdirb, shell, indent=opts.indent, - cleanenv=not opts.preserve_env, debug=opts.debug) + cleanenv=not opts.preserve_env, debug=opts.debug, + noerrfiles=opts.no_err_files) if not opts.debug: tests = runcli(tests, quiet=opts.quiet, verbose=opts.verbose, - patchcmd=patchcmd, answer=answer) + patchcmd=patchcmd, answer=answer, + noerrfiles=opts.no_err_files) if opts.xunit_file is not None: tests = runxunit(tests, opts.xunit_file) diff --git a/cram/_run.py b/cram/_run.py index 43813a45..4a609c7c 100644 --- a/cram/_run.py +++ b/cram/_run.py @@ -30,7 +30,8 @@ def _findtests(paths): else: yield os.path.normpath(p) -def runtests(paths, tmpdir, shell, indent=2, cleanenv=True, debug=False): +def runtests(paths, tmpdir, shell, indent=2, cleanenv=True, debug=False, + noerrfiles=False): """Run tests and yield results. This yields a sequence of 2-tuples containing the following: @@ -69,7 +70,7 @@ def test(): os.chdir(testdir) return testfile(abspath, shell, indent=indent, cleanenv=cleanenv, debug=debug, - testname=path) + testname=path, noerrfile=noerrfiles) finally: os.chdir(cwd) diff --git a/cram/_test.py b/cram/_test.py index 2cec870d..3293f39c 100644 --- a/cram/_test.py +++ b/cram/_test.py @@ -21,7 +21,7 @@ def _escape(s): b' (esc)\n') def test(lines, shell='/bin/sh', indent=2, testname=None, env=None, - cleanenv=True, debug=False): + cleanenv=True, debug=False, noerrfile=False): r"""Run test lines and return input, output, and diff. This returns a 3-tuple containing the following: @@ -177,7 +177,7 @@ def test(lines, shell='/bin/sh', indent=2, testname=None, env=None, return refout, postout, [] def testfile(path, shell='/bin/sh', indent=2, env=None, cleanenv=True, - debug=False, testname=None): + debug=False, testname=None, noerrfile=False): """Run test at path and return input, output, and diff. This returns a 3-tuple containing the following: @@ -218,6 +218,6 @@ def testfile(path, shell='/bin/sh', indent=2, env=None, cleanenv=True, if testname is None: # pragma: nocover testname = os.path.basename(abspath) return test(f, shell, indent=indent, testname=testname, env=env, - cleanenv=cleanenv, debug=debug) + cleanenv=cleanenv, debug=debug, noerrfile=noerrfile) finally: f.close() diff --git a/tests/test.t b/tests/test.t index e1f74b12..387ba490 100644 --- a/tests/test.t +++ b/tests/test.t @@ -151,3 +151,25 @@ Test running tests with the same filename in different directories: # Ran 2 tests, 0 skipped, 2 failed. [1] + +Test failing a test in a read-only directory with the --no-err-files option: + + $ mkdir subdir + $ cat > subdir/test.t < $ echo 1 + > EOF + $ chmod a-w subdir + $ cram subdir >/dev/null 2>&1 + [1] + $ cram --no-err-files subdir + ! + --- subdir/test.t + +++ subdir/test.t.err + @@ -1,1 +1,2 @@ + $ echo 1 + + 1 + + # Ran 1 tests, 0 skipped, 1 failed. + [1] + + $ chmod a+w subdir diff --git a/tests/usage.t b/tests/usage.t index c193d7bb..44ed6fd0 100644 --- a/tests/usage.t +++ b/tests/usage.t @@ -17,6 +17,7 @@ Usage: -y, --yes answer yes to all questions -n, --no answer no to all questions -E, --preserve-env don't reset common environment variables + -e, --no-err-files don't write .err files on test failures --keep-tmpdir keep temporary directories --shell=PATH shell to use for running tests (default: /bin/sh) --shell-opts=OPTS arguments to invoke shell with