CI環境で特定のテストが常に失敗するコードがあります。環境条件に基づいて無効にしたいと思います。
ランタイムの実行中にmochaのテストをプログラムでスキップする方法は?
プログラムでテストをスキップする文書化されていない方法があります。
// 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 で説明されています。
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,
}
}
}
この回答はES6で機能します。
の代わりに:
describe('your describe block', () => {
あなたが欲しい:
(condition ? describe : describe.skip)('your describe block', () => {
これは、条件がfalseの場合、describeブロックのすべてのテストを条件付きでスキップします。
または、代わりに:
it('your it block', () => {
あなたが欲しい:
(condition ? it : it.skip)('your it block', () => {
これは、条件が偽の場合、条件付きで1つのテストをスキップします。
あなたが説明しているのと同じシナリオで、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')
です。
プログラムによってテストをスキップする方法によって異なります。スキップの条件を決定できる場合before任意のテストコードが実行されると、条件に基づいて必要に応じて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!");
});
});
最初の例では、テストを正式にスキップ(「保留中」)としてマークしましたが、今示した方法では実際のテストの実行を回避しますが、テストは正式にスキップとしてマークされません。それらは合格としてマークされます。それらを絶対にスキップしたい場合は、テスト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!");
});
});
describe.skip
またはit.skip
を使用しますdescribe('Array', function() {
it.skip('#indexOf', function() {
// ...
});
});
describe.only
またはit.only
を使用できますdescribe('Array', function() {
it.only('#indexOf', function() {
// ...
});
});
次のように、条件付きでテストを実行するニースクリーンラッパー関数を作成できます。
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のようなタグを追加できます。これらのテストを除外するには、package.jsonで特定の「ciターゲット」を定義し、次のような--grep
および--invert
パラメーターを使用できます。
"scripts": {
"test": "mocha",
"test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
私のパッケージ mocha-assume を使用して、プログラムでテストをスキップできますが、テストの外部からのみです。次のように使用します。
assuming(myAssumption).it("does someting Nice", () => {});
Mocha-assumeは、myAssumption
がtrue
の場合にのみテストを実行します。そうでない場合は、Niceメッセージで(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"
で)テスト済みです。
そのため、テストが失敗しても新しい情報は得られません。実際、それは偽陽性ですらあります。「何かクール」が機能しなかったためにテストは失敗しませんでしたが、テストの前提条件が満たされていないためです。 mocha-assume
を使用すると、多くの場合、このような誤検出を回避できます。
これは実際にmochaの機能を使用しているのではなく、望んでいる動作を得るために微調整しています
分度器モカテストで後続の「it」をスキップしたかったため、1つの「it」が失敗しました。これは、一度旅のテストの1つのステップが失敗すると、残りはほぼ確実に失敗し、ブラウザなどを使用してページに要素が表示されるのを待っている場合、ビルドサーバーを占有する可能性があるためです.
(分度器ではなく)標準のモカテストを実行するだけで、次のようにテストの親に 'skipSubsequent'フラグを付けることで、グローバルbeforeEachおよびafterEachフックでこれを実現できます。
beforeEach(function() {
if(this.currentTest.parent.skipSubsequent) {
this.skip();
}
});
afterEach(function() {
if (this.currentTest.state === 'failed') {
this.currentTest.parent.skipSubsequent = 'true'
}
})
分度器とモカでこれを試みると、「これ」の範囲が変更され、上記のコードは機能しません。最終的に「error calling done()」のようなエラーメッセージが表示され、分度器が停止します。
代わりに、私は以下のコードで終わりました。最もきれいではありませんが、残りのテスト関数の実装をthis.skip()に置き換えてしまいます。これはおそらく、後のバージョンで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'
}
});
mocha test/ --grep <pattern>
テストの説明に文字列「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をキーオフする値に設定し、その値を使用できる場合は、テストをスキップまたは実行します。 (FYI NodeJSのprocess.envのドキュメントはここにあります: https://nodejs.org/api/process.html#process_process_env )
このソリューションの最初の部分を完全に評価するつもりはありません。答えを見つけてテストしたところ、このリソースを通じて単純な条件に基づいてテストをスキップすることができました: https://github.com/mochajs/mocha/issues/591
お役に立てれば! :)