公式Mochaサイト のドキュメントには、この例が含まれています。
describe('User', function(){
describe('#save()', function(){
it('should save without error', function(done){
var user = new User('Luna');
user.save(function(err){
if (err) throw err;
done();
});
})
})
})
describe
関数にテストをネストする時期と、describe
の基本的な目的は何かを知りたいです。 describe
に渡された最初の引数をプログラミング言語のコメントと比較できますか?コンソールの出力にdescribe
の何も表示されません。読みやすさのみを目的としていますか、またはこの機能には他の用途がありますか?
このように使用すると何か問題はありますか?
describe('User', function(){
describe('#save()', function(){
var user = new User('Luna');
user.save(function(err){
if (err) throw err;
done();
})
})
})
このようにすると、テストに合格します。
it
呼び出しは個々のテストを識別しますが、it
自体は、テストスイートが構造化である方法についてMochaに何も伝えません。 describe
呼び出しを使用する方法は、テストスイートに構造を与えるものです。 describe
を使用してテストスイートを構造化することのいくつかを次に示します。議論のために簡略化されたテストスイートの例を次に示します。
function Foo() {
}
describe("Foo", function () {
var foo;
beforeEach(function () {
foo = new Foo();
});
describe("#clone", function () {
beforeEach(function () {
// Some other hook
});
it("clones the object", function () {
});
});
describe("#equals", function () {
it("returns true when the object passed is the same", function () {
});
it("returns false, when...", function () {
});
});
afterEach(function () {
// Destroy the foo that was created.
// foo.destroy();
});
});
function Bar() {
}
describe("Bar", function () {
describe("#clone", function () {
it("clones the object", function () {
});
});
});
Foo
とBar
が本格的なクラスであると想像してください。 Foo
にはclone
およびequals
メソッドがあります。 Bar
にはclone
があります。上記の構造は、これらのクラスのテストを構造化する方法の1つです。
(#
表記は、一部のシステム(jsdocなど)でインスタンスフィールドを示すために使用されます。したがって、メソッド名とともに使用する場合、クラスではなくクラスのインスタンスで呼び出されるメソッドを示します。メソッド(クラス自体で呼び出されます)。テストスイートは、#
がなくても同様に実行されます。
Mochaのレポーターの一部は、作成するレポートでdescribe
に付けた名前を示しています。たとえば、spec
レポーター($ mocha -R spec
を実行することで使用できます)は、以下を報告します。
Foo
#clone
✓ clones the object
#equals
✓ returns true when the object passed is the same
✓ returns false, when...
Bar
#clone
✓ clones the object
4 passing (4ms)
一部のテストのみを実行する場合は、--grep
オプションを使用できます。したがって、Bar
クラスのみに関心がある場合は、$ mocha -R spec --grep Bar
を実行して、出力を取得できます。
Bar
#clone
✓ clones the object
1 passing (4ms)
または、すべてのクラスのclone
メソッドのみに関心がある場合は、$ mocha -R spec --grep '\bclone\b'
を実行して出力を取得します。
Foo
#clone
✓ clones the object
Bar
#clone
✓ clones the object
2 passing (5ms)
--grep
に指定された値は正規表現として解釈されるため、\bclone\b
を渡すと、clone
やclones
などの単語ではなく、cloned
という単語のみを要求しています。
上記の例では、beforeEach
およびafterEach
呼び出しはフックです。各フックは、フックの親であるit
呼び出し内にあるdescribe
呼び出しに影響します。さまざまなフックは次のとおりです。
beforeEach
は、it
呼び出し内の個々のdescribe
の前に実行されます。
afterEach
は、it
呼び出し内の個々のdescribe
の後に実行されます。
before
呼び出し内の個々のit
のいずれかが実行される前に1回実行されるdescribe
。
after
呼び出し内の個々のit
がすべて実行された後に1回実行されるdescribe
。
これらのフックを使用して、リソースを取得したり、テストに必要なデータ構造を作成したり、テストの完了後にリソースを解放したり、必要に応じてこれらの構造を破棄したりできます。
質問の最後に表示するスニペットはエラーを生成しませんが、テストはit
で定義されているため、実際にはテストは含まれていません。
私の知る限りでは、describeは実際には人間のためだけにあります...したがって、アプリのさまざまな領域を見ることができます。 nレベルの深さまでネストできます。
describe('user',function(){
describe('create',function(){}
});
ルイの優れた答えに加えるのは難しい。 skip
およびonly
関数である、彼が言及しなかった記述ブロックにはいくつかの利点があります。
_describe.skip(...) {
...
}
_
この記述とすべてのネストされた記述をスキップし、次の間に機能します。
_describe.only(...) {
...
}
_
その記述とそのネストされた記述のみを実行し、機能します。 skip()
およびonly()
修飾子もit()関数に適用できます。
Describeはテストの目的を理解するために使用されるだけであり、テストを論理的にグループ化するためにも使用されます。データベースAPIをテストしているとしましょう。すべてのデータベーステストは外部記述の下にある可能性があるため、外部記述はすべてのデータベース関連を論理的にグループ化します。テストするデータベース関連のAPIが10個あるとしましょう。各内部記述関数は、それらのテストが何であるかを定義します。
Describeの特定の役割は、テストされているコンポーネントとそのコンポーネントのメソッドもテストされていることを示すことです。
たとえば、ユーザープロトタイプがあるとします
var User = function() {
const self = this;
function setName(name) {
self.name = name
}
function getName(name) {
return self.name;
}
return{setName, getName};
}
module.exports = User;
また、テストする必要があるため、単体テスト用のスペックファイルが作成されます
var assert = require('assert');
var User = require("../controllers/user.controller");
describe("User", function() {
describe('setName', function() {
it("should set the name on user", function() {
const pedro = new User();
name = "Pedro"
pedro.setName(name);
assert(pedro.getName(), name);
});
});
});
Describeの目的はテストするコンポーネントを示しており、ネストされたdescribeメソッドはどのメソッドをテストする必要があるかを示していることがわかりやすい