[jsinterp] Multi level logging in tests

This commit is contained in:
sulyi 2018-06-04 06:14:04 +02:00
parent 2ce996c688
commit 70d9194719
6 changed files with 90 additions and 54 deletions

View File

@ -27,11 +27,12 @@ Each `dict` in ``tests`` may have the following keys:
objects. objects.
In the `dict` named ``skip`` is optional and may have the following keys: In the `dict` named ``skip`` is optional and may have the following keys:
jsinterp
interpret interpret
parse parse
Both used as the argument of `skipTest` decorator of the created test method in `test_jsinterp` Each used as the argument of `skipTest` decorator of the created test method in `test_jsinterp`
and `test_jsinterp_parse` respectably. Unless they're value is `True`, that case the test method is skipped entirely, and `test_jsinterp_parse` respectably. Unless they're value is `True`, that case the test method is skipped entirely,
or `False`, which is the default value. or `False`, which is the default value and has no effect.
Example: Example:
This is not a functional template, rather a skeleton: This is not a functional template, rather a skeleton:

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _OPERATORS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _OPERATORS
skip = {'interpret': 'Interpreting object literals is not yet implemented'} skip = {
'jsinterp': 'Unsupported JS expression',
'interpret': 'Interpreting object literals is not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -21,7 +21,9 @@ __doc__ = """see: `js2tests`"""
defs = gettestcases() defs = gettestcases()
# set level to logging.DEBUG to see messages about missing assertions # set level to logging.DEBUG to see messages about missing assertions
logging.basicConfig(stream=sys.stderr, level=logging.WARNING) # set level to logging.DEBUG to see messages about code tests are running
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
log = logging.getLogger('TestJSInterpreter')
class TestJSInterpreter(unittest.TestCase): class TestJSInterpreter(unittest.TestCase):
@ -29,8 +31,9 @@ class TestJSInterpreter(unittest.TestCase):
self.defs = defs self.defs = defs
def generator(test_case, name): def generator(test_case, my_log):
def test_template(self): def test_template(self):
my_log.debug('Started...')
for test in test_case['subtests']: for test in test_case['subtests']:
excluded = test.get('exclude') excluded = test.get('exclude')
if excluded is not None and 'jsinterp' in excluded: if excluded is not None and 'jsinterp' in excluded:
@ -50,40 +53,46 @@ def generator(test_case, name):
if variables is not None: if variables is not None:
code = 'function f(%s){%s}' % ((''.join(variables.keys())), code) code = 'function f(%s){%s}' % ((''.join(variables.keys())), code)
call = ('f',) + tuple(v for v in variables.values()) call = ('f',) + tuple(v for v in variables.values())
my_log.debug('globals: %s' % variables)
my_log.debug(code)
jsi = JSInterpreter(code, objects=variables) jsi = JSInterpreter(code, objects=variables)
for assertion in test['asserts']: for assertion in test['asserts']:
if 'value' in assertion: if 'value' in assertion:
if call is None: if call is None:
call = assertion['call'] call = assertion['call']
if call is not None:
my_log.debug('call: %s(%s)' % (call[0], ', '.join(str(arg) for arg in call[1:])))
self.assertEqual(jsi.call_function(*call), assertion['value']) self.assertEqual(jsi.call_function(*call), assertion['value'])
else: else:
log.debug('No value in assertion, skipping') my_log.info('No value in assertion, skipping')
else: else:
log.debug(log_reason) my_log.info(log_reason)
log = logging.getLogger('TestJSInterpreter.%s' % name)
return test_template return test_template
# And add them to TestJSInterpreter # And add them to TestJSInterpreter
for n, tc in enumerate(defs): for testcase in defs:
reason = tc['skip'].get('jsinterp', False) reason = testcase['skip'].get('jsinterp', False)
tname = 'test_' + str(tc['name']) tname = 'test_' + str(testcase['name'])
i = 1 i = 1
while hasattr(TestJSInterpreter, tname): while hasattr(TestJSInterpreter, tname):
tname = 'test_%s_%d' % (tc['name'], i) tname = 'test_%s_%d' % (testcase['name'], i)
i += 1 i += 1
if reason is not True: if reason is True:
log_reason = 'Entirely' log_reason = 'Entirely'
elif not any('asserts' in test for test in tc['subtests']): elif not any('asserts' in test for test in testcase['subtests']):
log_reason = '''There isn't any assertion''' log_reason = '''There isn't any assertion'''
else: else:
log_reason = None log_reason = None
if log_reason is not None: if log_reason is None:
test_method = generator(tc, tname) test_method = generator(testcase, log.getChild(tname))
test_method.__name__ = str(tname) test_method.__name__ = str(tname)
if reason is not False: if reason is not False:
test_method.__unittest_skip__ = True test_method.__unittest_skip__ = True
@ -91,8 +100,7 @@ for n, tc in enumerate(defs):
setattr(TestJSInterpreter, test_method.__name__, test_method) setattr(TestJSInterpreter, test_method.__name__, test_method)
del test_method del test_method
else: else:
log = logging.getLogger('TestJSInterpreter') log.info('Skipping %s:%s' % (tname, log_reason))
log.debug('Skipping %s:%s' % (tname, log_reason))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -21,20 +21,23 @@ __doc__ = """see: `js2tests`"""
defs = gettestcases() defs = gettestcases()
# set level to logging.DEBUG to see messages about missing assertions # set level to logging.DEBUG to see messages about missing assertions
logging.basicConfig(stream=sys.stderr, level=logging.WARNING) # set level to logging.DEBUG to see messages about code tests are running
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
log = logging.getLogger('TestJSInterpreter2')
class TestJSInterpreter(unittest.TestCase): class TestJSInterpreter2(unittest.TestCase):
def setUp(self): def setUp(self):
self.defs = defs self.defs = defs
def generator(test_case, name): def generator(test_case, my_log):
def test_template(self): def test_template(self):
my_log.debug('Started...')
for test in test_case['subtests']: for test in test_case['subtests']:
excluded = test.get('exclude') excluded = test.get('exclude')
if excluded is not None and 'jsinterp2' in excluded: if excluded is not None and 'jsinterp2' in excluded:
log_reason = 'jsinterp does not support this subtest:\n%s' % test['code'] log_reason = 'jsinterp2 does not support this subtest:\n%s' % test['code']
elif 'code' not in test: elif 'code' not in test:
log_reason = 'No code in subtest, skipping' log_reason = 'No code in subtest, skipping'
elif 'asserts' not in test: elif 'asserts' not in test:
@ -43,48 +46,57 @@ def generator(test_case, name):
log_reason = None log_reason = None
if log_reason is None: if log_reason is None:
variables = test.get('globals')
code = test['code']
if variables is not None:
my_log.debug('globals: %s' % variables)
my_log.debug(code)
jsi = JSInterpreter(test['code'], variables=(test.get('globals'))) jsi = JSInterpreter(test['code'], variables=(test.get('globals')))
jsi.run() jsi.run()
for assertion in test['asserts']: for assertion in test['asserts']:
if 'value' in assertion: if 'value' in assertion:
call = assertion['call'] call = assertion['call']
if call is not None:
my_log.debug('call: %s(%s)' % (call[0], ', '.join(str(arg) for arg in call[1:])))
self.assertEqual(jsi.call_function(*call), assertion['value']) self.assertEqual(jsi.call_function(*call), assertion['value'])
else: else:
log.debug('No value in assertion, skipping') my_log.info('No value in assertion, skipping')
else: else:
log.debug(log_reason) my_log.info(log_reason)
log = logging.getLogger('TestJSInterpreter.%s' % name)
return test_template return test_template
# And add them to TestJSInterpreter # And add them to TestJSInterpreter2
for n, tc in enumerate(defs): for testcase in defs:
reason = tc['skip'].get('interpret', False) reason = testcase['skip'].get('interpret', False)
tname = 'test_' + str(tc['name']) tname = 'test_' + str(testcase['name'])
i = 1 i = 1
while hasattr(TestJSInterpreter, tname): while hasattr(TestJSInterpreter2, tname):
tname = 'test_%s_%d' % (tc['name'], i) tname = 'test_%s_%d' % (testcase['name'], i)
i += 1 i += 1
if reason is not True: if reason is True:
log_reason = 'Entirely' log_reason = 'Entirely'
elif not any('asserts' in test for test in tc['subtests']): elif not any('asserts' in test for test in testcase['subtests']):
log_reason = '''There isn't any assertion''' log_reason = '''There isn't any assertion'''
else: else:
log_reason = None log_reason = None
if log_reason is not None: if log_reason is None:
test_method = generator(tc, tname) test_method = generator(testcase, log.getChild(tname))
test_method.__name__ = str(tname) test_method.__name__ = str(tname)
if reason is not False: if reason is not False:
test_method.__unittest_skip__ = True test_method.__unittest_skip__ = True
test_method.__unittest_skip_why__ = reason test_method.__unittest_skip_why__ = reason
setattr(TestJSInterpreter, test_method.__name__, test_method) setattr(TestJSInterpreter2, test_method.__name__, test_method)
del test_method del test_method
else: else:
log = logging.getLogger('TestJSInterpreter') log.info('Skipping %s:%s' % (tname, log_reason))
log.debug('Skipping %s:%s' % (tname, log_reason))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -34,51 +34,63 @@ __doc__ = """see: `js2tests`"""
defs = gettestcases() defs = gettestcases()
# set level to logging.DEBUG to see messages about not set ASTs # set level to logging.INFO to see messages about not set ASTs
# set level to logging.DEBUG to see messages about code tests are running
logging.basicConfig(stream=sys.stderr, level=logging.WARNING) logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
log = logging.getLogger('TestJSInterpreter2Parse')
class TestJSInterpreterParse(unittest.TestCase): class TestJSInterpreter2Parse(unittest.TestCase):
def setUp(self): def setUp(self):
self.defs = defs self.defs = defs
def generator(test_case, name): def generator(test_case, my_log):
def test_template(self): def test_template(self):
my_log.debug('Started...')
for test in test_case['subtests']: for test in test_case['subtests']:
if 'code' in test: if 'code' in test:
jsp = Parser(test['code']) code = test['code']
my_log.debug(code)
jsp = Parser(code)
parsed = list(jsp.parse()) parsed = list(jsp.parse())
if 'ast' in test: if 'ast' in test:
self.assertEqual(traverse(parsed), traverse(test['ast'])) self.assertEqual(traverse(parsed), traverse(test['ast']))
else: else:
log.debug('No AST for subtest, trying to parse only') my_log.info('No AST for subtest, trying to parse only')
else: else:
log.debug('No code in subtest, skipping') my_log.info('No code in subtest, skipping')
log = logging.getLogger('TestJSInterpreterParse.%s' % name)
return test_template return test_template
# And add them to TestJSInterpreterParse # And add them to TestJSInterpreter2Parse
for testcase in defs: for testcase in defs:
reason = testcase['skip'].get('parse', False) reason = testcase['skip'].get('parse', False)
tname = 'test_' + str(testcase['name']) tname = 'test_' + str(testcase['name'])
i = 1 i = 1
while hasattr(TestJSInterpreterParse, tname): while hasattr(TestJSInterpreter2Parse, tname):
tname = 'test_%s_%d' % (testcase['name'], i) tname = 'test_%s_%d' % (testcase['name'], i)
i += 1 i += 1
if reason is not True:
test_method = generator(testcase, tname) if reason is True:
log_reason = 'Entirely'
elif not any('asserts' in test for test in testcase['subtests']):
log_reason = '''There isn't any assertion'''
else:
log_reason = None
if log_reason is None:
test_method = generator(testcase, log.getChild(tname))
test_method.__name__ = str(tname)
if reason is not False: if reason is not False:
test_method.__unittest_skip__ = True test_method.__unittest_skip__ = True
test_method.__unittest_skip_why__ = reason test_method.__unittest_skip_why__ = reason
test_method.__name__ = str(tname) setattr(TestJSInterpreter2Parse, test_method.__name__, test_method)
setattr(TestJSInterpreterParse, test_method.__name__, test_method)
del test_method del test_method
else: else:
log = logging.getLogger('TestJSInterpreterParse') log.info('Skipping %s:%s' % (tname, log_reason))
log.debug('Skipping %s:Entirely' % tname)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -11,7 +11,7 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from youtube_dl.jsinterp import JSInterpreter from youtube_dl.jsinterp import JSInterpreter
class TestJSInterpreter(unittest.TestCase): class TestJSInterpreterOrig(unittest.TestCase):
def test_basic(self): def test_basic(self):
jsi = JSInterpreter('function x(){;}') jsi = JSInterpreter('function x(){;}')
self.assertEqual(jsi.call_function('x'), None) self.assertEqual(jsi.call_function('x'), None)