如何以编程方式跳过摩卡测试?

时间:2015-09-22 17:26:51

标签: mocha

我有一个代码,其中某些测试将始终在CI环境中失败。我想根据环境条件禁用它们。

如何在运行时执行期间以编程方式跳过mocha中的测试?

16 个答案:

答案 0 :(得分:136)

您可以通过在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,
         }
    }
}

答案 1 :(得分:75)

有一种以无记录方式以编程方式跳过测试:

// test.js

describe('foo', function() {
  before(function() {
    this.skip();
  });

  it('foo', function() {
    // will not run
    console.log('This will not be printed');
  });
});

运行:

$ mocha test.js


  foo
    - foo


  0 passing (9ms)
  1 pending

这在https://github.com/mochajs/mocha/issues/1901中进行了讨论。

答案 2 :(得分:28)

此答案适用于ES6

而不是:

describe('your describe block', () => {

你想:

(condition ? describe : describe.skip)('your describe block', () => {

如果条件为假,这有条件地跳过描述块中的所有测试。

或者,而不是:

it('your it block', () => {

你想:

(condition ? it : it.skip)('your it block', () => {

如果条件为假,则有条件地跳过一次测试。

答案 3 :(得分:24)

我使用Mocha运行时跳过与您描述的相同的场景。它是docs

的复制粘贴
it('should only test in the correct environment', function() {
  if (/* check test environment */) {
    // make assertions
  } else {
    this.skip();
  }
});

如您所见,它会根据环境跳过测试。我自己的条件是if(process.env.NODE_ENV === 'continuous-integration')

答案 4 :(得分:6)

这取决于您希望以编程方式跳过测试。如果在运行任何测试代码之前可以确定跳过的条件,那么您可以根据条件根据需要调用itit.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!");
    });

});

虽然我的第一个例子是将测试标记为正式跳过(又名"待定"),但我刚刚展示的方法将避免执行实际测试,但测试不会被测试被标记为正式跳过。它们将被标记为已通过。如果你绝对想要跳过它们,我不知道如何访问那些没有正确说出测试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!");
    });

});

答案 5 :(得分:2)

我们可以编写一个很好的干净包装函数来有条件地运行测试,如下所示:

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();
});

答案 6 :(得分:1)

您可以使用我的包mocha-assume以编程方式跳过测试,但仅限于测试之外。你这样使用它:

assuming(myAssumption).it("does someting nice", () => {});

Mocha-assume只会在myAssumptiontrue时运行您的测试,否则会跳过它(使用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... */
        });
    });
});

以这种方式使用它可以避免级联故障。假设当某些假设不成立时,测试"Does something cool"将总是失败 - 但是这个假设已在上面进行过测试(在Tests that verify someAssuption is always true"中)。

因此测试失败不会给您任何新信息。事实上,它甚至是一种假阳性:测试没有失败,因为"一些很酷的东西"不起作用,但因为测试的前提条件不满意。使用mocha-assume,您通常可以避免这种误报。

答案 7 :(得分:1)

我不确定这是否属于“程序化跳过”,但为了有选择地跳过我们CI环境的某些特定测试,我使用了Mocha的标记功能(https://github.com/mochajs/mocha/wiki/Tagging)。 在describe()it()消息中,您可以添加@ no-ci等标记。要排除这些测试,您可以定义特定的" ci目标"在package.json中使用--grep--invert参数,例如:

"scripts": {
  "test": "mocha",
  "test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}

答案 8 :(得分:1)

要跳过测试,请使用describe.skipit.skip

describe('Array', function() {
  describe.skip('#indexOf()', function() {
    // ...
  });
});

包括测试,您可以使用describe.only

describe('Array', function() {
  describe.only('#indexOf()', function() {
    // ...
  });
});

更多信息,https://www.caniuse.com/#search=email

答案 9 :(得分:0)

如果我的测试描述包含字符串“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

希望这有帮助! :)

答案 10 :(得分:0)

for j in range(15):
    fancycode
    k = j % 3
    print(k)

https://mochajs.org/

答案 11 :(得分:0)

这并不是真的使用摩卡的功能,而是调整它以获得我想要的行为。

我想跳过任何后续的'''在我的量角器摩卡测试和一个'它'失败。这是因为一旦旅程测试的一步失败,几乎可以肯定其余部分会失败,并且如果他们使用浏览器等待元素出现在页面等上,则可能需要很长时间并且占用构建服务器。

当只运行标准的mocha测试(不是量角器)时,可以使用全局的beforeEach和afterEach挂钩来实现,这可以通过附加一个' skipSubsequent'标记为测试的父级(描述),如下所示:

  handleClick(event) {
   const value = event.currentTarget.value;
   this.setState({ touched: value });
  }

 render() {
  return(
   <ChildComponent {...this.state} />
  )

 }

当使用量角器尝试这个时,mocha它的范围是&#39;这个&#39;已更改,上面的代码不起作用。您最终会收到一条错误消息,例如错误调用done()&#39;和量角器停止。

相反,我最终得到了以下代码。不是最漂亮的,但它最终用this.skip()替换剩余测试函数的实现。如果/当mocha的内部与更高版本一起改变时,这可能会停止工作。

通过调试和检查mocha的内部结构,通过一些反复试验得出结论......有助于在测试失败时尽快完成浏览器测试套件。

    beforeEach(function() {
      if(this.currentTest.parent.skipSubsequent) {
            this.skip();
      }
    }); 


    afterEach(function() {
      if (this.currentTest.state === 'failed') {
        this.currentTest.parent.skipSubsequent = 'true'
      }
    })

答案 12 :(得分:0)

可以根据条件使用, 例如,声明一个var,当条件失败时,使用this.skip();

<块引用>

注意skip()在箭头函数中不起作用

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();
                }
                }
  }
});

答案 13 :(得分:0)

我们在测试环境中有一些不稳定的测试,有时会使用这种方法关闭测试:

mocha --config ./config/parallelrc.cjs --parallel --jobs 3 -- tests/spec/**/index.js -g @flaky -i

我们在tests describe中标记了flaky测试@flaky并设置了特殊的-g规则,这意味着mocha只运行带有@flaky标签的测试,接下来使用-i - 这意味着反转,所以 mocha 只运行测试而不是 @flaky

所以,认为它对你有用)

答案 14 :(得分:-2)

由于@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();
        }

        ...

答案 15 :(得分:-3)

请不要。对于环境不一致的测试,您的构建基础架构应该承认这一点。当CI构建具有与本地不同的测试数量时,它可能非常迷惑。

它还会破坏重复性。如果在服务器和本地运行不同的测试,我可以让测试在dev中失败并传入CI,反之亦然。没有强制功能,我无法快速准确地纠正失败的构建。

如果必须在环境之间关闭测试,而不是有条件地运行测试,请标记测试并使用过滤器来消除在某些构建目标中不起作用的测试。这样每个人都知道发生了什么,这会缓和他们的期望。它还让每个人都知道测试框架中存在不一致,并且有人可能有一个解决方案可以让它们再次正常运行。如果你只是将测试静音,他们可能甚至不知道有问题。