Jasmine 与咖啡脚本共享规范范围问题

Posted

技术标签:

【中文标题】Jasmine 与咖啡脚本共享规范范围问题【英文标题】:Jasmine shared specs scoping issues with coffeescript 【发布时间】:2013-02-16 04:50:30 【问题描述】:

我试图通过提取共享示例来干掉一些茉莉花测试。

@sharedExamplesForThing = (thing) ->
  beforeEach ->
    @thingy = new thing

  it "is neat", ->
    expect(@thingy.neat).toBeTruthy()


describe "widget with shared behavior", ->
  sharedExamplesForThing(-> new Widget)

当所有内容都定义在一个文件中时,这很有效。当我尝试将 sharedExamples 移动到单独的文件时,会出现我遇到的问题。我得到Can't find variable: sharedExamplesForThing ...

所以为了调试,我尝试了以下方法:

describe "widget with shared behavior", ->
  it "is acting like a meany", ->
    console.log sharedExamplesForThing
    expect(false).toBeTruthy()
  sharedExamplesForThing(-> new Widget)

is acting like a meany 块中,日志将sharedExamplesForThing 显示为[Function],但我仍然在it 之外得到Can't find variable。我觉得这可能与我当前经验之外的范围界定问题有关,但我可能完全错了。我在这里错过了什么?

(使用 rails、jasminerice、guard-jasmine)

【问题讨论】:

【参考方案1】:

当您在 CoffeeScript 中分配***成员变量时,它被分配为全局对象的属性(浏览器中的window)。因此它会生成以下 javascript

window.sharedExamplesForThing = ...;

这意味着您可以在文件外部将其称为window.sharedExamplesForThing 或只是sharedExamplesForThing。因此,假设已在规范文件之前加载了共享示例文件,那么您所做的应该可以工作。我认为您遇到的问题是首先加载了规范文件(因为在加载文件时运行描述函数,而在加载所有文件后运行函数)。因此,您可能需要调整加载顺序,您可以尝试将共享示例文件放在 support 目录中,然后首先要求这样做。

与其将变量直接分配给窗口对象,不如设置一个命名空间来将您的共享变量导出到其中(这样您就不会弄乱全局对象):

window.MyNamespace = 

MyNamespace.sharedExamplesForThing = ...

然后在您的规范文件中,您可以将其称为MyNamespace.sharedExamplesForThing

我发现查看生成的 JavaScript 有助于了解 CoffeeScript 如何在文件之间导出变量。

【讨论】:

【参考方案2】:

这是我写的关于如何最好地共享示例的博客文章。希望这会有所帮助。

http://pivotallabs.com/drying-up-jasmine-specs-with-shared-behavior/

【讨论】:

您的博文非常不完整。首先,它错过了你在那里谈论的sharedBehaviorForGameOf ,其次,我有一个测试规范文件,它几乎是你的 100% 的副本,即使是精确的层次结构,每个 @987654324 只有一个 it() 块@块,我的“共享”变量仅对我的第一个测试可见,并且在第一个测试以下的任何其他测试中都不可引用。如果你完成你的文章并提供一些关于共享变量/函数的提示,我想很少有人像我这样会感激。除此之外,你在图书馆做得很好,我喜欢它。 忘了提到我正在尝试使用runs() 块中的共享变量,这些变量消耗了真实(非模拟)AJAX 调用的结果。也许这是一个范围问题,因为显然您的香草示例效果很好。【参考方案3】:

我发现shared examples from thoughtbot 上的文章非常有用。

我在coffeescript中实现如下:

1) 在所有规范文件之前加载的一些帮助文件中:

window.FooSpec =
  sharedExamples: 

window.itShouldBehaveLike = (->
  exampleName      = _.first(arguments)
  exampleArguments =
    _.select(_.rest(arguments), ((arg) => return !_.isFunction(arg)))
  innerBlock       = _.detect(arguments, ((arg) => return _.isFunction(arg)))
  exampleGroup     = FooSpec.sharedExamples[exampleName]

  if(exampleGroup)
    return describe(exampleName, (->
      exampleGroup.apply(this, exampleArguments)
      if(innerBlock) then innerBlock()
      )
    )
  else
    return it("cannot find shared behavior: '" + exampleName + "'", (->
      expect(false).toEqual(true)
      )
    )
)

2) 对于我的规格:

(a) 我可以定义共享行为:

FooSpec.sharedExamples["had a good day"] = (->
  it "finds good code examples", ->
      expect(this.thoughtbot_spy).toHaveBeenCalled()
)

(b) 并在某些规范中的任何地方使用它:

itShouldBehaveLike("had a good day")

(注意:我假设规范在上述行之前相应地定义了this.thoughtbot_spy

【讨论】:

以上是关于Jasmine 与咖啡脚本共享规范范围问题的主要内容,如果未能解决你的问题,请参考以下文章

本地和全球范围的咖啡脚本[重复]

在 CoffeeScript 文件上运行 Jasmine 测试时对象未定义错误

Jasmine:Angular Typescript 项目中的“不完整:未找到规范”

Jasmine在等待Protractor与页面同步时出错:“hooks is undefined”

为啥 jasmine-node 找不到我的规范文件?

使用grunt-contrib-jasmine运行单个规范