Lesson Monday

Debugging is an essential part of testing and coding in general. We learned how to use console.log() and debugger in Introduction to Programming. Fortunately, we can use these tools with Jasmine and Karma as well.

Let’s take another look at an example with our Triangle Tracker app. This time the application has a bug. Here are the tests so far:

triangle-tracker/spec/triangle-spec.js
describe('Triangle', function() {

  it('should test whether a Triangle has three sides', function() {
    var triangle = new Triangle(3,4,5)
    expect(triangle.side1).toEqual(3)
    expect(triangle.side2).toEqual(4)
    expect(triangle.side3).not.toEqual(6)
  });


  it('should correctly determine whether three sides are not a triangle', function() {
    var triangle = new Triangle(12,3,3)
    expect(triangle.checkType()).toEqual("not a triangle");
  });
});

If we run Karma we’ll see the first test passes but the second does not. Here’s the source code (with an intentional bug introduced):

js/triangle.js
function Triangle(side1, side2, side3) {
  this.side1 = side1;
  this.side2 = side2;
  this.side3 = side3;
}

Triangle.prototype.checkType = function() {
  if ((this.side1 < (this.side2 + this.side3)) || (this.side2 > (this.side1 + this.side3)) || (this.side3 > (this.side1 + this.side2))) {
    return "not a triangle";
  }
};

exports.triangleModule = Triangle;

To debug we must have the console open in the debugging window where we’re running Karma. In fact, the console should always be open so we can see errors that could break our Karma tests!

Debugging with console.log()

Let’s start by adding console.log() to our code. First, we’ll put one in our tests:

triangle-tracker/spec/triangle-spec.js
...
  it('should correctly determine whether three sides are not a triangle', function() {
    var triangle = new Triangle(12,3,3)
    console.log(triangle);
    expect(triangle.checkType()).toEqual("not a triangle");
  });
...

And here’s a console.log() added to our source code:

js/triangle.js
function Triangle(side1, side2, side3) {
  this.side1 = side1;
  this.side2 = side2;
  this.side3 = side3;
}

Triangle.prototype.checkType = function() {
  if ((this.side1 < (this.side2 + this.side3)) || (this.side2 > (this.side1 + this.side3)) || (this.side3 > (this.side1 + this.side2))) {
    return "not a triangle";
  }
  console.log("conditional not reached.");
};

exports.triangleModule = Triangle;

If we refresh Karma, we’ll see the following in the console:

We log two messages to the console with console.log.

We now have some extra information. We confirm that we’ve properly instantiated a triangle in our tests: Triangle {side1: 12, side2: 3, side3: 3}. (No surprises here.)

We also confirm that the conditional isn’t being reached because we receive another console.log() message: conditional not reached. (We know code inside the conditional didn’t run because the function would’ve immediately returned with the return keyword .)

Okay, neither of these messages are particularly helpful, but they both illustrate how console.log() can be used to pinpoint errors in our tests and our source code. At the very least, we’ve narrowed down the issue a little.

Debugging with debugger

Let’s try adding a debugger now. When we refresh the tests, the code will stop running at the breakpoint where we inserted debugger. We are now “inside” our code at the breakpoint and we can go into the console and test our code.

We use debugger to test code at the breakpoint

We can verify the value of each side of the triangle (or non-triangle, as is the case here). We can also check each part of our conditional. The bug quickly becomes obvious; the conditional has a < operator when it should have a > operator. We can test the rest of our conditional to see if it works as it should, and then we have a fix for our code.

This example illustrates how we can use both console.log() and debugger with Karma. Make sure to use both regularly when debugging tests!