如何以编程方式跳过 mocha 中的测试?
How to programmatically skip a test in mocha?
我有一个代码,其中某些测试在 CI 环境中总是会失败。我想根据环境条件禁用它们。
如何在运行时执行期间以编程方式跳过 mocha 中的测试?
您可以通过在 describe 或 it 块前面放置一个 x 或在其后放置一个 .skip
来跳过测试。
xit('should work', function (done) {});
describe.skip('features', function() {});
您还可以 运行 通过在测试上放置 .only
来进行单个测试。例如
describe('feature 1', function() {});
describe.only('feature 2', function() {});
describe('feature 3', function() {});
在这种情况下,只有功能 2 块 运行。
似乎没有办法以编程方式跳过测试,但您可以在 beforeEach
语句中进行某种检查,如果设置了标志,则只 运行 测试.
beforeEach(function(){
if (wrongEnvironment){
runTest = false
}
}
describe('feature', function(){
if(runTest){
it('should work', function(){
// Test would not run or show up if runTest was false,
}
}
}
这取决于您希望如何以编程方式跳过测试。如果在之前任何测试代码都可以确定跳过的条件是运行,那么你可以根据需要调用it
或it.skip
,根据一个条件。例如,如果环境变量 ONE
设置为任何值,这将跳过一些测试:
var conditions = {
"condition one": process.env["ONE"] !== undefined
// There could be more conditions in this table...
};
describe("conditions that can be determined ahead of time", function () {
function skip_if(condition, name, callback) {
var fn = conditions[condition] ? it.skip: it;
fn(name, callback);
};
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
如果要检查的条件只能在测试时才能确定,就稍微复杂一些。如果您不想访问严格来说不属于测试部分的任何内容 API,那么您可以这样做:
describe("conditions that can be determined at test time", function () {
var conditions = {};
function skip_if(condition, name, callback) {
if (callback.length) {
it(name, function (done) {
if (conditions[condition])
done();
else
callback(done);
});
}
else {
it(name, function () {
if (conditions[condition])
return;
callback();
});
}
};
before(function () {
conditions["condition one"] = true;
});
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
虽然我的第一个示例是将测试标记为正式跳过(又名 "pending"),但我刚才展示的方法只会避免执行实际测试,但不会将测试标记为正式跳过.他们将被标记为通过。如果你绝对想跳过它们,除了访问测试中不正确的部分之外,我不知道有什么方法 API:
describe("conditions that can be determined at test time", function () {
var condition_to_test = {}; // A map from condition names to tests.
function skip_if(condition, name, callback) {
var test = it(name, callback);
if (!condition_to_test[condition])
condition_to_test[condition] = [];
condition_to_test[condition].push(test);
};
before(function () {
condition_to_test["condition one"].forEach(function (test) {
test.pending = true; // Skip the test by marking it pending!
});
});
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
使用 Mocha 的 skip()
功能
它可用于静态禁用测试或整个套件,或在运行时动态跳过它。
这是一个运行时用法示例:
it('should only test in the correct environment', function() {
if (/* check test environment */) {
// make assertions
} else {
this.skip();
}
});
假设我想跳过我的参数化测试,如果我的测试描述包含字符串 "foo",我会这样做:
// Skip parametrized test if description contains the string "foo"
(test.description.indexOf("foo") === -1 ? it : it.skip)("should test something", function (done) {
// Code here
});
// Parametrized tests
describe("testFoo", function () {
test({
description: "foo" // This will skip
});
test({
description: "bar" // This will be tested
});
});
在你的情况下,我相信如果你想检查环境变量,你可以使用 NodeJS 的:
process.env.ENV_VARIABLE
例如(警告:我还没有测试这段代码!),可能是这样的:
(process.env.NODE_ENV.indexOf("prod") === -1 ? it : it.skip)("should...", function(done) {
// Code here
});
您可以将 ENV_VARIABLE 设置为您键入的任何内容,并使用该值跳过或 运行 测试。 (仅供参考,NodeJS process.env 的文档在这里:https://nodejs.org/api/process.html#process_process_env)
我不会完全相信这个解决方案的第一部分,我找到并测试了答案,它完美地通过这个资源跳过基于简单条件的测试:https://github.com/mochajs/mocha/issues/591
希望对您有所帮助! :)
正如@danielstjules 回答的那样here 有一种方法可以跳过测试。该主题的@author 复制了 github.com mochajs 讨论的答案,但没有关于可用的 mocha 版本的信息。
我正在使用 grunt-mocha-test 模块在我的项目中集成 mocha 测试功能。跳转到最后(现在)版本 - 0.12.7 给我 mocha 版本 2.4.5 实现 this.skip().
所以,在我的 package.json
"devDependencies": {
"grunt-mocha-test": "^0.12.7",
...
然后
npm install
这个钩子让我很开心:
describe('Feature', function() {
before(function () {
if (!Config.isFeaturePresent) {
console.log('Feature not configured for that env, skipping...');
this.skip();
}
});
...
it('should return correct response on AB', function (done) {
if (!Config.isABPresent) {
return this.skip();
}
...
请不要。您的构建基础架构应承认无法跨环境一致工作的测试。当 CI 构建的测试数量 运行 与本地不同时,这可能会让人迷失方向。
它也搞砸了可重复性。如果在服务器和本地进行不同的测试 运行,我可以让测试在开发中失败并通过 CI,反之亦然。没有强制功能,我无法快速准确地更正失败的构建。
如果您必须关闭环境之间的测试,而不是有条件地 运行 测试,标记您的测试并使用过滤器来消除在某些构建目标中不起作用的测试。这样每个人都知道发生了什么,这会降低他们的期望。它还让每个人都知道测试框架中存在不一致,并且有人可能有一个解决方案可以让他们再次 运行ning 正确。如果您只是将测试静音,他们甚至可能不知道有问题。
mocha test/ --grep <pattern>
您可以使用我的包 mocha-assume 以编程方式跳过测试,但只能从测试外部进行。你这样使用它:
assuming(myAssumption).it("does someting nice", () => {});
当 myAssumption
为 true
时,Mocha-assume 只会 运行 你的测试,否则它会跳过它(使用 it.skip
)并显示一条好消息。
这里有一个更详细的例子:
describe("My Unit", () => {
/* ...Tests that verify someAssuption is always true... */
describe("when [someAssumption] holds...", () => {
let someAssumption;
beforeAll(() => {
someAssumption = /* ...calculate assumption... */
});
assuming(someAssumption).it("Does something cool", () => {
/* ...test something cool... */
});
});
});
这样使用,可以避免级联故障。假设当 someAssumption 不成立时测试 "Does something cool"
总是会失败 - 但这个假设已经在上面测试过(在 Tests that verify someAssuption is always true"
中)。
所以测试失败并没有给你任何新的信息。事实上,它甚至是一个误报:测试没有失败,因为 "something cool" 没有工作,而是因为测试的前提条件不满足。使用 mocha-assume
您通常可以避免此类误报。
对于与您描述的相同的场景,我使用从 Mocha 跳过的运行时。这是docs:
的复制粘贴
it('should only test in the correct environment', function() {
if (/* check test environment */) return this.skip();
// make assertions
});
如您所见,它跳过了基于环境的测试。我自己的条件是if(process.env.NODE_ENV === 'continuous-integration')
.
这并不是真正使用 mocha 的功能,而是调整它以获得我想要的行为。
我想跳过我的量角器 mocha 测试中的任何后续 'it',但有一个 'it' 失败了。这是因为一旦旅程测试的一个步骤失败,几乎可以肯定其余步骤也会失败,并且如果他们使用浏览器等待元素出现在页面上等,则可能需要很长时间并占用构建服务器
当只有 运行 标准 mocha 测试(不是量角器)时,这可以通过将 'skipSubsequent' 标志附加到测试的父级(描述)来使用全局 beforeEach 和 afterEach 挂钩来实现,如下所示:
beforeEach(function() {
if(this.currentTest.parent.skipSubsequent) {
this.skip();
}
});
afterEach(function() {
if (this.currentTest.state === 'failed') {
this.currentTest.parent.skipSubsequent = 'true'
}
})
尝试使用量角器和 mocha 时,'this' 的范围发生了变化,上面的代码不起作用。您最终得到一条错误消息,如 'error calling done()' 并且量角器停止。
相反,我得到了下面的代码。不是最漂亮的,但它最终用 this.skip() 替换了剩余测试函数的实现。这可能会停止工作 if/when mocha 的内部结构随着更高版本的变化而变化。
它是通过调试和检查 mocha 的内部结构通过反复试验得出的...虽然测试失败时有助于使浏览器测试套件更快地完成。
beforeEach(function() {
var parentSpec = this.currentTest.parent;
if (!parentSpec.testcount) {
parentSpec.testCount = parentSpec.tests.length;
parentSpec.currentTestIndex = 0;
} else {
parentSpec.currentTestIndex = parentSpec.currentTestIndex + 1;
}
if (parentSpec.skipSubsequent) {
parentSpec.skipSubsequent = false;
var length = parentSpec.tests.length;
var currentIndex = parentSpec.currentTestIndex;
for (var i = currentIndex + 1; i < length; i++) {
parentSpec.tests[i].fn = function() {
this.skip();
};
}
}
});
afterEach(function() {
if (this.currentTest.state === 'failed') {
this.currentTest.parent.skipSubsequent = 'true'
}
});
这个答案适用于 ES6。
而不是:
describe('your describe block', () => {
你想要:
(condition ? describe : describe.skip)('your describe block', () => {
如果条件为假,这将有条件地跳过描述块中的所有测试。
或者,而不是:
it('your it block', () => {
你想要:
(condition ? it : it.skip)('your it block', () => {
如果条件为假,这将有条件地跳过一个测试。
我不确定这是否符合“编程跳过”的条件,但为了有选择地跳过我们 CI 环境的某些特定 cific 测试,我使用了 Mocha 的标记功能(https://github.com/mochajs/mocha/wiki/Tagging).
在 describe()
或 it()
消息中,您可以添加 @no-ci 之类的标签。要排除这些测试,您可以在 package.json 中定义一个 specific "ci target" 并使用 --grep
和 --invert
参数,例如:
"scripts": {
"test": "mocha",
"test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
我们可以编写一个漂亮的干净包装函数来有条件地 运行 测试如下:
function ifConditionIt(title, test) {
// Define your condition here
return condition ? it(title, test) : it.skip(title, test);
}
这可以在您的测试中被要求和使用,如下所示:
ifConditionIt('Should be an awesome test', (done) => {
// Test things
done();
});
要跳过测试,请使用 describe.skip
或 it.skip
describe('Array', function() {
it.skip('#indexOf', function() {
// ...
});
});
要包括您可以使用 describe.only
或 it.only
的测试
describe('Array', function() {
it.only('#indexOf', function() {
// ...
});
});
可以根据条件使用,
例如,声明一个 var,当条件失败时,使用 this.skip();
Note that skip() does not work in arrow function
let shouldRun: boolean;
before(function(){
if ($('#nsErrorIframe').isDisplayed()) {
driver.switchToFrame($('#nsErrorIframe'));
if ($('.ns-error-wrapper').isDisplayed()) {
console.log('PAGE IS NOT AVAILABLE');
shouldRun = false;
if ( shouldRun === false) {
this.skip();
}
}
}
});
我们的测试环境中有一些不可靠的测试,有时会使用这种方法关闭某些测试:
mocha --config ./config/parallelrc.cjs --parallel --jobs 3 -- tests/spec/**/index.js -g @flaky -i
我们在 tests describe 中标记 flaky 测试@flaky 并设置特殊的 -g
规则,这意味着 mocha 运行s 仅使用 @flaky
标签进行测试,接下来使用 -i
- 这意味着反转,所以 mocha 运行 只测试 NOT @flaky
.
所以,认为它对你有用)
我有一个代码,其中某些测试在 CI 环境中总是会失败。我想根据环境条件禁用它们。
如何在运行时执行期间以编程方式跳过 mocha 中的测试?
您可以通过在 describe 或 it 块前面放置一个 x 或在其后放置一个 .skip
来跳过测试。
xit('should work', function (done) {});
describe.skip('features', function() {});
您还可以 运行 通过在测试上放置 .only
来进行单个测试。例如
describe('feature 1', function() {});
describe.only('feature 2', function() {});
describe('feature 3', function() {});
在这种情况下,只有功能 2 块 运行。
似乎没有办法以编程方式跳过测试,但您可以在 beforeEach
语句中进行某种检查,如果设置了标志,则只 运行 测试.
beforeEach(function(){
if (wrongEnvironment){
runTest = false
}
}
describe('feature', function(){
if(runTest){
it('should work', function(){
// Test would not run or show up if runTest was false,
}
}
}
这取决于您希望如何以编程方式跳过测试。如果在之前任何测试代码都可以确定跳过的条件是运行,那么你可以根据需要调用it
或it.skip
,根据一个条件。例如,如果环境变量 ONE
设置为任何值,这将跳过一些测试:
var conditions = {
"condition one": process.env["ONE"] !== undefined
// There could be more conditions in this table...
};
describe("conditions that can be determined ahead of time", function () {
function skip_if(condition, name, callback) {
var fn = conditions[condition] ? it.skip: it;
fn(name, callback);
};
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
如果要检查的条件只能在测试时才能确定,就稍微复杂一些。如果您不想访问严格来说不属于测试部分的任何内容 API,那么您可以这样做:
describe("conditions that can be determined at test time", function () {
var conditions = {};
function skip_if(condition, name, callback) {
if (callback.length) {
it(name, function (done) {
if (conditions[condition])
done();
else
callback(done);
});
}
else {
it(name, function () {
if (conditions[condition])
return;
callback();
});
}
};
before(function () {
conditions["condition one"] = true;
});
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
虽然我的第一个示例是将测试标记为正式跳过(又名 "pending"),但我刚才展示的方法只会避免执行实际测试,但不会将测试标记为正式跳过.他们将被标记为通过。如果你绝对想跳过它们,除了访问测试中不正确的部分之外,我不知道有什么方法 API:
describe("conditions that can be determined at test time", function () {
var condition_to_test = {}; // A map from condition names to tests.
function skip_if(condition, name, callback) {
var test = it(name, callback);
if (!condition_to_test[condition])
condition_to_test[condition] = [];
condition_to_test[condition].push(test);
};
before(function () {
condition_to_test["condition one"].forEach(function (test) {
test.pending = true; // Skip the test by marking it pending!
});
});
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
使用 Mocha 的 skip()
功能
它可用于静态禁用测试或整个套件,或在运行时动态跳过它。
这是一个运行时用法示例:
it('should only test in the correct environment', function() {
if (/* check test environment */) {
// make assertions
} else {
this.skip();
}
});
假设我想跳过我的参数化测试,如果我的测试描述包含字符串 "foo",我会这样做:
// Skip parametrized test if description contains the string "foo"
(test.description.indexOf("foo") === -1 ? it : it.skip)("should test something", function (done) {
// Code here
});
// Parametrized tests
describe("testFoo", function () {
test({
description: "foo" // This will skip
});
test({
description: "bar" // This will be tested
});
});
在你的情况下,我相信如果你想检查环境变量,你可以使用 NodeJS 的:
process.env.ENV_VARIABLE
例如(警告:我还没有测试这段代码!),可能是这样的:
(process.env.NODE_ENV.indexOf("prod") === -1 ? it : it.skip)("should...", function(done) {
// Code here
});
您可以将 ENV_VARIABLE 设置为您键入的任何内容,并使用该值跳过或 运行 测试。 (仅供参考,NodeJS process.env 的文档在这里:https://nodejs.org/api/process.html#process_process_env)
我不会完全相信这个解决方案的第一部分,我找到并测试了答案,它完美地通过这个资源跳过基于简单条件的测试:https://github.com/mochajs/mocha/issues/591
希望对您有所帮助! :)
正如@danielstjules 回答的那样here 有一种方法可以跳过测试。该主题的@author 复制了 github.com mochajs 讨论的答案,但没有关于可用的 mocha 版本的信息。
我正在使用 grunt-mocha-test 模块在我的项目中集成 mocha 测试功能。跳转到最后(现在)版本 - 0.12.7 给我 mocha 版本 2.4.5 实现 this.skip().
所以,在我的 package.json
"devDependencies": {
"grunt-mocha-test": "^0.12.7",
...
然后
npm install
这个钩子让我很开心:
describe('Feature', function() {
before(function () {
if (!Config.isFeaturePresent) {
console.log('Feature not configured for that env, skipping...');
this.skip();
}
});
...
it('should return correct response on AB', function (done) {
if (!Config.isABPresent) {
return this.skip();
}
...
请不要。您的构建基础架构应承认无法跨环境一致工作的测试。当 CI 构建的测试数量 运行 与本地不同时,这可能会让人迷失方向。
它也搞砸了可重复性。如果在服务器和本地进行不同的测试 运行,我可以让测试在开发中失败并通过 CI,反之亦然。没有强制功能,我无法快速准确地更正失败的构建。
如果您必须关闭环境之间的测试,而不是有条件地 运行 测试,标记您的测试并使用过滤器来消除在某些构建目标中不起作用的测试。这样每个人都知道发生了什么,这会降低他们的期望。它还让每个人都知道测试框架中存在不一致,并且有人可能有一个解决方案可以让他们再次 运行ning 正确。如果您只是将测试静音,他们甚至可能不知道有问题。
mocha test/ --grep <pattern>
您可以使用我的包 mocha-assume 以编程方式跳过测试,但只能从测试外部进行。你这样使用它:
assuming(myAssumption).it("does someting nice", () => {});
当 myAssumption
为 true
时,Mocha-assume 只会 运行 你的测试,否则它会跳过它(使用 it.skip
)并显示一条好消息。
这里有一个更详细的例子:
describe("My Unit", () => {
/* ...Tests that verify someAssuption is always true... */
describe("when [someAssumption] holds...", () => {
let someAssumption;
beforeAll(() => {
someAssumption = /* ...calculate assumption... */
});
assuming(someAssumption).it("Does something cool", () => {
/* ...test something cool... */
});
});
});
这样使用,可以避免级联故障。假设当 someAssumption 不成立时测试 "Does something cool"
总是会失败 - 但这个假设已经在上面测试过(在 Tests that verify someAssuption is always true"
中)。
所以测试失败并没有给你任何新的信息。事实上,它甚至是一个误报:测试没有失败,因为 "something cool" 没有工作,而是因为测试的前提条件不满足。使用 mocha-assume
您通常可以避免此类误报。
对于与您描述的相同的场景,我使用从 Mocha 跳过的运行时。这是docs:
的复制粘贴it('should only test in the correct environment', function() {
if (/* check test environment */) return this.skip();
// make assertions
});
如您所见,它跳过了基于环境的测试。我自己的条件是if(process.env.NODE_ENV === 'continuous-integration')
.
这并不是真正使用 mocha 的功能,而是调整它以获得我想要的行为。
我想跳过我的量角器 mocha 测试中的任何后续 'it',但有一个 'it' 失败了。这是因为一旦旅程测试的一个步骤失败,几乎可以肯定其余步骤也会失败,并且如果他们使用浏览器等待元素出现在页面上等,则可能需要很长时间并占用构建服务器
当只有 运行 标准 mocha 测试(不是量角器)时,这可以通过将 'skipSubsequent' 标志附加到测试的父级(描述)来使用全局 beforeEach 和 afterEach 挂钩来实现,如下所示:
beforeEach(function() {
if(this.currentTest.parent.skipSubsequent) {
this.skip();
}
});
afterEach(function() {
if (this.currentTest.state === 'failed') {
this.currentTest.parent.skipSubsequent = 'true'
}
})
尝试使用量角器和 mocha 时,'this' 的范围发生了变化,上面的代码不起作用。您最终得到一条错误消息,如 'error calling done()' 并且量角器停止。
相反,我得到了下面的代码。不是最漂亮的,但它最终用 this.skip() 替换了剩余测试函数的实现。这可能会停止工作 if/when mocha 的内部结构随着更高版本的变化而变化。
它是通过调试和检查 mocha 的内部结构通过反复试验得出的...虽然测试失败时有助于使浏览器测试套件更快地完成。
beforeEach(function() {
var parentSpec = this.currentTest.parent;
if (!parentSpec.testcount) {
parentSpec.testCount = parentSpec.tests.length;
parentSpec.currentTestIndex = 0;
} else {
parentSpec.currentTestIndex = parentSpec.currentTestIndex + 1;
}
if (parentSpec.skipSubsequent) {
parentSpec.skipSubsequent = false;
var length = parentSpec.tests.length;
var currentIndex = parentSpec.currentTestIndex;
for (var i = currentIndex + 1; i < length; i++) {
parentSpec.tests[i].fn = function() {
this.skip();
};
}
}
});
afterEach(function() {
if (this.currentTest.state === 'failed') {
this.currentTest.parent.skipSubsequent = 'true'
}
});
这个答案适用于 ES6。
而不是:
describe('your describe block', () => {
你想要:
(condition ? describe : describe.skip)('your describe block', () => {
如果条件为假,这将有条件地跳过描述块中的所有测试。
或者,而不是:
it('your it block', () => {
你想要:
(condition ? it : it.skip)('your it block', () => {
如果条件为假,这将有条件地跳过一个测试。
我不确定这是否符合“编程跳过”的条件,但为了有选择地跳过我们 CI 环境的某些特定 cific 测试,我使用了 Mocha 的标记功能(https://github.com/mochajs/mocha/wiki/Tagging).
在 describe()
或 it()
消息中,您可以添加 @no-ci 之类的标签。要排除这些测试,您可以在 package.json 中定义一个 specific "ci target" 并使用 --grep
和 --invert
参数,例如:
"scripts": {
"test": "mocha",
"test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
我们可以编写一个漂亮的干净包装函数来有条件地 运行 测试如下:
function ifConditionIt(title, test) {
// Define your condition here
return condition ? it(title, test) : it.skip(title, test);
}
这可以在您的测试中被要求和使用,如下所示:
ifConditionIt('Should be an awesome test', (done) => {
// Test things
done();
});
要跳过测试,请使用 describe.skip
或 it.skip
describe('Array', function() {
it.skip('#indexOf', function() {
// ...
});
});
要包括您可以使用 describe.only
或 it.only
的测试
describe('Array', function() {
it.only('#indexOf', function() {
// ...
});
});
可以根据条件使用, 例如,声明一个 var,当条件失败时,使用 this.skip();
Note that skip() does not work in arrow function
let shouldRun: boolean;
before(function(){
if ($('#nsErrorIframe').isDisplayed()) {
driver.switchToFrame($('#nsErrorIframe'));
if ($('.ns-error-wrapper').isDisplayed()) {
console.log('PAGE IS NOT AVAILABLE');
shouldRun = false;
if ( shouldRun === false) {
this.skip();
}
}
}
});
我们的测试环境中有一些不可靠的测试,有时会使用这种方法关闭某些测试:
mocha --config ./config/parallelrc.cjs --parallel --jobs 3 -- tests/spec/**/index.js -g @flaky -i
我们在 tests describe 中标记 flaky 测试@flaky 并设置特殊的 -g
规则,这意味着 mocha 运行s 仅使用 @flaky
标签进行测试,接下来使用 -i
- 这意味着反转,所以 mocha 运行 只测试 NOT @flaky
.
所以,认为它对你有用)