Browse Source

examples tests

Eric Charles 5 năm trước cách đây
mục cha
commit
4fa7d7a82f
3 tập tin đã thay đổi với 76 bổ sung95 xóa
  1. 1 1
      examples/app/main.py
  2. 34 23
      examples/example_check.py
  3. 41 71
      jupyterlab/browser_check.py

+ 1 - 1
examples/app/main.py

@@ -19,7 +19,7 @@ with open(os.path.join(HERE, 'package.json')) as fid:
 def _jupyter_server_extension_paths():
     return [
         {
-            'module': __name__,
+            'module': 'example',
             'app': ExampleApp
         }
     ]

+ 34 - 23
examples/example_check.py

@@ -15,28 +15,25 @@ from os import path as osp
 import os
 import shutil
 import sys
+import subprocess
 
 from tornado.ioloop import IOLoop
 from traitlets import Bool, Dict, Unicode
 from jupyter_server.serverapp import ServerApp
 from jupyterlab.labapp import get_app_dir
-from jupyterlab.browser_check import run_test, run_async_process
+from jupyterlab.browser_check import run_test
+# from jupyterlab.browser_check import run_async_process
 from jupyter_server.serverapp import ServerApp
 
-here = osp.abspath(osp.dirname(__file__))
-
 
-class ExampleServerApp(ServerApp):
-    def start(self):
-        run_test(self, run_browser)
-        super().start()
+here = osp.abspath(osp.dirname(__file__))
 
 
 def main():
     # Load the main file and grab the example class so we can subclass
     example_dir = sys.argv.pop()
     mod_path = osp.abspath(osp.join(example_dir, 'main.py'))
-    spec = importlib.util.spec_from_file_location("example", mod_path)
+    spec = importlib.util.spec_from_file_location('example', mod_path)
     mod = importlib.util.module_from_spec(spec)
     spec.loader.exec_module(mod)
     sys.modules['example'] = mod
@@ -46,31 +43,33 @@ def main():
         JS console errors, JS errors, and Python logged errors.
         """
         extension_name = 'example'
+        extension_url = '/example'
         default_url = '/example'
-        open_browser = Bool(False)
-        base_url = '/foo/'
+        open_browser = Bool(False)        
+#        base_url = '/foo/'
         ip = '127.0.0.1'
 
-        def initialize_handlers(self):
+        def initialize_settings(self):
             run_test(self.serverapp, run_browser)
-            super().initialize_handlers()
+            super().initialize_settings()
 
-    App.__name__ = osp.basename(example_dir).capitalize() + 'Test'
 
-    def _jupyter_server_extension_paths():
-        return [
-            {
-                'module': 'example',
-                'app': App
-            }
-        ]
-    sys.modules['example']._jupyter_server_extension_paths = _jupyter_server_extension_paths
+        def _jupyter_server_extension_paths():
+            return [
+                {
+                    'module': 'example',
+                    'app': App
+                }
+            ]
+
+        mod._jupyter_server_extension_paths = _jupyter_server_extension_paths
 
+    App.__name__ = osp.basename(example_dir).capitalize() + 'Test'
     App.launch_instance()
 
+"""
 async def run_browser(url):
-    """Run the browser test and return an exit code.
-    """
+    Run the browser test and return an exit code.
     target = osp.join(get_app_dir(), 'example_test')
     if not osp.exists(osp.join(target, 'node_modules')):
         os.makedirs(target)
@@ -78,6 +77,18 @@ async def run_browser(url):
         await run_async_process(["jlpm", "add", "puppeteer"], cwd=target)
     shutil.copy(osp.join(here, 'chrome-example-test.js'), osp.join(target, 'chrome-example-test.js'))
     await run_async_process(["node", "chrome-example-test.js", url], cwd=target)
+"""
+
+def run_browser(url):
+    """Run the browser test and return an exit code.
+    """
+    target = osp.join(get_app_dir(), 'example_test')
+    if not osp.exists(osp.join(target, 'node_modules')):
+        os.makedirs(target)
+        subprocess.call(["jlpm", "init", "-y"], cwd=target)
+        subprocess.call(["jlpm", "add", "puppeteer"], cwd=target)
+    shutil.copy(osp.join(here, 'chrome-example-test.js'), osp.join(target, 'chrome-example-test.js'))
+    return subprocess.check_call(["node", "chrome-example-test.js", url], cwd=target)
 
 
 if __name__ == '__main__':

+ 41 - 71
jupyterlab/browser_check.py

@@ -4,17 +4,15 @@
 This module is meant to run JupyterLab in a headless browser, making sure
 the application launches and starts up without errors.
 """
-import asyncio
 from concurrent.futures import ThreadPoolExecutor
-import inspect
 import logging
 from os import path as osp
 import os
 import shutil
 import sys
+import subprocess
 
 from tornado.ioloop import IOLoop
-from tornado.iostream import StreamClosedError
 from jupyter_server.serverapp import flags, aliases, ServerApp
 from jupyter_server.utils import urljoin, pathname2url
 from traitlets import Bool, Dict
@@ -47,11 +45,11 @@ class LogErrorHandler(logging.Handler):
         self.errored = False
 
     def filter(self, record):
-        # Handle known StreamClosedError from Tornado
-        # These occur when we forcibly close Websockets or
-        # browser connections during the test.
-        # https://github.com/tornadoweb/tornado/issues/2834
-        if hasattr(record, 'exc_info') and isinstance(record.exc_info[1], StreamClosedError):
+        # known startup error message
+        if 'paste' in record.msg:
+            return
+        # handle known shutdown message
+        if 'Stream is closed' in record.msg:
             return
         return super().filter(record)
 
@@ -61,30 +59,41 @@ class LogErrorHandler(logging.Handler):
 
 
 def run_test(app, func):
-    """Synchronous entry point to run a test function.
-
-    func is a function that accepts an app url as a parameter and returns a result.
-
-    func can be synchronous or asynchronous.  If it is synchronous, it will be run
-    in a thread, so asynchronous is preferred.
-    """
-    IOLoop.current().spawn_callback(run_test_async, app, func)
-
-
-async def run_test_async(app, func):
     """Run a test against the application.
-
     func is a function that accepts an app url as a parameter and returns a result.
-
-    func can be synchronous or asynchronous.  If it is synchronous, it will be run
-    in a thread, so asynchronous is preferred.
     """
     handler = LogErrorHandler()
-    app.log.addHandler(handler)
 
     env_patch = TestEnv()
     env_patch.start()
 
+    def finished(future):
+        try:
+            result = future.result()
+        except Exception as e:
+            app.log.error(str(e))
+        app.log.info('Stopping server...')
+        app.stop()
+        if handler.errored:
+            app.log.critical('Exiting with 1 due to errors')
+            result = 1
+        elif result != 0:
+            app.log.critical('Exiting with %s due to errors' % result)
+        else:
+            app.log.info('Exiting normally')
+            result = 0
+
+        try:
+            app.http_server.stop()
+            app.io_loop.stop()
+            env_patch.stop()
+            os._exit(result)
+        except Exception as e:
+            self.log.error(str(e))
+            if 'Stream is closed' in str(e):
+                os._exit(result)
+            os._exit(1)
+
     # The entry URL for browser tests is different in notebook >= 6.0,
     # since that uses a local HTML file to point the user at the app.
     if hasattr(app, 'browser_open_file'):        
@@ -92,61 +101,22 @@ async def run_test_async(app, func):
     else:
         url = app.display_url
 
-    # Allow a synchronous function to be passed in.
-    if inspect.isawaitable(func):
-        test = func(url)
-    else:
-        loop = asyncio.get_event_loop()
-        executor = ThreadPoolExecutor()
-        task = loop.run_in_executor(executor, func, url)
-        test = asyncio.wait([task])
-
-    try:
-       await test
-    except Exception as e:
-        app.log.critical("Caught exception during the test:")
-        app.log.error(str(e))
-
-    app.log.info("Test Complete")
-
-    result = 0
-    if handler.errored:
-        result = 1
-        app.log.critical('Exiting with 1 due to errors')
-    else:
-        app.log.info('Exiting normally')
-
-    app.log.info('Stopping server...')
-    try:
-        app.http_server.stop()
-        app.io_loop.stop()
-        env_patch.stop()
-    except Exception as e:
-        self.log.error(str(e))
-        result = 1
-    finally:
-        sys.exit(result)
-
-
-async def run_async_process(cmd, **kwargs):
-    """Run an asynchronous command"""
-    proc = await asyncio.create_subprocess_exec(
-            *cmd,
-            **kwargs)
-
-    return await proc.communicate()
+    app.log.addHandler(handler)
+    pool = ThreadPoolExecutor()
+    future = pool.submit(func, url)
+    IOLoop.current().add_future(future, finished)
 
 
-async def run_browser(url):
+def run_browser(url):
     """Run the browser test and return an exit code.
     """
     target = osp.join(get_app_dir(), 'browser_test')
     if not osp.exists(osp.join(target, 'node_modules')):
         os.makedirs(target)
-        await run_async_process(["jlpm", "init", "-y"], cwd=target)
-        await run_async_process(["jlpm", "add", "puppeteer@^2"], cwd=target)
+        subprocess.call(["jlpm", "init", "-y"], cwd=target)
+        subprocess.call(["jlpm", "add", "puppeteer"], cwd=target)
     shutil.copy(osp.join(here, 'chrome-test.js'), osp.join(target, 'chrome-test.js'))
-    await run_async_process(["node", "chrome-test.js", url], cwd=target)
+    return subprocess.check_call(["node", "chrome-test.js", url], cwd=target)
 
 
 class BrowserApp(LabApp):