Pull to refresh

Comments 9

А какие преимущества у тестирования с помощью PhantomJS? Скорость запуска? Отсутствие необходимости ставить X-server на CI-сервере? Я, например, тестирую модули для ExtJS с помощью JsTestDriver, который позволяет тестировать код сразу во всех браузерах, в которых должно работать приложение, но требует X-server и выполняет тесты относительно медленно (если каждый раз регенерировать окружение для тестов). Вы сами какой фреймворк для тестирования используете?
Да, основные плюсы PhantomJS в том, что он достаточно быстро отрабатывает и не требует UI. Но при этом он по необходимости позволяет выгрузить рендер страницы в файл.

Для наших целей мы сейчас рассматриваем различные варианты тестирования компонентов и приложений на ExtJS. Смотрим на Selenium, QUnit, тот же JsTestDriver. Не факт, что в итоге остановимся именно на PhantomJS, но в ходе его опробования накопилась некоторая информация, которой я и решил поделиться.
Очень было бы хорошо, если бы результат этого рассмотрения вылился в итоге в новою статью.
Спасибо, думаю, это не последняя статья, так как я вижу, что тема оказалась достаточно интересной.
Я остановился на JsTestDriver по следующим причинам:
* Тесты пишутся в привычном стиле «Класс теста -> методы -> набор assert»
* Инструмент объединяет в себе библиотеку assert и инфраструктуру для запуска тестов в наборе браузеров
* Перехват сообщений от браузеров об ошибках
* Консольный вывод (удобно интегрировался в сборку с помощью Ant и CI на основе Hudson)
* Для написания тестов нужен только js-файл (не нужно писать html, что удобно при работе с ExtJS)
* Легкая расширяемость (хотя видимо этого можно добиться в любой библиотеке, подключив свой js-модуль)

Пример теста:

(function() {

var SwitcherTest =
{
    object : null,

    setUp : function()
    {
        this.object = JSTime.create('JSTime.widgets.toolbar.Switcher',
        {
            renderTo : Ext.getBody()
        });
    },

    tearDown : function()
    {
        this.object.destroy();
    },

    testToggleButton : function()
    {
        var viewer  = this.object.down('button[sysname=' + this.object.VIEWER + ']'),
            creator = this.object.down('button[sysname=' + this.object.CREATOR + ']');

        this.object.toggleButton(viewer);

        assertTrue(viewer.pressed);
        assertFalse(creator.pressed);

        this.object.toggleButton(creator);

        assertFalse(viewer.pressed);
        assertTrue(creator.pressed);
    },

    testSetActiveItem : function()
    {
        var viewer  = this.object.down('button[sysname=' + this.object.VIEWER + ']'),
            creator = this.object.down('button[sysname=' + this.object.CREATOR + ']');

        this.object.setActiveItem(this.object.VIEWER);

        assertTrue(viewer.pressed);
        assertFalse(creator.pressed);

        this.object.setActiveItem(this.object.CREATOR);

        assertFalse(viewer.pressed);
        assertTrue(creator.pressed);
    },

    testClickButtons : function()
    {
        var viewer  = this.object.down('button[sysname=' + this.object.VIEWER + ']'),
            creator = this.object.down('button[sysname=' + this.object.CREATOR + ']');

        Helpers.click(viewer);

        assertTrue(viewer.pressed);
        assertFalse(creator.pressed);

        Helpers.click(creator);

        assertTrue(creator.pressed);
        assertFalse(viewer.pressed);
    },

    testChangeEvent : function()
    {
        assertEvent(this.object, 'change', function()
        {
            Helpers.click('button[sysname=' + this.object.CREATOR + ']');
        },
        this);

        assertEvent(this.object, 'change', function()
        {
            Helpers.click('button[sysname=' + this.object.VIEWER + ']');
        },
        this);

        assertEvent(this.object, 'change', function()
        {
            this.object.setActiveItem(this.object.CREATOR);
        },
        this);

        assertEvent(this.object, 'change', function()
        {
            this.object.setActiveItem(this.object.VIEWER);
        },
        this);
    }
};

TestCase('SwitcherTest', SwitcherTest);

})();
Спасибо за информацию, обязательно попробую и такой вариант.
А с select приходилось работать? Пару дней назад пытался через PhantomJS делать onchange для select-ам, но почему-то не срабатывало. Работал из PHP, поэтому вот задумался, на чьей стороне проблема. Думается, что я неправильно JS написал, но хочется быть уверенным, что это именно так ибо обработку событий как я понял добавили не так давно (в плане версий, а не по времени).
Я так понимаю, имеется ввиду нечто подобное:
var page = require('webpage').create();

page.open('test.html', function(success) {

    page.onConsoleMessage = function (msg) {
        console.log(msg);
    };

    page.evaluate(function() {
        document.getElementById('sel').onchange = function() {
            console.log('onchange');
        };
        document.getElementById('sel').onchange();
    });
    
    phantom.exit();
    
});

Такой код при запуске выводит в консоль 'onchange'. Но обработчик приходится задавать прямо в evaluate. Насколько я понял из документации, передать внутрь evaluate что-либо снаружи нельзя.
Я пытался делать через создание объекта-события и использовать его. Что же, опробую зайти со стороны onchange.

А код возрата мне не нужен, мне нужно программно изменить select перебрав все возможные option и для каждого варианта получить динамический html что бы его потом уже из PHP по XPath разобрать.
Sign up to leave a comment.

Articles