~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest.py

  • Committer: Martin Pool
  • Date: 2005-06-06 04:47:33 UTC
  • Revision ID: mbp@sourcefrog.net-20050606044733-e902b05ac1747cd2
- fix invocation of testbzr when giving explicit bzr location

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
18
 
from unittest import TestResult, TestCase
19
 
 
20
 
try:
21
 
    import shutil
22
 
    from subprocess import call, Popen, PIPE
23
 
except ImportError, e:
24
 
    sys.stderr.write("testbzr: sorry, this test suite requires the subprocess module\n"
25
 
                     "this is shipped with python2.4 and available separately for 2.3\n")
26
 
    raise
27
 
 
28
 
 
29
 
class CommandFailed(Exception):
30
 
    pass
31
 
 
32
 
 
33
 
class TestBase(TestCase):
34
 
    """Base class for bzr test cases.
35
 
 
36
 
    Just defines some useful helper functions; doesn't actually test
37
 
    anything.
38
 
    """
39
 
    
40
 
    # TODO: Special methods to invoke bzr, so that we can run it
41
 
    # through a specified Python intepreter
42
 
 
43
 
    OVERRIDE_PYTHON = None # to run with alternative python 'python'
44
 
    BZRPATH = 'bzr'
45
 
    
46
 
 
47
 
    def formcmd(self, cmd):
48
 
        if isinstance(cmd, basestring):
49
 
            cmd = cmd.split()
50
 
 
51
 
        if cmd[0] == 'bzr':
52
 
            cmd[0] = self.BZRPATH
53
 
            if self.OVERRIDE_PYTHON:
54
 
                cmd.insert(0, self.OVERRIDE_PYTHON)
55
 
 
56
 
        self.log('$ %r' % cmd)
57
 
 
58
 
        return cmd
59
 
 
60
 
 
61
 
    def runcmd(self, cmd, retcode=0):
62
 
        """Run one command and check the return code.
63
 
 
64
 
        Returns a tuple of (stdout,stderr) strings.
65
 
 
66
 
        If a single string is based, it is split into words.
67
 
        For commands that are not simple space-separated words, please
68
 
        pass a list instead."""
69
 
        cmd = self.formcmd(cmd)
70
 
 
71
 
        self.log('$ ' + ' '.join(cmd))
72
 
        actual_retcode = call(cmd, stdout=self.TEST_LOG, stderr=self.TEST_LOG)
73
 
 
74
 
        if retcode != actual_retcode:
75
 
            raise CommandFailed("test failed: %r returned %d, expected %d"
76
 
                                % (cmd, actual_retcode, retcode))
77
 
 
78
 
 
79
 
    def backtick(self, cmd, retcode=0):
80
 
        """Run a command and return its output"""
81
 
        cmd = self.formcmd(cmd)
82
 
        child = Popen(cmd, stdout=PIPE, stderr=self.TEST_LOG)
83
 
        outd, errd = child.communicate()
84
 
        self.log(outd)
85
 
        actual_retcode = child.wait()
86
 
 
87
 
        outd = outd.replace('\r', '')
88
 
 
89
 
        if retcode != actual_retcode:
90
 
            raise CommandFailed("test failed: %r returned %d, expected %d"
91
 
                                % (cmd, actual_retcode, retcode))
92
 
 
93
 
        return outd
94
 
 
95
 
 
96
 
 
97
 
    def build_tree(self, shape):
98
 
        """Build a test tree according to a pattern.
99
 
 
100
 
        shape is a sequence of file specifications.  If the final
101
 
        character is '/', a directory is created.
102
 
 
103
 
        This doesn't add anything to a branch.
104
 
        """
105
 
        # XXX: It's OK to just create them using forward slashes on windows?
106
 
        import os
107
 
        for name in shape:
108
 
            assert isinstance(name, basestring)
109
 
            if name[-1] == '/':
110
 
                os.mkdir(name[:-1])
111
 
            else:
112
 
                f = file(name, 'wt')
113
 
                print >>f, "contents of", name
114
 
                f.close()
115
 
 
116
 
 
117
 
    def log(self, msg):
118
 
        """Log a message to a progress file"""
119
 
        print >>self.TEST_LOG, msg
120
 
               
121
 
 
122
 
class InTempDir(TestBase):
123
 
    """Base class for tests run in a temporary branch."""
124
 
    def setUp(self):
125
 
        import os
126
 
        self.test_dir = os.path.join(self.TEST_ROOT, self.__class__.__name__)
127
 
        os.mkdir(self.test_dir)
128
 
        os.chdir(self.test_dir)
129
 
        
130
 
    def tearDown(self):
131
 
        import os
132
 
        os.chdir(self.TEST_ROOT)
133
 
 
134
 
 
135
 
 
136
 
 
137
 
 
138
 
class _MyResult(TestResult):
139
 
    """
140
 
    Custom TestResult.
141
 
 
142
 
    No special behaviour for now.
143
 
    """
144
 
    def __init__(self, out):
145
 
        self.out = out
146
 
        TestResult.__init__(self)
147
 
 
148
 
    def startTest(self, test):
149
 
        # TODO: Maybe show test.shortDescription somewhere?
150
 
        print >>self.out, '%-60.60s' % test.id(),
151
 
        TestResult.startTest(self, test)
152
 
 
153
 
    def stopTest(self, test):
154
 
        # print
155
 
        TestResult.stopTest(self, test)
156
 
 
157
 
 
158
 
    def addError(self, test, err):
159
 
        print >>self.out, 'ERROR'
160
 
        TestResult.addError(self, test, err)
161
 
 
162
 
    def addFailure(self, test, err):
163
 
        print >>self.out, 'FAILURE'
164
 
        TestResult.addFailure(self, test, err)
165
 
 
166
 
    def addSuccess(self, test):
167
 
        print >>self.out, 'OK'
168
 
        TestResult.addSuccess(self, test)
169
 
 
170
 
 
171
 
 
172
18
def selftest():
173
 
    from unittest import TestLoader, TestSuite
 
19
    import unittest
 
20
    from unittest import TestLoader
174
21
    import bzrlib
175
 
    import bzrlib.selftest.whitebox
176
 
    import bzrlib.selftest.blackbox
177
 
    import bzrlib.selftest.versioning
178
22
    from doctest import DocTestSuite
179
 
    import os
180
 
    import shutil
181
 
    import time
182
 
    import sys
183
 
 
184
 
    _setup_test_log()
185
 
    _setup_test_dir()
186
 
    print
187
 
 
188
 
    suite = TestSuite()
189
 
    tl = TestLoader()
190
 
 
191
 
    for m in bzrlib.selftest.whitebox, \
192
 
            bzrlib.selftest.versioning:
193
 
        suite.addTest(tl.loadTestsFromModule(m))
194
 
 
195
 
    suite.addTest(bzrlib.selftest.blackbox.suite())
196
 
 
 
23
    
 
24
    tr = unittest.TextTestRunner(verbosity=2)
 
25
    suite = unittest.TestSuite()
 
26
    import bzrlib.whitebox
 
27
 
 
28
    suite.addTest(TestLoader().loadTestsFromModule(bzrlib.whitebox))
 
29
    
197
30
    for m in bzrlib.store, bzrlib.inventory, bzrlib.branch, bzrlib.osutils, \
198
 
            bzrlib.commands:
 
31
            bzrlib.tree, bzrlib.commands, bzrlib.add:
199
32
        suite.addTest(DocTestSuite(m))
200
33
 
201
 
    # save stdout & stderr so there's no leakage from code-under-test
202
 
    real_stdout = sys.stdout
203
 
    real_stderr = sys.stderr
204
 
    sys.stdout = sys.stderr = TestBase.TEST_LOG
205
 
    try:
206
 
        result = _MyResult(real_stdout)
207
 
        suite.run(result)
208
 
    finally:
209
 
        sys.stdout = real_stdout
210
 
        sys.stderr = real_stderr
211
 
 
212
 
    _show_results(result)
213
 
 
 
34
    result = tr.run(suite)
214
35
    return result.wasSuccessful()
215
 
 
216
 
 
217
 
 
218
 
 
219
 
def _setup_test_log():
220
 
    import time
221
 
    import os
222
 
    
223
 
    log_filename = os.path.abspath('testbzr.log')
224
 
    TestBase.TEST_LOG = open(log_filename, 'wt', buffering=1) # line buffered
225
 
 
226
 
    print >>TestBase.TEST_LOG, "bzr tests run at " + time.ctime()
227
 
    print '%-30s %s' % ('test log', log_filename)
228
 
 
229
 
 
230
 
def _setup_test_dir():
231
 
    import os
232
 
    import shutil
233
 
    
234
 
    TestBase.ORIG_DIR = os.getcwdu()
235
 
    TestBase.TEST_ROOT = os.path.abspath("testbzr.tmp")
236
 
 
237
 
    print '%-30s %s' % ('running tests in', TestBase.TEST_ROOT)
238
 
 
239
 
    if os.path.exists(TestBase.TEST_ROOT):
240
 
        shutil.rmtree(TestBase.TEST_ROOT)
241
 
    os.mkdir(TestBase.TEST_ROOT)
242
 
    os.chdir(TestBase.TEST_ROOT)
243
 
 
244
 
    # make a fake bzr directory there to prevent any tests propagating
245
 
    # up onto the source directory's real branch
246
 
    os.mkdir(os.path.join(TestBase.TEST_ROOT, '.bzr'))
247
 
 
248
 
    
249
 
 
250
 
def _show_results(result):
251
 
     for case, tb in result.errors:
252
 
         _show_test_failure('ERROR', case, tb)
253
 
 
254
 
     for case, tb in result.failures:
255
 
         _show_test_failure('FAILURE', case, tb)
256
 
         
257
 
     print
258
 
     print '%4d tests run' % result.testsRun
259
 
     print '%4d errors' % len(result.errors)
260
 
     print '%4d failures' % len(result.failures)
261
 
 
262
 
 
263
 
 
264
 
def _show_test_failure(kind, case, tb):
265
 
     print (kind + '! ').ljust(60, '-')
266
 
     print case
267
 
     desc = case.shortDescription()
268
 
     if desc:
269
 
         print '   (%s)' % desc
270
 
     print tb
271
 
     print ''.ljust(60, '-')
272