简短的回答是,您需要运行:
phantomjs.exe script-runner.js simple_test.html
长答案:
您将需要一个 javascript 文件来调用您的测试,我写了很多变体,但我发现最好的一个是 QUnitTeamCityDriver https://github.com/redbadger/QUnitTeamCityDriver。即使我不与 TeamCity 合作,我也使用了一些小改动。
这是文件的内容,可能有一些更改(我在最近的一个项目中使用过它),但你应该在 github 上找到原始文件(称之为 script-runner.js 并放在与 phantom 相同的文件夹中.exe 为方便起见):
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function () {
if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof (testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if (!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
typeof (onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 250ms
};
var page = new WebPage();
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function (msg) {
console.log(msg);
};
page.open(phantom.args[0], function (status) {
if (status !== "success") {
console.log("Unable to access network");
phantom.exit(1);
} else {
waitFor(function () {
return page.evaluate(function () {
var el = document.getElementById('qunit-testresult');
if (el && el.innerText.match('completed')) {
return true;
}
return false;
});
}, function () {
phantom.exit();
}, 10000);
}
});
这基本上会打开你的 html 页面并解析它。这对我来说是一个令人困惑的部分,phantomjs 最终是一个浏览器,你应该将这个脚本传递给它,最终将打开一个 HTML 页面而不是 Javascript 文件。所以你像这样调用phantomjs:
phantomjs.exe script-runner.js [path to file containing tests]
所以在你的情况下,它将是:
phantomjs.exe script-runner.js simple_test.html
难题的最后一点是,在包含测试的 html 页面中,您应该添加对 javascript 文件的引用,即引用中名为 QUnitTeamCityDriver.js 的文件。这将连接到 qUnit 事件并将它们引导到幻象,以决定什么是通过的测试,什么是失败的测试。文件的内容(同样你可以在 github 的项目页面上找到更好的最新版本):
/*
Reference this file in the html files of the QUnit tests
Based on the work on this team city driver: https://github.com/redbadger/QUnitTeamCityDriver/
*/
if (navigator.userAgent.indexOf("PhantomJS") !== -1) {
String.prototype.format = function () {
var args = arguments;
return this.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] != 'undefined'
? args[number]
: '{' + number + '}';
});
};
var suiteName = "QUnit Tests";
var currentTestName = "";
var hasBegun = false;
qunitBegin = function () {
console.log("[testSuiteStarted name='{0}']".format(suiteName));
};
/* QUnit.testStart({ name }) */
QUnit.testStart = function (args) {
if (!hasBegun) {
qunitBegin();
hasBegun = true;
}
currentTestName = args.name;
};
QUnit.moduleStart = function (args) {
console.log("Module started: {0}".format(args.name));
};
/* QUnit.log({ result, actual, expected, message }) */
QUnit.log = function (args) {
var currentAssertion = "{0} > {1}".format(currentTestName, args.message);
//console.log("[testStarted name='{0}']".format(currentAssertion));
if (!args.result) {
console.log("**[testFailed] type='comparisonFailure' name='{0}' details='expected={1}, actual={2}' expected='{1}' actual='{2}'".format(currentAssertion, args.expected, args.actual));
}
console.log("[testFinished] name='{0}'".format(currentAssertion));
};
/* QUnit.done({ failed, passed, total, runtime }) */
QUnit.done = function (args) {
console.log("[testSuiteFinished name='{0}']".format(suiteName));
};
}
这基本上与 QUnit 定义的回调挂钩,并将消息发送到由 phantomjs 显示的控制台。QUnit 回调文档可在此处找到:http: //api.qunitjs.com/category/callbacks/
至于与 TeamCity 挂钩,它可能只是构建步骤定义中的一个设置,用于检查输出中的某个字符串(例如,输出中存在“[testFailed]”表示失败),我已经完成了CruiseControl 并围绕它创建了一个 Nunit 包装器。最后,同样的概念适用,您只需解析 phatomjs 输出以检查是否存在 [testFailed] 或任何指示失败的字符串。