~bzr-pqm/bzr/bzr.dev

608 by Martin Pool
- Split selftests out into a new module and start changing them
1
# Copyright (C) 2005 by Canonical Ltd
2
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
609 by Martin Pool
- cleanup test code
17
720 by Martin Pool
- start moving external tests into the testsuite framework
18
from unittest import TestResult, TestCase
719 by Martin Pool
- reorganize selftest code
19
727 by Martin Pool
- move more code to run external commands from testbzr to selftest
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
721 by Martin Pool
- framework for running external commands from unittest suite
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
    """
727 by Martin Pool
- move more code to run external commands from testbzr to selftest
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
732 by Martin Pool
- move more tests into bzr selftest
79
    def backtick(self, cmd, retcode=0):
80
        cmd = self.formcmd(cmd)
81
        child = Popen(cmd, stdout=PIPE, stderr=self.TEST_LOG)
82
        outd, errd = child.communicate()
83
        self.log(outd)
84
        actual_retcode = child.wait()
85
86
        outd = outd.replace('\r', '')
87
88
        if retcode != actual_retcode:
89
            raise CommandFailed("test failed: %r returned %d, expected %d"
90
                                % (cmd, actual_retcode, retcode))
91
92
        return outd
93
94
95
721 by Martin Pool
- framework for running external commands from unittest suite
96
97
    def log(self, msg):
98
        """Log a message to a progress file"""
726 by Martin Pool
- more rearrangement of blackbox tests
99
        print >>self.TEST_LOG, msg
721 by Martin Pool
- framework for running external commands from unittest suite
100
               
101
732 by Martin Pool
- move more tests into bzr selftest
102
class InTempDir(TestBase):
103
    """Base class for tests run in a temporary branch."""
104
    def setUp(self):
105
        import os
735 by Martin Pool
- clean up code for running tests in selfcontained directories
106
        self.test_dir = os.path.join(self.TEST_ROOT, self.__class__.__name__)
107
        os.mkdir(self.test_dir)
108
        os.chdir(self.test_dir)
732 by Martin Pool
- move more tests into bzr selftest
109
        
110
    def tearDown(self):
111
        import os
735 by Martin Pool
- clean up code for running tests in selfcontained directories
112
        os.chdir(self.TEST_ROOT)
732 by Martin Pool
- move more tests into bzr selftest
113
114
115
721 by Martin Pool
- framework for running external commands from unittest suite
116
117
720 by Martin Pool
- start moving external tests into the testsuite framework
118
class _MyResult(TestResult):
721 by Martin Pool
- framework for running external commands from unittest suite
119
    """
120
    Custom TestResult.
121
122
    No special behaviour for now.
123
    """
733 by Martin Pool
- show test names while running
124
    def startTest(self, test):
125
        print str(test).ljust(60),
126
        TestResult.startTest(self, test)
127
128
    def stopTest(self, test):
129
        # print
130
        TestResult.stopTest(self, test)
131
132
133
    def addError(self, test, err):
134
        print 'ERROR'
135
        TestResult.addError(self, test, err)
136
137
    def addFailure(self, test, err):
138
        print 'FAILURE'
139
        TestResult.addFailure(self, test, err)
140
141
    def addSuccess(self, test):
142
        print 'OK'
143
        TestResult.addSuccess(self, test)
719 by Martin Pool
- reorganize selftest code
144
145
720 by Martin Pool
- start moving external tests into the testsuite framework
146
608 by Martin Pool
- Split selftests out into a new module and start changing them
147
def selftest():
721 by Martin Pool
- framework for running external commands from unittest suite
148
    from unittest import TestLoader, TestSuite
149
    import bzrlib
723 by Martin Pool
- move whitebox/blackbox modules into bzrlib.selftest subdirectory
150
    import bzrlib.selftest.whitebox
151
    import bzrlib.selftest.blackbox
743 by Martin Pool
- new simple versioning test cases
152
    import bzrlib.selftest.versioning
721 by Martin Pool
- framework for running external commands from unittest suite
153
    from doctest import DocTestSuite
154
    import os
155
    import shutil
156
    import time
157
158
    _setup_test_log()
159
    _setup_test_dir()
160
161
    suite = TestSuite()
162
    tl = TestLoader()
163
743 by Martin Pool
- new simple versioning test cases
164
    for m in bzrlib.selftest.whitebox, \
165
            bzrlib.selftest.versioning:
721 by Martin Pool
- framework for running external commands from unittest suite
166
        suite.addTest(tl.loadTestsFromModule(m))
167
726 by Martin Pool
- more rearrangement of blackbox tests
168
    suite.addTest(bzrlib.selftest.blackbox.suite())
169
721 by Martin Pool
- framework for running external commands from unittest suite
170
    for m in bzrlib.store, bzrlib.inventory, bzrlib.branch, bzrlib.osutils, \
171
            bzrlib.commands:
172
        suite.addTest(DocTestSuite(m))
173
174
    result = _MyResult()
175
    suite.run(result)
176
177
    _show_results(result)
178
179
    return result.wasSuccessful()
180
181
182
def _setup_test_log():
183
    import time
184
    import os
185
    
186
    log_filename = os.path.abspath('testbzr.log')
726 by Martin Pool
- more rearrangement of blackbox tests
187
    TestBase.TEST_LOG = open(log_filename, 'wt', buffering=1) # line buffered
721 by Martin Pool
- framework for running external commands from unittest suite
188
726 by Martin Pool
- more rearrangement of blackbox tests
189
    print >>TestBase.TEST_LOG, "bzr tests run at " + time.ctime()
721 by Martin Pool
- framework for running external commands from unittest suite
190
    print '%-30s %s' % ('test log', log_filename)
191
192
193
def _setup_test_dir():
194
    import os
195
    import shutil
196
    
726 by Martin Pool
- more rearrangement of blackbox tests
197
    TestBase.ORIG_DIR = os.getcwdu()
735 by Martin Pool
- clean up code for running tests in selfcontained directories
198
    TestBase.TEST_ROOT = os.path.abspath("testbzr.tmp")
199
200
    print '%-30s %s' % ('running tests in', TestBase.TEST_ROOT)
201
202
    if os.path.exists(TestBase.TEST_ROOT):
203
        shutil.rmtree(TestBase.TEST_ROOT)
204
    os.mkdir(TestBase.TEST_ROOT)
205
    os.chdir(TestBase.TEST_ROOT)
726 by Martin Pool
- more rearrangement of blackbox tests
206
207
    # make a fake bzr directory there to prevent any tests propagating
208
    # up onto the source directory's real branch
735 by Martin Pool
- clean up code for running tests in selfcontained directories
209
    os.mkdir(os.path.join(TestBase.TEST_ROOT, '.bzr'))
721 by Martin Pool
- framework for running external commands from unittest suite
210
211
    
212
213
def _show_results(result):
214
     for case, tb in result.errors:
215
         _show_test_failure('ERROR', case, tb)
216
217
     for case, tb in result.failures:
218
         _show_test_failure('FAILURE', case, tb)
219
         
220
     print
719 by Martin Pool
- reorganize selftest code
221
     print '%4d tests run' % result.testsRun
222
     print '%4d errors' % len(result.errors)
223
     print '%4d failures' % len(result.failures)
224
721 by Martin Pool
- framework for running external commands from unittest suite
225
226
227
def _show_test_failure(kind, case, tb):
228
     print (kind + '! ').ljust(60, '-')
229
     print case
230
     print tb
231
     print ''.ljust(60, '-')
232