2014-09-10 5 views
4

У меня есть приложение Backbone, написанное на CoffeeScript. Я пытаюсь использовать Mocha (с Chai и Sinon) для написания тестов для поведения, связанного с DOM, но кажется, что скрытые приспособления (я использую js-fixtures сейчас, но я также пробовал это безуспешно со скрытым '#fixtures' div) don Зарегистрируйте определенное поведение, связанное с DOM, которое делает тестирование определенных типов поведения, связанных с DOM (по-видимому) невозможным.Тесты Mocha на поведение, связанное с фокусом (приложение Backbone/CoffeeScript)

Например, у моего основного приложения есть несколько подзапросов, которые никогда не отображаются в одно и то же время: когда вид приложения отображает subview A, он запоминает сфокусированный элемент активного в настоящее время subview B (@_visibleView), сохраняет эту информацию на подтаблицы B, закрывает подвид B, а затем делает подвид A.

_rememberFocusedElement: -> 
     focusedElement = $ document.activeElement 
     if focusedElement 
     focusedElementId = focusedElement.attr 'id' 
     if focusedElementId 
      @_visibleView?.focusedElementId = focusedElementId 

Это работает, когда я проверить его вручную, но когда я пытаюсь писать тесты для такого поведения они терпят неудачу, потому что я не могу установить фокус (например, через $(selector).focus()) к элементу в скрытом div/iframe. (У меня такая же проблема с функциональностью, которая слушает события изменения размера окна.)

Я думал, что если бы я изменил $ document.activeElement на @$ ':focus" Я могу получить разные результаты, но это не проблема.

Вот как выглядят соответствующие части моих тестов Mocha (BDD). Эта спецификация напечатает TEXTAREA на консоли, а затем undefined, указывая, что - это текстовое поле с id = 'транскрипция', но я не могу установить на него фокус.

beforeEach (done) -> 
     fixtures.path = 'fixtures' 
     callback = => 
     @$fixture = fixtures.window().$ "<div id='js-fixtures-fixture'></div>" 
     @appView = new AppView el: @$fixture 
     done() 

    describe 'GUI stuff', -> 
     it 'remembers the currently focused element of a subview', (done) -> 
     @appView.mainMenuView.once 'request:formAdd', => 
      @appView._visibleView.$('#transcription').focus() 
      console.log @appView._visibleView.$('#transcription').prop 'tagName' 
      console.log @appView._visibleView.$(':focus').prop 'tagName' 
      done() 
     @appView.mainMenuView.trigger 'request:formAdd' 

Есть ли способ, которым я могу написать модульные тесты для этих типов поведения?

ответ

1

Хорошо, позвольте мне прояснить что-то: термин «единичный тест» означает для человека разные вещи. Часто это становится синонимом «любого теста, написанного с использованием модульной тестовой среды (например, Mocha)». Когда я использую термин «единичный тест», это не то, что я имею в виду: я имею в виду тест, который проверяет только одну единицу работы (которая в среде JS обычно будет одной функцией, но может быть целым классом).

Хорошо, если вы действительно пытаетесь выполнить модульный тест своего кода, вы как бы ошибаетесь. Единичный тест действительно не должен полагаться на что-либо вне контекста проверяемой функции, и поэтому полагаться на (внешнюю) DOM - вот где ваша проблема.

Предположим, что ваш код обработки фокусировки находится в функции под названием handleFocus (я не знаю имя фактического метода). Рассмотрим следующий тест, который я буду писать с помощью JavaScript, так как мой CoffeScript ржавый:

describe('#handleFocus', function() { 
    it('remembers the currently focused element of a subview', function() { 
     var setFocusStub = sinon.stub($.fn, 'focus'); 
     appView._visibleView.handleFocus(); 
     expect(setFocusStub.calledOnce).to.be(true); 
    }); 
}); 

Выше немного упрощением, но, надеюсь, это иллюстрирует точку. То, что вы действительно пытаетесь проверить, заключается не в том, делает ли DOM (поддельный или настоящий) X; то, что вы пытаетесь проверить, является ли ваша функция X. Сосредоточив внимание на том, что в вашем тесте, и полагаясь на заглушку, которая проверяет, произошло ли «X» или нет, вы полностью исключаете необходимость участия DOM.

Теперь, конечно, вы можете задаться вопросом: «Хорошо, что помогает мне на испытательной площадке, но как я узнаю, что она будет работать в реальной среде?» Мой ответ на этот вопрос будет заключаться в том, что ваши (вероятно, на основе селена) тесты должны охватывать такие вещи.Приемочные тесты должны проверять, работает ли ваш общий код в реальном мире, в то время как модульные тесты должны гарантировать, что отдельные части этого кода работают в поддельной среде.

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

Смежные вопросы