Sunday, March 23, 2014

Scheduled Polymer Page Objects Tests


Page Objects for testing Polymer seem to be working out for me nicely. What's not working out so well for me is asynchronous testing—with either the Dart or JavaScript versions of Polymer.

If anything, testing is a little easier in JavaScript, thanks to Jasmine's asynchronous helpers like wait() and run(). As odd as it may seem, I am struggling more with Dart testing than JavaScript testing. Thankfully, the fine Dart folks maintain scheduled_test for asynchronous testing in Dart. Let's see if that make my life any easier when testing Polymer code.

I start by switching my development dependencies from vanilla unittest to scheduled_test in my projects pubspec.yaml:
name: model_example
dependencies:
  polymer: any
dev_dependencies:
  scheduled_test: any
transformers:
- polymer:
    entry_points: web/index.html
A quick pub update and I am ready:
➜  dart git:(master) ✗ pub update
Resolving dependencies.....................
...
Downloading scheduled_test 0.10.1...
...
Changed 2 dependencies!
The resulting tests are much cleaner. That is not too surprising given my experience in the past with scheduled_test. For instance, adding a whole topping to my <x-pizza> pizza builder element is now just a series of schedules:
  group("[adding toppings]", (){
    test('updates the pizza state accordingly', (){
      var toppings = JSON.encode({
        'firstHalfToppings': [],
        'secondHalfToppings': [],
        'wholeToppings': ['green peppers']
      });

      schedule(()=> new Future.delayed(new Duration(milliseconds: 150)));

      schedule(()=> xPizza.addWholeTopping('green peppers'));

      schedule(()=> new Future.delayed(new Duration(milliseconds: 1500)));

      schedule((){
        expect(
          xPizza.currentPizzaStateDisplay,
          equals(toppings)
        );
      });
    });
  });
Some of those schedules are delays to allow the Polymer platform to do its thing. Others are the Page Objects interaction or interrogation.

But as nice as this is to read, it is not working any better for me. If anything, things are worse. No matter what delays I try, I am still getting test failures. Worse, the test failures seem to be more consistent. With the non-scheduled_test tests, I could reliably get the tests to pass under content_shell, even if they usually failed in Dartium. With scheduled_test, I now reliably get failures in both content_shell and Dartium.

Bother. I suspect my tests are trying to tell me something—especially now that I am (hopefully) being more strict with the order in which test code is evaluated. But I'll be darned if I can figure out what my tests are saying. Stumped, I call it a night here, but I think I need to give this another go tomorrow.


Day #12

5 comments:

  1. Have you tried this?

    setUp((){
    var _completer = new Completer();
    _el.async((_) => _completer.complete()));
    return _completer.future;
    });

    I found it here http://www.polymer-project.org/docs/polymer/polymer.html#asyncmethod

    Don't know if it is exactly what you're looking for.

    ReplyDelete
  2. Sorry should mention that async() is present in both Polymer Dart and Polymer JS

    ReplyDelete
  3. Also thanks for introducing me to Page Objects. Inspired me to try and implement some tests for elements I've created. We'll see if I like Page Objects too :-) So far they seem alright.

    ReplyDelete
  4. Now that I've had some sleep, I realise it's probably not what you want, but, I think you can use the async() to wait for a change like updating the DOM thus.

    completer = ...
    el.async((_) => completer.complete() );
    completer.future.then((_) {
    expect(
    xPizza.currentPizzaStateDisplay,
    equals(toppings)
    );
    });
    expect(completer.future, completes);

    I stole that method from Seth and someone else I can't remember the name of. I'll remember at some point when I don't want to.

    ReplyDelete
    Replies
    1. Much thanks for all the suggestions. I'll give this one a try tonight!

      Delete