From c89f64cc7cda7c6f7dbfcaacf007a3add3a4199a Mon Sep 17 00:00:00 2001 From: Dave Borowitz Date: Mon, 23 Nov 2015 14:59:24 -0500 Subject: [PATCH] Run PolyGerrit tests with Buck Since Buck has no native support for web tests, wrap the tests in a Python shim that calls wct. As in other Polymer cases, we need to prepare a set of inputs and create a directory containing exactly what wct expects to be there. Buck exposes resources to python_tests using the pkg_resources API, which is cumbersome to use, and easier just to ship around zip files as we do elsewhere. Unlike other npm binaries we've encountered, the web-component-tester module has numerous native dependencies, up to and including Selenium. Rather than get in the game of distributing platform-specific binaries, punt and require `wct` to be on the user's $PATH for now. Tests are currently excluded in .buckconfig but can be run directly with either: buck test //polygerrit-ui/app:polygerrit_tests buck test --include web Change-Id: Ia314213925ac27ff271374a96ed539fb2acf0187 --- .buckconfig | 3 + lib/js/BUCK | 19 ++++ polygerrit-ui/README.md | 37 +++++++- polygerrit-ui/app/BUCK | 37 +++++++- polygerrit-ui/app/polygerrit_wct_tests.py | 105 ++++++++++++++++++++++ 5 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 polygerrit-ui/app/polygerrit_wct_tests.py diff --git a/.buckconfig b/.buckconfig index 38fcc58356..fc51e19ef5 100644 --- a/.buckconfig +++ b/.buckconfig @@ -28,3 +28,6 @@ [cache] mode = dir dir = ~/.gerritcodereview/buck-cache/locally-built-artifacts + +[test] + excluded_labels = manual diff --git a/lib/js/BUCK b/lib/js/BUCK index c6831284fc..9f5390ff0e 100644 --- a/lib/js/BUCK +++ b/lib/js/BUCK @@ -113,6 +113,16 @@ bower_component( sha1 = 'e06281b6ddb3355ceca44975a167381b1fd72ce5', ) +bower_component( + name = 'iron-test-helpers', + package = 'PolymerElements/iron-test-helpers', + version = '1.0.6', + semver = '~1.0.6', + deps = [':polymer'], + license = 'DO_NOT_DISTRIBUTE', + sha1 = 'c0f7c7f010ca3c63fb08ae0d9462e400380cde2c', +) + bower_component( name = 'iron-validatable-behavior', package = 'PolymerElements/iron-validatable-behavior', @@ -151,6 +161,15 @@ bower_component( sha1 = 'a3b598c06cbd7f441402e666ff748326030905d6', ) +bower_component( + name = 'test-fixture', + package = 'PolymerElements/test-fixture', + version = '1.0.3', + semver = '^1.0.0', + license = 'DO_NOT_DISTRIBUTE', + sha1 = '21192d554ff6ad7eea894ca751c73b6bc46867dc', +) + bower_component( name = 'webcomponentsjs', package = 'webcomponentsjs', diff --git a/polygerrit-ui/README.md b/polygerrit-ui/README.md index 00ff6127e3..c2cd4bd905 100644 --- a/polygerrit-ui/README.md +++ b/polygerrit-ui/README.md @@ -1,5 +1,18 @@ # PolyGerrit +## Installing [Node.js](https://nodejs.org/en/download/) + +```sh +# Debian/Ubuntu +sudo apt-get install nodejs-legacy + +# OS X with Homebrew +brew install node +``` + +All other platforms: [download from +nodejs.org](https://nodejs.org/en/download/). + ## Local UI, Production Data To test the local UI against gerrit-review.googlesource.com: @@ -31,7 +44,27 @@ java -jar buck-out/gen/polygerrit/polygerrit.war daemon --polygerrit-dev -d ../g ## Running Tests +One-time setup: + ```sh -npm install -g web-component-tester -wct +# Debian/Ubuntu +sudo apt-get install npm + +# OS X with Homebrew +brew install npm + +# All platforms (including those above) +sudo npm install -g web-component-tester +``` + +Run all web tests: + +```sh +buck test --include web +``` + +If you need to pass additional arguments to `wct`: + +```sh +WCT_ARGS='-p --some-flag="foo bar"' buck test --no-results-cache --include web ``` diff --git a/polygerrit-ui/app/BUCK b/polygerrit-ui/app/BUCK index 9da030d14f..317d6b20fb 100644 --- a/polygerrit-ui/app/BUCK +++ b/polygerrit-ui/app/BUCK @@ -1,5 +1,9 @@ include_defs('//lib/js.defs') +WCT_TEST_PATTERNS = ['test/**'] +PY_TEST_PATTERNS = ['polygerrit_wct_tests.py'] +APP_SRCS = glob(['**'], excludes = WCT_TEST_PATTERNS + PY_TEST_PATTERNS) + WEBJS = 'bower_components/webcomponentsjs/webcomponents-lite.js' # TODO(dborowitz): Putting these rules in this package avoids having to handle @@ -38,7 +42,38 @@ genrule( vulcanize( name = 'polygerrit', app = 'elements/gr-app.html', - srcs = glob(['**'], excludes = ['index.html']), + srcs = APP_SRCS, components = ['//polygerrit-ui:polygerrit_components'], ) + +bower_components( + name = 'test_components', + deps = [ + '//polygerrit-ui:polygerrit_components', + '//lib/js:iron-test-helpers', + '//lib/js:test-fixture', + ], +) + +genrule( + name = 'test_resources', + cmd = ' && '.join([ + 'cd $TMP', + 'unzip -q $(location :test_components)', + 'cp -rL $SRCDIR/* .', + 'zip -r $OUT .', + ]), + srcs = APP_SRCS + glob(WCT_TEST_PATTERNS), + out = 'test_resources.zip', +) + +python_test( + name = 'polygerrit_tests', + srcs = glob(PY_TEST_PATTERNS), + resources = [':test_resources'], + labels = [ + 'manual', + 'web', + ], +) diff --git a/polygerrit-ui/app/polygerrit_wct_tests.py b/polygerrit-ui/app/polygerrit_wct_tests.py new file mode 100644 index 0000000000..571dcb8042 --- /dev/null +++ b/polygerrit-ui/app/polygerrit_wct_tests.py @@ -0,0 +1,105 @@ +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function + +import atexit +from distutils import spawn +import json +import os +import pkg_resources +import shlex +import shutil +import subprocess +import sys +import tempfile +import unittest +import zipfile + + +def _write_wct_conf(root, exports): + with open(os.path.join(root, 'wct.conf.js'), 'w') as f: + f.write('module.exports = %s;\n' % json.dumps(exports)) + + +def _wct_cmd(): + return ['wct'] + shlex.split(os.environ.get('WCT_ARGS', '')) + + +class PolyGerritWctTests(unittest.TestCase): + + # Should really be setUpClass/tearDownClass, but Buck's test runner doesn't + # produce sane stack traces from those methods. There's only one test method + # anyway, so just use setUp. + + def _check_wct(self): + self.assertTrue( + spawn.find_executable('wct'), + msg='wct not found; try `npm install -g web-component-tester`') + + def _extract_resources(self): + tmpdir = tempfile.mkdtemp() + atexit.register(lambda: shutil.rmtree(tmpdir)) + root = os.path.join(tmpdir, 'polygerrit') + os.mkdir(root) + + tr = 'test_resources.zip' + zip_path = os.path.join(tmpdir, tr) + s = pkg_resources.resource_stream(__name__, tr) + with open(zip_path, 'w') as f: + shutil.copyfileobj(s, f) + + with zipfile.ZipFile(zip_path, 'r') as z: + z.extractall(root) + + return tmpdir, root + + def test_wct(self): + self._check_wct() + tmpdir, root = self._extract_resources() + + cmd = _wct_cmd() + print('Running %s in %s' % (cmd, root), file=sys.stderr) + + _write_wct_conf(root, { + 'suites': ['test'], + 'webserver': { + 'pathMappings': [ + {'/components/bower_components': 'bower_components'}, + ], + }, + 'plugins': { + 'local': { + # For some reason wct tries to install selenium into its node_modules + # directory on first run. If you've installed into /usr/local and + # aren't running wct as root, you're screwed. Turning this option off + # seems to still work, so there's that. + 'skipSeleniumInstall': True, + }, + }, + }) + + p = subprocess.Popen(cmd, cwd=root, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + sys.stdout.write(out) + sys.stderr.write(err) + self.assertEquals(0, p.returncode) + + # Only remove tmpdir if successful, to allow debugging. + shutil.rmtree(tmpdir) + + +if __name__ == '__main__': + unittest.main()