blob: 9dc3f6ed6553e0d354ac00380eb2f322559adb46 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Run unittests in a new browser."""
import argparse
import logging
import os
import subprocess
import sys
import libdot
# Path to our html test page.
TEST_PAGE = os.path.join(libdot.DIR, 'html', 'lib_test.html')
def get_parser():
"""Get a parser for our test runner."""
parser = libdot.ArgumentParser(
description='HTML test runner',
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('--browser', default=os.getenv('CHROME_BIN'),
help='Browser program to run tests against.')
parser.add_argument('--profile', default=os.getenv('CHROME_TEST_PROFILE'),
help='Browser profile dir to run against.')
parser.add_argument('--skip-mkdeps', dest='run_mkdeps',
action='store_false', default=True,
help='Skip (re)building of dependencies.')
parser.add_argument('--visible', action='store_true',
help='Show the browser window to interact with.')
parser.add_argument('--reporter', default='spec',
help='Set the mocha test results report format.')
# Note: This CLI option matches Chrome's own naming.
parser.add_argument('--no-sandbox', dest='sandbox',
action='store_false', default=True,
help='Disable Chrome sandboxing.')
return parser
def test_runner_main(argv, path, serve=False, mkdeps=False):
"""Open the test page at |path|.
Args:
argv: The program's command line arguments.
path: Path to the test page.
serve: Whether to launch a webserver or load the page from disk.
mkdeps: Callback to build dependencies after we've initialized.
"""
parser = get_parser()
opts = parser.parse_args(argv)
# Try to use default X session.
os.environ.setdefault('DISPLAY', ':0')
# Ensure chai/mocha node modules exist.
libdot.node_and_npm_setup()
# Set up any deps.
if mkdeps:
if opts.run_mkdeps:
mkdeps(opts)
else:
logging.info('Skipping building dependencies due to --skip-mkdeps')
# Set up a unique profile to avoid colliding with user settings.
profile_dir = opts.profile
if not profile_dir:
profile_dir = os.path.expanduser('~/.config/google-chrome-run_local')
os.makedirs(profile_dir, exist_ok=True)
# Find a Chrome version to run against.
browser = opts.browser
if not browser:
browser = libdot.headless_chrome.chrome_setup()
# Kick off server if needed.
if serve:
server = subprocess.Popen(
[libdot.node.NODE,
os.path.join(libdot.node.NODE_BIN_DIR, 'http-server'),
'-a', 'localhost', '-c-1', '--cors'],
cwd=libdot.LIBAPPS_DIR)
path = 'http://localhost:8080/%s' % path
# Some environments are unable to utilize the sandbox: we're not running as
# root, and userns is unavailable. For example, while using docker.
if opts.sandbox:
sb_arg = mocha_sb_arg = []
else:
sb_arg = ['--no-sandbox']
# The wrapper requires omitting the leading dashes for no real reason.
mocha_sb_arg = ['--args=no-sandbox']
try:
# Kick off test runner in the background so we exit.
logging.info('Running tests against browser "%s".', browser)
logging.info('Tests page: %s', path)
if opts.visible:
subprocess.Popen([browser, '--user-data-dir=%s' % (profile_dir,),
path] + sb_arg)
else:
# The standalone mocha runner doesn't have a timeout. The headless
# one defaults to 1 minute which is too slow for some of our suites.
# Increase it to 5 minutes as that should be good enough for all.
libdot.node.run(['mocha-headless-chrome', '-e', browser, '-f', path,
'--reporter', opts.reporter, '--timeout=300000'] +
mocha_sb_arg)
finally:
# Wait for the server if it exists.
if serve:
if opts.visible:
try:
server.wait()
except KeyboardInterrupt:
pass
else:
server.terminate()
def main(argv):
"""The main func!"""
return test_runner_main(argv, 'file://%s' % (TEST_PAGE,))
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))