Jasmine basics and thinking in BDD

Based on the application presented previously, we can start writing acceptance criteria that define investment:

  • Given an investment, it should be of a stock
  • Given an investment, it should have the invested shares quantity
  • Given an investment, it should have the share paid price
  • Given an investment, it should have a cost

And to start coding these as a Jasmine spec, the first thing we need to do, is to create a new spec file. This file can be created anywhere, but it is a good idea to stick to a convention, and Jasmine already has a good one: specs should be in the /spec folder. Create a spec/InvestmentSpec.js file and add the following lines:

describe("Investment", function() {

});

describe is a global Jasmine function used to define test contexts. When used as the first call in a spec, it creates a new test suite. It accepts two parameters:

  • The name of the test suite, in this case, Investment
  • A functions which will contain all its specs

Then to translate the first acceptance criterion (given an investment, it should be of a stock) into a Jasmine spec, we are going to use another global Jasmine function called it:

describe("Investment", function() {
  it("should be of a stock", function() {

  });
});

It also accepts two parameters:

  • The title of the spec, in this case, should be of a stock
  • A function, which will contain the spec code

To run this spec, add it to the runner:

<!-- include spec files here... -->
<script type="text/javascript" src="spec/InvestmentSpec.js"></script>

And execute it by opening the runner on the browser:

Jasmine basics and thinking in BDD

First spec's passing result on the browser

This might sound strange to have an empty spec passing, but in Jasmine, as with other test frameworks, a failed assertion is required to make the spec fail.

An assertion is a comparison between two values that must result in a Boolean value. The assertion is only considered a success if the result of the comparison is true.

In Jasmine, assertions are written by using the global Jasmine function expect , along with a matcher that indicates what comparison must be made with the values.

Regarding the current spec (it is expected that the investment is of a stock), in Jasmine this translates into:

describe("Investment", function() {
  it("should be of a stock", function() {
    expect(investment.stock).toBe(stock);
  });
});

The expect function takes only one parameter, which defines the actual value, or in other words, what is going to be tested: investment.stock and expects the chaining call to a matcher function: in this case toBe. That defines the expected value : stock, and the comparison method to be performed (to be the same).

Behind the scenes, Jasmine makes a comparison to check if the actual value (investment.stock) and expected value (stock) are the same, and if they are not, the test fails.

With the assertion written, the previously passing test is now failing:

Jasmine basics and thinking in BDD

First spec's failing results

This spec is failing because, as the error message states: investment is not defined.

The idea here is to do only what the error is indicating us to do, so although you might feel the urge to write something else, for now let's just create this investment variable with an Investment instance.

describe("Investment", function() {
  it("should be of a stock", function() {
    var investment = new Investment();
    expect(investment.stock).toBe(stock);
  });
});

Don't worry that the Investment() function doesn't exist yet, the spec is about to ask for it on the next run:

Jasmine basics and thinking in BDD

Spec asks for an Investment class

You can see that the error has changed to Investment is not defined. It now asks for the Investment function. So create a new file Investment.js in the src folder and add it to the runner:

<!-- include source files here... -->
<script type="text/javascript" src="src/Investment.js"></script>

To define the Investment, write a constructor function inside the src/Investment.js file:

function Investment () {};

This makes the error change. It now complains about the missing stock variable:

Jasmine basics and thinking in BDD

Missing stock error

One more time, we feed the code for which it is asking:

describe("Investment", function() {
  it("should be of a stock", function() {
    var stock = new Stock();
    var investment = new Investment();
    expect(investment.stock).toBe(stock);
  });
});

And the error changes again, this time is the missing Stock function:

Jasmine basics and thinking in BDD

Spec asks for a Stock class

Create a new file called src/Stock.js, and add it to the runner. Since the Stock function is going to be a dependency of Investment, we should add it just before Investment:

<!-- include source files here... -->
<script type="text/javascript" src="src/Stock.js"></script>
<script type="text/javascript" src="src/Investment.js"></script>

And write the Stock constructor function:

function Stock () {};

Finally the error is on the expectation:

Jasmine basics and thinking in BDD

Expected undefined to be Stock

To fix this and complete this exercise, open the src/Investment.js file and add the reference to the stock parameter:

function Investment (stock) {
  this.stock = stock;
};

And on the spec, pass stock as a parameter to Investment:

describe("Investment", function() {
  it("should be of a stock", function() {
    var stock = new Stock();
    var investment = new Investment(stock);
    expect(investment.stock).toBe(stock);
  });
});

Finally you shall have a passing test:

Jasmine basics and thinking in BDD

Passing Investment spec

This exercise was meticulously conducted, to show how a developer works by feeding the spec with what it wants, when doing test-first development.

Tip

The drive to write code must come from a failing spec. You must not write code, unless its purpose is to fix a failing spec.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.137.38