Random Developments And Random Toys

Taking screenshots of failed Protractor test cases on Travis CI

So. You got a Protractor test suite doing amazing tricks via browser running under xvfb. And then it ocassionally fails, on remote environment like Travis CI only. Now what? Take a screenshot!

Protractor uses Jasmine and it has a quick and easy reporter API. Which you can define and add within protractor.conf.js:

{
  // ... rest of Protractor conf ...

  onPrepare: function() {
    var FailureScreenshotReporter = function() {
      // ... skipped ...
    };

    jasmine.getEnv().addReporter(new FailureScreenshotReporter());
  }
}

The screenshot reporter itself:

var FailureScreenshotReporter = function() {
  this.specDone = function(spec) {
    if(spec.status === 'failed') {
      var fileName = [];

      try { fs.mkdirSync('.tmp/shots'); } catch(e) {}

      fileName.push('.tmp/shots/');

      if(process.env.TRAVIS_BUILD_ID) {
        fileName.push('BUILD-');
        fileName.push(process.env.TRAVIS_BUILD_ID);
        fileName.push('_');
      }

      if(process.env.TRAVIS_PULL_REQUEST) {
        fileName.push('PR-');
        fileName.push(process.env.TRAVIS_PULL_REQUEST);
        fileName.push('_');
      }

      fileName.push(spec.fullName.toLowerCase().replace(/[^a-z0-9\s]/g, '').replace(/\s+/g, '_'));
      fileName.push('.png');

      console.info('Left a screenshot of failed spec at ' + fileName.join(''));

      browser.takeScreenshot().then(function(png) {
        var stream = fs.createWriteStream(fileName.join(''));
        stream.write(new Buffer(png, 'base64'));
        stream.end();
      });
    }
  };
};

This will create a screenshot with Travis build/PR identifier and spec, for example PR-123_this_and_that_button_opens_a_popup.png.

Next step would be collecting those screenshots since Travis environments are discarded immediately after the build. Probably easiest solution is to upload those to S3. That can be by adding the following to project’s .travis.yml:

before_install:
- pip install --user awscli
- export PATH=$PATH:$HOME/.local/bin

after_script:
- aws s3 cp .tmp/shots s3://my-automated-tests/my-project/ --recursive --exclude="*" --include="*.png"

That of course requires your S3 credentials in environment variables.

Learning something new: Rust programming language

New programming languages lately have been popping up almost monthly but one has really caught my eye: Rust. While everyone else is mostly doing new interpreted, garbage collected languages, Rust is quite a bit different. Key points of interest for me are:

  • Rust is compiled systems language allowing to go as low as C
  • Unique memory model – guaranteed memory safety
  • Non garbage collected but it kind of feels like one
  • Threading without data races
  • Supporting pure-functional, concurrent-actor, imperative-procedural, and object-oriented styles

It’s a modern language systems language which can potentially become a very strong competitor C and C++.

While I have no plans to write actual real world WEB applications in Rust, for me personally it looks like a very promising Internet of Things language. Speed and power of C for microcontrollers without headaches of memory management. Sure, microcontrollers nowadays are cheap and powerful but running Python on your light bulb simply does not make sense. And there’s already at least one project with aim to bring Rust into embedded environment: zinc.rs.

Why I *love* Linux

One tool fails with message about failed child process. No further details. No verbose mode / no debug logs. strace to the rescue:

strace -ostrace.txt -f -e trace=process grunt test:e2e

Result? One of many lines in strace output:

9713 execve("/usr/local/bin/java", ["java", "-jar", "/vagrant/node_modules/protractor"..., "-port", "4444", "-Dwebdriver.chrome.driver=/vagra"...], [/* 30 vars */]) = -1 ENOENT (No such file or directory)

9713 execve("/bin/java", ["java", "-jar", "/vagrant/node_modules/protractor"..., "-port", "4444", "-Dwebdriver.chrome.driver=/vagra"...], [/* 30 vars */]) = -1 ENOENT (No such file or directory)

9713 execve("/usr/bin/java", ["java", "-jar", "/vagrant/node_modules/protractor"..., "-port", "4444", "-Dwebdriver.chrome.driver=/vagra"...], [/* 30 vars */]) = -1 ENOENT (No such file or directory)

9713 execve("/usr/local/sbin/java", ["java", "-jar", "/vagrant/node_modules/protractor"..., "-port", "4444", "-Dwebdriver.chrome.driver=/vagra"...], [/* 30 vars */]) = -1 ENOENT (No such file or directory)

Oh yeah, I don’t have Java isntalled on this machine!

Kickstart your Vagrant

A couple night adventure in building custom kickstarted CentOS install disks and then Vagrant base boxes from that. It’s rather satisfying to make it work without any interactions from start to end.

Learn Python the hard and *fun* way

learnpythonthehardway.org is a good resource but.. It can be bland and tedious for an experienced developer. I think I might have found and answer for this… (drumroll) Bioinformatics Algorithms (Part 1) course at Coursera. Why?

  • It’s all about searching / scanning and manipulating lots of very long strings ;)
  • You cannot avoid learning core Python data structures and it’s properties, loops, map, reduce, etc..
  • Exercises are easy to break up into smaller tasks which can be unit tested. It’s perfect for good fun uncomplicated unit testing
  • Because.. Science!

(don’t take this too seriously please)