6

在 Javascript 中,污染全局命名空间通常被认为是一件坏事。这就是 Coffeescript 将所有 Javascript 包装在一个(function() {}).call(this);包装器中的原因。

但是,我已经开始为我的 Coffeescript 代码编写 QUnit 测试,而 QUnit 抱怨它找不到我的函数。

1. Died on test #1: getGoodNamePart is not defined
getGoodNamePart is not defined at Object.<anonymous> (file:///Users/kevin/Documents/docs/code/chrome/tests.js:2:10) at Object.run 

我想在不污染全局命名空间的情况下测试变量。有什么好方法可以做到这一点?

这是我要测试的生成的 Javascript:

(function() {
getGoodNamePart = function(str) {
    if (str.charAt(0) === '"') {
      str.replace(/" <[^>]+>$"/g, "");
      str.replace(/"/g, "");
      return str;
    } else if (str.charAt(0) === '<') {
      str.replace(/<|>/g, "");
      return str;
    } else {
      return str;
    }
  };
}).call(this);

我的 test.js 文件是:

test('getGoodNamePart()', function() {
  equals(getGoodNamePart("\"Kev Burke\" <kev@inburke.com>"), "Kev Burke", "\"name\" <email> works");
  equals(getGoodNamePart("", "", "empty string works"));
  equals(getGoodNamePart("kev@inburke.com", "kev@inburke.com", "raw email works"));
  return equals(getGoodNamePart("<kev@inburke.com>", "kev@inburke.com", "email inside carets -> carets get stripped"));
});

谢谢,凯文

4

2 回答 2

6

所以,你说你想在getGoodNamePart不污染全局命名空间的情况下进行测试。但是,CoffeeScript 自动模块化每个文件(有充分的理由——请参阅我的答案),这意味着跨文件访问函数的唯一方法是将它们附加到某个全局对象。(我假设我们在这里讨论的是浏览器,而不是 CommonJS 环境,例如 Node.js,你会在其中使用exports.)

这为您提供了三个选择:

  1. 附加getGoodNamePartwindow. 这是最简单的,因为唯一需要的更改是前缀getGoodNamePartwindow.或只是@),但这当然会最大化命名空间污染。
  2. 附加到已经附加到或getGoodNamePart的其他东西上。windowglobal
  3. 将您的测试移动到同一个文件中getGoodNamePart(在 JS 世界中这是一种不寻常的做法,但值得考虑,因为它保持全局命名空间不变,让您可以轻松地在代码和测试之间切换)。

假设您想使用#2,导出getGoodNamePart纯粹用于测试的函数。称它们为“测试目标”。在每个带有测试目标的文件的顶部,添加

window.testTargets ?= {}

当你定义时getGoodNamePart,写

testTargets.getGoodNamePart = getGoodNamePart = (str) ->
  ...

然后在 QUnit 测试套件的顶部,编写

{getGoodNamePart} = testTargets

获取功能。

于 2011-06-25T19:37:35.533 回答
2

我用 --bare 标志编译咖啡文件,出于测试目的,

$ coffee -c -b your_file

这不会模块化编译的代码

于 2011-07-16T21:36:24.490 回答