Модульное тестирование JS-приложения с перезагрузками страниц и фреймами
У меня есть приложение, для которого перезагрузка страницы / навигация и iframes имеют решающее значение, и эти части, кажется, очень сложно покрыть юнит-тестами.
Я хочу быть в состоянии написать smt. как это:
it('should fire appropriate callbacks on start and page reload', function() {
app.start();
expect(app.onStart).toHaveBeenCalled();
page.reload();
expect(app.onRestart).toHaveBeenCalled();
}
it('should know whether it runs in iframe or not', function() {
expect(app.isInIframe()).toBe(false);
iframe = createTestIframe();
expect(iframe.getApp().isInIframe()).toBe(true);
}
Известные мне фреймворки для модульного тестирования (mocha, Jasmine, QUnit) предназначены для выполнения всего набора тестов на одной странице в верхнем контексте.
С другой стороны, фреймворки функционального тестирования (FuncUnit, TestCafé, Selenium WebDriver), похоже, сосредоточены на высокоуровневых абстракциях, таких как "щелкнуть элемент", "проверить значение элемента" и т. Д., Не давая возможности углубиться в выполнение кода.
Отказ от ответственности: я довольно плохо знаком с тестированием в целом, поэтому, возможно, мне следует взглянуть на проблему с другой точки зрения.
3 ответа
Стажер разработан именно для того, чтобы разрешить такого рода функциональные тесты в подобных ситуациях, и был фактически создан из-за описанной вами проблемы, когда существующие платформы тестирования JS не разрешали такого рода взаимодействия. Он включает в себя интерфейс функционального тестирования, который будет работать так, если app
на стороне Node.js, вы бы сделали что-то вроде этого:
define([ 'intern!bdd', 'intern/chai!expect', 'my/app' ], function (bdd, expect, app) {
var it = bdd.it;
it('should fire appropriate callbacks on start and page reload', function() {
app.start();
return this.remote.get('http://path/to/server')
.then(function () {
expect(app.onStart).toHaveBeenCalled();
})
.refresh()
.then(function () {
expect(app.onRestart).toHaveBeenCalled();
});
});
// ...etc.
});
Учебное пособие Intern предоставляет лучший обзор различий между модульным и функциональным тестированием и того, как их использовать. В отличие от некоторых других предложений, таких как CasperJS, на самом деле он будет запускать ваши функциональные тесты на реальных браузерах, используя стандартный API WebDriver, в сочетании с такой службой, как Sauce Labs или вашим собственным сервером Selenium.
Тесты, которые вы описываете, кажутся полными интеграционными тестами, а не модульными тестами (обновления / вставки).
С другой стороны, показанные вами модульные тесты предназначены для тестирования отдельных модулей программы, таких как контроллеры, путем проверки всех взаимодействующих частей и тестирования модуля в отдельности.
Для типов тестов, которые вы хотите выполнить (в том числе iframes/refreshes), лучше использовать инструмент интеграционного тестирования, такой как Selenium IDE.
Этот инструмент имеет макрос-рекордер, который записывает действия вашего браузера в тесте, и позволяет воспроизводить действия и добавлять утверждения для проверки результатов теста. Взгляните на это демонстрационное видео, чтобы увидеть, насколько просто его использовать.
Этот вид интеграционных тестов дополняет, но не заменяет тип показанных вами модульных тестов.
Интеграционные тесты должны быть намного менее многочисленными, чем модульные тесты, ознакомьтесь с пирамидой тестов для получения рекомендаций по тестированию и балансировке количества модульных и интеграционных тестов.
Вы можете попробовать CasperJS. Он запускает функциональные тесты в PhantomJS, и вы можете оценить произвольный код на ваших тестовых страницах. В вашем случае вы должны сделать что-то вроде этого:
casper.test.begin('iframe', 1, function (test) {
casper
.start('your.page.url')
.thenEvaluate(function () {
window.iframe = createTestIframe()
})
.then(function () {
test.assertEval(function () {
return iframe.getApp().isInIframe()
})
})
})