Автоматизированное модульное тестирование с помощью JavaScript

StackOverflow https://stackoverflow.com/questions/96066

Вопрос

Я пытаюсь включить модульное тестирование JavaScript в свой автоматизированный процесс сборки.В настоящее время JsUnit хорошо работает с JUnit, но, похоже, он заброшен и ему не хватает хорошей поддержки AJAX, отладки и тайм-аутов.

Кому-нибудь удалось автоматизировать (с помощью ANT) библиотеку модульного тестирования, такую как YUI test, QUnit от jQuery или jQUnit (http://code.google.com/p/jqunit/)?

Примечание:Я использую специально созданную библиотеку AJAX, поэтому проблема с DOH от Dojo заключается в том, что она требует, чтобы вы использовали их собственные вызовы функций AJAX и обработчики событий для работы с любым модульным тестированием AJAX.

Это было полезно?

Решение

Существует множество фреймворков модульного тестирования javascript (JsUnit, scriptaculous, ...), но JsUnit - единственный, который я знаю, который может использоваться с автоматической сборкой.

Если вы выполняете "настоящий" модульный тест, вам не должна понадобиться поддержка AJAX.Например, если вы используете RPC-фреймворк ajax, такой как DWR, вы можете легко написать макет функции :

   function mockFunction(someArg, callback) {
      var result = ...; // some treatments   
      setTimeout(
function() { callback(result); }, 300 // some fake latency
); }

И да, JsUnit обрабатывает тайм-ауты : Моделирование времени в тестах JsUnit

Другие советы

Я как раз собираюсь начать использовать Javascript TDD в новом проекте, над которым я работаю.Мой текущий план состоит в том, чтобы использовать кунит чтобы провести модульное тестирование.Во время разработки тесты можно запускать, просто обновив тестовую страницу в браузере.

Для непрерывной интеграции (и обеспечения выполнения тестов во всех браузерах) я буду использовать Селен автоматически загружать тестовый жгут в каждый браузер и считывать результат.Эти тесты будут выполняться при каждой проверке системы управления версиями.

Я также собираюсь использовать Акционерное общество " Покрытие " чтобы получить анализ покрытия кода тестов.Это также будет автоматизировано с помощью Selenium.

В настоящее время я нахожусь в процессе настройки этого приложения.Я обновлю этот ответ более точными деталями, как только улажу настройку.


Инструменты тестирования:

Я большой поклонник js-тестировщик

Он хорошо работает в среде CI и способен захватывать реальные браузеры для кроссбраузерного тестирования.

Недавно я прочитал статью Бруно, использующего JsUnit и создающего фреймворк JsMock поверх этого...очень интересно.Я подумываю использовать его работу, чтобы начать модульное тестирование моего кода Javascript.

Макет Javascript или Как модульно протестировать Javascript вне среды браузера

Я просто поручил информатору Хадсона управлять JasmineBDD (безголовый), по крайней мере, для чистого модульного тестирования javascript.

(Хадсон запускает Java через shell, запускает Envjs, запускает JasmineBDD.)

Однако у меня пока нет такой возможности, чтобы хорошо работать с большой библиотекой, как prototype.

Загляни в Юитест

Я согласен с тем, что jsunit как бы умирает на корню.Мы только что закончили заменять его тестом YUI.

Подобно примеру с использованием QUnit, мы запускаем тесты с использованием Selenium.Мы запускаем этот тест независимо от наших других тестов selenium просто потому, что у него нет зависимостей, которые есть у обычных регрессионных тестов пользовательского интерфейса (напримерразвертывание приложения на сервере).

Для начала у нас есть базовый файл javascript, который включен во все наши тестовые html-файлы.Это обрабатывает настройку экземпляра YUI, тестового запуска, объекта YUI.Test.Suite, а также Test.Case.У него есть методы, к которым можно получить доступ через Selenium, чтобы запустить набор тестов, проверить, все ли еще запущен тестовый модуль (результаты будут доступны только после его завершения), и получить результаты теста (мы выбрали формат JSON)

var yui_instance; //the YUI instance
var runner;  //The YAHOO.Test.Runner
var Assert; //an instance of YAHOO.Test.Assert to save coding
var testSuite; //The YAHOO.Test.Suite that will get run.

/**
 * Sets the required value for the name property on the given template, creates
 * and returns a new YUI Test.Case object.
 * 
 * @param template the template object containing all of the tests
 */
function setupTestCase(template) {
    template.name = "jsTestCase";
    var test_case = new yui_instance.Test.Case(template);
    return test_case;
}

/**
 * Sets up the test suite with a single test case using the given 
 * template.
 * 
 * @param template the template object containing all of the tests
 */
function setupTestSuite(template) {
    var test_case = setupTestCase(template);
    testSuite = new yui_instance.Test.Suite("Bond JS Test Suite");
    testSuite.add(test_case);
}

/**
 * Runs the YAHOO.Test.Suite
 */
function runTestSuite() {
    runner = yui_instance.Test.Runner;
    Assert = yui_instance.Assert;

    runner.clear();
    runner.add(testSuite);
    runner.run();
}

/**
 * Used to see if the YAHOO.Test.Runner is still running.  The
 * test results are not available until it is done running.
 */
function isRunning() {
    return runner.isRunning();
}

/**
 * Gets the results from the YAHOO.Test.Runner
 */
function getTestResults() {
    return runner.getResults(yui_instance.Test.Format.JSON);
}

Что касается селеновой стороны вещей, мы использовали параметризованный тест.Мы запускаем наши тесты как в IE, так и в FireFox методом data, преобразуя результаты теста в список массивов объектов, каждый из которых содержит имя браузера, имя тестового файла, название теста, результат (pass, fail или ignore) и сообщение.

Сам тест просто подтверждает результат теста.Если оно не равно "pass", то тест завершается неудачей с сообщением, возвращенным из результата теста YUI.

    @Parameters
public static List<Object[]> data() throws Exception {
    yui_test_codebase = "file:///c://myapppath/yui/tests";

    List<Object[]> testResults = new ArrayList<Object[]>();

    pageNames = new ArrayList<String>();
    pageNames.add("yuiTest1.html");
    pageNames.add("yuiTest2.html");

    testResults.addAll(runJSTestsInBrowser(IE_NOPROXY));
    testResults.addAll(runJSTestsInBrowser(FIREFOX));
    return testResults;
}

/**
 * Creates a selenium instance for the given browser, and runs each
 * YUI Test page.
 * 
 * @param aBrowser
 * @return
 */
private static List<Object[]> runJSTestsInBrowser(Browser aBrowser) {
    String yui_test_codebase = "file:///c://myapppath/yui/tests/";
    String browser_bot = "this.browserbot.getCurrentWindow()"
    List<Object[]> testResults = new ArrayList<Object[]>();
    selenium = new DefaultSelenium(APPLICATION_SERVER, REMOTE_CONTROL_PORT, aBrowser.getCommand(), yui_test_codebase);
    try {
        selenium.start();

        /*
         * Run the test here
         */
        for (String page_name : pageNames) {
            selenium.open(yui_test_codebase + page_name);
            //Wait for the YAHOO instance to be available
            selenium.waitForCondition(browser_bot + ".yui_instance != undefined", "10000");
            selenium.getEval("dom=runYUITestSuite(" + browser_bot + ")");

            //Output from the tests is not available until 
            //the YAHOO.Test.Runner is done running the suite
            selenium.waitForCondition("!" + browser_bot + ".isRunning()", "10000");
            String output = selenium.getEval("dom=getYUITestResults(" + browser_bot + ")");

            JSONObject results = JSONObject.fromObject(output);
            JSONObject test_case = results.getJSONObject("jsTestCase");
            JSONArray testCasePropertyNames = test_case.names();
            Iterator itr = testCasePropertyNames.iterator();

            /*
             * From the output, build an array with the following:
             *  Test file
             *  Test name
             *  status (result)
             *  message
             */
            while(itr.hasNext()) {
                String name = (String)itr.next();
                if(name.startsWith("test")) {
                    JSONObject testResult = test_case.getJSONObject(name);
                    String test_name = testResult.getString("name");
                    String test_result = testResult.getString("result");
                    String test_message = testResult.getString("message");
                    Object[] testResultObject = {aBrowser.getCommand(), page_name, test_name, test_result, test_message};
                    testResults.add(testResultObject);
                }
            }

        }
    } finally {
        //if an exception is thrown, this will guarantee that the selenium instance
        //is shut down properly
        selenium.stop();
        selenium = null;
    }
    return testResults;
}
/**
 * Inspects each test result and fails if the testResult was not "pass"
 */
@Test
public void inspectTestResults() {
    if(!this.testResult.equalsIgnoreCase("pass")) {
        fail(String.format(MESSAGE_FORMAT, this.browser, this.pageName, this.testName, this.message));
    }
}

Я надеюсь, что это полезно.

Есть новый проект, который позволяет вам запускать кунит проводит тесты в среде Java (например, ant), чтобы вы могли полностью интегрировать свой набор тестов на стороне клиента с другими модульными тестами.

http://qunit-test-runner.googlecode.com

Я использовал его для модульного тестирования плагинов jQuery, objx код, пользовательский OO JavaScript, и он работает для всего без изменений.

Проект, над которым я работаю, использует Js-Тестировщик хостинг Жасмин в Chrome 10 с Jasmine-JSTD-Adapter включая использование Покрытие кода тесты включены в JS-Test-Driver.Хотя каждый раз, когда мы меняем или обновляем браузеры на Среда CI тесты jasmine выполняются довольно гладко, с незначительными проблемами с асинхронными тестами, но, насколько я знаю, с ними можно справиться с помощью Jasmine Clock, но у меня еще не было возможности их исправить.

Я опубликовал маленькая библиотека для проверки зависящих от браузера тестов JavaScript без необходимости использования браузера.Это node.js модуль, который использует zombie.js для загрузки тестовой страницы и проверки результатов.Я уже писал об этом в моем блоге.Вот как выглядит автоматизация:

var browsertest = require('../browsertest.js').browsertest;

describe('browser tests', function () {

it('should properly report the result of a mocha test page', function (done) {
    browsertest({
        url: "file:///home/liam/work/browser-js-testing/tests.html",
        callback: function() { 
            done();
        }
    });
});

});

Я посмотрел дату вашего вопроса, и тогда было несколько хороших JS-библиотек для тестирования / фреймворка.Сегодня вы можете найти гораздо больше приложений различной направленности, таких как TDD, BDD, Assetion и с поддержкой runners / без нее.

В этой игре есть много игроков, таких как Мокко, Чай, Кунит, Жасмин и т.д...Вы можете найти более подробную информацию в это блог о JS/ мобильном / веб-тестировании...

Другим фреймворком тестирования JS, который можно запустить с помощью Ant, является Перекрестная проверка.В файле сборки проекта есть пример запуска перекрестной проверки через Ant.

CrossCheck пытается, с ограниченным успехом, эмулировать браузер, включая реализации XMLHttpRequest и timeout / interval в стиле mock.

Однако в настоящее время он не обрабатывает загрузку javascript с веб-страницы.Вам необходимо указать файлы javascript, которые вы хотите загрузить и протестировать.Если вы сохраните весь свой JS отдельно от HTML, это может сработать у вас.

Я написал муравьиную задачу, которая использует Фантомный JS, безголовый браузер webkit, предназначенный для запуска тестовых файлов QUnit html в процессе сборки Ant.Это также может привести к сбою сборки, если какие-либо тесты завершатся неудачей.

https://github.com/philmander/ant-jstestrunner

Это хорошая оценка нескольких инструментов тестирования.

Инструменты модульного тестирования JavaScript для TDD

Лично я предпочитаю https://code.google.com/p/js-test-driver/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top