Joe White’s Blog

Life, .NET, and Cats


Archive for October, 2013

Growl for angular-seed test-status notifications

Sunday, October 20th, 2013

Updated 5/4/2014 for Angular 1.2.16 and Karma 0.10.10.

When you run angular-seed’s test runner (formerly scripts\test.bat, now npm test), it runs all the tests once, and then enters watch mode. If you make a change to any of your source files (either production code or test code), it will automatically re-run the tests. This is pretty cool, but you need some way to see the test results.

If I were doing Angular development at work, I’d have dual monitors, and I could put my editor on one monitor and the test runner’s console window on the other monitor, so I’d get instant feedback. But then I’d go to look something up in the documentation, and now the console is covered up by a Web browser, so I’d have to juggle that. And in my case, Angular is just a hobby, and I don’t have dual monitors at home.

So I went looking for a way to show the build status via toast alerts. And it turned out to be pretty easy.

Growl

The Jasmine test runner has lots of extensions available, and one of them shows build status via Growl notifications.

Growl for Windows in action

Growl is a toast-alert platform for the Mac, and there’s also a Growl for Windows. I’ve included a screenshot of a couple of alerts so you can see what it looks like. Each alert sticks around for a few seconds, so I made my test fail, saved, quickly made it pass, saved, and took a screenshot.

So this is pretty cool. You’ll still have to look at the console window to see which tests failed and why, but if you expected it to pass and it did, you can just keep storming along.

Configuring angular-seed and Growl

  1. Download and install Growl for Windows. The installation is pretty simple.

  2. Go to a command prompt, cd to your project directory (the directory with the package.json in it), and type:

    npm install --save-dev karma-growl-reporter
    

    This will install the karma-growl-reporter Node.js module (and all its dependencies) into your project’s node_modules directory, where they need to be for Jasmine to find them.

    It will also (because of the --save-dev option) automatically modify your package.json file to say that you depend on the karma-growl-reporter package. This isn’t important now, but will be when you want to check out your code on another computer — you can rebuild your node_modules directory on that other computer by running npm install to install all the dependencies listed in your package.json.

  3. Edit your config/karma.conf.js and make the changes labeled “STEP 1” and “STEP 2”. (The below config file also includes the changes to make angular-seed run CoffeeScript tests.)

    module.exports = function(config){
        config.set({
        basePath : '../',
    
        files : [
          'app/lib/angular/angular.js',
          'app/lib/angular/angular-*.js',
          'test/lib/angular/angular-mocks.js',
          'app/js/**/*.js',
          'test/unit/**/*.coffee',
          'test/unit/**/*.js'
        ],
    
        autoWatch : true,
    
        frameworks: ['jasmine'],
    
        browsers : ['Chrome'],
    
        plugins : [
                // STEP 1: Add 'karma-growl-reporter' to this list
                'karma-growl-reporter',
                'karma-coffee-preprocessor',
                'karma-junit-reporter',
                'karma-chrome-launcher',
                'karma-firefox-launcher',
                'karma-jasmine'
                ],
    
        // STEP 2: Add the following section ("reporters") -- or if you already have
        // a "reporters" section, add 'growl' to the list:
        reporters: ['progress', 'growl'],
    
        junitReporter : {
          outputFile: 'test_out/unit.xml',
          suite: 'unit'
        }
    
    })}
    

Then run npm test, and you should see a toast alert pop up, telling you your tests are passing.

Writing CoffeeScript tests with angular-seed

Friday, October 18th, 2013

Updated 5/4/2014 for Angular 1.2.16 and Karma 0.10.10.

The first thing I did, after snagging a copy of angular-seed, was try to write a test in CoffeeScript. It didn’t work out of the box, so I went hunting to figure out how to make it work.

(I also found a few GitHub projects that are prepackaged angular-seed with CoffeeScript, but I didn’t see any that have been kept up-to-date with new Angular versions like angular-seed has. Maybe that’ll change when Angular 1.2 ships. Nope, they’ve pretty much been abandoned.)

Why CoffeeScript rocks for Jasmine/Mocha tests

As awesome as nested describes are, they’re even more awesome in CoffeeScript.

Jasmine tests look like this:

describe('calculator', function() {
    it('adds', function() {
        expect(calculator.add(2, 2)).toBe(4);
    });
});

CoffeeScript has some nice advantages for code like this.

  1. CoffeeScript has a built-in lambda operator, ->, that replaces function() {. So that’s a little less typing, and a lot less of the line taken up by furniture.
  2. CoffeeScript doesn’t need curly braces. Instead, you indicate nested blocks by indenting them (and heck, you were doing that anyway).
  3. CoffeeScript lets you leave off the parentheses around a method’s arguments. (Unlike Ruby, you do still need the () if you’re not passing any arguments.)

Combine these, and you get code that looks like this:

describe 'calculator', ->
    it 'adds', ->
        expect(calculator.add 2, 2).toBe 4

Each line is shorter than before, so there’s less typing and a little better signal-to-noise. But you also don’t need those }); lines at the end, because you don’t need the close-curlies to end the lambdas, and you don’t need the close-parens to end the argument lists for describe and it — in both cases, the indentation suffices. Less ceremony, more essence.

Until you see it on your screen, it’s hard to appreciate just how much it improves your tests, not having all those }); lines. Many tests will consist of a single assertion, so by cutting that worthless extra line, you go from almost 33% noise-by-line-count to 0%. Plus, the entire test goes from three lines to two — so now you can fit 50% more tests on your screen. That’s a win.

The syntax is uncluttered enough that it can even be reasonable to put the whole test on one line:

describe 'calculator', ->
    it 'adds',      -> expect(calculator.add 2, 2).toBe 4
    it 'subtracts', -> expect(calculator.subtract 6, 2).toBe 4

When you’ve got a bunch of little tests that are all on the same theme, this can work really well. That would look a lot uglier if it was function() { instead of ->, and if you had to find a place for the }); as well.

And last but not least, it’s really easy to find a text editor that can do code folding based on indentation (and not as easy to find an editor that can collapse based on curly braces). I use Sublime Text, which is a bit pricey, but you can also do indentation-based code folding with the free SciTE if you put it in Python mode. So if you’ve got a whole nested describe for your calculator’s trig functions, and you want to collapse that because now you’re focusing on hex arithmetic, you just fold that whole section of your code up into a single line.

CoffeeScript tests with angular-seed

It takes some ritual to get angular-seed working with CoffeeScript, but the good news is, you only have to do it once (well, once per project).

Updated 5/4/2014: With Angular 1.2.16 and Karma 0.10.10, the “preprocessors” and “coffeePreprocessor” sections no longer need to be added, so I removed them from the instructions below. If you’re on a version where you do need them, you can copy them from the karma-coffee-preprocessor readme.

All the changes are in config/karma.conf.js. Look for the parts I tagged “STEP 1” and “STEP 2”.

module.exports = function(config){
    config.set({
    basePath : '../',

    files : [
      'app/lib/angular/angular.js',
      'app/lib/angular/angular-*.js',
      'test/lib/angular/angular-mocks.js',
      'app/js/**/*.js',
      // STEP 1: Add 'test/unit/**/*.coffee' to this list:
      'test/unit/**/*.coffee',
      'test/unit/**/*.js'
    ],

    autoWatch : true,

    frameworks: ['jasmine'],

    browsers : ['Chrome'],

    plugins : [
            // STEP 2: Add 'karma-coffee-preprocessor' to this list:
            'karma-coffee-preprocessor',
            'karma-junit-reporter',
            'karma-chrome-launcher',
            'karma-firefox-launcher',
            'karma-jasmine'
            ],

    junitReporter : {
      outputFile: 'test_out/unit.xml',
      suite: 'unit'
    }

})}

Once that’s done, you’re off and running: you can drop a .coffee file in your project’s test/unit directory, and the test runner will pick up all the tests in it and run them.

Note that, at least with the current versions of angular-seed and jasmine, you’ll have to stop and restart scripts\test.bat before it’ll pick up the new test file. (This is true any time you add a new test file; it’s not CoffeeScript-specific.) Watch mode apparently doesn’t extend to watching for new test files. Just Ctrl+C to stop it, say Yes (or hit Ctrl+C again) to the “Terminate batch job (Y/N)?” prompt, and then run scripts\test.bat again, and you’re on your way. No longer an issue with Karma 0.10.10.

Home page redesign

Tuesday, October 15th, 2013

The excastle.com home page has been looking pretty drab for years now. Recently I decided to flex my creative muscles and make it look prettier, with the power of Bootstrap and OpenGameArt (props to extradave and pixel32).

Before:

ExCastle.com, pre-2013

After:

ExCastle.com, circa 2013

This was a fun way to spend a Saturday, and I like how it turned out. I’m still not going to call myself a graphic designer, but at least the page won’t put you to sleep right away.

Latest project: a video game in AngularJS

Monday, October 14th, 2013

I’ve been playing with AngularJS (“Superheroic JavaScript MVW Framework”) for a while. And, as is my wont, I’m trying to learn it by writing a video game with it.

Here’s an introduction to what I’m doing. I’ll go into more details in the near future.

The video game

I’ve been writing and re-writing the same video game for probably at least ten years now, sometimes in Delphi (with or without DirectX), sometimes in WinForms or XNA or XAML, now in HTML5/JavaScript. (It’s a spare-time project, which means I don’t do it to finish something; I do it to learn something.)

The game I’m trying to write is a 2D console RPG, in the vein of the early Final Fantasy games. I haven’t decided whether I’ll target a Web browser, or a Windows Store app; possibly both. Gameplay will be much like Final Fantasy if it were written with a touchscreen in mind. Artwork will come largely from OpenGameArt, especially the Liberated Pixel Cup-style artwork (including some of my own) and the Universal LPC Spritesheet.

And yes, I’m going to try to do this using Angular. Hey, you don’t really know a tool until you’ve tested its limits, right?

A brief introduction to Angular

Some JavaScript frameworks, like jQuery and Handlebars and Knockout, try to solve one small problem and solve it well. Angular, on the other hand, tries to do it all — everything from templating to two-way databinding to extending HTML to dependency injection to testing. And it does it all with relatively few mechanisms — you’ve got services for shared code, directives for manipulating the DOM, and controllers/scopes, and that’s about it.

One nice perk is that Angular uses Jasmine for testing, which means you get those beautiful nested describes. God, I wish I could do that in .NET for my day job.

Angular has a fairly steep learning curve, so I’m not going to cover the mechanics here. The Angular web site has good documentation, including a tutorial. There’s also some good stuff on YouTube, and I picked up a copy of “Mastering Web Application Development with AngularJS”, which is pretty decent.

angular-seed

The angular-seed project looks like it’s probably the best starting point for writing a generic Angular app. Sure, you could start from zero and reference Angular via CDN, but angular-seed gives you a few niceties like a local Web server (node scripts/web-server.js), and it comes pre-configured for you to be able to run your tests (scripts\test.bat) — in watch mode, yet, so they automatically re-run whenever you save one of your source files. Pretty nice.

(There are other starting-point projects out there too, so if you want something with Bootstrap already baked in, or a Node.js/Express backend, there may already be something better than angular-seed for you. But I don’t want any of that stuff, so angular-seed is great for me.)

My only real complaint about angular-seed is that it doesn’t have any Grunt support built-in. It’d be nice to at least have a Grunt task to run the tests, especially since Grunt doesn’t look nearly as easy to get started with as something like Rake. But otherwise, angular-seed seems to be a great jumping-off point.

So… Angular for a video game? Really?

I don’t know whether it would be practical for the overland map, but I think Angular has some potential for the battle screen. There’s a lot of state management that would work well with an MV* framework, like showing a hero’s menu when it’s his turn. And the upcoming Angular 1.2 has some nice support for CSS3 animations — and there are a lot of little animations during a battle: hero takes a step forward, swings his sword, bad guy flinches from the hit, damage numbers appear, etc. I think I can make all those animations happen with databinding — which would mean it’d all be just as testable as I wanted it to be.

Of course, if you’re just using the built-in databinding, then Angular doesn’t tell you when the animation is done so you can start the next one. But Angular is extensible, and if you write your own directive, you can get those notifications easily. I’ve been working on an animation queue to coordinate all these animations across different scopes and elements, and it’ll be interesting to see if I can pull it off.

What’s next?

Angular-seed gives you a workable start. But to be honest, it’s not really a comfortable environment, at least not right out of the box. In particular, Jasmine tests are much nicer in CoffeeScript than they are in JavaScript. And you need a good way to see whether your tests are passing or failing. More on those next time.


Joe White's Blog copyright © 2004-2011. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS). Privacy policy