Javascript testing

Preview:

Citation preview

ТЕСТИРОВАНИЕ JAVASCRIPT КОДА

Wednesday, January 30, 13

Зачем тестировать javascript?

Мы пишем рабочий код, зачем нам писать ещекакие то тесты?!

Тестировщики и так тестируют функционал!

Wednesday, January 30, 13

Код без тестирования

Wednesday, January 30, 13

Код покрытый тестами

Wednesday, January 30, 13

Писать тесты круто!

Wednesday, January 30, 13

Писать тесты необходимо

1. инструкция для вашего кода (документация)2. уверенность в вашем коде и завтрашнем дне3. эволюция разработчика4. рефакторинг без страха

Wednesday, January 30, 13

Подходы

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)); }) })

BDDОписывает поведение юнита (модуля), как он должен себя вести

Эволюция TDD под требования бизнеса, когда надо говорить о поведении, а не о коде. Это значит, что надо думать не функциями и возвращаемыми значениями, а поведением тестируемой сущности

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

•Код должен быть модульным, а не монолитным. Мы пишем тесты для юнита

•Слабая связанность между компонентами

•Один юнит должен решать одну задачу. Ведем разработку методом “Разделяй и влавствуй”

•Тестируем поведение. Нужен контрольный пример идеального поведения

Какой код можно покрыть тестами?

Wednesday, January 30, 13

• Пишем тест, смотрим чтобы тест запускался

• Пишем код.

• Запускаем тест

• Дорабатываем код, чтобы тест был пройден

Как писать тесты? Теория BDD.

Wednesday, January 30, 13

•Не весь код надо покрывать тестами. Определяем что тестируем, а что не тестируем.

• Сложные юниты, связанные с другими юнитами, тестируем методом декомпозиции снизу вверх. Те тестируем обособленные юниты, а потом общий юнит.

Как писать тесты? Теория BDD. Дополнение

Wednesday, January 30, 13

• Jasmine BDD testing framework

• Jasmine-jQuery (помощь для DOM testing)

• SinonJS: spies, mock, fixtures, fakeServer

• TestAcular или Testem (test runner)

• PhantomJS (или любой другой браузер)

•NodeJS (для запуска JS-кода)

Инструментарий

Нужно: Test runner и test framework

Wednesday, January 30, 13

•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

• basePath = “./” - где находятся все файлы.

• files = [“.*coffee”, “jquery.js” ....] - зависимости, тесты, код

• reporters = [“dots”] - формат отчета

• port = 9090 - где запускается сервер

• autoWatch = false - отключаем мониторинг файлов

• browsers = [“PhantomJS”, “Chrome” ...] - в каких браузерах запускать тесты

• preprocessors = {“**/*.coffee” : “coffee”}

Конфигурируем TestAcular

Wednesday, January 30, 13

Запускаем из консоли

Wednesday, January 30, 13

Настраиваем запуск в IntelliJ IDEA

Wednesday, January 30, 13

Запуск в IntelliJ Idea

Wednesday, January 30, 13

CoffeeScript minimal skills

javascript coffeescript

function test( ) { }function test(a, b, c){ }

test = ->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

CoffeeScript minimal skills

Block Stringshtml = """ <div class=”test”> cup of <strong>coffeescript</strong> </div> """

Wednesday, January 30, 13

Jasmine BDD

describe("A suite", function() { it("contains spec with an expectation", function() { expect(true).toBe(true); });});

suites

describe("A suite is just a function", function() { var a;

it("and so is a spec", function() { a = true;

expect(a).toBe(true); });});

Test

Wednesday, January 30, 13

• toBe - сравнение

• toEqual - тождество

• toMatch - регулярка

• toBeDefined / toBeUndefined - существование

• toBeNull

• toBeTruthy - истина

• toBeFalsy - ложь

• toContain - содержит

• not.toBe / not.toBeDefined / not.toBeUndefined / not.toBeNull ..... отрицание

Matchers

Wednesday, January 30, 13

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

Jasmine. Setup and Teardown

beforeEach - инициализация ресурсов и выполнение действий необходимых для каждого теста

afterEach - освобождение ресурсов и выполнение действий после каждого теста

Wednesday, January 30, 13

Jasmine. Spies.

Когда не важен результат функции, а важен лишь факт ее вызова на помощь приходят шпионы!spyOn - создаем шпионаtoHaveBeenCalled - вызывался ли онtoHaveBeenCalledWith - вызывался с аргументамиandCallFake - говорим, чтобы вызвал нашу функцию вместо стандартной

Wednesday, January 30, 13

Jasmine. Spies

Для тестирования сложных юнитов, можно создавать fake objects имитирующих поведение реальных объектов

createSpyObj - создает объект с указанными фейковыми свойствами

Wednesday, January 30, 13

Jasmine. Async tests

Для тестирования функций, которые выполняются асинхронно необходим особый подходwaitFor - ждем указанное время. Возвращает Boolean, который говорит о прохождении теста, либо fail при окончании указанного промежутка времени

runs - выполнение инструкций. Зависит от waitFor

Анимации, таймауты, ajax и тд и тп.

Wednesday, January 30, 13

• stubs - подменяет вызов функции

• useFakeXMLHttpRequest - подменяет нативный request на фейковый

• fakeServer (.create/.restore) - создает фэйковый сервер и проксирует через него все запросы

SinonJS. или как тестировать ajax requests, mocks

Wednesday, January 30, 13

sinon.fakeServer.create()

1. создаем сервер server = sinon.fakeServer.create( )2. добавляем мапинг запросов server.respondWith3. делаем запрос $.get4. отдаем запрос фейковым сервером server.respond( )

Wednesday, January 30, 13

Тестирование DOM.

1. тестировать все не нужно. Достаточно проверить наличие элемента и его атрибуты

2. Создаем html fixture: переменная или test page

3. перед каждым тестом вставляем его в DOM

4. после каждого теста очищаем DOM

Wednesday, January 30, 13

Спасибо за внимание!

Wednesday, January 30, 13