Back to index

plone3  3.1.7
conftest.py
Go to the documentation of this file.
00001 # JS unit test support for py.test - (c) 2007 Guido Wesdorp. All rights
00002 # reserved
00003 #
00004 # This software is distributed under the terms of the JSBase
00005 # License. See LICENSE.txt for license text.
00006 
00007 import py
00008 
00009 here = py.magic.autopath().dirpath()
00010 
00011 class JSTest(py.test.collect.Item):
00012     def run(self):
00013         path = self.fspath
00014         test = self.name.split('/')[-1]
00015         paths = [path.strpath, 
00016                     (here / 'exception.js').strpath,
00017                     (here / 'testing.js').strpath,
00018                     (here / 'misclib.js').strpath,
00019                 ]
00020         testjs = (here / 'testing/testbase.js').read() % (
00021                     paths, test, '__main__')
00022         curdir = str(py.path.local('.'))
00023         py.std.os.chdir(str(self.fspath.dirpath()))
00024         try:
00025             jspath = self.fspath.new(basename='__testbase_temp.js')
00026             try:
00027                 jspath.write(testjs)
00028                 pipe = py.std.os.popen('js "%s"' % (jspath,))
00029                 try:
00030                     data = {}
00031                     for line in pipe:
00032                         done = self._handle_line(line, data)
00033                         if done:
00034                             errdata = data[data['current']]
00035                             if errdata:
00036                                 self.fail(errdata)
00037                 finally:
00038                     pipe.close()
00039             finally:
00040                 jspath.remove()
00041         finally:
00042             py.std.os.chdir(curdir)
00043 
00044     def fail(self, errdata):
00045         py.test.fail(
00046         '\nJS traceback (most recent last): \n%s\n%s\n' % (
00047                 (errdata[1:] and 
00048                     self._format_tb(errdata[1:-5]) or
00049                     'no traceback available'
00050                 ),
00051                 errdata[0], 
00052             )
00053         )
00054 
00055     _handling_traceback = False
00056     def _handle_line(self, line, data):
00057         line = line[:-1]
00058         if line.startswith('end test'):
00059             return True
00060         if self._handling_traceback and line != 'end traceback':
00061             data[data['current']].append(line)
00062         if line.startswith('PRINTED: '):
00063             print line[9:]
00064         elif line.startswith('running test '):
00065             testname = line[13:]
00066             data['current'] = testname
00067             data[testname] = []
00068         elif line.startswith('success'):
00069             pass
00070         elif line.startswith('failure: '):
00071             data[data['current']].append(line[9:])
00072         elif line.startswith('traceback'):
00073             self._handling_traceback = True
00074         elif line.startswith('end traceback'):
00075             self._handling_traceback = False
00076 
00077     def _format_tb(self, tb):
00078         tb.reverse()
00079         ret = []
00080         for line in tb:
00081             line = line.strip()
00082             if not line:
00083                 continue
00084             funcsig, lineinfo = line.split('@', 1)
00085             fpath, lineno = lineinfo.rsplit(':', 1)
00086             fname = py.path.local(fpath).basename
00087             # XXX might filter out too much... but it's better than leaving it
00088             # all in (since it adds a couple of lines to the end of the tb,
00089             # making it harder to find the problem line)
00090             if fname in ['__testbase_temp.js', '__testbase_find.js',
00091                             'exception.js']: 
00092                 continue
00093             lineno = int(lineno)
00094             if lineno == 0:
00095                 fname = "<unknown>"
00096             ret.append('File "%s", line %s, in %s' % (
00097                         fname, lineno, funcsig or '?'))
00098             if lineno > 0:
00099                 line = py.path.local(fpath).readlines()[lineno - 1]
00100                 ret.append('    %s' % (line.strip(),))
00101         return '\n'.join(['  %s' % (r,) for r in ret]) 
00102             
00103 class JSChecker(py.test.collect.Module):
00104     def __repr__(self): 
00105         return py.test.collect.Collector.__repr__(self) 
00106 
00107     def setup(self): 
00108         pass 
00109 
00110     def teardown(self): 
00111         pass 
00112 
00113     def run(self): 
00114         findjs = here.join('testing/findtests.js').read() % (
00115                     self.fspath.strpath, '__main__')
00116         curdir = str(py.path.local('.'))
00117         py.std.os.chdir(str(self.fspath.dirpath()))
00118         tests = []
00119         try:
00120             jspath = self.fspath.new(basename='__findtests.js')
00121             try:
00122                 jspath.write(findjs)
00123                 stdin, pipe, stderr = py.std.os.popen3('js "%s"' % (jspath,))
00124                 try:
00125                     error = stderr.next()
00126                     print 'Error read:', error
00127                 except StopIteration:
00128                     pass
00129                 else:
00130                     if error.find('command not found') > -1:
00131                         py.test.skip(
00132                             'error running "js" (SpiderMonkey), which is '
00133                             'required to run JS tests')
00134                     else:
00135                         py.test.fail(error)
00136                     return
00137                 try:
00138                     for line in pipe:
00139                         tests.append(line.strip())
00140                 finally:
00141                     py.std.sys.stdout = py.std.sys.__stdout__
00142                     pipe.close()
00143             finally:
00144                 jspath.remove()
00145         finally:
00146             py.std.os.chdir(curdir)
00147         return ['%s/%s' % (self.fspath.basename, test) for test in tests]
00148 
00149     def join(self, name):
00150         if py.path.local(name).dirpath().strpath.endswith('.js'):
00151             return JSTest(name, self)
00152         return super(JSChecker, self).join(name)
00153 
00154 class Directory(py.test.collect.Directory):
00155     def run(self):
00156         if self.fspath == here:
00157             return [p.basename for p in self.fspath.listdir('test_*') if
00158                     p.ext in ['.py', '.js']]
00159         return super(Directory, self).run()
00160 
00161     def join(self, name):
00162         if not name.endswith('.js'):
00163             return super(Directory, self).join(name)
00164         p = self.fspath.join(name)
00165         if p.check(file=1):
00166             return JSChecker(p, parent=self)