検索

Writing high quality tests

残念ながら、テストは依然として多くの組織で当然の注目を集めていません。開発者はテストをまったく書いていないことに罪悪感を感じているように感じることがありますが、同時にテストコードが適切にレビューされていないことがよくあります。代わりに、レビューでよくチェックされるのはテストがあるかどうかだけですが、テストがあるだけでは十分ではありませんので、これは残念です。実際には、プロジェクト内の他のすべてのコードと少なくとも同じ品質、あるいはそれ以上の品質である必要があります。そうしないと、テストがあまりにも頻繁に失敗したり、理解しにくくなったり、実行に時間がかかりすぎたりするため、実際にテストを行うのをためらう可能性があります。リポジトリ モックの代わりにメモリ内実装を使用することについては、ブログ投稿でこれらの点のいくつかをすでに説明しました。ここで、テストを作成するときに私が気をつけている他の、より一般的なことについて説明したいと思います。

ミニマリズムが鍵です

スタック オーバーフローでは、質問に最小限の再現可能な例を追加するよう求められます。私の意見では、これはまったく同じ理由でテストを作成する場合にも非常に良いアドバイスです。特に、テストを書いてから数か月後にテストを読む場合、起こっていることが少なければ、何が起こっているのかを完全に理解するのがはるかに簡単です。したがって、テストに絶対に必要なコードのみを記述してください。簡単だからという理由だけでさらにコードを追加する誘惑に抵抗してください。ただし、テスト コードはもちろん完全である必要があります。つまり、テストには必要なだけ多くの行が含まれますが、できる限り少なくする必要があります。

100% のコード カバレッジを目指します

これは不人気な意見かもしれませんが、多くの人がこれを悪い習慣だと考えているようですが、100% のコード カバレッジを目指すのは完全に理にかなっていると思います。

チームは、より低い値で妥協することがあります。コードカバレッジは90%。しかし、それは私にとってあまり意味がありません。まず第一に、これらの数値はすべてやや恣意的なものであり、データを使用してバックアップするのは困難です。また、新しいコードを作成する場合、そのしきい値を通過するためにすべてのコードをテストする必要はありません。そして、誰かがなんとかカバレッジを上げることができたとしても、次の人はコード カバレッジを 90% 以上に保ちながらまったくテストを書かずに済んでしまう可能性があり、その結果、誤った自信が生まれてしまいます。

私がよく聞く言い訳の 1 つは、ゲッターやセッターのような単純な関数のテストを書くのは意味がないというものです。そして驚くべきことに、私もそれに完全に同意します。しかし、ここに落とし穴があります: どのテストも実際にこれらのゲッターとセッターを使用しない場合、おそらくそれらを使用する必要はありません。 したがって、100% のテスト カバレッジを達成することがいかに難しいかについて不平を言う代わりに、次のようにします。そもそも、必要のないコードは書かないほうがよいでしょう。これにより、コードの各行に伴うメンテナンスの負担も回避されます。

ただし、小さな落とし穴があります。コードが時々奇妙な動作をするため、テスト実行中に実行された場合でも、コード カバレッジ ツールが一部の行を未カバーとしてマークする可能性があります。このような状況にはあまり遭遇しませんでしたが、これを機能させる方法がない場合は、コードカバレッジから除外します。例えば。 PHPUnit では、codeCoverageIgnore アノテーションを使用してこれを行うことができます:

<?php class SomeClass
{
    /**
     * @codeCoverageIgnore
     */
    public function doSomethingNotDetectedAsCovered()
    {

    }
}

この方法では、この関数はコード カバレッジ分析に含まれません。これは、コード カバレッジ 100% に到達する可能性がまだあることを意味します。また、その値もチェックし続けます。別の方法としては、100% よりも低い値に落ち着くこともありますが、その場合、上記と同じ問題が発生します。他のコードもテストでカバーされていない可能性があり、それが見逃される可能性があります。

とはいえ、コード カバレッジが 100% であっても、コードにバグがないという保証はありません。しかし、アプリケーション コード内に発見されていない行がある場合、その行の潜在的なエラーを検出するためにテストに変更を加えているわけではありません。

良いアサーションを書く

テストが書かれる理由は、コードの特定の動作を主張したいからです。したがって、アサーションはテストの非常に重要な部分です。

もちろん、アサーションを作成するときに最も重要な考慮事項は、コードの動作を正しくテストすることです。しかし、非常に近いのは、コードが失敗したときにアサーションがどのように動作するかです。何らかの理由でアサーションが失敗した場合、問題は開発者にとって可能な限り明らかである必要があります。これが明らかな状況は、この Symfony プル リクエストで現在取り組んでいる状況です。 Symfony にはassertResponseStatusCodeSame メソッドが付属しており、機能テストで応答のステータス コードをチェックできます:

<?php declare(strict_types=1);

class LoginControllerTest extends WebTestCase
{
    public function testFormAttributes(): void
    {
        $client = static::createClient();

        $client->request('GET', '/login');
        $this->assertResponseStatusCodeSame(200);

        $this->assertSelectorCount(1, 'input[name="email"][required]');
    }
}

このテストの問題は、ステータス コードが 200 でない場合に生成される出力です。テストは通常​​開発環境で実行されるため、この URL にアクセスすると Symfony はエラー ページを返し、assertResponseStatusCodeSame メソッドはアサーションが失敗した場合の応答全体。この出力は HTML だけでなく CSS と JavaScript も返すため、非常に長くなります。また、スクロールバック バッファーが文字通り小さすぎてメッセージ全体を読むことができないためです。

これは私がこれまでに遭遇した最悪の例ですが、コード内で間違ったアサーションが使用されている場合は迷惑な場合もあります。上記のassertSelectorCount アサーションの出力を見てみましょう。指定されたセレクターが正確に 1 つの要素を生成しない場合、このアサーションは失敗し、次のメッセージが表示されます。

Failed asserting that the Crawler selector "input[name="email"][required]" was expected to be found 1 time(s) but was found 0 time(s).

発生している問題についてかなり良いアイデアが得られます。ただし、アサーションは別の方法で書くこともできます (自宅ではこれを行わないでください)。

<?php class SomeClass
{
    /**
     * @codeCoverageIgnore
     */
    public function doSomethingNotDetectedAsCovered()
    {

    }
}

これはまったく同じことを行うので、どのバリアントが使用されるかは問題ではない、と主張する人もいるかもしれません。電子メールに必須の入力フィールドが 1 つも存在しない場合、次のメッセージが表示されるため、これは真実からは程遠いはずです。

<?php declare(strict_types=1);

class LoginControllerTest extends WebTestCase
{
    public function testFormAttributes(): void
    {
        $client = static::createClient();

        $client->request('GET', '/login');
        $this->assertResponseStatusCodeSame(200);

        $this->assertSelectorCount(1, 'input[name="email"][required]');
    }
}

これはまったく役に立ちません。問題の解決に取り組む人は、まず問題が実際に何なのかを把握する必要があります。これが示しているのは、常に適切なアサーションを使用する必要があり、PHPUnit にはあらゆる種類のユースケースに適合する多くのアサーションが付属しているということです。場合によっては、カスタム アサーションを作成することが意味があることもあります。

近年人気が高まっている比較的新しい主張は、スナップショット テストです。特にフロントエンドプロジェクトに取り組み始める場合には、大いに役立つようです。以前はReactでよく使っていました。主な要点は、テストが次のようになることです:

Failed asserting that the Crawler selector "input[name="email"][required]" was expected to be found 1 time(s) but was found 0 time(s).

魔法は toMatchSnapshot メソッドで起こります。最初の実行では、ツリー変数の内容が別のファイルに書き込まれます。以降の実行では、ツリー値の新しい値と、以前に別のファイルに保存されていた値が比較されます。何かが変更された場合、テストは失敗し、スナップショットを再度更新するオプションとともに差分が表示されます。これは、テストを瞬時に修正できることを意味します。

これはとても良いことのように聞こえますが、いくつかの欠点もあります。まず、コンポーネントのレンダリングされたマークアップが変更されるたびにテストが失敗するため、スナップショットは非常に脆弱です。第二に、作成者が実際に何をテストしたかったのかが説明されていないため、テストの意図が隠されています。

しかし、私が本当に楽しかったのは、コンポーネントを変更するたびに、そのコンポーネントを使用している他のすべてのコンポーネントが思い出されることでした。これは、次回の実行ではそれらのスナップショットがすべて失敗したためです。このため、私はコンポーネントごとに少なくとも 1 つのスナップショット テストを行うことを好みました。

結論

要約すると、テストの品質を向上させるためにすぐに始められることがいくつかあると思います。

  • テスト内のコードは絶対に必要な最小限にとどめてください
  • 100% のコード カバレッジを目指し、テストできない場合はコード カバレッジ メカニズムからコードを適切に除外します
  • テストが失敗した場合に適切なエラー メッセージを取得するには、正しいアサーションを使用します

私の意見では、これらのいくつかのルールに従うだけで、すでに大きな違いが生まれ、コードベースでの作業を長期間楽しむのに役立ちます!

以上が高品質のテストを書くの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
セッションに関連するクロスサイトスクリプティング(XSS)攻撃からどのように保護できますか?セッションに関連するクロスサイトスクリプティング(XSS)攻撃からどのように保護できますか?Apr 23, 2025 am 12:16 AM

セッション関連のXSS攻撃からアプリケーションを保護するには、次の測定が必要です。1。セッションCookieを保護するためにHTTPonlyとセキュアフラグを設定します。 2。すべてのユーザー入力のエクスポートコード。 3.コンテンツセキュリティポリシー(CSP)を実装して、スクリプトソースを制限します。これらのポリシーを通じて、セッション関連のXSS攻撃を効果的に保護し、ユーザーデータを確保できます。

PHPセッションのパフォーマンスを最適化するにはどうすればよいですか?PHPセッションのパフォーマンスを最適化するにはどうすればよいですか?Apr 23, 2025 am 12:13 AM

PHPセッションのパフォーマンスを最適化する方法は次のとおりです。1。遅延セッション開始、2。データベースを使用してセッションを保存します。これらの戦略は、高い並行性環境でのアプリケーションの効率を大幅に改善できます。

session.gc_maxlifetime構成設定とは何ですか?session.gc_maxlifetime構成設定とは何ですか?Apr 23, 2025 am 12:10 AM

thesession.gc_maxlifettinginttinginphpdethinesthelifsessessiondata、setinseconds.1)it'sconfiguredinphp.iniorviaini_set()。 2)AbalanceSneededToAvoidPerformanceIssues andunexpectedLogouts.3)php'sgarbagecollectionisisprobabilistic、影響を受けたBygc_probabi

PHPでセッション名をどのように構成しますか?PHPでセッション名をどのように構成しますか?Apr 23, 2025 am 12:08 AM

PHPでは、session_name()関数を使用してセッション名を構成できます。特定の手順は次のとおりです。1。session_name()関数を使用して、session_name( "my_session")などのセッション名を設定します。 2。セッション名を設定した後、session_start()を呼び出してセッションを開始します。セッション名の構成は、複数のアプリケーション間のセッションデータの競合を回避し、セキュリティを強化することができますが、セッション名の一意性、セキュリティ、長さ、設定タイミングに注意してください。

セッションIDをどのくらいの頻度で再生する必要がありますか?セッションIDをどのくらいの頻度で再生する必要がありますか?Apr 23, 2025 am 12:03 AM

セッションIDは、機密操作の前、30分ごとにログイン時に定期的に再生する必要があります。 1.セッション固定攻撃を防ぐためにログインするときにセッションIDを再生します。 2。安全性を向上させるために、敏感な操作の前に再生します。 3.定期的な再生は長期的な利用リスクを減らしますが、ユーザーエクスペリエンスの重量を量る必要があります。

PHPでセッションCookieパラメーターをどのように設定しますか?PHPでセッションCookieパラメーターをどのように設定しますか?Apr 22, 2025 pm 05:33 PM

PHPのセッションCookieパラメーターの設定は、session_set_cookie_params()関数を通じて達成できます。 1)この関数を使用して、有効期限、パス、ドメイン名、セキュリティフラグなどのパラメーターを設定します。 2)session_start()を呼び出して、パラメーターを有効にします。 3)ユーザーログインステータスなど、ニーズに応じてパラメーターを動的に調整します。 4)セキュリティを改善するために、セキュアとhttponlyフラグを設定することに注意してください。

PHPでセッションを使用する主な目的は何ですか?PHPでセッションを使用する主な目的は何ですか?Apr 22, 2025 pm 05:25 PM

PHPでセッションを使用する主な目的は、異なるページ間でユーザーのステータスを維持することです。 1)セッションはsession_start()関数を介して開始され、一意のセッションIDを作成し、ユーザーCookieに保存します。 2)セッションデータはサーバーに保存され、ログインステータスやショッピングカートのコンテンツなど、さまざまなリクエスト間でデータを渡すことができます。

サブドメイン間でセッションをどのように共有できますか?サブドメイン間でセッションをどのように共有できますか?Apr 22, 2025 pm 05:21 PM

サブドメイン間でセッションを共有する方法は?一般的なドメイン名にセッションCookieを設定することにより実装されます。 1.セッションCookieのドメインをサーバー側の.example.comに設定します。 2。メモリ、データベース、分散キャッシュなど、適切なセッションストレージ方法を選択します。 3. Cookieを介してセッションIDを渡すと、サーバーはIDに基づいてセッションデータを取得および更新します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません