I spy with my little eye, some faulty code.

As growing up, I have always wanted to be a spy. Its been 23 years and I am now a happy programmer. But little did I know that destiny hath a surprise for me.

Art of war

Spying is an art, an art of war. These are not my words. These are words of a Chinese military strategist, Sun Tzu (also called Master Sun). Roughly around 771 to 476 BC (yes, that's way back in time) Master Sun composed 13 chapters devoted to the distinct aspect of warfare.[1] Its 13th chapter is titled Use of spies.

Did I just write a paragraph that has no relation about the actual blog post? Yes, I think I did. I hope they find it interesting. I should keep writing. Okay, here's the thing.

Since we don't live in an ideal world and because God is a funny creature, things we code stop working when needed the most. Now, what I am going to tell in the blog post is not a magical solution. Things can still fail, but hey, we tried right. That counts!

Test the code

The basic rule to make sure we are not embarrassed while showcasing our app is - Test the code before, so it won't fail.

Theoretically, this makes sense, if we have tested our code, and fixed all the bugs we came across. Then there shouldn't be any problem when we are releasing our project. But most of the time, our testing is well not that efficient.

Tada! Create a spy

We will now listen to the wise Master Sun and use spies to defeat our enemies(motivational background music plays). Being a programmer is a superpower, we can do anything we want. I can plant a secret spy in my code. And not just one spy, I can create a spy army which will monitor all the functions in my code and report back to me (the programmer).

What do I mean by spy?

Okay, I won't be anymore dramatic. I am a javascript guy. And if you are javascript guy/girl as well, you might already know, all cool tutorials start with, "There is a javascript library that can do this". So yeah, there is a javascript library that can do this spy thing. It's called SinonJs

We can attach a spy to a block of code using this library. The spy will quietly follow the code wherever it's executed, taking notes of what's happening.

I think they are getting bored now. I should just start with the tutorial.

Not-so-secret recipe of creating a spy

Here lies the steps of how to add a spy in our code.

Step 1: Gather the code, which we want to spy

I'll write some quick javascript code. If you already have some code, you can surely skip this step. For this tutorial, we will need an object that has a function defined in it.

const animals = {
  'cat': (n) => {
    let catSpeaks = "";
    for(let i=0; i<n; i++){
      catSpeaks += "meow ";
    }
    return catSpeaks;
  },
};

Nothing fancy here, created an object animals. It has a function named cat in it. The cat function returns meows given number of times.

Step 2: Include the library

Gather the SinonJs library. cdnjs makes it easy to include it anywhere. In this tutorial, I will be adding it inside the head tag of my html file.

<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/6.3.5/sinon.min.js"></script>

Step 3: Create the spy

We can create a spy using the spy function. We need to give two parameters here.

  • The name of object that contains the function.
  • The name of function we will be spying.
const catSpy = sinon.spy(animals, 'cat');

Step 4: Let the code do it's thing

Let the code run. In this step we will act like, we don't know anything about a spy in the code. We are just doing our regular programming thing with a cat function. This is just another day for a javascript programmer.

...
animals.cat(2);
animals.cat(1);
animals.cat(5);

Step 5: Check the spy report

  • To get the total no of times cat function was called.
const timesCalled = spyCat.callCount;
  • To get the return values of all the function calls.
const arrayOfReturnValues = spyCat.returnValues;
// arrayOfReturnValues[0] is the return value of first call.
  • To get the arguments sent in all function calls.
const arrayOfArguments = spyCat.args;
// arrayOfReturnValues[0] is the array of arguments sent in first call.
  • To see if any function call threw a exception
const didYouThrew = spyCat.threw();
// returns true if the function call threw exception atleast once.
  • To see if any function call threw a exception every time.
const didYouThrew = spyCat.alwaysThrew();
// returns true if the function call threw exception every time.

Here's my SpyCat report

See the Pen Spying the code by Gauravjeet Singh (@Gauravjeetsingh) on CodePen.

It has many more such interesting functions. Check out the Spy API documentation here.

Free the Spy

When you trust your code enough, you can free the spy from your code.

spyCat.restore();

After this no history of cat function will be recorded. You code has freedom to do anything it wants.

Tastes best when served with Unit testing.

The application of spy lies when we unit test our code. We can attach spies to our code. Get the report using above mentioned spy API functions. And use them inside our it block of unit test to check everything is working fine.

That's all folks. Thank you for sticking with me till the end.