Developing on Staxmanade

Testing Asynchronous Code with MochaJS and ES7 async/await

(Comments)

A JavaScript project I'm working on recently underwent a pretty good refactor. Many of the modules/methods in the application worked in a synchronous fashion which meant their unit tests were also generally synchronous. This was great because synchronous code is pretty much always easier to test since they're simpler and easier to reason about.

However, even though I new early on that I would likely have to turn a good number of my synchronous methods into asynchronous ones I tried holding off on that as long as absolutely necessary. I was in a mode of prototyping as much of the application out as possible before I wanted to be worried/thinking about asynchronous aspects of the code base.

Part of why I held of on this was because I was pretty confident using the new proposed ES7 async/await syntax to turn the sync code into async code relatively easily. While there were a few bumps along the refactor actually went extremely well.

An example of one bump I ran into included replacing items.forEach(item => item.doSomethingNowThatWillBecomeAsyncSoon()) with something that worked asynchronously and I found this blog post immensely helpful. Basically, don't try to await a forEach instead build a list of promises you can await.

Another one I ran into was dealing with async mocha tests, which is what the rest of this post is about.

MochaJS is great because the asynchronous testing has been there from the beginning. If you've done (see what I did there?) any asynchronous testing with MochaJS then you already know that you can signal to Mocha an asynchronous test is done by calling the test's async callback method.

Before we look at how to test asynchronous Mocha tests leveraging the new ES 7 async/await syntax, let's first take a little journey through some of the various asynchronous testing options with Mocha.

Note: you will see example unit tests that use the expect(...).to.equal(...) style assertions from ChaiJS.

How to create an asynchronous MochaJS test?

If you look at a normal synchronous test:

it("should work", function(){
    console.log("Synchronous test");
});

all we have to do to turn it into an asynchronous test is to add a callback function as the first parameter in the mocha test function (I like to call it done) like this

it("should work", function(done){
    console.log("Synchronous test");
});

But that's an invalid asynchronous test.

Invalid basic async mocha test

This first async example test we show is invalid because the done callback is never called. Here's another example using setTimeout to simulate proper asynchronicity. This will show up in Mocha as a timeout error because we never signal back to mocha by calling our done method.

it("where we forget the done() callback!", function(done){
    setTimeout(function() {
        console.log("Test");
    }, 200);
});

Valid basic async mocha test

When we call the done method it tells Mocha the asynchronous work/test is complete.

it("Using setTimeout to simulate asynchronous code!", function(done){
    setTimeout(function() {
        done();
    }, 200);
});

Valid basic async mocha test (that fails)

With asynchronous tests, the way we tell Mocha the test failed is by passing an Error or string to the done(...) callback

it("Using setTimeout to simulate asynchronous code!", function(done){
    setTimeout(function() {
        done(new Error("This is a sample failing async test"));
    }, 200);
});

Invalid async with Promise mocha test

If you were to run the below test it would fail with a timeout error.

it("Using a Promise that resolves successfully!", function(done) {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello!");
        }, 200);
    });

    testPromise.then(function(result) {
        expect(result).to.equal("Hello World!");
        done();
    }, done);
});

If you were to open up your developer tools you may notice an error printed to the console:

    Uncaught (in promise) i {message: "expected 'Hello!' to equal 'Hello World!'", showDiff: true, actual: "Hello!", expected: "Hello World!"}

The problem here is the expect(result).to.equal("Hello World!"); above will fail before we can signal to Mocha via the done() of either an error or a completion which causes a timeout.

We can update the above test with a try/catch around our expectations that could throw exceptions so that we can report any errors to Mocha if they happened.

it("Using a Promise that resolves successfully with wrong expectation!", function(done) {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    testPromise.then(function(result){
        try {
            expect(result).to.equal("Hello!");
            done();
        } catch(err) {
            done(err);
        }
    }, done);
});

This will correctly report the error in the test.

But there is a better way with promises. (mostly)

Mocha has built-in support for async tests that return a Promise. However, run into troubles with async and promises in the hook functions like before/beforEach/etc.... So if you keep reading you'll see a helper function that I've not had any issues with (besides it's a bit more work...).

Thanks to a comment from @syrnick below, I've extended this write-up...

Async tests can be accomplished in two ways. The first is the already shown done callback. The second is if you returned a Promise object from the test. This a great building block. The above example test has become a little verbose with all the usages of done and the try/catch - it just gets a little cumbersome to write.

If we wanted to re-write the above test we can simplify it to return just promise.

IMPORTANT: if you want to return a promise, you have to remove the done callback or mocha will assume you'll be using that first and not look for a promise return. Although I've seen comments in Mocha's github issues list where some people depend on it working with both a callback and a promise - you're mileage may vary.

Here's an example of returning a Promise that correctly fails the test with the readable error message from Chaijs.

it("Using a Promise that resolves successfully with wrong expectation!", function() {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    return testPromise.then(function(result){
        expect(result).to.equal("Hello!");
    });
});

The great thing here is we can remove the second error promise callback (where we passed in done) as Mocha should catch any Promise rejections and fail the test for us.

Running the above test will result in the following easy to understand error message:

AssertionError: expected 'Hello!' to equal 'Hello World!'

Turn what we know above into async/await.

Now that we know there are some special things we need to do in our async mocha tests (done callbacks and try/catch or Promises) let's see what happens if we start to use the new ES7 async/await syntax in the language and if it can enable more readable asynchronous unit tests.

The beauty of the async/await syntax is we get to reduce the .then(callback, done)... mumbo jumbo and turn that into code that reads like it were happening synchronously. The downside of this approach is that it's not happening synchronously and we can't forget that when we're looking at code and starting to use it this way. But overall it is generally easier to reason about in this style.

The big changes from the above Promise style test and the transformed async test below are:

  1. Place the async word in front of the async function(done){.... This tells the system that inside of this function there may (or may not be) the use of the await keyword and in the end the function is turned into a Promise under the hood. a Promise to simplify our unit tests.
  2. We replace the .then(function(result){ promise work and in place use the await keyword to have it return the promise value assign it to result so after that we can run our expectations against it.
  3. Remove the done callback. If you aren't aware, async/await is a fancy compiler trick that under-the-hood turns the code into simple Promise chaining and callbacks. So we can use what we learned above about Mocha using 5. return the Promise.

If we apply the 5 notes listed above, we see that we can greatly improve the test readability.

it("Using a Promise with async/await that resolves successfully with wrong expectation!", async function() {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    var result = await testPromise;

    expect(result).to.equal("Hello!");
});

Notice the async function(){ part above turns this into a function that will (under-the-hood) return a promise that should correclty report errors when the expect(...) fails.

Handling errors with async/await

One interesting implementation detail around async await is that exceptions and errors are handled just like you were to handle them in synchronous code using a try/catch. While under-the-hood the errors turn into rejected Promises.

NOTE: You're mileage may vary with the async/await and mocha tests with promises. I tried playing around with async in mocha hooks like before/beforeEach but ran into some troubles.

Since there may or may-not be issues with mocha hook methods, one work-around is to leverage a try/catch and the done callback to manually handle exceptions. You may run into this so I'll show examples of how to avoid relying on Mocha to trap errors.

Below shows the (failing) but alternative way (not using a return Promsie) but using the done callback instead.

it("Using a Promise with async/await that resolves successfully with wrong expectation!", async function(done) {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    try {
        var result = await testPromise;

        expect(result).to.equal("Hello!");

        done();
    } catch(err) {
        done(err);
    }
});

Removing the test boilerplate

One I started seeing the pattern and use of try/catch boilerplate showing up in my async tests, it became apparent that there had to be a more terse approach that could help me avoid forgetting the try/catch needed in each async test. This was because I would often remember the async/await syntax changes for my async tests but would often forget the try/catch which often resulted in timeout errors instead of proper failures.

another example below with the async/await and try/catch

it("Using an async method with async/await!", async function(done) {
    try {
        var result = await somethingAsync();

        expect(result).to.equal(something);

        done();
    } catch(err) {
        done(err);
    }
});

So I refactored that to reduce the friction.

And the mochaAsync higher order function was born

This simple little guy takes an async function which looks like async () => {...}. It then returns a higher order function which is also asynchronous but has wrapped your test function in a try/catch and also takes care of calling the mocha done in the proper place (either after your test is asynchronously completed, or errors out).

var mochaAsync = (fn) => {
    return async (done) => {
        try {
            await fn();
            done();
        } catch (err) {
            done(err);
        }
    };
};

You can use it like this:

it("Sample async/await mocha test using wrapper", mochaAsync(async () => {
    var x = await someAsyncMethodToTest();
    expect(x).to.equal(true);
}));

It can also be used with the mocha before, beforeEach, after, afterEach setup/teardown methods.

beforeEach(mochaAsync(async () => {
    await someLongSetupCode();
}));

In closing.

This post may have seemed like quite a journey to get to the little poorly named mochaAsync or learn to use Mocha's Promise support but I hope it was helpful and I can't wait for the async/await syntax to become mainstream in JavaScript, but until then I'm thankful we have transpiling tools like Babel so we can take advantage of these features now. ESNext-pecially in our tests...

Happy Testing!

(Comments)

Habit of a Solid Developer - Part 7 - Changes Should be Taken with Baby Steps

(Comments)



This article is Part 7 of 11 in a series about Habit of a Solid Developer.

Have you ever made some code changes and while in the process of making those changes realize you need to change something else, which leads to changes to that thing over there and then again up there, and down here, and over there and since we're in here and I've been meaning to tweak this well... and paused to realize you forgot the original goal of why you are even looking at this module of code? No never? (well I have). git reset --hard and start over :)

If you're one who likes to apply the ol Boy Scout rule of Always leave the campground cleaner than you found it to your code, just don't, at lest not yet. While I'm a big fan of cleaning up those legacy areas of code that just need a good sweep up, the approach taken here needs to be handled with care. I'm also referring to code that is likely covered well with automated testing.

But Why?

Before you go around making a bunch of cleanup changes, fixing formatting, changing variable names, general cleanup. Accomplish a tiny part of your overall objective and commit just that change.

If you see other things along the way, take note and come back to them later. Or if, like me you can't help yourself, just don't check all of those changes in at once. Use something like git add -p to segregate your code commits into tiny topical changes.

If the job is to rename a variable, don't also fix spelling, format code, extract method, etc.... Save those other changes for different commits.

But what if you don't know what you're planning to change?

Sometimes, it's good to go off and spike a big swath of changes just to get an idea how much impact a refactor could have on the architecture or project as a whole. Prototype something to get a good picture of whether a change is possible or not or to see how many coupled items need to be adjusted along the way.

However, you go into it knowing you will likely just undo all of your changes all together with the goal to surface more knowledgeable and either:

A) determine that it is a do-able change and should or should not even be attempted in a proper fashion B) or you've uncovered some challenges that are not easily overcome and require more thought or prior preparatory refactorings.

Use TDD as a forcing mechanism to small changes

TDD (Test Driven Development) is a great way to take as tiny a step as possible. With this approach, you can write a test, make it pass (consider that a change) and possibly check it in to source control. One test at a time ensures that you're taking baby steps along the way to solving the bigger problem(s).

Baby Steps also when Debugging

Taking baby steps is also important when debugging. Running around the codebase changing X, Y, and Z just to see if you can fix a bug will often times get you in a bigger mess than the original bug you tried to fix. Making one change at a time, verifying the bug, then the next change is quite often a better approach. So consider going slow and taking baby steps.

It doesn't matter if you're making project-wide architectural changes or surgical bug fixes, if you can, try to take baby steps, commit the changes and verify each change along the way. It may feel like you're going slower, but in the long haul you may actually save time.

Happy Baby Steps!

(Comments)

How to Base64 and save a binary audio file to local storage and play it back in the browser

(Comments)

I wanted to see if it was possible to save a small audio file into localStorage, read it back out and play the file. In this post I'll show you short example on how to download an audio file, save it to localStorage, read it back and set it up for playback.

Disclaimers

works on my machine

  • This was tested in IE 10 (Win 8), Chrome 46 (Mac), and Firefox 41 (Mac); however, some of the api's and techniques used in this demo are not supported in all browsers, such as the FileReader, Blob, Promise, and fetch api's. The Promise and fetch api's can be polyfilled. There may be polyfills for the other api's, but I haven't researched those.
  • This post isn't going to go into much of the "should I do this", as I'm sure you can come up with many reasons why you shouldn't. But I couldn't find any examples that demonstrated these steps in one place. So I prototyped the idea and am putting it here in case I do want to use this in the future sometime (or maybe you do too).
  • My tests in Chrome didn't go great if I tried to re-run the experiment multiple times. Sometimes it would work, other times it seemed to get into a bad state and always raised a MediaError event. Refreshing the page would get it working again.

First we need an audio file

I don't want to point to any specific audio example since I'd feel bad if some poor soul's hosted mp3 file gets hammered (not likely) because of this example. But you just need a link to a simple, short mp3 (or whatever audio type you're trying to test). If you look at the sample below replace <<SampleAudioUrlHere>> with the link to your test audio file.

Won't fit in localStorage?

If you're trying to save an audio file that's too large as a Base64 encoded audio file will be larger than it's original size and we don't get very much space in localStorage then, ya you're using a file that's too large... Get something smaller or don't to this. Just sayin :P

How does it work?

  1. Use fetch api we can easily get at the blob()
  2. Run the Blob through the FileReader
  3. Which also handily turned it into a data url for us
  4. The data url is just a base64 encoded string which is easy to save to localStorage
  5. Read the string back out of localStorage
  6. Set the audio's src attribute to the audio data url
  7. Profit!

While I was prototyping this I was borrowing someone else short mp3 file and to work around CORS (cross origin http request) I used the handy https://crossorigin.me/<<SampleAudioUrlHere>> service. This may be ok to do for a prototype, but you should't typically run your requests through this service. It's insecure and against pretty much all the different web religions.

Show me the code

This was just a quick get-er-done example. Lots of not-great-practices, but it demonstrates the possibility. Enjoy!

<!DOCTYPE html>
<html>

  <head>
    <script>

      // Code goes here
      var audioFileUrl = '<<SampleAudioUrlHere>>';

      window.onload = function() {

        var downloadButton = document.getElementById('download');
        var audioControl = document.getElementById('audio');

        audioControl.onerror = function(){
          console.log(audioControl.error);
        };

        downloadButton.addEventListener('click', function() {

          audioControl.src = null;

          fetch(audioFileUrl)
            .then(function(res) {
              res.blob().then(function(blob) {
                var size = blob.size;
                var type = blob.type;

                var reader = new FileReader();
                reader.addEventListener("loadend", function() {

                  // console.log('reader.result:', reader.result);

                  // 1: play the base64 encoded data directly works
                  // audioControl.src = reader.result;

                  // 2: Serialize the data to localStorage and read it back then play...
                  var base64FileData = reader.result.toString();

                  var mediaFile = {
                    fileUrl: audioFileUrl,
                    size: blob.size,
                    type: blob.type,
                    src: base64FileData
                  };

                  // save the file info to localStorage
                  localStorage.setItem('myTest', JSON.stringify(mediaFile));

                  // read out the file info from localStorage again
                  var reReadItem = JSON.parse(localStorage.getItem('myTest'));

                  audioControl.src = reReadItem.src;

                });

                reader.readAsDataURL(blob);

              });
            });

        });

      };

    </script>
  </head>

  <body>
    <button id="download">Run Example</button>
    <br />
    <audio controls="true" id="audio" src=""></audio>
  </body>

</html>

I hope you found this quick tutorial useful. Would love to hear any feedback or thoughts on the approach.

As earways, Happy Listening!

(Comments)

Integrate WinJS.Navigation with the Browser's History

(Comments)

I've been playing with WinJS a bit lately, specifically the React-WinJS and wanted the native WinJS Navigation to play a little nicer with a web browser. The original/default environment for WinJS app is within a WinRT/Metro application where there is no "url/address" bar to be seen.

My uneducated guess is that the WinJS team decided not to worry about how WinJS.Navigation would integrate with a normal browser's history as there doesn't appear to be native integration or documentation about how to do it so far.

I asked the team if they had plans to work on any integration options, but only asked that last night so don't expect to hear back from over the weekend.

UPDATE: I got tired of updating this blog post with my bug fixes/iterations of the idea - so I've moved it over to GitHub: github.com/staxmanade/WinJSBrowserHistory.

So I spent a moment and prototyped one possible solution which works for this simple test using the browser's history api since I'm not looking to support browsers older than IE 10.

Ideally we could leverage WinJS controls without worrying about how to "integrate" the WinJS.Navigation with anything, but sadly some of the WinJS controls take a dependency on WinJS.Navigation (like the BackButton) so finding a way to play nice with this can be challenging.

If you want to get this prototype running yourself, you can:

  1. save both files below to a folder
  2. start up a simple web server. (I like to use nws)

This prototype is 2 files:

  • index.html <-- basic JSPM bootstrapping and configuration
  • app.jsx <-- my whole navigation app in here...

index.html

Couple mentions on this bootstrapping code:

  1. I set the background style to black (since in app.jsx I'm using the WinJS dark css) - this avoids a flash from white to black when the page loads
  2. This is using SystemJS which makes it really easy to prototype and bootstrap dependencies like WinJS and React. Please don't deploy something like this to production - follow proper JSPM production workflow procedures...
  3. The map section in the System.config defines a pointer to a fork of react-winjs I have that supports React 0.14 (so if you find this in the future and need it, try to use the native react-winjs if they've merged in my pull request instead.)
<!DOCTYPE html>
<html>
  <head>
    <style media="screen"> body{ background-color: black; } </style>
    <script src="https://jspm.io/system@0.18.js"></script>
    <script type="text/javascript">
      System.config({
        transpiler: 'babel',
        packages: {
          './': {
            defaultExtension: false
          }
        },
        map: {
          'react': 'npm:react@0.14',
          'react-winjs': 'github:staxmanade/react-winjs@2.4.0-react-0.14',
        }
      });

      System.import('./app.jsx');

    </script>
  </head>
  <body>
    <div id="main"></div>
  </body>
</html>

app.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import WinJS from 'npm:winjs';
import 'npm:winjs/css/ui-dark.css!';
import { BackButton } from 'react-winjs';


class WinJSBrowserHistory {
    isNavigationBeingHandled;
    isWinJSNavigationBackBeingHandled;
    isNavigationTriggeredByPopStateEvent;

    constructor(onApplyNavigaitonChange) {

        if(typeof onApplyNavigaitonChange !== "function") {
          throw new Error("Expecting first argumet to be a function that can take 2 parametes (location, state) => {}");
        }

        this.onApplyNavigaitonChange = onApplyNavigaitonChange;

        WinJS.Navigation.addEventListener("beforenavigate", this.handleBeforeNavigate.bind(this));
        WinJS.Navigation.addEventListener("navigating", this.handleNavigating.bind(this));
        WinJS.Navigation.addEventListener("navigated", this.handleNavigated.bind(this));

        window.addEventListener('popstate', (eventObject) => {
            console.log('popstate', this.isNavigationBeingHandled, eventObject);

            if(!this.isNavigationBeingHandled && !this.isWinJSNavigationBackBeingHandled) {
              this.handlePopState(eventObject);
            }
            this.isWinJSNavigationBackBeingHandled = false;
        })
    }

    cleanup() {
      WinJS.Navigation.removeEventListener("navigated", this.handleNavigated);
    }


    handlePopState(eventObject) {
      console.log("handlePopState", eventObject, location.hash);

      this.isNavigationTriggeredByPopStateEvent = true;

      WinJS.Navigation.navigate(location.hash, location.state);
    }

    handleBeforeNavigate(eventObject) {
        this.isNavigationBeingHandled = true;
        console.log("handleBeforeNavigate:", eventObject);
    }

    handleNavigating(eventObject) {
        console.log("handleNavigating:", eventObject);
        console.log("handleNavigating delta:", eventObject.detail.delta);

        var location = eventObject.detail.location;
        var state = eventObject.detail.state;
        var delta = eventObject.detail.delta;

        this.onApplyNavigaitonChange(location, state);

        if(delta < 0) {
            this.isWinJSNavigationBackBeingHandled = true;
            window.history.go(delta);
        } else {
            //router.setRoute(location);
            window.history.pushState(state, "", "#" + location);
        }
    }

    handleNavigated(eventObject) {
        this.isNavigationBeingHandled = false;
        this.isNavigationTriggeredByPopStateEvent = false;

        console.log("handleNavigated", eventObject);
    }

}


export default class App extends React.Component {

    constructor(props) {
        super(props);

        this.winJSBrowserHistory = new WinJSBrowserHistory(this.onApplyNavigaitonChange.bind(this));

        this.state = {
            nav: {
                state: WinJS.Navigation.state,
                location: WinJS.Navigation.location
            }
        }
    }

    componentWillMount () {
        console.log("componentWillMount");
        WinJS.Navigation.navigate(this.state.nav.location, this.state.nav.state);
    }

    componentWillUnmount () {
        console.log("componentWillUnmount");
    }

    onApplyNavigaitonChange(location, state) {
        this.setState({
            nav: {
                location: location,
                state: state
            }
        });
    }

    gotoPage1Nested() {
        WinJS.Navigation.navigate("/page1/nested");
    }

    gotoPage1() {
        WinJS.Navigation.navigate("/page1");
    }

    render() {

        console.log("render() location:", this.state.nav.location);

        var componentWithBackButton = component => {
            return (
                <div>
                    <BackButton />
                    <div>
                        {component}
                    </div>
                </div>
            );
        };

        var page;

        switch(this.state.nav.location) {
            case "/page1":
                page = componentWithBackButton(<div>page 1<br/> <button type="button" onClick={this.gotoPage1Nested.bind(this)}>Goto Page 1 Nested</button></div>);
            break;

            case "/page1/nested":
                page = componentWithBackButton(<div>page 1 nested</div>);
            break;

            case "/page2":
                page = componentWithBackButton(<div>page 1</div>);
            break;

            default:
                page = (
                    <div>
                      <button type="button" onClick={this.gotoPage1.bind(this)}>Goto Page 1</button>
                    </div>
                );
        }

        return page;
    }
}

ReactDOM.render(<App />, document.getElementById('main'));

Next I'd like to see if I could leverage something like flatiron/director for routing and get it to play nice with WinJS.Navigation and if I do, I'll post it as well...

Hope this helps.

(Comments)

Habit of a Solid Developer - Part 6 - Dig a Little Deeper

(Comments)



This article is Part 6 of 11 in a series about Habit of a Solid Developer.

The number of things you can learn in this field is mind blowing. The rate at which change happens, frameworks come and go and the various levels of abstraction can be daunting at times.

Regardless of how much or little you know, there is always a new level of abstraction you can dive into and get a better understanding of what's going on. I love the example Scott Hanselman uses about this topic in Please Learn to Think about Abstractions.

It is amazing how much you can accomplish without having a clue about what is going under your abstractions. But if you were to take a moment now and then to try to understand what those abstractions are hiding from you, it will likely open your eyes to a level of understanding and insight as to how to use the abstraction that you may likely not understand how you made it work without that deeper insight. The understanding may help you get just needed bit of performance improvement, or fault tolerance in your projects, or how to set things up to be more maintainable.

An example of this for me recently is while working at Vertigo I have helped to ship a number of streaming video based products without having to know anything about some of the specifics of say HLS. On this recent project we were having issues with a live stream and it just so happened we could peek through an HTTP Debugger proxy at the raw streaming manifest. This was previously a scary place for me to dig in an try to understand. However, taking the time to understand various parts of the HLS Spec have not only made me appreciate what it takes to put together one of these live streams, but I have now become just that much stronger as a team member on a video related projects.

As the famous philosopher Dory once said:

Dory saying just keep digging, just keep digging, digging, digging

Happy Digging!

(Comments)

Red - Possibly the Most Important Step in Red, Green, Refactor

(Comments)

If you do any sort of test driven development, you've likely heard of the following steps

  • Red: In this case means you write a test first and see the red (meaning failing test).
  • Green: This is where you actually write a tiny bit of production code to see the red test from above go green and pass.
  • Refactor: Now that you have a passing test (or suite of tests) you can presumably safely refactor and apply any common code cleanup practices to the code.

The importance of the Red step.

I don't want to go in to each of these steps in detail today, but I did want to drill into the Red step by giving you a short little example that happened to me today.

If you are interested in a little more detail on the subject check out:

If you're new to any sort of TDD/BDD/anything-DD you may not quite get how important this first step is, but hopefully the rest of this post helps...

Make sure it fails

The Red step is one of the most important, but one that a new practitioner may skip out of laziness. It takes discipline to write the failing test, run it and verify that it fails. It is so easy to write the test code AND the production code together, run it and see it pass that skipping the red step is something even seasoned veterans in the field can fall prey to.

However, if you don't see the test fail, how do you know it will ever fail?

I can tell you on numerous occasions in the past where I have written both production code and test code together, run it see it pass, just in case - comment out the production code and STILL see the test pass. Wait what?

If you are not careful you may have created a bad test and if you run this Red step first and you don't see it turn Red, you likely have a problem.

It could be a problem with the test itself, or possibly something you put in the test that is triggering something deeper in the system. It doesn't matter what the problem is, you first need to get the test to turn red before you write any production code to make it turn green.

Make sure it fails FOR THE RIGHT REASON

While it's easy to see a red bar and move on, it's also good to review the exact reason it failed. Did you get a FileNotFoundException exception when you were expecting a NullReferenceException? Or did you get an integer value of 10 when you were thinking at that moment it would have failed because it returned a string?

If you're writing proper tests, your red step will include a true failure case that not only just fails, but fails for the reason you would expect it to fail - at least until you go to write the production code that satisfies the tests intent.

Now a little example.

In the example below I was behaving myself and I DID run the red step first. I am using plain-ish JavaScript (I say ish here because I'm using ES6 with babel compiler).

It's much easier to make the type of mistake I'm going to highlight below with plain JavaScript than if you were using a statically typed language. You can try something like TypeScript for flow as these compilers provide a static type checker over your JavaScript. Compilers are a great first test...

Alas, I'm not doing that at the moment.

So here is what I did...

First I wrote a test:

import FeedData from '../app/feed.js';

describe("feed cache", function() {

  var feedCache;

  before(function() {
    feedCache = FeedData.loadCache();
  });

  it("Feed Cache should have two items", function() {
    expect(feedCache.length).to.equal(2);
  });

});

When I tried to run it I got the error saying that TypeError: FeedData.loadCache is not a function. This was great and made total sense because I haven't written this loadCache() function yet.

Next I opened up my FeedData.js file and added the loadCache() function.

export default class FeedData {
  loadCache() {

  }
}

I left the implementation blank for now and re-ran my tests. Same error TypeError: FeedData.loadCache is not a function as above.

That was odd, because I know I added the function but apparently it didn't think I had... some scratching... looking... hmm... Ahh ha - I had imported from feed.js not feedData.js.

It's subtle, but in my app feedData and feed are different things. So I moved the function to the correct ES6 class and re-ran the tests. I was certain this time that it may fail but at least fail for the right reason (not a missing function).

ARGGG....

Again I got the same error TypeError: FeedData.loadCache is not a function. Ok, that was weird. Now I'm wondering if I have a caching problem in my browser, but before I try to debug Chrome's caching (kidding there, if I ever have to go that far I'm really having a rough day) I better have another look at my code.

It didn't take long in this case to realize where my issue was. FeedData is an ES6 class and I'm calling what I thought was a static function on the class from within the test, however it wasn't declared as static in the implementation.

Adding the static keyword below turned this function into what my test was originally expecting.

export default class FeedData {
  static loadCache() {

  }
}

Now, all this work just to get the first part of my red test. What a journey it's been for something as silly as declaring a function.

It was a good reminder just how important the red step in red, green, refactor is.

Happy Testing!

(Comments)

In App Unit test example with JSPM, React, WinJS and Mocha

(Comments)

A while back I wrote about In App Unit Tests and have been having too much fun creating little starter plunks on Plunker. So...

As a simple demonstration on in-app unit tests I've thrown together a little plunk that shows in-app tests within the a WinJS Pivot. And add to the layers of abstraction I'm using react-winjs which I'm LOVING over normal WinJS development.

Link to: JSPM/React/WinJS/Mocha Plunk

If you like this starter, I have it and a few more linked here: for re-use

I'd like to highlight this particular starter at bit more in this post, not only because there are a few more concepts to this basic plunk, but also because I'm fairly happy with the MochaJS React component that I've now copied around and re-used a few times in some small projects where use In App Unit Tests.

Plunker file overview

  • index.html - The index file is a very basic JSPM bootstrap page that loads the app.jsx react component.
  • app.jsx - Defines a WinJS Pivot control where we render the in-app MochaTests.jsx React component. This also defines the test file(s) and using MochaJS's global detection we can tell the react MochaTests component what test files to load and run as well as what globals are allowed to exist.
  • config.js - This is JSPM's config that defines what version of React we're using and to use babel for transpilation.
  • tests.js - is our Mocha set of unit tests. We can have multiple test files if we want, just have to define what files to load in app.jsx.

Lastly the MochaTests.jsx which I'll include the full component below:

easier to copy-paste inherit for myself in the future

import mocha from 'mocha';
import React from 'react';

export default class MochaTests extends React.Component {

    static get propTypes() {
        return {
            testScripts: React.PropTypes.array.isRequired,
            allowedGlobals: React.PropTypes.array
        };
    }

    constructor(props) {
        super(props);
    }

    componentDidMount() {

        var testScripts = this.props.testScripts;
        var runTests = this.runTests.bind(this);

        // for some reason importing mocha with JSPM and ES6 doesn't
        // place the mocha globals on the window object. The below
        // handles that for us - as well as setting up the rest of the
        // test scripts for the first run
        mocha.suite.on('pre-require', context => {
            var exports = window;

            exports.afterEach = context.afterEach || context.teardown;
            exports.after = context.after || context.suiteTeardown;
            exports.beforeEach = context.beforeEach || context.setup;
            exports.before = context.before || context.suiteSetup;
            exports.describe = context.describe || context.suite;
            exports.it = context.it || context.test;
            exports.setup = context.setup || context.beforeEach;
            exports.suiteSetup = context.suiteSetup || context.before;
            exports.suiteTeardown = context.suiteTeardown || context.after;
            exports.suite = context.suite || context.describe;
            exports.teardown = context.teardown || context.afterEach;
            exports.test = context.test || context.it;
            exports.run = context.run;

            // now use SystemJS to load all test files
            Promise
            .all(testScripts.map(function(testScript) {
                console.log("Adding Mocha Test File: ", testScript);
                return System.import(testScript);
            })).then(runTests, function(err) {
                console.error("Error loading test modules");
                console.error(err);
            });

        });
        mocha.setup('bdd');
    }

    runTests() {
        var allowedGlobals = this.props.allowedGlobals || [];

        this.refs.mocha.getDOMNode().innerHTML = "";

        mocha.checkLeaks();
        mocha.globals(allowedGlobals);
        mocha.run();

    }

    render() {
        return (
            <div>
                <style>{"\
                  #mocha-stats em { \
                      color: inherit; \
                  } \
                  #mocha-stats { \
                    position: inherit; \
                  }\
                  #mocha .test.fail pre { \
                      color: red; \
                  } \
                "}</style>

                <button onClick={this.runTests.bind(this)}>Rerun Tests</button>

                <div id="mocha" ref="mocha"></div>
            </div>
        );
    }
}

Usage example of this React MochaTests component.

// Define what test files get loaded by the MochaTests component
var testScripts = [
  './tests.js'
];


var allowedTestGlobals = [
  // Declare what globals are allowed to be created during any test runs.
];


// Usage of MochaTests in a react render() method.
<MochaTests testScripts={testScripts} allowedGlobals={allowedTestGlobals} />

I'm not expecting to see a large up-tick in WinJS apps out there with in-app unit tests that run in the browser, however hopefully the MochaTests.jsx React Component is of value to you and can be utilized outside of WinJS within almost any React app.

Please drop a line if you end up using it or if it can be adapted. If there's value in the component, maybe

Known Issue

If the number of tests starts to go beyond the height of the pivot in this sample, it has an issue where the WinJS Pivot cuts off at the bottom not allowing you to scroll and see the rest of the test output. I haven't dug into it yet because I've been clicking the failures: X link and it filters the U.I. to just the erroring tests.

If you happen to come up with a good solution, drop me a note - I'd love it. Thanks in advance!

Happy Testing!

(Comments)

Habit of a Solid Developer - Part 5 - Update or Add Documentation while Reading Code

(Comments)



This article is Part 5 of 11 in a series about Habit of a Solid Developer.

While I generally sit on the side of the fence that your code should read clearly enough that comments should not be necessary. I concede that there are (often) times when a comment can really help to make the job of understanding the code much easier than just how a variable or method is named or organized.

One example of such case is when you've gotten lost in the code and don't understand how a piece of it works.

The second you figure or re-discover it's intent, try to add or update some comments in the code that may help you or the next person understand it more clearly in the future.

You can argue that a comment should have been added initially, but life happens and we don't always save little nuances like we should or we're given a codebase that is not as clean as we would like. So if you catch yourself digging through some code and a bit confused in an area, take the time to document it (once you figure out what you didn't understand).

This is especially true when you are the original writer of sed un-clear code. I know I've gone through code I've written and been like, "hmm, no idea what I was thinking here..." or "well, there was a reason I did this stupid thing, but now I don't remember what that was. Wish I would have commented a little more to my future self".

Sometimes it may be a simple variable rename or refactor that would clean it up. But don't just figure it out and not leave a breadcrumb for the next person (or yourself) to more easily grok the code.

Add clarity to un-clear code.

// When I wrote this, only God and I understood what I was doing
// Now, God only knows
//
// http://stackoverflow.com/a/316233/1402137

Now go read these comments and enjoy!

Happy Understanding!

(Comments)

Habit of a Solid Developer - Part 4 - Git Dance

(Comments)



This article is Part 4 of 11 in a series about Habit of a Solid Developer.

When it comes to solid dev habits, source control should be on the top of your list as a given. So much so that I'm not going to talk about the pro's and pro's (see what I did there?) of source control. I did however, want to walk through something I call my git dance which is mostly just the rhythmic steps I take while pulling in changes from a remote repository while working on a project.

For a little context, this workflow is what I usually do while working on an internal project using git with a team where we may or may not be using pull requests, but the goal of this dance is to bring in any remote changes and layer my changes in on the master branch (or whatever branch we're developing on).

My favorite thing about git is there is no "right way" to do things and when you get good enough at it the 'rules' people place on using git can mostly be wiped away. However, the below steps, while not always followed, are generally what I use to stay happy and healthy when dealing with others changes.

Fetch remote changes (don't pull)

So if we know or don't know that there are changes remotely

git fetch

or sometimes (if I have multiple remotes)

git fetch --all

Why use fetch when I could be using pull?

I prefer to fetch any changes as this gives me the opportunity to review a visual of the commit graph before any action is taken. This allows me to take different paths depending on what the before commit graph looks like vs what I want the after to look like. Git pull is essentially a short-cut for both fetching and mergeing the code and I often don't want to just merge a remote change.

After I have any remote changes pulled (err fetched) locally I like to get a mental model of the recent commits.

Review remote changes

gitk --all

Now the gitk U.I. is horrible to look at (and I'm sure you have your favorite git visualizer), but it provides enough info to review changes between the current HEAD of my local branch and any remote changes that have come in with the git fetch step above. The --all is important in gitk, as it will show you all branches (including remote branches) that were fetched.

I use this overview to not only code review changes, but to help determine whether I want to merge or rebase with the remote changes.

Merge or Rebase

Once my review is complete, I've taken a look at the overall changes, and I have a mental model of what the current commit graph looks like. I generate a mental visual of what I want the commit graph to look like when I'm done. I will decide to either:

Merge

git merge [origin/master | otherBranch]

Or

Rebase

git rebase [origin/master | otherBranch]

Once my changes have been synced up with the remote changes, I push them up.

Ship changes up to the origin

git push origin master

or

git push origin <branchName>

Now it's not a complicated workflow and it can get a bit trickier, but the key here is doing the fetch, review, integrate workflow over automatically pulling in remote changes. This allows me the space to potentially interactive rebase or muck with my commits locally before pushing anything public.

Happy gitting!

(Comments)

tvOS Simulator Remote - Keyboard Shortcuts/Replacement

(Comments)

I've begun some baby steps on my journey to learn the new Apple TV development tools and platform and we just discovered that the cumbersome tvOS Simulator Remote can almost be ignored because we can use our development keyboards in it's place.

Playing around with the new Apple tvOS development kit you may have noticed that using the simulator remote is quite annoying. Not only does it force you to take you hand off the keyboard (to move to the mouse), but's just plain awkward to have to hold down Option while you use the Mouse and Swipe Up/Down/Left/Right when you may be trying to do is navigate the U.I.

Luckily a coworker stumbled upon the arrow key commands and we quickly figured out a mapping of tvOS Remote Buttons <--> Keyboard Keys that can help any developer navigate and test their tvOS app just a little faster within the simulator.

Mac Simulator Remote Developer Keyboard Alias Notes
Touch Surface (←, ↑, →, ↓) Keyboard Arrow Keys (←, ↑, →, ↓)  
Touch Surface (click/select) <Enter> Also <Enter> on the number pad does NOT appear to work.
Menu Tap <ESC>  
Home Long-Press <ESC>  
Siri Unknown (so far) Not sure if this is supported in the simulator, but if you figure it out, let me know and I'll update the post
Play/Pause <SpaceBar>`  
Volume Up/Down Unknown (so far)  

If you discover what the two Unknown values above map to, leave a comment below and I'll update this post with the complete list.

Screenshot of Simulator Apple TV Remote

Screenshot of Simulator Apple TV Remote

Diagram of actual Apple TV Remote

Diagram of tvOS buttons

Happy tvOS building!

(Comments)