src/HelloWorld.js:
function helloWorld() {
return 'Hello World!';
}
spec/HelloWorldSpec.js:
describe('Hello World', function () { // suite
it('says hello', function () { // spec
expect(helloWorld()).toEqual("Hello World!"); // matcher
});
});
SpecRunner.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner v2.3.4</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.3.4/jasmine_favicon.png">
<link rel="stylesheet" href="lib/jasmine-2.3.4/jasmine.css">
<script src="lib/jasmine-2.3.4/jasmine.js"></script>
<script src="lib/jasmine-2.3.4/jasmine-html.js"></script>
<script src="lib/jasmine-2.3.4/boot.js"></script>
<!-- include source files here... -->
<script src="src/HelloWorld.js"></script>
<!-- include spec files here... -->
<script src="spec/HelloWorldSpec.js"></script>
</head>
<body>
</body>
</html>
exe:
$ open -a Safari SpecRunner.html
result:

HelloWorldSpec.js:
describe('Hello World', function () {
it('says hello', function () {
expect(helloWorld()).toEqual('Hello World!');
// toEqual: 값이 같은지.
expect(helloWorld()).toContain('World');
// toContain: 해당 문자열이 포함 되는지.
expect(helloWorld()).not.toEqual('Hello World...');
// 값이 다른지.
});
});
- toBe
- toEqual
- toMatch
- toBeDefined
- toBeUndefined
- toBeNull
- toBeTruthy
- toBeFalsy
- toContain
- toBeLessThan
- toBeGreaterThan
- toBeCloseTo
- toThrow
- toThrowError
exa:
describe("Included matchers:", function() {
it("The 'toBe' matcher compares with ===", function() {
var a = 12;
var b = a;
expect(a).toBe(b);
// 같은 객체인지. (===) 비교.
expect(a).not.toBe(null);
// 부정.
});
describe("The 'toEqual' matcher", function() {
it("works for simple literals and variables", function() {
var a = 12;
expect(a).toEqual(12);
// 값이 같은지.
});
it("should work for objects", function() {
var foo = {
a: 12,
b: 34
};
var bar = {
a: 12,
b: 34
};
expect(foo).toEqual(bar);
// objects 도 비교 가능.
});
});
it("The 'toMatch' matcher is for regular expressions", function() {
var message = "foo bar baz";
expect(message).toMatch(/bar/);
// 정규식.
expect(message).toMatch("bar");
expect(message).not.toMatch(/quux/);
});
it("The 'toBeDefined' matcher compares against `undefined`", function() {
var a = {
foo: "foo"
};
expect(a.foo).toBeDefined();
// 정의 되었는지 'undefined' 부정.
expect(a.bar).not.toBeDefined();
});
it("The `toBeUndefined` matcher compares against `undefined`", function() {
var a = {
foo: "foo"
};
expect(a.foo).not.toBeUndefined();
// undefined
expect(a.bar).toBeUndefined();
});
it("The 'toBeNull' matcher compares against null", function() {
var a = null;
var foo = "foo";
expect(null).toBeNull();
// null
expect(a).toBeNull();
expect(foo).not.toBeNull();
});
it("The 'toBeTruthy' matcher is for boolean casting testing", function() {
var a, foo = "foo";
expect(foo).toBeTruthy();
// boolean 으로 케스팅 되어 true 인지.
expect(a).not.toBeTruthy();
});
it("The 'toBeFalsy' matcher is for boolean casting testing", function() {
var a, foo = "foo";
expect(a).toBeFalsy();
// boolean 으로 케스팅 되어 false 인지.
expect(foo).not.toBeFalsy();
});
it("The 'toContain' matcher is for finding an item in an Array", function() {
var a = ["foo", "bar", "baz"];
expect(a).toContain("bar");
// 해당 Array에 'bar' 아이템이 있는지. String 도 가능.
expect(a).not.toContain("quux");
});
it("The 'toBeLessThan' matcher is for mathematical comparisons", function() {
var pi = 3.1415926,
e = 2.78;
expect(e).toBeLessThan(pi);
// 보다 작은지.
expect(pi).not.toBeLessThan(e);
});
it("The 'toBeGreaterThan' matcher is for mathematical comparisons", function() {
var pi = 3.1415926,
e = 2.78;
expect(pi).toBeGreaterThan(e);
// 보다 큰지.
expect(e).not.toBeGreaterThan(pi);
});
it("The 'toBeCloseTo' matcher is for precision math comparison", function() {
var pi = 3.1415926,
e = 2.78;
expect(pi).not.toBeCloseTo(e, 2);
expect(pi).toBeCloseTo(e, 0);
// pi 와 e 사이가 e 와 0 사이보다 가까운지.
});
it("The 'toThrow' matcher is for testing if a function throws an exception", function() {
var foo = function() {
return 1 + 2;
};
var bar = function() {
return a + 1;
};
expect(foo).not.toThrow();
expect(bar).toThrow();
// 예외를 뱉는지.
});
it("The 'toThrowError' matcher is for testing a specific thrown exception", function() {
var foo = function() {
throw new TypeError("foo bar baz");
};
expect(foo).toThrowError("foo bar baz");
expect(foo).toThrowError(/bar/);
expect(foo).toThrowError(TypeError);
expect(foo).toThrowError(TypeError, "foo bar baz");
});
});
result:

code:
describe('custom equality', function () {
var myCustomEquality = function (first, second) {
if(typeof first == 'string' && typeof second == 'string') {
return first[0] == second[1]
}
};
beforeEach(function () {
jasmine.addCustomEqualityTester(myCustomEquality);
});
it('should be custom equal', function () {
expect('abc').toEqual('aaa');
});
it('should be custom not equal', function () {
expect('abc').not.toEqual('abc');
});
});
result:

code:
var customMatchers = {
toBeGoofy: function (util, customEqualityTesters) {
return {
// actual: expect(actual), expected: toBeGoofy(expected)
compare: function (actual, expected) {
if(expected === undefined) {
expected = '';
}
var result = {};
result.pass = util.equals(actual.hyuk, 'gawrsh' + expected, customEqualityTesters);
// .pass: 통과 했는지에 대한 boolean 값을 리턴해야 한다.
if(result.pass) {
result.message = 'Expected ' + actual + ' not to be quite so goofy';
} else {
result.message = 'Expected ' + actual + ' to be goofy, but it was note very goofy';
}
return result;
}
}
}
};
describe("Custom matcher: 'toBeGoofy'", function () {
beforeEach(function () {
jasmine.addMatchers(customMatchers); // custom matcher 추가.
});
it('is available on an expectation', function () {
expect({
hyuk: 'gawrsh'
}).toBeGoofy();
});
it("can take an 'expected' parameter", function () {
expect({
hyuk: 'gawrsh is fun'
}).toBeGoofy(' is fun');
});
if('can be negated', function () {
expect({
hyuk: 'this is fun'
}).not.toBeGoofy();
});
});
result:

앞에서 사용한 beforeEach()를 볼 것이고 afterEach()도 있습니다.
모든 스펙이 실행되기 이전에 변수를 설정하거나 함수를 정의하는 등 어떤 동작이 필요하다면 beforeEach()안에 이러한 코드를 둬서 모든 스펙 이전에 실행되게 할 수 있습니다. 모든 스펙이후에 무언가 실행되기를 원한다면 afterEach()안에 코드를 작성하면 됩니다.
함수가 호출되었는지 여부나 어떻게 호출하기를 원하는지를 확인하고 싶다고 해보겠습니다. 이 때 spy를 사용할 수 있습니다. Spy는 테스트하는 프로그램의 일부분을 스파이해줍니다.
code:
var Person = function () {
};
Person.prototype.helloSomeone = function (toGreet) {
return this.sayHello() + ' ' + toGreet;
};
Person.prototype.sayHello = function () {
return 'Hello';
};
describe('Person', function () {
it('calls the sayHello() function', function () {
var fakePerson = new Person();
spyOn(fakePerson, 'sayHello');
fakePerson.helloSomeone('world');
expect(fakePerson.sayHello).toHaveBeenCalled();
});
});
result:

code:
describe('Person', function () {
it('greets the world', function () {
var fakePerson = new Person();
spyOn(fakePerson, 'helloSomeone');
fakePerson.helloSomeone('world');
expect(fakePerson.helloSomeone).toHaveBeenCalledWith('world');
});
});
result:

자스민에서는 테스트하는 동안 함수의 내용을 비어있게 만들 수 있습니다. 아래 예제를 보겠습니다.
code:
describe('Person', function () {
it('says hello', function () {
var fakePerson = new Person();
fakePerson.sayHello = jasmine.createSpy('Say-hello spy');
fakePerson.helloSomeone('world');
expect(fakePerson.sayHello).toHaveBeenCalled();
});
});
result:

더미함수가 비어있지 않고 어떤 값을 리턴해주기를 원한다면 다음과 같이 만들어 줄 수 있습니다.
fakePerson.sayHello = jasmine.createSpy('"Say hello" spy').andReturn("ello ello");
여기서 만족하지 못하고 spy 더미함수가 어떤 것을 수행하기를 원한다면 아래와 같이 정의할 수 있습니다.
code:
fakePerson.sayHello = jasmine.createSpy('"Say hello" spy').andCallFake(function() {
document.write("Time to say hello!");
return "bonjour";
});
code:
describe('Asynchronous specs', function () {
var value;
beforeEach(function (done) {
setTimeout(function () {
value = 0;
done();
}, 1);
});
it('should support async execution of test preparation and expectations'
, function (done) {
value++;
expect(value).toBeGreaterThan(0);
done();
});
describe('long asynchronous specs', function () {
beforeEach(function (done) {
done();
}, 1000);
it('takes a long time', function (done) {
setTimeout(function () {
done();
}, 9000);
}, 10000);
afterEach(function (done) {
done();
}, 1000);
});
describe('A spec using done.fail', function () {
var foo = function (x, callback1, callback2) {
if(x) {
setTimeout(callback1, 0);
} else {
setTimeout(callback2, 0);
}
};
it('should not call the second callback', function (done) {
foo(true, done, function () {
done.fail('Second callback has been called');
});
});
});
});
result:

Promises
Working with promises is rather easy in Atom. You can use our waitsForPromise function.
describe "when we open a file", ->
it "should be opened in an editor", ->
waitsForPromise ->
atom.workspace.open('c.coffee').then (editor) ->
expect(editor.getPath()).toContain 'c.coffee'
This method can be used in the describe, it, beforeEach and afterEach functions.
describe "when we open a file", ->
beforeEach ->
waitsForPromise ->
atom.workspace.open 'c.coffee'
it "should be opened in an editor", ->
expect(atom.workspace.getActiveTextEditor().getPath()).toContain 'c.coffee'
If you need to wait for multiple promises use a new waitsForPromise function for each promise. (Caution: Without beforeEach this example will fail!)
describe "waiting for the packages to load", ->
beforeEach ->
waitsForPromise ->
atom.workspace.open('sample.js')
waitsForPromise ->
atom.packages.activatePackage('tabs')
waitsForPromise ->
atom.packages.activatePackage('tree-view')
it 'should have waited long enough', ->
expect(atom.packages.isPackageActive('tabs')).toBe true
expect(atom.packages.isPackageActive('tree-view')).toBe true