Sunday, July 21, 2013

Easy Sanity Checks with Early Alpha Dart Packages


I am beginning to feel a tad desperate to get an updated Dart for Hipsters out. The main blocker at this point is the ability to test and analyze some of the more HTTP intensive chapters. Some of the lessons on Dart testing that I have learned over the past few weeks would certainly help.

In the source code for the book, I wound up mocking my HTTP requests so that I could test things:
  void fetch() {
    var req = MaybeMockHttpRequest.httpRequest();
    req.on.load.add((event) {
      var list = JSON.parse(req.responseText);
      _handleOnLoad(list);
    });
    req.open('get', url, async: true);
    req.send();
  }
This has the advantage of being able to be run, but also being testable. The problem is, of course, that I cannot include this code in the book without some kind of pre-processing.

Rather than worry that my pre-processing might introduce bugs in the book copy as the language evolves, I would rather use the test server that I have been working up recently. Really, I'd just as soon use a stubbing strategy like Sinon.js but that is not an option because Dart does not support dynamic method redefinition. Dart boasts some dynamic language features, just nothing that will help me here.

I have a small repository that contains some of the testing work that I have been doing. It is local-only, but it is a git repository, which means that I can install it in other Dart applications using the Pub packaging tool that is built into Dart.

So, in my book's top-level directory, I add my test server repository as a dependency:
name: DartForHipsters
dependencies:
  unittest: any
  browser: any
  plummbur_kruk:
    git:
      /home/chris/repos/plummbur-kruk
A quick pub update and I am ready to go:
➜  code git:(master) ✗ pub update
Resolving dependencies............
Dependencies updated!

➜  mvc git:(master) ✗ ls -l packages 
...
lrwxrwxrwx 1 chris chris 85 Jul 21 22:10 plummbur_kruk -> /home/chris/.pub-cache/git/plummbur_kruk-4e23fa5c4423b6f8226821bd4cdda231ed633dec/lib
...
I have yet to settle on an code organization for the test code. I could put it in the test sub-directory, but there is already a testing sub-directory that supports the Testing chapter in the book. I defer organization for another day and simple create my “Plummbur Kruk” test server as test_server.dart right in the top-level code directory as:
import 'package:plummbur_kruk/server.dart' as PlummburKruk;

main() => PlummburKruk.main();
With that, I can start my test server:
➜  code git:(master) ✗ dart test_server.dart
Server started on port: 31337
Now, back in the code, I can switch to a real HttpRequest object:
  void fetch() {
    var req = new HttpRequest();

    req.on.load.add((event) {
      var list = JSON.parse(req.responseText);
      _handleOnLoad(list);
    });

    req.open('get', url, async: true);
    req.send();
  }
After updating the url getter to point to my test server, I have a passing test again, this time without any mock-post-processing malarkey. I will still have to add some kind of server stop/start/reset code. That could be done as a Bash script or as a Hop task. But the important thing is that I have been able to perform a quick sanity check of running a test server from a very alpha package repository. Hopefully I can build the two together.


Day #819

2 comments:

  1. > It is local-only, but it is a git repository, which means that I can install it in other Dart applications using the Pub packaging tool that is built into Dart.

    For local-only packages, path dependencies are probably a bit easier than a git dependency. The former will give you a live symlink to the other local package which means changes to it will be immediately visible in your main package. When you do a git dependency on a local package, it pins it to the current commit.

    If you're doing a lot of testing with servers and async IO, you may want to check out the scheduled_test package. It's what we use for testing pub and gives you a nicer API for sequencing out a bunch of asynchronous operations.

    ReplyDelete
    Replies
    1. I just got around to testing the path dependency thing… it's great.

      name: awesome_package
      dependencies:
       other:
          path: /path/to/local

      It creates a symlink to /path/to/local just as you say. I remember doing that manually way back when. Love it.

      The Scheduled Test stuff, is pretty cool as well, of course :)

      Delete