mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Infrastructure for testing RapydScript code
This commit is contained in:
parent
f0f5ca509e
commit
4f106199d6
@ -329,6 +329,59 @@ def atomic_write(base, name, content):
|
|||||||
atomic_rename(tname, name)
|
atomic_rename(tname, name)
|
||||||
|
|
||||||
|
|
||||||
|
def run_rapydscript_tests():
|
||||||
|
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript
|
||||||
|
from PyQt5.Qt import QApplication, QEventLoop
|
||||||
|
from calibre.gui2.webengine import secure_webengine
|
||||||
|
from calibre.gui2 import must_use_qt
|
||||||
|
must_use_qt()
|
||||||
|
base = base_dir()
|
||||||
|
rapydscript_dir = os.path.join(base, 'src', 'pyj')
|
||||||
|
fname = os.path.join(rapydscript_dir, 'test.pyj')
|
||||||
|
with lopen(fname, 'rb') as f:
|
||||||
|
js = compile_fast(f.read(), fname)
|
||||||
|
|
||||||
|
def create_script(src, name):
|
||||||
|
s = QWebEngineScript()
|
||||||
|
s.setName(name)
|
||||||
|
s.setInjectionPoint(QWebEngineScript.DocumentReady)
|
||||||
|
s.setWorldId(QWebEngineScript.ApplicationWorld)
|
||||||
|
s.setRunsOnSubFrames(False)
|
||||||
|
s.setSourceCode(src)
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Tester(QWebEnginePage):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
QWebEnginePage.__init__(self)
|
||||||
|
self.titleChanged.connect(self.title_changed)
|
||||||
|
secure_webengine(self)
|
||||||
|
self.scripts().insert(create_script(js, 'test-rapydscript.js'))
|
||||||
|
self.setHtml('<p>initialize')
|
||||||
|
self.working = True
|
||||||
|
|
||||||
|
def title_changed(self, title):
|
||||||
|
if title == 'initialized':
|
||||||
|
self.titleChanged.disconnect()
|
||||||
|
self.runJavaScript('window.main()', QWebEngineScript.ApplicationWorld, self.callback)
|
||||||
|
|
||||||
|
def spin_loop(self):
|
||||||
|
while self.working:
|
||||||
|
QApplication.instance().processEvents(QEventLoop.ExcludeUserInputEvents)
|
||||||
|
return self.result
|
||||||
|
|
||||||
|
def callback(self, result):
|
||||||
|
self.result = result
|
||||||
|
self.working = False
|
||||||
|
|
||||||
|
def javaScriptConsoleMessage(self, level, msg, line_num, source_id):
|
||||||
|
print(msg, file=sys.stderr if level > 0 else sys.stdout)
|
||||||
|
|
||||||
|
tester = Tester()
|
||||||
|
result = tester.spin_loop()
|
||||||
|
raise SystemExit(int(result))
|
||||||
|
|
||||||
|
|
||||||
def compile_editor():
|
def compile_editor():
|
||||||
base = base_dir()
|
base = base_dir()
|
||||||
rapydscript_dir = os.path.join(base, 'src', 'pyj')
|
rapydscript_dir = os.path.join(base, 'src', 'pyj')
|
||||||
|
47
src/pyj/test.pyj
Normal file
47
src/pyj/test.pyj
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
from __python__ import bound_methods, hash_literals
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from testing import registered_tests, reset_dom
|
||||||
|
|
||||||
|
|
||||||
|
def get_matching_tests_for_name(name):
|
||||||
|
ans = []
|
||||||
|
for k in Object.keys(registered_tests):
|
||||||
|
q = k.split('.')[-1]
|
||||||
|
if not name or q is name:
|
||||||
|
ans.append(registered_tests[k])
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def run_tests(tests):
|
||||||
|
failed_tests = []
|
||||||
|
count = 0
|
||||||
|
for f in tests:
|
||||||
|
print(f.test_name, '...')
|
||||||
|
reset_dom()
|
||||||
|
try:
|
||||||
|
f()
|
||||||
|
count += 1
|
||||||
|
except:
|
||||||
|
traceback.print_stack()
|
||||||
|
failed_tests.append((f.test_name, traceback.format_stack()))
|
||||||
|
return failed_tests, count
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tests = get_matching_tests_for_name()
|
||||||
|
st = window.performance.now()
|
||||||
|
failed_tests, total = run_tests(tests)
|
||||||
|
time = window.performance.now() - st
|
||||||
|
if failed_tests.length:
|
||||||
|
console.error(f'{failed_tests.length} out of {total} failed in {time:.1f} seconds')
|
||||||
|
else:
|
||||||
|
print(f'Ran {total} tests in {time:.1f} seconds')
|
||||||
|
return 1 if failed_tests.length else 0
|
||||||
|
|
||||||
|
|
||||||
|
window.main = main
|
||||||
|
document.title = 'initialized'
|
78
src/pyj/testing.pyj
Normal file
78
src/pyj/testing.pyj
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
from __python__ import bound_methods, hash_literals
|
||||||
|
|
||||||
|
from dom import clear
|
||||||
|
|
||||||
|
def raise_fail(preamble, msg):
|
||||||
|
if msg:
|
||||||
|
msg = '. ' + msg
|
||||||
|
else:
|
||||||
|
msg = ''
|
||||||
|
raise AssertionError(preamble + msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_equal(a, b, msg):
|
||||||
|
|
||||||
|
def fail():
|
||||||
|
raise_fail(f'{a} != {b}', msg)
|
||||||
|
|
||||||
|
atype = jstype(a)
|
||||||
|
btype = jstype(b)
|
||||||
|
base_types = {'number': True, 'boolean': True, 'string': True, 'undefined': True}
|
||||||
|
if base_types[a] or base_types[b] or a is None or b is None:
|
||||||
|
if a is not b:
|
||||||
|
fail()
|
||||||
|
return
|
||||||
|
if a.__eq__:
|
||||||
|
if not a.__eq__(b):
|
||||||
|
fail()
|
||||||
|
return
|
||||||
|
if b.__eq__:
|
||||||
|
if not b.__eq__(a):
|
||||||
|
fail()
|
||||||
|
return
|
||||||
|
if a.length? or b.length?:
|
||||||
|
if a.length is not b.length:
|
||||||
|
fail()
|
||||||
|
for i in range(a.length):
|
||||||
|
assert_equal(a[i], b[i])
|
||||||
|
return
|
||||||
|
if atype is 'object':
|
||||||
|
for key in Object.keys(a):
|
||||||
|
assert_equal(a[key], b[key])
|
||||||
|
if btype is 'object':
|
||||||
|
for key in Object.keys(b):
|
||||||
|
assert_equal(a[key], b[key])
|
||||||
|
|
||||||
|
if a is not b:
|
||||||
|
fail()
|
||||||
|
|
||||||
|
|
||||||
|
def assert_true(x, msg):
|
||||||
|
if not x:
|
||||||
|
raise_fail(f'{x} is not truthy', msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_fale(x, msg):
|
||||||
|
if x:
|
||||||
|
raise_fail(f'{x} is truthy', msg)
|
||||||
|
|
||||||
|
|
||||||
|
def reset_dom():
|
||||||
|
html = document.documentElement
|
||||||
|
clear(html)
|
||||||
|
head = document.createElement('head')
|
||||||
|
body = document.createElement('body')
|
||||||
|
html.appendChild(head)
|
||||||
|
html.appendChild(body)
|
||||||
|
|
||||||
|
|
||||||
|
registered_tests = {}
|
||||||
|
|
||||||
|
|
||||||
|
def test(f):
|
||||||
|
mod = f.__module__ or 'unknown_test_module'
|
||||||
|
f.test_name = mod + '.' + f.name
|
||||||
|
registered_tests[f.test_name] = f
|
||||||
|
return f
|
Loading…
x
Reference in New Issue
Block a user