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
This commit is contained in:
Dave Borowitz 2015-11-23 14:59:24 -05:00
parent 9ef32374ba
commit c89f64cc7c
5 changed files with 198 additions and 3 deletions

View File

@ -28,3 +28,6 @@
[cache]
mode = dir
dir = ~/.gerritcodereview/buck-cache/locally-built-artifacts
[test]
excluded_labels = manual

View File

@ -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',

View File

@ -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
```

View File

@ -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',
],
)

View File

@ -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()