Программирование на стороне клиента давно стало нормой, а объем JavaScript кода и его сложность постоянно растут. Часто тестирование применяется только на серверной стороне, но при этом не стоит забывать о тестировании клиентского кода. Для тестирования JavaScript как на стороне клиента, так и для Node.js можно с успехом применять Jasmine.
Jasmine это BDD фреймворк (Behavior-Driven Development — Разработка на Основе Поведений) для тестирования JavaScript кода, позаимствовавший многие черты из RSpec.
Для удобства, будет рассматриваться тестирование в браузере, а для лаконичности примеры приводятся с использованием CoffeeScript (примеры на JavaScript).
Установить Jasmine можно скачав пакет Jasmine standalone. Потребуются файлы:
- lib/jasmine-*/jasmine.js — сам фреймворк
- lib/jasmine-*/jasmine-html.js — оформление результатов в виде HTML
- lib/jasmine-*/jasmine.css — внешний вид результата выполнения тестов
- SpecRunner.html — файл, который следует открыть в браузере для запуска тестов
Основными ключевыми словами при работе с Jasmine являются:
- describe — определение набора тестов, наборы могут быть вложенными
- it — определение теста внутри любого набора тестов
- expect — определяет ожидания, которые проверяются в тесте
Ключевые слова describe и it являются обычными вызовами функций, которым передаются два параметра. Первый — название группы или теста, второй — функция содержащая код. Простой пример для ясности:
describe "Набор тестов", ->
it "проверка ожиданий", ->
expect(1 + 2).toBe(3)
Для того чтобы отключить выполнение набора тестов или конкретного теста, необходимо воспользоваться ключевыми словами xdescribe и xit соответственно.
describe "Отключение", ->
xdescribe "отключенный набор тестов", ->
it "тест не будет запущен, так как набор отключен", ->
expect(true).toBe(true)
xit "отключеный тест", ->
expect(true).toBe(true)
Jasmine имеет стандартный набор ожиданий для проверки результатов:
it "сравнение с использованием ===", ->
expect(1 + 2).toBe(3)
it "сравнение переменных и объектов (включая содержимое)", ->
a = {x: 8, y: 9}
b = {x: 8, y: 9}
expect(a).toEqual(b)
expect(a).not.toBe(b) # отрицание - a не является b
it "значение должно быть определено", ->
expect(window.document).toBeDefined()
it "значение должно быть не определено", ->
expect(window.notExists).toBeUndefined()
it "значение должно быть null", ->
a = null
expect(a).toBeNull()
it "значение должно быть верно", ->
expect(5 > 0).toBeTruthy()
it "значение должно быть не верно", ->
expect(5 < 0).toBeFalsy()
it "значение должно быть меньше чем", ->
expect(1 + 2).toBeLessThan(5)
it "значение должно быть больше чем", ->
expect(1 + 2).toBeGreaterThan(0)
it "значение должно быть близко к числу", ->
expect(1.2345).toBeCloseTo(1.2, 1)
it "значение должно соответствовать регулярному выражению", ->
expect("some string").toMatch(/string/)
it "значение должно содержать", ->
expect([1, 2, 3]).toContain(2)
expect("some string").toContain("some")
it "должно быть вызвано исключение", ->
func = -> window.notExists.value
expect(func).toThrow()
Для того чтобы избежать повторения при создании/удалении объектов и загрузки фикстур, необходимых для выполнения тестов, используются функции beforeEach/afterEach. Они запускаются перед/после каждого теста в наборе.
describe "Подготовка/чистка", ->
val = 0 # определение переменной в зоне видимости набора тестов
beforeEach ->
val += 1
afterEach ->
val = 0
it "использует val", ->
expect(val).toEqual(1)
Jasmine поддерживает тестирование асинхронных вызовов с помощью функций runs и waitsFor.
- runs — принимает асинхронную функцию для выполнения.
- waitsFor — принимает первым параметром функцию, которая должна вернуть true, если асинхронный вызов сделанный в runs был выполнен, второй параметр — сообщение об ошибке, третий — время ожидания в миллисекундах.
describe "Асинхронно", ->
a = 0
async = ->
setTimeout((-> a = 5), 1000)
it "асинхронное выполнение кода", ->
runs(-> async())
waitsFor((-> a == 5), "значение должно быть изменено", 3000)
Рассмотрение работы со “шпионами” spies (mock object) и работы со временем (mock clock) оставим для следующей статьи. Если у Вас есть вопросы или замечания, буду рад на них ответить.
Ссылки:
github.com/pivotal/jasmine — страница Jasmine на GitHub
www.inexfinance.com/en/blog/2013/1/25/jasmine_for_clientside_testing — английский вариант статьи
github.com/inex-finance/blog-examples/tree/master/jasmine — примеры кода из данной статьи
Автор: DeltaSpace