【问题标题】:Mocha tests on focus-related behaviors (Backbone/CoffeeScript app)焦点相关行为的 Mocha 测试(Backbone/CoffeeScript 应用程序)
【发布时间】:2014-12-18 08:22:07
【问题描述】:

我有一个用 CoffeeScript 编写的 Backbone 应用程序。我正在尝试使用 Mocha(与 Chai 和 Sinon)来编写与 DOM 相关的行为的测试,但似乎隐藏的固定装置(我现在正在使用 js-fixtures 但我也尝试使用隐藏的 @987654322 未成功@div) 不要注册某些与 DOM 相关的行为,这使得测试某些类型的 DOM 相关行为(似乎)不可能。

例如,我的主应用视图有几个从不同时渲染的子视图:当应用视图渲染子视图 A 时,它会记住当前活动的子视图 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='transcription' 的文本区域,但我无法设置焦点。

    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'

有什么方法可以为这些类型的行为编写单元测试?

【问题讨论】:

    标签: javascript jquery backbone.js coffeescript mocha.js


    【解决方案1】:

    好的,首先让我澄清一下:“单元测试”这个词对很多人来说意味着不同的东西。通常它成为“使用单元测试框架(如 Mocha)编写的任何测试”的同义词。当我使用术语“单元测试”时,这并不是我的意思:我的意思是只测试单个工作单元的测试(在 JS 环境中,通常是单个函数,但可能是整个类)。

    好吧,顺便说一句,如果你真的想对你的代码进行单元测试,那你就采取了错误的方法。单元测试真的不应该依赖于被测试函数上下文之外的任何东西,因此依赖(外部)DOM 是您的问题所在。

    假设您的焦点处理代码在一个名为handleFocus 的函数中(我不知道实际的方法名称)。考虑以下测试,因为我的 CoffeScript 生锈了,我将使用 JavaScript 编写它:

    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。

    现在您当然可能会想:“很好,这对我在测试领域有帮助,但我怎么知道它会在真实环境中工作?”我对此的回答是你的(可能是基于 Selenium 的)acceptance 测试应该涵盖这类事情。验收测试应检查您的整体代码是否在现实世界中工作,而单元测试应确保该代码的各个部分在假环境中工作。

    前者非常适合确保您的客户看不到错误,而后者非常适合找出这些错误的确切来源,并让您可以安全地重构。

    【讨论】:

      猜你喜欢
      • 2012-02-06
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多