Based on the application presented previously, we can start writing acceptance criteria that define investment:
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:
Investment
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:
should be of a stock
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:
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:
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:
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:
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:
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:
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:
This exercise was meticulously conducted, to show how a developer works by feeding the spec with what it wants, when doing test-first development.