- Spy — эмуляция функций/объектов
- Clock — синхронизация вызовов при использовании setTimeout/setInterval
- Runner и Reporter — запуск тестов и оформление отчета
Для удобства, будет рассматриваться тестирование в браузере, а для лаконичности примеры приводятся с использованием CoffeeScript (примеры на JavaScript).
В Jasmine отслеживания вызова функции и параметров вызова осуществляется с помощью spyOn. Функции spyOn передается два параметра — объект, для которого осуществляется вызов функции, и имя функции, которую необходимо отслеживать:
spyOn(window, 'isNaN')
При обычном использовании spyOn вызов оригинальной функции не производится.
Примеры приведены с использованием небольшого класса Person:
class Person name: null age: 0 constructor: (@name, @age) -> getName: -> @name setName: (value) -> @name = value getAge: -> @age addYear: -> @age += 1
При тестировании с использованием spyOn можно отслеживать количество вызовов, их параметры и каждый вызов в отдельности:
describe "Spy", -> person = null beforeEach -> person = new Person("Jim", 25) it "осуществлен вызов функции", -> spyOn(person, 'getName') person.getName() expect(person.getName).toHaveBeenCalled() it "проверка количества вызовов", -> spyOn(person, 'addYear') person.addYear() person.addYear() expect(person.addYear.calls.length).toEqual(2) it "проверка аргументов", -> spyOn(person, 'setName') person.setName("Ira") expect(person.setName).toHaveBeenCalledWith("Ira") # может быть несколько аргументов it "есть доступ к последнему вызову", -> spyOn(person, 'setName') person.setName("Ira") expect(person.setName.mostRecentCall.args[0]).toEqual("Ira") it "есть доступ ко всем вызовам", -> spyOn(person, 'setName') person.setName("Ira") expect(person.setName.calls[0].args[0]).toEqual("Ira")
При использовании spyOn вместе с andCallThrough, будет осуществлен вызов оригинальной функции:
it "вызывает оригинальную функцию", -> spyOn(person, 'getName').andCallThrough() expect(person.getName()).toEqual("Jim") expect(person.getName).toHaveBeenCalled()
Если необходимо возвращать из функции определенное значение, то для этого надо вызвать spyOn вместе с andReturn:
it "возвращает указанное значение", -> spyOn(person, 'getName').andReturn("Dan") expect(person.getName()).toEqual("Dan") expect(person.getName).toHaveBeenCalled()
При использовании spyOn вместе с andCallFake, вместо вызова оригинальной функции, будет вызвана указанная функция:
it "вызывает указанную функцию", -> spyOn(person, 'getAge').andCallFake(-> return 5 * 11) expect(person.getAge()).toEqual(55) expect(person.getAge).toHaveBeenCalled()
Для создания функции без реализации можно воспользоваться createSpy, при этом доступны все возможности для тестирования обычного spy. Единственный параметр, который принимает createSpy — это имя функции для идентификации.
it "создает фальшивую функцию", -> concat = jasmine.createSpy('CONCAT') concat("one", "two") expect(concat.identity).toEqual('CONCAT') # есть имя для идентификации expect(concat).toHaveBeenCalledWith("one", "two") expect(concat.calls.length).toEqual(1)
Создания объекта заглушки осуществляется с помощью createSpyObj. В качестве параметров createSpyObj принимает имя объекта и массив строк, являющийся списком методов объекта заглушки:
it "создает фальшивый объект", -> button = jasmine.createSpyObj('BUTTON', ['click', 'setTitle', 'getTitle']) button.click() button.setTitle("Help") expect(button.click).toBeDefined() expect(button.click).toHaveBeenCalled() expect(button.setTitle).toHaveBeenCalledWith("Help") expect(button.getTitle).not.toHaveBeenCalled()
Проверка типа объекта осуществляется вызовом jasmine.any, которому передается ожидаемый тип:
it "проверяет тип", -> spyOn(person, 'setName') person.setName("Ira") expect(person.setName).toHaveBeenCalledWith(jasmine.any(String))
Синхронное тестирование вызовов setTimeout/setInterval осуществляется с помощью jasmine.Clock.useMock. Для перемещения времени вперед используется вызов jasmine.Clock.tick, которому передается время в миллисекундах:
describe "Время", -> callback = null beforeEach -> callback = jasmine.createSpy('TIMER') jasmine.Clock.useMock() it "вызывает timeout синхронно", -> setTimeout((-> callback()), 100) # задержка вызова в 100ms expect(callback).not.toHaveBeenCalled() jasmine.Clock.tick(101) # передвинуть время на 101ms expect(callback).toHaveBeenCalled()
Для запуска тестов в Jasmine, как правило, используется небольшой скрипт:
# Выполнение тестов jasmineEnv = jasmine.getEnv() jasmineEnv.updateInterval = 250 currentWindowOnload = window.onload window.onload = -> currentWindowOnload() if currentWindowOnload execJasmine() execJasmine = -> jasmineEnv.execute() # Вид отчета htmlReporter = new jasmine.HtmlReporter() jasmineEnv.addReporter(htmlReporter) jasmineEnv.specFilter = (spec) -> htmlReporter.specFilter(spec)
Jasmine поддерживает несколько типов отчетов о прохождении тестов, основными из них являются:
- HtmlReporter — древовидная структура с прогрессом выполнения
- TrivialReporter — простая древовидная структура (помечен как устаревший)
- ConsoleReporter — вывод результатов тестирования в консоль (для node.js)
Если у Вас есть вопросы или замечания, буду рад на них ответить.
Ссылки:
github.com/pivotal/jasmine — страница проекта на GitHub
www.inexfinance.com/en/blog/2013/2/17/jasmine_additional_features — английский вариант этой статьи
github.com/inex-finance/blog-examples/tree/master/jasmine — примеры кода из данной статьи
ссылка на оригинал статьи http://habrahabr.ru/post/169699/
Добавить комментарий