为什么这个QUnit RegExp测试失败了?

时间:2011-04-18 18:41:05

标签: javascript regex unit-testing qunit

我正在乱搞QUnit,我偶然发现了一件事。

我在Chrome上尝试了这个简单的测试:

deepEqual(new RegExp(), /(?:)/);

我认为它会通过,因为new RegExp()会在开发者控制台中返回/(?:)/。对于new RegExp() === /(?:)/来说,似乎不能“只”执行RegExp,但两者的toString()函数都返回相同而 相等。

我认为文字/非文字符号会产生影响,但自从此测试通过以来情况并非如此:

deepEqual(new RegExp(" "), / /);

因此,从以下测试中,第一次失败:

test("test", function() {
    deepEqual(new RegExp(), /(?:)/); // fail
    deepEqual(new RegExp(" "), / /); // pass
    equal(new RegExp().toString(), /(?:)/.toString()); // pass
});

因此,有人可以指出我正确的方向,为什么第一次测试失败了吗?

1 个答案:

答案 0 :(得分:3)

简短回答source属性的值与正则表达式文字/(?:)/和从new RegExp()获得的对象不同。在文字的情况下它是/(?:)/,而在对象的情况下,它是一个空字符串。执行/ /new RegExp(" ")时,source属性的值相同(两者都是包含一个空格字符的字符串)。

长答案:如果你看一下Qunit的来源,你会看到这段代码:

"regexp": function (b, a) {
    return QUnit.objectType(b) === "regexp" &&
        a.source === b.source && // the regex itself
        a.global === b.global && // and its modifers (gmi) ...
        a.ignoreCase === b.ignoreCase &&
        a.multiline === b.multiline;
};

您可以使用此代码查看源参数的不同之处(它只是输出每个正则表达式参数的属性并测试它们是否相等):

function eq(x, y) {
   console.log("x.source:", "'" + x.source + "'", "y.source:", "'" + y.source + "'", "===:", x.source === y.source);
   console.log("x.global:", x.global, "y.global:", y.global, "===:", x.global === y.global);
   console.log("x.ignoreCase:", x.ignoreCase, "y.ignoreCase:", y.ignoreCase, "===:", x.ignoreCase === y.ignoreCase);
   console.log("x.multiline:", x.multiline, "y.multiline:", y.multiline, "===:", x.multiline === y.multiline);
}

当您使用eq(/(?:)/, new RegExp());拨打此电话时,您会收到:

x.source: '(?:)' y.source: '' ===: false
x.global: false y.global: false ===: true
x.ignoreCase: false y.ignoreCase: false ===: true
x.multiline: false y.multiline: false ===: true

当你用eq(/ /, new RegExp(" "));打电话时,你会得到:

x.source: ' ' y.source: ' ' ===: true
x.global: false y.global: false ===: true
x.ignoreCase: false y.ignoreCase: false ===: true
x.multiline: false y.multiline: false ===: true