Slobodan Stojanovic
CTO of Cloud Horizon and JS Belgrade Meetup organizer. Programmer, mostly JS.
software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation
is just the piece of the code
that tests the correctness
of some (small) piece of your code
describe('Addition functionality', function() {
it('should add 2 numbers', function() {
expect(add(1, 1)).toBe(2);
});
});
describe('Addition functionality', () =>
it('should add 2 numbers', () =>
expect(add(1, 1)).toBe(2);
);
);
Yes, of course, ie.
A bit more detailed answer:
software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the software is improved to pass the new tests, only
Behaviour-Driven Development (BDD) is an evolution in the thinking behind TDD.
It brings TDD and Domain Driven Design into an integrated whole, making the relationship between these 2 approaches more evident.
It aims to help focus development on the delivery of prioritised, verifiable business value by providing a common vocabulary.
Core principles of BDD:
Business and Technology should refer to the same system in the same way
Any system should have an identified, verifiable value to the business
Up-front analysis, design and planning all have a diminishing return
BDD relies on the use of a very specific (and small) vocabulary to minimise miscommunication and to ensure that everyone – the business, developers, testers, analysts and managers – are not only on the same page but using the same words.
behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests.
- BDD framework for testing JavaScript code
Because we are writing our tests more as specifications that describe behaviour
- It does not depend on any other JavaScript frameworks and it does not require a DOM
So we can use it to test browser JavaScript, node.js or any other JavaScript code
- And it has a clean, obvious syntax so that you can easily write tests.
Let's see
describe('Addition functionality', () =>
it('should add 2 numbers', () =>
expect(add(1, 1)).toBe(2);
);
);
Let's split the syntax in 3 groups:
Cheatsheet:
https://www.cheatography.com/citguy/cheat-sheets/jasmine-js-testing/
describe('Calculator', () =>
describe('Addition function', () =>
it('should add numbers', () => {
expect(add(1, 1)).toBe(2);
expect(add(2, 2)).toBeGreaterThan(3);
});
);
);
<link rel="stylesheet" type="text/css"
href="libs/jasmine/2.4.1/jasmine.css">
<script type="text/javascript"
src="libs/jasmine/2.4.1/jasmine.js"></script>
<script type="text/javascript"
src="libs/jasmine/2.4.1/jasmine-html.js"></script>
<script type="text/javascript"
src="libs/jasmine/2.4.1/boot.js"></script>
<!-- include source files here... -->
<script type="text/javascript"
src="src/calculator.js"></script>
<!-- include spec files here... -->
<script type="text/javascript"
src="spec/calculator-spec.js"></script>
describe('Calculator', function() {
describe('Addition function', function() {
it('should add numbers', function() {
expect(add(1, 1)).toBe(2);
expect(add(2, 2)).toBeGreaterThan(3);
});
});
});
Let's use our calculator test example.
And let's keep calculator.js empty.
And... We have our first test 🎉
It's failing, but that's ok (remember TDD flow)
Add simple function to src/calculator.js and run it again
function add() {
return false;
}
Now let's add a functionality and try again
function add(a, b) {
return a + b;
}
🎉🎉🎉
Our test is passing now!
Ok, new errors:
I know, basic example is not that useful, let's see what else Jasmine can do
Jasmine has test double functions called spies.
A spy can stub any function and tracks calls to it and all arguments.
A spy only exists in the describe or it block in which it is defined, and will be removed after each spec
Creating a spy
// Spy on an existing method
spyOn(obj, 'method');
// Create a new function to use as a spy
jasmine.createSpy('optional name');
// Create a new object with spy functions as properties
jasmine.createSpyObj('name', ['fn1', 'fn2', ...]);
Modify behavior when the spy is called
// Call through to the original
obj.method.and.callThrough();
// Return the specified value
obj.method.and.returnValue(val);
// Call the given function instead of the real one
obj.method.and.callFake(function() {...});
// Throw an error
obj.method.and.throwError(err);
// Reset to default stubbing behavior (resets the operations above)
obj.method.and.stub();
Verifying and counting calls on a spy
// Returns true if any calls have been made
obj.method.calls.any();
// Returns the number of times the spy got called
obj.method.calls.count();
// Reset the call tracker
obj.method.calls.reset();
// Returns the first call’s context and arguments
obj.method.calls.first();
// Returns the most recent call’s context and arguments
obj.method.calls.mostRecent();
// Returns array of context and arguments passed to each call
obj.method.calls.all();
You can also add your custom matchers:
jasmine.addMatchers({
toBeDivisibleByTwo: function () {
return {
compare: function (actual, expected) {
return {
pass: (actual % 2) === 0
};
}
};
}
});
There's also a lot of custom matchers published as plugins, ie:
Jasmine jQuery
Provides matchers for jQuery objects, and an easy way to build HTML fixtures to test with.
AngularJS Matchers
Provides matchers for working with the Angular JS framework.
A helper utility that lets you match against a constructor or "class".
expect(date).toBe(jasmine.any(Date));
By Slobodan Stojanovic
CTO of Cloud Horizon and JS Belgrade Meetup organizer. Programmer, mostly JS.