Асинхронные юнит-тесты в Ruby - PullRequest
       11

Асинхронные юнит-тесты в Ruby

2 голосов
/ 24 августа 2010

Я тестирую некоторые библиотеки javascript, созданные мною с использованием harmony . Все работает отлично, кроме вызовов AJAX - у кого-нибудь есть идеи, как этого добиться?

Мой код выглядит примерно так (я использую RightJS ):

my.js

function makerequest(argument) {
    new Xhr('http://mysite.com/some/jsonp'),{
        jsonp: true,
        params: {something: argument},
        onSuccess: function() {
            // Calls a function defined outside my library
            parse_response(this.json)
        }
    }).send()
}

test_makerequest.rb

require 'rubygems'
require 'harmony'
require 'test/unit'
require 'shoulda'

class RequestTest < Test::Unit::TestCase
    context "The requesty thing" do
        setup do
            @page = Harmony::Page.new
            @page.load(File.expand_path('js/my.js'))
        end

        should "get stuff from mysite.com" do
            # Here I need to define a 'parse_response' which this
            # should section will wait for and then do an 'assert'
            # on the results.
            results = callback_to_get_results_from__make_request
            @page.execute('make_request("an argument")')
            assert results == {'foo' => 'bar'}
        end
    end
end

Так что да, мой вопрос, как мне назначить results выше, чтобы я мог получить результаты асинхронного обратного вызова?

1 Ответ

0 голосов
/ 12 марта 2011

Асинхронные вызовы обычно проблематичны при модульном тестировании JS.В прошлом я решил эту проблему, сделав вызовы XHR эффективно синхронными, заблокировав основной поток до тех пор, пока вызов XHR не будет успешным.Как это сделать, зависит от вашей структуры, и я незнаком с Harmony и RightJS.Однако логика будет выглядеть примерно так:

  1. Переопределите ваш метод XHR, чтобы он поддерживал блокировку / мьютекс.Замок может быть простым логическим значением.Когда какой-либо XHR находится в процессе, блокировка будет true, когда XHR не обрабатывается, блокировка будет false.
  2. . В вашем тесте, прежде чем запустить утверждение, добавьте цикл, который выполняетсяваш XHR, а затем ждет, пока блокировка не будет снята.
  3. Как только цикл завершится, вы будете уверены, что XHR завершен, и вы можете запустить свое утверждение.

НамерениеЭтот подход заключается в том, чтобы избежать изменения вашего кода, который сделает ваши тесты недействительными.К сожалению, это также означает, что вы не можете сами протестировать возвращаемое значение, но я думаю, что это будет предостережением для любой стратегии, которая не изменяет ваш код.

Другим подходом будет фактический запуск ваших тестов асинхронно--ie.приложите свое утверждение к обратному вызову onSuccess, используя AOP.Однако многие тестовые наборы не очень хорошо работают с асинхронными тестами, поскольку настройка одного теста может начинаться до завершения предыдущего теста (т. Е. Потому что предыдущий тест все еще ожидает возврата асинхронного вызова).

Последний подход заключается в том, чтобы макетировать все асинхронные вызовы.То есть.просто переопределите XHR, и ваш тест подтвердит, что он был вызван с правильными аргументами.Я мог бы предпочесть такой подход, если у меня есть интеграционные тесты, которые проходят через весь асинхронный стек.

...