我正在努力避免进行20个左右的非常小的测试,每个测试都会测试一个白色标签网站列表,并显示一些基本信息。
我有一个网站列表(数组),网址,预期标题和网站名称。
我想迭代数组,转到每个URL并验证标题是否正确。
像这样:
var x = require('casper').selectXPath;
var white_labels = [
{
URL: "http://site1.com",
Title: "Site 1 Title",
Name: "Site 1"
},
{
URL: "http://site2.com",
Title: "Site 2 Title",
Name: "Site 2"
}
]
casper.test.begin('White Labels Test Suite', white_labels.length, function suite(test) {
var urls;
var i = -1;
casper.start(white_labels[0]["URL"], function() {
urls = white_labels;
});
casper.then(function() {
this.each(urls, function() {
i++;
this.echo("I: " + i);
this.thenOpen(urls[i].URL, function() {
this.echo("URL: " + urls[i].URL);
test.assertTitle(urls[i].Title, urls[i].Name + " title is correct");
});
});
});
casper.run(function() {
test.done();
});
});
当我运行时,每次打印出“I”时,它都是正确的... 0,然后是1.
然而,第一次测试失败,因为它获取的标题是站点2的标题,而不是站点1.第二次测试成功。
我在这一点上感到困惑。
答案 0 :(得分:4)
问题是i
的变量范围。 casper.each
本质上是一个同步for循环。它内部是异步casper.thenOpen
语句,它只调度一个动作。它实际上是同步调用的,并将正确的url传递给它。执行each
循环后,casper步骤队列开始执行(通过casper.run
触发),其中包括所有then*
个调用。
问题是i
处于全局状态,这意味着当最终执行两个casper.thenOpen
回调时,i
对于它们都是1。
您的案例有不同的解决方案:
i++;
交换var j = ++i;
,为i
交换casper.each
内的所有其他j
,将每次迭代的索引修复到该次迭代。casper.each
将迭代项注入迭代的事实,并且根本不使用任何索引:this.each(urls, function(self, url) { ... });
。this.each
更改为this.eachThen
,以使其本身处于步调状态,而您没有i
- 问题。最后,请参阅JavaScript closure inside loops – simple practical example和How do JavaScript closures work?了解详情。