特定のテストがCI環境で常に失敗するコードがあります。環境条件によって無効にしたい。
ランタイム実行中にプログラムでモカのテストをスキップする方法は?
特定のテストがCI環境で常に失敗するコードがあります。環境条件によって無効にしたい。
ランタイム実行中にプログラムでモカのテストをスキップする方法は?
回答:
記述またはブロックの前にxを配置するか、.skip
後にa を配置することで、テストをスキップできます。
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,
}
}
}
beforeEach
呼び出しが実行は、モカは記録のために無名関数(「フック」)未来の際、使用describe
コール実行、モカはすぐにそれに渡された匿名関数を実行します。したがって、if (runTest)
実行されるまでに、beforeEach
フックは実行されません。
プログラムでテストをスキップする、文書化されていない方法があります。
// 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
describe
がスキップされたとマークされる(つまり、のすべてのテストdescribe
がスキップされる)ことを知りたいと思うかもしれません。
この回答はES6では機能します。
の代わりに:
describe('your describe block', () => {
あなたが欲しい:
(condition ? describe : describe.skip)('your describe block', () => {
これは、条件が偽の場合、条件付きで記述ブロック内のすべてのテストをスキップします。
または、代わりに:
it('your it block', () => {
あなたが欲しい:
(condition ? it : it.skip)('your it block', () => {
これは、条件がfalseの場合、条件付きで1つのテストをスキップします。
const contextualDescribe = shouldAvoidTests ? describe.skip : describe
それからそれを使うことができます: contextualDescribe('your it block', () => {
(condition ? describe : describe.skip)('your describe block', () => {
(it)('my test', () => {})
あなたが説明しているのと同じシナリオで、Mochaからのランタイムスキップを使用します。それはドキュメントからのコピーペーストです:
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')
です。
if (/* skipTestCondition */) return this.skip();
describe.skip
またはを使用しますit.skip
describe('Array', function() {
it.skip('#indexOf', function() {
// ...
});
});
describe.only
か、it.only
describe('Array', function() {
it.only('#indexOf', function() {
// ...
});
});
プログラムでテストをスキップする方法によって異なります。テストコードを実行する前にスキップの条件を決定できる場合は、条件に基づいて、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!");
});
});
これが「プログラムによるスキップ」に該当するかどうかはわかりませんが、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
(を使用して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"
someAssumptionが成り立たない場合、テストは常に失敗するとします-しかし、この仮定は(上記でTests that verify someAssuption is always true"
)すでにテスト済みです。
したがって、テストが失敗しても新しい情報は得られません。実際、それは偽陽性でさえあります。「クールな何か」が機能しなかったためにテストは失敗しませんでしたが、テストの前提条件が満たされていないためです。でmocha-assume
、あなたは、多くの場合、このような偽陽性を回避することができます。
beforeAll
フックは、すべてのテストが収集される前に実行することが保証されていません。実際には、後で実行される可能性が非常に高いですが、この場合、assuming(someAssumption)
は、最初の(未定義の)値を既に受け取ってはずです。目的の効果を実現するには、その部分を関数でラップすることも必要です。
次のように、条件付きでテストを実行するためのすっきりとしたクリーンなラッパー関数を作成できます。
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();
});
テストの説明に「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
お役に立てれば!:)
これは実際にはモカの機能を使用しているのではなく、微調整を行って希望する動作を実現しています。
分度器モカテストで後続の「it's」をスキップしたかったのですが、1つの「it」が失敗しました。これは、ジャーニーテストの1つのステップが失敗すると、残りが失敗することはほぼ確実であり、ブラウザを使用している場合、要素がページに表示されるのを待つなど、ビルドサーバーに時間がかかる可能性があるためです。
標準のモカテスト(分度器ではない)を実行するだけの場合、グローバルなbeforeEachフックとafterEachフックを使用して、次のようにテストの親(説明)に 'skipSubsequent'フラグを付加することでこれを実現できます。
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()に置き換えてしまいます。これはおそらく、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>
@danielstjulesがここに答えたようにでたように、テストをスキップする方法があります。このトピックの@作成者はgithub.com mochajsディスカッションから回答をコピーしましたが、利用可能なmochaのバージョンに関する情報はありません。
プロジェクトにモカテスト機能を統合するためにgrunt-mocha-testモジュールを使用しています。最後の(今のところ)バージョンへのジャンプ-0.12.7はthis.skip()の実装を備えたモカバージョン2.4.5をもたらします。
だから、私の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ビルドでローカルとは異なる数のテストを実行すると、混乱を招く可能性があります。
また、それは再現性を台無しにします。サーバーとローカルで異なるテストを実行すると、テストがdevで失敗し、CIで合格するか、またはその逆になります。強制機能はなく、失敗したビルドを迅速かつ正確に修正する方法はありません。
条件付きで実行するテストではなく、環境間でテストをオフにする必要がある場合は、テストにタグを付け、フィルターを使用して、特定のビルドターゲットで機能しないテストを排除します。そうすれば、誰もが何が起こっているのかを理解し、期待を和らげることができます。また、テストフレームワークに不整合があることを全員に知らせます。また、誰かが適切に実行するためのソリューションを持っている可能性があります。テストをミュートするだけでは、問題があることさえ知らないかもしれません。
this.skip()
、mochajs.org /#inclusive- testsと@zatzikyの以下の回答で説明されています。モカv3以降では、残りの回答は廃止されます