I need to improve my continuous integration solutions for Patterns in Polymer. I do not know that I necessarily need to include a chapter on it in the book, but I ought to at least be able to point to some solutions in my research notes. Especially since I have been asked about it multiple times this week alone.
With that in mind, I first need to test my
AFormInputMixin
class from last night, which serves as mixin or baseclass for other Polymer.dart elements so that they can behave like native HTML form input elements. This turns out to be a little trickier than I had expected, but I'll get to that in a bit.I start with the usual Polymer.dart
test/index.html
entry point in this package's pubspec.yaml
file:name: a-form-input author: "Chris Strom <github@eeecomputes.com>" description: "Polymer element that mimics a native <form> input." dependencies: polymer: any dev_dependencies: unittest: any transformers: - polymer: entry_points: - test/index.htmlThe
test/index.html
page loads a concrete element that uses the mixin, then pulls in the necessary test code:<!doctype html> <html> <head> <!-- Load component(s) --> <link rel="import" href="x-double.html"> <!-- The actual tests --> <script type="application/dart" src="test.dart"></script> <script src="packages/unittest/test_controller.js"></script> </head> <body> </body> </html>The test/test.dart file is pretty typical Polymer testing code. It pulls in the necessary libraries, initializes Polymer (there can be only one
main()
so the test entry point has to start Polymer), creates DOM containers for the test elements and establishes tear downs for the same:library plain_old_forms_test; import 'package:unittest/unittest.dart'; import 'dart:html'; import 'dart:async'; import 'package:polymer/polymer.dart'; main() { initPolymer(); var _el, _form, _container; group("AFormInputMixin mixed into <x-double>", (){ setUp((){ _container = createElement('<div></div>'); _form = createElement('<form></form>'); _el = createElement('<x-double></x-double>'); _form.append(_el); _container.append(_form); document.body.append(_container); }); tearDown((){ _container.remove(); }); group('acts like <input> -', (){ setUp((){ _el.name = 'my_field_name'; _el.start = '21'; var completer = new Completer(); _el.async(completer.complete); return completer.future; }); test('value property is updated when internal state changes', (){ expect(_el.value, '42'); // Doubled by <x-double> }); // ... }); }); }Aside from the funkiness of the
async()
callback in setUp()
, the tests themselves are straight-forward. In the test above, I ensure that the <x-double>
example element places the doubled start
value on the value
property. This all works in the browser, so now I need a script that can be used on a continuous integration server.I start by running some static type analysis with test/run.sh:
#!/bin/bash # Static type analysis results=$(dartanalyzer lib/a_form_input.dart 2>&1) echo "$results" if [[ "$results" != *"No issues found"* ]] then exit 1 fi echo "Looks good!" echoThat works fine, so now it is time for the actual tests. I start those with the standard
content_shell
:#!/bin/bash # Static type analysis.... # Run a set of Dart Unit tests results=$(content_shell --dump-render-tree test/index.html) echo -e "$results" # check to see if DumpRenderTree tests # fails, since it always returns 0 if [[ "$results" == *"Some tests failed"* ]] then exit 1 fi if [[ "$results" == *"Exception: "* ]] then exit 1 fiAnd here is where I run into problems. All of the tests pass when run from
pub serve
, but with content_shell, I get:CONSOLE MESSAGE: warning: polymer.html not found. CONSOLE WARNING: line 213: Error: www.polymer-project.org. CONSOLE WARNING: line 213: FAIL CONSOLE ERROR: Exception: Bad state: polymer.js must be loaded before polymer.dart, please add <link rel="import" href="packages/polymer/polymer.html"> to your <head> before any Dart scripts. Alternatively you can get a different version of polymer.js by following the instructions at http://www.polymer-project.org
Since I am mixing the solution in this package into another class, I seem to be running afoul of resource loading limitations and the lack of transformers being run on local resources. So I have to borrow my solution for testing ajax resources with a pub server in the test:
#!/bin/bash # Static type analysis.... pub serve & pub_pid=$! # Wait for server to build elements and spin up... sleep 15 # Run a set of Dart Unit tests results=$(content_shell --dump-render-tree http://localhost:8080) echo -e "$results" kill $pub_pid # check to see if DumpRenderTree tests fail...That is less than ideal, but it does the trick:
$ /test/run.sh Analyzing [lib/a_form_input.dart]... No issues found Looks good! Loading source assets... Loading polymer transformers... Serving a-form-input test on http://localhost:8080 Build completed successfully ... CONSOLE MESSAGE: unittest-suite-wait-for-done CONSOLE MESSAGE: PASS: AFormInputMixin mixed into <x-double> has a shadowRoot CONSOLE MESSAGE: PASS: AFormInputMixin mixed into <x-double> acts like <input> - value property is updated when internal state changes CONSOLE MESSAGE: PASS: AFormInputMixin mixed into <x-double> acts like <input> - value attribute is updated when internal state changes CONSOLE MESSAGE: PASS: AFormInputMixin mixed into <x-double> acts like <input> - form value attribute is updated when internal state changes CONSOLE MESSAGE: PASS: AFormInputMixin mixed into <x-double> acts like <input> - containing form includes input with supplied name attribute CONSOLE MESSAGE: PASS: AFormInputMixin mixed into <x-double> acts like <input> - setting the name property updates the name attribute CONSOLE MESSAGE: CONSOLE MESSAGE: All 6 tests passed. CONSOLE MESSAGE: unittest-suite-success CONSOLE WARNING: line 213: PASSIt might be nice for this to work without the server, so I may take some time tomorrow to explore that a bit. Regardless, I have a solution for testing Polymer.dart base and mixin classes.
Day #18
> I do not know that I necessarily need to include a chapter on it in the book,
ReplyDeleteI would love to have a chapter on this in THE book : for me TDD goes in pair with continuous integration with regression tests. What the point of writing tests if they don't tell you when thing become broken ?
I completely agree that there is no point to writing tests unless you run them all the time. The only reason that I would not include it in the book proper is that such a solution would be tied to a specific CI service. The book is really meant for solutions that transcend the Dart and JavaScript implementations. I can do that with testing approaches, but I don't think it's possible with testing services.
DeleteI could be wrong (and I usually am!). I'll play around with it over the next couple of days to be sure...
I converted bash script to Dart test app.
ReplyDeleteGitHub: https://github.com/DisDis/DartUITest.git
Nifty! I normally prefer Bash scripts, but Dart scripts have definite cross-platform advantages. I have never tried running the analyzer as a service like that -- very good to know. Thanks!
Delete