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

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


当前回答

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

});

其他回答

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

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

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

我想在量角器摩卡测试中跳过所有后续的“it’s”,但有一个“it’s”失败了。这是因为一旦旅程测试的一个步骤失败,几乎可以肯定其他步骤也会失败,并且可能需要很长时间,如果他们使用浏览器等待元素出现在页面上等,可能会占用构建服务器。

当只是运行标准摩卡测试(不是量角器)时,这可以通过全局beforeEach和afterEach钩子来实现,在测试的父(描述)上附加一个' skipfollow '标志,如下所示:

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


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

当尝试使用量角器和摩卡时,“this”的范围发生了变化,上面的代码不起作用。你最终会得到一个错误消息,比如'error calling done()',量角器会停止。

相反,我最终得到了下面的代码。不是最漂亮的,但它最终用this.skip()替换了其余测试函数的实现。如果/当摩卡的内部结构在后续版本中发生变化时,这可能会停止工作。

这是通过调试和检查摩卡内部的一些试验和错误发现的……不过,当测试失败时,有助于更快地完成浏览器测试套件。

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', () => {

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

我们在测试环境中有一些不可靠的测试,有时会使用以下方法关闭这些测试:

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

我们在测试描述中标记flaky测试@flaky,并设置特殊的-g规则,这意味着mocha只运行带有@flaky标签的测试,接下来使用-i -它意味着反转,因此mocha只运行测试而不是@flaky。

所以,我认为这对你很有用)

可根据情况使用, 例如,声明一个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();
                }
                }
  }
});