config/mozunit.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/config/mozunit.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,152 @@
     1.4 +# This Source Code Form is subject to the terms of the Mozilla Public
     1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.7 +
     1.8 +from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
     1.9 +import unittest
    1.10 +import inspect
    1.11 +from StringIO import StringIO
    1.12 +import os
    1.13 +
    1.14 +'''Helper to make python unit tests report the way that the Mozilla
    1.15 +unit test infrastructure expects tests to report.
    1.16 +
    1.17 +Usage:
    1.18 +
    1.19 +import unittest
    1.20 +import mozunit
    1.21 +
    1.22 +if __name__ == '__main__':
    1.23 +    mozunit.main()
    1.24 +'''
    1.25 +
    1.26 +class _MozTestResult(_TestResult):
    1.27 +    def __init__(self, stream, descriptions):
    1.28 +        _TestResult.__init__(self)
    1.29 +        self.stream = stream
    1.30 +        self.descriptions = descriptions
    1.31 +
    1.32 +    def getDescription(self, test):
    1.33 +        if self.descriptions:
    1.34 +            return test.shortDescription() or str(test)
    1.35 +        else:
    1.36 +            return str(test)
    1.37 +
    1.38 +    def addSuccess(self, test):
    1.39 +        _TestResult.addSuccess(self, test)
    1.40 +        filename = inspect.getfile(test.__class__)
    1.41 +        testname = test._testMethodName
    1.42 +        self.stream.writeln("TEST-PASS | {0} | {1}".format(filename, testname))
    1.43 +
    1.44 +    def addError(self, test, err):
    1.45 +        _TestResult.addError(self, test, err)
    1.46 +        self.printFail(test, err)
    1.47 +
    1.48 +    def addFailure(self, test, err):
    1.49 +        _TestResult.addFailure(self, test, err)
    1.50 +        self.printFail(test,err)
    1.51 +
    1.52 +    def printFail(self, test, err):
    1.53 +        exctype, value, tb = err
    1.54 +        # Skip test runner traceback levels
    1.55 +        while tb and self._is_relevant_tb_level(tb):
    1.56 +            tb = tb.tb_next
    1.57 +        if not tb:
    1.58 +            self.stream.writeln("TEST-UNEXPECTED-FAIL | NO TRACEBACK |")
    1.59 +        _f, _ln, _t = inspect.getframeinfo(tb)[:3]
    1.60 +        self.stream.writeln("TEST-UNEXPECTED-FAIL | {0} | line {1}, {2}: {3}" 
    1.61 +                            .format(_f, _ln, _t, value.message))
    1.62 +
    1.63 +    def printErrorList(self):
    1.64 +        for test, err in self.errors:
    1.65 +            self.stream.writeln("ERROR: {0}".format(self.getDescription(test)))
    1.66 +            self.stream.writeln("{0}".format(err))
    1.67 +
    1.68 +
    1.69 +class MozTestRunner(_TestRunner):
    1.70 +    def _makeResult(self):
    1.71 +        return _MozTestResult(self.stream, self.descriptions)
    1.72 +    def run(self, test):
    1.73 +        result = self._makeResult()
    1.74 +        test(result)
    1.75 +        result.printErrorList()
    1.76 +        return result
    1.77 +
    1.78 +class MockedFile(StringIO):
    1.79 +    def __init__(self, context, filename, content = ''):
    1.80 +        self.context = context
    1.81 +        self.name = filename
    1.82 +        StringIO.__init__(self, content)
    1.83 +
    1.84 +    def close(self):
    1.85 +        self.context.files[self.name] = self.getvalue()
    1.86 +        StringIO.close(self)
    1.87 +
    1.88 +    def __enter__(self):
    1.89 +        return self
    1.90 +
    1.91 +    def __exit__(self, type, value, traceback):
    1.92 +        self.close()
    1.93 +
    1.94 +class MockedOpen(object):
    1.95 +    '''
    1.96 +    Context manager diverting the open builtin such that opening files
    1.97 +    can open "virtual" file instances given when creating a MockedOpen.
    1.98 +
    1.99 +    with MockedOpen({'foo': 'foo', 'bar': 'bar'}):
   1.100 +        f = open('foo', 'r')
   1.101 +
   1.102 +    will thus open the virtual file instance for the file 'foo' to f.
   1.103 +
   1.104 +    MockedOpen also masks writes, so that creating or replacing files
   1.105 +    doesn't touch the file system, while subsequently opening the file
   1.106 +    will return the recorded content.
   1.107 +
   1.108 +    with MockedOpen():
   1.109 +        f = open('foo', 'w')
   1.110 +        f.write('foo')
   1.111 +    self.assertRaises(Exception,f.open('foo', 'r'))
   1.112 +    '''
   1.113 +    def __init__(self, files = {}):
   1.114 +        self.files = {}
   1.115 +        for name, content in files.iteritems():
   1.116 +            self.files[os.path.abspath(name)] = content
   1.117 +
   1.118 +    def __call__(self, name, mode = 'r'):
   1.119 +        absname = os.path.abspath(name)
   1.120 +        if 'w' in mode:
   1.121 +            file = MockedFile(self, absname)
   1.122 +        elif absname in self.files:
   1.123 +            file = MockedFile(self, absname, self.files[absname])
   1.124 +        elif 'a' in mode:
   1.125 +            file = MockedFile(self, absname, self.open(name, 'r').read())
   1.126 +        else:
   1.127 +            file = self.open(name, mode)
   1.128 +        if 'a' in mode:
   1.129 +            file.seek(0, os.SEEK_END)
   1.130 +        return file
   1.131 +
   1.132 +    def __enter__(self):
   1.133 +        import __builtin__
   1.134 +        self.open = __builtin__.open
   1.135 +        self._orig_path_exists = os.path.exists
   1.136 +        __builtin__.open = self
   1.137 +        os.path.exists = self._wrapped_exists
   1.138 +
   1.139 +    def __exit__(self, type, value, traceback):
   1.140 +        import __builtin__
   1.141 +        __builtin__.open = self.open
   1.142 +        os.path.exists = self._orig_path_exists
   1.143 +
   1.144 +    def _wrapped_exists(self, p):
   1.145 +        if p in self.files:
   1.146 +            return True
   1.147 +
   1.148 +        abspath = os.path.abspath(p)
   1.149 +        if abspath in self.files:
   1.150 +            return True
   1.151 +
   1.152 +        return self._orig_path_exists(p)
   1.153 +
   1.154 +def main(*args):
   1.155 +    unittest.main(testRunner=MozTestRunner(),*args)

mercurial