私も多くのソフトウェア開発者と同様に🦁ライオンの人にインスパイアされ、20年近くもテストを書いています。
RSpecも初期の頃から使っていますが、最近になって大きな勘違いをしていた事に気がつきました。
Stable Diffusion(mage.space)が生成した画像です
順をおって説明
1. 最初
テスト対象の関数は、少ないパラメーターを受け取り複数のテーブルにレコードを作成します。テストとしては複数のテーブルに作成されたレコードを検証することなので、以下のようなテストを書きました。テスティングフレームワークはMocha です。
describe('ある関数のテスト', () => {
beforeEach(() => {
// 1. いろいろと準備
// 2. パラメータAで、ある関数を呼び出す
});
it('テーブル1が作成されている', () => {
// 作成されたレコードの検証
});
it('テーブル2が作成されている', () => {
// 作成されたレコードの検証
});
// ・・・
});
2. テストの高速化
1.では it()
の実行毎にある関数を呼び出されます。いろいろとあってある関数の実行が遅いのでbeforeEach()
をbefore()
に置き換えました(RSpecでいうとbefore(:all)
です)。こうするとある関数の実行は1回になりテストが高速されます。
ちなみにit()
内は、テーブルを読み出すだけで副作用がないので、問題は起きません。
describe('ある関数のテスト', () => {
before(() => {
// 1. いろいろと準備
// 2. パラメータAで、ある関数を呼び出す
});
it('テーブル1が作成されている', () => {
// 作成されたレコードの検証
});
it('テーブル2が作成されている', () => {
// 作成されたレコードの検証
});
// ・・・
});
3. テストケースの追加
ある関数を別のパラメーターで実行するテストケースを追加しました。
describe('ある関数のテスト', () => {
describe('パラメータAでテスト', () => {
before(() => {
// 1. いろいろと準備
// 2. パラメータBで、ある関数を呼び出す
});
it('テーブル1が作成されている', () => {
// 作成されたレコードの検証
});
it('テーブル2が作成されている', () => {
// 作成されたレコードの検証
});
// ・・・
});
describe('パラメータBでテスト', () => {
before(() => {
// 1. いろいろと準備
// 2. パラメータBで、ある関数を呼び出す
});
it('テーブル1が作成されている', () => {
// 作成されたレコードの検証
});
it('テーブル2が作成されている', () => {
// 作成されたレコードの検証
});
// ・・・
});
});
4. いろいろと準備を共通化
これから他のパラメーターのテストも追加されるの、いろいろと準備を共通化しました。
しかしテストが失敗してしまいました。😅
describe('ある関数のテスト', () => {
beforeEach(() => {
// いろいろと準備
});
describe('パラメータAでテスト', () => {
before(() => {
// パラメータBで、ある関数を呼び出す
});
it('テーブル1が作成されている', () => {
// 作成されたレコードの検証
});
it('テーブル2が作成されている', () => {
// 作成されたレコードの検証
});
// ・・・
});
describe('パラメータBでテスト', () => {
before(() => {
// パラメータBで、ある関数を呼び出す
});
it('テーブル1が作成されている', () => {
// 作成されたレコードの検証
});
it('テーブル2が作成されている', () => {
// 作成されたレコードの検証
});
// ・・・
});
});
失敗の原因
わかる方は判ると思いますが、いろいろと準備をbeforeEach()
にしたのが原因でしてた。
私はbeforeEach()
は、コード上でそれ以降に書かれている describe()
の直前で実行されると思っていたのですが、真実はit()
の直前で実行されるのです(ドキュメントにも書かれていますね)。
ただし、いろいろと準備の中にはテーブルのクリーンアップも含まれているので、ある関数の実行前には必ず実行したいのです。3.に戻すしかないのでしょうか・・・