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

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


当前回答

假设我想跳过我的参数化测试,如果我的测试描述包含字符串“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进程的文档。Env在这里:https://nodejs.org/api/process.html#process_process_env)

我不会把这个解决方案的第一部分完全归功于我,我找到并测试了答案,它可以通过这个资源完美地跳过基于简单条件的测试:https://github.com/mochajs/mocha/issues/591

希望这能有所帮助!:)

其他回答

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

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

我不确定这是否可以称为“程序性跳过”,但是为了有选择性地跳过我们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"
}

请不要。在不同环境中不能一致工作的测试应该得到构建基础设施的承认。当CI构建运行的测试数量与本地构建不同时,可能会非常令人困惑。

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

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

假设我想跳过我的参数化测试,如果我的测试描述包含字符串“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进程的文档。Env在这里:https://nodejs.org/api/process.html#process_process_env)

我不会把这个解决方案的第一部分完全归功于我,我找到并测试了答案,它可以通过这个资源完美地跳过基于简单条件的测试:https://github.com/mochajs/mocha/issues/591

希望这能有所帮助!:)

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

});