web-dev-qa-db-ja.com

テストはどれくらいうまく書けますか?

私は約2年間キャリアとしてコーディングしてきましたが、今では、重要なアプリケーション用の最初の「実際の」テストを書いています。私はインターネットのあちこちで見つけたベストプラクティスに従うように努めていますが、自分がやっていることと正しい/改善するために何ができるかで正しい方向に進んでいるかどうかについてフィードバックをお願いします処理する。


アプリケーションはヘッドレスAPIであり、数か月以内にパブリック(つまり、完全にパブリックではなく、APIと統合したいクライアント)の消費が見られます。

スタックとレイヤーは上から下のようになります。

  • RESTful API(JSON)
  • Oauth 2.0認証
  • (ほとんど)CRUDコントローラー(PHP、 Laravel 5
  • Doctrine ORM DALの場合
  • MySQL DB

私は、テストをできるだけ単純でありながら完全なものにしたかったのです。しかし、私はすべてのコントローラーとすべてのビジネスロジックに対して本当に基本的なテスト(おそらく単体テスト)を書くための永遠の日がないので、 laravelの組み込みのルートのモック とテストを利用することにしましたAPIのすべてのエンドポイント。

私の考え方は、リクエスト/レスポンスの標準的なデータ構造とフォーマット(JSON、オブジェクトに定義されたjsonスキーマなど)があるため、レスポンスがどのように見えるかを知っているリクエストをエミュレートして、2つを比較できるということです。

EX。 GET api/user/1は、user 1をjsonオブジェクトとして返す必要があります。これを、実際のオブジェクトが提供するシリアル化されたjsonと等しいかどうかを比較できます。


したがって、実際のテストは次のようになります(PHPunitを使用)。

  1. アプリケーションの起動時にLaravelは、アプリケーション環境を「testing」に設定し、デフォルトのDB接続をSQLiteファイルに変更します
  2. PHPunitブート時にDoctrineはモデルメタデータを取得し、DBに私のドメインのテーブルを作成します。ドメイン外のもののためのいくつかの追加スクリプト(oauthテーブル)もそれらを作成します
  3. Alice は、Doctrineのオブジェクトジェネレーターで、 Faker からのランダムデータを使用して適切に多様なドメインエンティティのセットを作成し、SQLite DBをハイドレートします。作成されたすべてのエンティティが返され、後で使用できるようにこれらをグローバル変数に格納します。
  4. 私はハイドレートされた、手つかずのDBのコピーを作成します 書き込み操作を伴うテストで使用するため、各テスト後にdbをリセットできます。
  5. さまざまな役割を持つユーザーに対してOAuthクライアントが生成されるため、テストごとにさまざまなユーザーにわたってoauthスコープと権限をテストできます
  6. 私は Laravelのルートモック を使用して各APIエンドポイントを呼び出し、
  7. 読み取り専用テスト(GET)の場合、以前に保存されたオブジェクトのjsonシリアル化形式(ステップ3)を使用して、応答の同等性をテストします。
  8. 書き込みテストの場合は、オブジェクトのjsonスキーマからリクエストを作成し、それを同等にする必要がある実際のオブジェクトを作成し、リクエストを作成して、応答をオブジェクトのシリアル化された形式と等しいかどうかを確認します(手順7など)。各書き込みテストの後、DBは次のテストのためにステップ4の元の水和DBで上書きされます。

それがその要点です。このアプローチを使用すると、素晴らしいパフォーマンスが得られます。87個のアサーションで26個のテストを実行すると、最大12秒かかります。

私の質問/懸念

  • 私は何もからかわない。私はこれが原因で何か間違っているように感じますが、同時にアプリケーション全体に「実際の」環境を提供しているので、モックする必要があるようには見えません。よろしいですか?
  • 各テストでやりすぎているのですか?テストが脆弱になり、効果が低下するため、テストに依存関係が多すぎることを警告する記事を読んだことがありますが、テストの「依存関係」はすべて実際のコードです。私は知りたいと思っている壊れています。

他に何を教えてくれますか?提案?どうすればこれを改善できますか?ありがとう!

6

コンセプトは十分いいです!

ここで、何を構築したかを決定する必要があります-統合テストまたは受け入れテスト、およびそれらを単一の目的でサポート/強化します。ここに違いがあります:

開発者は統合テストを使用して、アプリケーションが基本的に機能していて、開発マシンから頻繁に実行されることを確認します。 TDDテストとバグ再現テストはこのように行われます。統合テストは、開発者を退屈させないように十分に高速でなければなりません。

受け入れテストは主にQAによって使用され、アプリケーションのビルドが本番環境に準備されていることを確認します。エラー条件を含むすべてのアプリケーション機能をカバーし、多数のテストのためにしばらく実行される傾向があります

また、データベースのセットアップ/復元を含め、シングルクリックで実行できるように、できるだけ自動化する必要があります。

次に、それらを継続的インテグレーションツールに追加して、コミットのたびに実行して楽しんでもらうことができます。

あなたの懸念について。

実際に懸念-あなたは単一のテストであまりにも多くをテストしていること。単独でテストできるほど複雑なものはありますか? DALの高速テストは、dbスキーマが変更されたときに本当に役立つので、DALは良い候補です。スコープ付きテストを作成する際の一般的なルールは、このコードが壊れる可能性がある、または壊れると思われる場合にそれらを書くことです。通常、これは単一の機能または大きな独立したモジュールに分類されます。テストは大量のモックになる傾向がありますa)壊れやすいb)書くのに費用がかかるc)複雑で価値のないグルーコードをテストする

5
Sergey Alaev

テストのパフォーマンスが好きで、本番コードでの間違いを見つけるのに役立つことがわかった場合、それは文字通り必要なすべてです(責任または規制上の懸念がある可能性のある特殊なドメイン以外で)。彼らがこれらのことをするなら、素晴らしい。そうでない場合は、それらを捨てて、新しい方法を試してください。

よくわからない場合は、テストを「A/Bテスト」することをお勧めします(ヨーヨー、テストが好きだと聞きました...)。自分のやり方で1つを記述し、単体テストが想定している方法で1+(おそらく複数)を記述します。多数の共同作業者がいることが問題である場合、その問題は、量産コード内のエラーの場所を特定することが難しいことです。どちらかの失敗をデバッグする前に両方のテストを実行し、エラーメッセージに基づいて推測を行ってから、どちらが実際の問題により近いところにあるかを推測するのに役立ったかどうかを確認してください。

しかし、常に:tilityテストは、いくつかの標準への準拠ではなく、テストによって得られるものを測定します

0
Sapphon