1713113943
2024-04-10 12:08:54
JavaScript / TypeScript でテストを作成する場合は、すでに関数に遭遇している可能性が高くなります。 describe など it 。 実際、Jest、Mocha、さらには Jasmine などの最も人気のあるテスト フレームワーク すべて RSpec からインスピレーションを得たもの これらの関数をテスト スイートの作成と構築に利用できるようにします。 Mocha はドキュメントでこの API を指定しています インターフェース BDD。
テスト ケースのコードを構造化するためのもう 1 つの一般的な方法は、コメントを使用してテストのさまざまな段階、特に 3 つの段階を分離することです。 Given、 When、 Then (再び BDD からインスピレーションを得たもの) またはその同等の略語がよく使われます。 AAA: Arrange、 Act、 Assert。 例えば :
describe('MyComponent', () => {
const sut = new MyComponent();
it('should do stuff when the input is something', () => {
const input = buildSomeInput();
sut.doStuff(input);
expect(sut).toHaveDoneSomething();
});
});
これらのコメントはコードの構造化に役立ちますが、いつものように、 コードをより表現力豊かにすることができないかどうかを自問する良い機会です。 など スポイラー警告、それがこの記事の主題です 😉
次の行はすでに注目されています。 Given によって示される状態の確立です。 when the input is something テストのタイトルにあります。 また、どのようなテスト フレームワークが使用されていたとしても、 describe はテストケースをグループ化するための API であるだけでなく、この機能は フック 特に、各テスト ケースの前、またはこのテスト ケースに含まれるすべてのテストの前にアクションをトリガーします。 describe。 したがって、適切な説明(の最初のパラメータ)を組み合わせることで、 describe)たとえば次から始まります 与えられた そして1つ 針 このコメントを組み込んだ、より表現力豊かなコードが得られます。 Given そしてそれを対応する動作に関連付けます。 滞在する When など Then、しかし、それらは非常に便利ですか? 系統的に When これはテスト ケースの最初の行を対象としており、おそらく Then 他のすべてに…
つまり、上記の例は次のように書き換えることができます。
describe('MyComponent', () => {
const sut = new MyComponent();
describe('given the input is something', () => {
let input;
beforeEach(() => {
input = buildSomeInput();
});
it('should do stuff', () => {
sut.doStuff(input);
expect(sut).toHaveDoneSomething();
});
})
});
明らかに、このような単純な例では差は最小限ですが、複数の状態を組み合わせたテスト スイートではこれが起こります。 パターン これは特に実用的であることがわかります。たとえば、ユーザーのプロファイルと構成に従ってユーザーに通知する役割を持つコンポーネントを想像してください。テスト スイートは次のようになります。
describe("Notifier", () => {
const sut = new Notifier();
describe("given the user is a free user", () => {
beforeEach(() => {
})
it("should not notify the user", () => {
});
})
describe("given the user is a premium user", () => {
beforeEach(() => {
})
describe("given she has configured the notifications to be issued by SMS", () => {
beforeEach(() => {
})
it("should notify the user by sms", () => {
});
});
describe("given she has configured the notifications to be issued by email", () => {
beforeEach(() => {
})
it("should notify the user by email", () => {
});
});
})
});
この構造にはいくつかの利点があります。
- 体系的なカップル
describe("given …")/beforeEachある種の凝集性が導入されているため、 針 実際に記述を実装するか、逆に前提条件が何を意味するかを理解します。 - テスト スイートは簡単に進化できます。たとえば、明日新しい構成で Slack またはその他の手段で通知を送信できるようにする場合は、ブロックを追加するだけです。
describeそして出来上がり。 - テストを開始すると、テスト対象のコンポーネントの仕様が取得されます (コンポーネントの仕様に応じて)。 レポーター 使用されます)、この例では次のようになります。
Notifier given the user is a free user ✔ should not notify the user given the user is a premium user given she has configured the notifications to be issued by SMS ✔ should notify the user by sms given she has configured the notifications to be issued by email ✔ should notify the user by emailこれは、既存のコード ベースを理解するのに非常に実用的です。
- テストが失敗した場合、この構造によりエラーが理解しやすくなり、バグの特定も容易になる可能性があります。
そして、私はおそらくいくつかを忘れています!
要するに、 describe そしてその フック テストを構造化できます。 この構造では、さまざまな状態を分離すること、そして何よりも正確に名前を付けることが特に必要です。これにより、比較的少ないコストでテストが読みやすく、保守しやすくなります。 いくつかのものから遠ざかる アンチパターン 電流 あるいは逆に試してみる 良いテストを書くために。
#テストを構造化して読みやすく保守しやすくする