[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.
In the `dict` named ``skip`` is optional and may have the following keys:
jsinterp
interpret
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,
or `False`, which is the default value.
or `False`, which is the default value and has no effect.
Example:
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.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 = [
{

View File

@ -21,7 +21,9 @@ __doc__ = """see: `js2tests`"""
defs = gettestcases()
# 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):
@ -29,8 +31,9 @@ class TestJSInterpreter(unittest.TestCase):
self.defs = defs
def generator(test_case, name):
def generator(test_case, my_log):
def test_template(self):
my_log.debug('Started...')
for test in test_case['subtests']:
excluded = test.get('exclude')
if excluded is not None and 'jsinterp' in excluded:
@ -50,40 +53,46 @@ def generator(test_case, name):
if variables is not None:
code = 'function f(%s){%s}' % ((''.join(variables.keys())), code)
call = ('f',) + tuple(v for v in variables.values())
my_log.debug('globals: %s' % variables)
my_log.debug(code)
jsi = JSInterpreter(code, objects=variables)
for assertion in test['asserts']:
if 'value' in assertion:
if call is None:
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'])
else:
log.debug('No value in assertion, skipping')
my_log.info('No value in assertion, skipping')
else:
log.debug(log_reason)
my_log.info(log_reason)
log = logging.getLogger('TestJSInterpreter.%s' % name)
return test_template
# And add them to TestJSInterpreter
for n, tc in enumerate(defs):
reason = tc['skip'].get('jsinterp', False)
tname = 'test_' + str(tc['name'])
for testcase in defs:
reason = testcase['skip'].get('jsinterp', False)
tname = 'test_' + str(testcase['name'])
i = 1
while hasattr(TestJSInterpreter, tname):
tname = 'test_%s_%d' % (tc['name'], i)
tname = 'test_%s_%d' % (testcase['name'], i)
i += 1
if reason is not True:
if reason is True:
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'''
else:
log_reason = None
if log_reason is not None:
test_method = generator(tc, tname)
if log_reason is None:
test_method = generator(testcase, log.getChild(tname))
test_method.__name__ = str(tname)
if reason is not False:
test_method.__unittest_skip__ = True
@ -91,8 +100,7 @@ for n, tc in enumerate(defs):
setattr(TestJSInterpreter, test_method.__name__, test_method)
del test_method
else:
log = logging.getLogger('TestJSInterpreter')
log.debug('Skipping %s:%s' % (tname, log_reason))
log.info('Skipping %s:%s' % (tname, log_reason))
if __name__ == '__main__':
unittest.main()

View File

@ -21,20 +21,23 @@ __doc__ = """see: `js2tests`"""
defs = gettestcases()
# 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):
self.defs = defs
def generator(test_case, name):
def generator(test_case, my_log):
def test_template(self):
my_log.debug('Started...')
for test in test_case['subtests']:
excluded = test.get('exclude')
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:
log_reason = 'No code in subtest, skipping'
elif 'asserts' not in test:
@ -43,48 +46,57 @@ def generator(test_case, name):
log_reason = 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.run()
for assertion in test['asserts']:
if 'value' in assertion:
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'])
else:
log.debug('No value in assertion, skipping')
my_log.info('No value in assertion, skipping')
else:
log.debug(log_reason)
my_log.info(log_reason)
log = logging.getLogger('TestJSInterpreter.%s' % name)
return test_template
# And add them to TestJSInterpreter
for n, tc in enumerate(defs):
reason = tc['skip'].get('interpret', False)
tname = 'test_' + str(tc['name'])
# And add them to TestJSInterpreter2
for testcase in defs:
reason = testcase['skip'].get('interpret', False)
tname = 'test_' + str(testcase['name'])
i = 1
while hasattr(TestJSInterpreter, tname):
tname = 'test_%s_%d' % (tc['name'], i)
while hasattr(TestJSInterpreter2, tname):
tname = 'test_%s_%d' % (testcase['name'], i)
i += 1
if reason is not True:
if reason is True:
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'''
else:
log_reason = None
if log_reason is not None:
test_method = generator(tc, tname)
if log_reason is None:
test_method = generator(testcase, log.getChild(tname))
test_method.__name__ = str(tname)
if reason is not False:
test_method.__unittest_skip__ = True
test_method.__unittest_skip_why__ = reason
setattr(TestJSInterpreter, test_method.__name__, test_method)
setattr(TestJSInterpreter2, test_method.__name__, test_method)
del test_method
else:
log = logging.getLogger('TestJSInterpreter')
log.debug('Skipping %s:%s' % (tname, log_reason))
log.info('Skipping %s:%s' % (tname, log_reason))
if __name__ == '__main__':
unittest.main()

View File

@ -34,51 +34,63 @@ __doc__ = """see: `js2tests`"""
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)
log = logging.getLogger('TestJSInterpreter2Parse')
class TestJSInterpreterParse(unittest.TestCase):
class TestJSInterpreter2Parse(unittest.TestCase):
def setUp(self):
self.defs = defs
def generator(test_case, name):
def generator(test_case, my_log):
def test_template(self):
my_log.debug('Started...')
for test in test_case['subtests']:
if 'code' in test:
jsp = Parser(test['code'])
code = test['code']
my_log.debug(code)
jsp = Parser(code)
parsed = list(jsp.parse())
if 'ast' in test:
self.assertEqual(traverse(parsed), traverse(test['ast']))
else:
log.debug('No AST for subtest, trying to parse only')
my_log.info('No AST for subtest, trying to parse only')
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
# And add them to TestJSInterpreterParse
# And add them to TestJSInterpreter2Parse
for testcase in defs:
reason = testcase['skip'].get('parse', False)
tname = 'test_' + str(testcase['name'])
i = 1
while hasattr(TestJSInterpreterParse, tname):
while hasattr(TestJSInterpreter2Parse, tname):
tname = 'test_%s_%d' % (testcase['name'], i)
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:
test_method.__unittest_skip__ = True
test_method.__unittest_skip_why__ = reason
test_method.__name__ = str(tname)
setattr(TestJSInterpreterParse, test_method.__name__, test_method)
setattr(TestJSInterpreter2Parse, test_method.__name__, test_method)
del test_method
else:
log = logging.getLogger('TestJSInterpreterParse')
log.debug('Skipping %s:Entirely' % tname)
log.info('Skipping %s:%s' % (tname, log_reason))
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
class TestJSInterpreter(unittest.TestCase):
class TestJSInterpreterOrig(unittest.TestCase):
def test_basic(self):
jsi = JSInterpreter('function x(){;}')
self.assertEqual(jsi.call_function('x'), None)