summaryrefslogtreecommitdiff
path: root/test/test_farm.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2009-04-12 11:46:52 -0400
committerNed Batchelder <ned@nedbatchelder.com>2009-04-12 11:46:52 -0400
commite8ee02440906524913f8d40507818ddaf8f87380 (patch)
tree8e9d62239c3f6a6a40e52cfa8e1b48d94c8aa617 /test/test_farm.py
parent0f70ada26802544922dc0dd2ab59fbbaf5745769 (diff)
downloadpython-coveragepy-git-e8ee02440906524913f8d40507818ddaf8f87380.tar.gz
Fix the use of nose test generators, so that we can use setUp and tearDown. Fix the changing of directories, so that failing tests don't cascade into other failures.
Diffstat (limited to 'test/test_farm.py')
-rw-r--r--test/test_farm.py94
1 files changed, 70 insertions, 24 deletions
diff --git a/test/test_farm.py b/test/test_farm.py
index 07ad2ddc..8febd2c1 100644
--- a/test/test_farm.py
+++ b/test/test_farm.py
@@ -1,4 +1,4 @@
-"""Run tests in the farm subdirectory. Requires nose."""
+"""Run tests in the farm subdirectory. Designed for nose."""
import filecmp, fnmatch, glob, os, shutil, sys
from coverage.files import FileLocator
@@ -13,21 +13,48 @@ def test_farm(clean_only=False):
"""A test-generating function for nose to find and run."""
for fname in glob.glob("test/farm/*/*.py"):
case = FarmTestCase(fname, clean_only)
- yield (case.execute,)
+ yield (case,)
class FarmTestCase(object):
+ """A test case from the farm tree.
+
+ Tests are short Python script files, often called run.py:
+
+ copy("src", "out")
+ run('''
+ coverage -x white.py
+ coverage -a white.py
+ ''', rundir="out")
+ compare("out", "gold", "*,cover")
+ clean("out")
+
+ Verbs (copy, run, compare, clean) are methods in this class. FarmTestCase
+ has options to allow various uses of the test cases (normal execution,
+ cleaning-only, or run and leave the results for debugging).
+
+ """
def __init__(self, runpy, clean_only=False, dont_clean=False):
+ """Create a test case from a run.py file.
+
+ `clean_only` means that only the clean() action is executed.
+ `dont_clean` means that the clean() action is not executed.
+
+ """
self.dir, self.runpy = os.path.split(runpy)
self.clean_only = clean_only
self.dont_clean = dont_clean
def cd(self, newdir):
+ """Change the current directory, and return the old one."""
cwd = os.getcwd()
os.chdir(newdir)
return cwd
- def execute(self):
+ def __call__(self):
+ """Execute the test from the run.py file.
+
+ """
cwd = self.cd(self.dir)
# Prepare a dictionary of globals for the run.py files to use.
@@ -39,10 +66,11 @@ class FarmTestCase(object):
glo = dict([(fn, getattr(self, fn)) for fn in fns])
if self.dont_clean:
glo['clean'] = self.noop
-
- execfile(self.runpy, glo)
-
- self.cd(cwd)
+
+ try:
+ execfile(self.runpy, glo)
+ finally:
+ self.cd(cwd)
def fnmatch_list(self, files, filepattern):
"""Filter the list of `files` to only those that match `filepattern`.
@@ -53,6 +81,16 @@ class FarmTestCase(object):
files = [f for f in files if fnmatch.fnmatch(f, filepattern)]
return ", ".join(files)
+ def setUp(self):
+ """Test set up, run by nose before __call__."""
+ pass
+
+ def tearDown(self):
+ """Test tear down, run by nose after __call__."""
+ # Make sure no matter what, the test is cleaned up.
+ self.clean_only = True
+ self()
+
# Functions usable inside farm run.py files
def noop(self, *args, **kwargs):
@@ -74,23 +112,30 @@ class FarmTestCase(object):
"""
cwd = self.cd(rundir)
- for cmd in cmds.split("\n"):
- if subprocess:
- proc = subprocess.Popen(cmd, shell=True,
- stdin=subprocess.PIPE, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- retcode = proc.wait()
- output = proc.stdout.read()
- else:
- stdin, stdouterr = os.popen4(cmd)
- output = stdouterr.read()
- retcode = 0 # Can't tell if the process failed.
- print output,
- if retcode:
- raise Exception("command exited abnormally")
- self.cd(cwd)
+ try:
+ for cmd in cmds.split("\n"):
+ if subprocess:
+ proc = subprocess.Popen(cmd, shell=True,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ retcode = proc.wait()
+ output = proc.stdout.read()
+ else:
+ stdin, stdouterr = os.popen4(cmd)
+ output = stdouterr.read()
+ retcode = 0 # Can't tell if the process failed.
+ print output,
+ if retcode:
+ raise Exception("command exited abnormally")
+ finally:
+ self.cd(cwd)
def compare(self, dir1, dir2, filepattern=None):
+ """Compare files matching `filepattern` in `dir1` and `dir2`.
+
+ An assertion will be raised if the directories don't match in some way.
+
+ """
dc = filecmp.dircmp(dir1, dir2)
diff_files = self.fnmatch_list(dc.diff_files, filepattern)
left_only = self.fnmatch_list(dc.left_only, filepattern)
@@ -100,6 +145,7 @@ class FarmTestCase(object):
assert not right_only, "Files in %s only: %s" % (dir2, right_only)
def clean(self, cleandir):
+ """Clean `cleandir` by removing it and all its children completely."""
if os.path.exists(cleandir):
shutil.rmtree(cleandir)
@@ -110,11 +156,11 @@ if __name__ == '__main__':
if op == 'run':
# Run the test for real.
case = FarmTestCase(sys.argv[2])
- case.execute()
+ case()
if op == 'out':
# Run the test, but don't clean up, so we can examine the output.
case = FarmTestCase(sys.argv[2], dont_clean=True)
- case.execute()
+ case()
elif op == 'clean':
# Run all the tests, but just clean.
for test in test_farm(clean_only=True):