1. ТЕСТИРОВАНИЕ
JAVASCRIPT КОДА
Wednesday, January 30, 13
2. Зачем тестировать javascript?
Мы пишем рабочий код, зачем нам писать еще
какие то тесты?!
Тестировщики и так тестируют функционал!
Wednesday, January 30, 13
6. Писать тесты необходимо
1. инструкция для вашего кода (документация)
2. уверенность в вашем коде и завтрашнем дне
3. эволюция разработчика
4. рефакторинг без страха
Wednesday, January 30, 13
7. Подходы
TDD BDD
Описывает юнит, с точки зрения его Описывает поведение юнита (модуля), как он
функциональности должен себя вести
Думаете как работает код. Эволюция TDD под требования бизнеса, когда
надо говорить о поведении, а не о коде.
describe('#indexOf()', function(){ Это значит, что надо думать не функциями и
it('should return -1 when the value is возвращаемыми значениями, а поведением
not present', function(){ тестируемой сущности
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
describe('#indexOf()', function(){
})
it('should return -1 when the value is
})
not present', function(){
[1,2,3].indexOf(5).should.equal(-1);
[1,2,3].indexOf(0).should.equal(-1);
})
})
Wednesday, January 30, 13
8. Какой код можно покрыть тестами?
• Код должен быть модульным, а не монолитным.
Мы пишем тесты для юнита
• Слабая связанность между компонентами
• Один юнит должен решать одну задачу. Ведем
разработку методом “Разделяй и влавствуй”
• Тестируем поведение. Нужен контрольный пример
идеального поведения
Wednesday, January 30, 13
9. Как писать тесты? Теория BDD.
• Пишем тест, смотрим чтобы тест запускался
• Пишем код.
• Запускаем тест
• Дорабатываем код, чтобы тест был пройден
Wednesday, January 30, 13
10. Как писать тесты? Теория BDD. Дополнение
• Не весь код надо покрывать тестами. Определяем что
тестируем, а что не тестируем.
• Сложные юниты, связанные с другими юнитами, тестируем
методом декомпозиции снизу вверх. Те тестируем
обособленные юниты, а потом общий юнит.
Wednesday, January 30, 13
11. Инструментарий
Нужно: Test runner и test framework
• Jasmine BDD testing framework
• Jasmine-jQuery (помощь для DOM testing)
• SinonJS: spies, mock, fixtures, fakeServer
• TestAcular или Testem (test runner)
• PhantomJS (или любой другой браузер)
• NodeJS (для запуска JS-кода)
Wednesday, January 30, 13
12. Порядок установки
• NodeJS (windows/linux/mac)
• PhantomJS (windows/linux/mac)
• npm -g install testacular (jasmine уже встроен)
• скачиваем jasmine-jquery, sinonjs
• npm -g install coffee-script (удобней писать тесты)
• настраиваем конфиг testacular
Wednesday, January 30, 13
13. Конфигурируем TestAcular
• basePath = “./” - где находятся все файлы.
• files = [“.*coffee”, “jquery.js” ....] - зависимости, тесты, код
• reporters = [“dots”] - формат отчета
• port = 9090 - где запускается сервер
• autoWatch = false - отключаем мониторинг файлов
• browsers = [“PhantomJS”, “Chrome” ...] - в каких
браузерах запускать тесты
• preprocessors = {“**/*.coffee” : “coffee”}
Wednesday, January 30, 13
17. CoffeeScript minimal skills
javascript coffeescript
function test( ) { } test = ->
function test(a, b, c){ } test = (a, b, c) ->
a = {key: “value”} a = key : “value”
test( ) test( )
test(a, b, c) test a, b, c
function( ){ }.bind(this) ( )=>
test.prototype.name test::name
this.name @name
Wednesday, January 30, 13
18. CoffeeScript minimal skills
Block Strings
html = """
<div class=”test”>
cup of <strong>coffeescript</strong>
</div>
"""
Wednesday, January 30, 13
19. Jasmine BDD
suites
describe("A suite", function() {
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});
});
Test
describe("A suite is just a function", function() {
var a;
it("and so is a spec", function() {
a = true;
expect(a).toBe(true);
});
});
Wednesday, January 30, 13
21. Jasmine. example case 1
describe "my first test case", ->
it "test trythy", ->
expect(true).toBeTruthy()
it "test equal", ->
expect(1).toEqual 1
it "test null", ->
expect(null).toBeNull()
it "test defined", ->
b = 100
expect(b).not.toBeUndefined()
it "test contain", ->
expect("bar").toContain "b"
expect("bar").not.toContain "z"
Wednesday, January 30, 13
22. Jasmine. Setup and Teardown
beforeEach - инициализация ресурсов и выполнение
действий необходимых для каждого теста
afterEach - освобождение ресурсов и выполнение
действий после каждого теста
Wednesday, January 30, 13
23. Jasmine. Spies.
Когда не важен результат функции, а важен лишь факт ее
вызова на помощь приходят шпионы!
spyOn - создаем шпиона
toHaveBeenCalled - вызывался ли он
toHaveBeenCalledWith - вызывался с аргументами
andCallFake - говорим, чтобы вызвал нашу функцию
вместо стандартной
Wednesday, January 30, 13
24. Jasmine. Spies
Для тестирования сложных юнитов, можно создавать
fake objects имитирующих поведение реальных
объектов
createSpyObj - создает объект с указанными
фейковыми свойствами
Wednesday, January 30, 13
25. Jasmine. Async tests
Для тестирования функций, которые выполняются
асинхронно необходим особый подход
waitFor - ждем указанное время. Возвращает
Boolean, который говорит о прохождении теста, либо
fail при окончании указанного промежутка времени
runs - выполнение инструкций. Зависит от waitFor
Анимации, таймауты, ajax и тд и тп.
Wednesday, January 30, 13
26. SinonJS. или как тестировать ajax requests, mocks
• stubs - подменяет вызов функции
• useFakeXMLHttpRequest - подменяет нативный request на
фейковый
• fakeServer (.create/.restore) - создает фэйковый сервер и
проксирует через него все запросы
Wednesday, January 30, 13
28. Тестирование DOM.
1. тестировать все не нужно. Достаточно проверить
наличие элемента и его атрибуты
2. Создаем html fixture: переменная или test page
3. перед каждым тестом вставляем его в DOM
4. после каждого теста очищаем DOM
Wednesday, January 30, 13