Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Python
Code

Python でプロのユニット テストを書く

by
Difficulty:IntermediateLength:LongLanguages:

Japanese (日本語) translation by Hakima Madani (you can also view the original English article)

テストは、固体ソフトウェア開発の基盤です。 テストの多くの種類がありますが、最も重要なタイプは単体テストします。 単体テストでは、プリミティブとして十分にテストされた作品を使用でき、プログラムを作成することを作成するとき、それらに頼ることの自信を与えます。 彼らは言語の組み込みコマンドと標準ライブラリ以外に信頼できるコードの在庫を増加させます。 さらに、Python は、ユニット テストを書くの素晴らしいサポートを提供します。

サンプルの実行

原則、ヒューリスティックとガイドラインにする前に、代表的な単体アクションのテストを見てみましょう。 SelfDrivingCar クラスは、自動運転車の運転のロジックの実装の一部です。 車の速度を制御する主を取り扱っています。 それはそれ、制限速度の前にオブジェクトを認識し、目的地に到着するかどうか。

ここでは、あなたの食欲を刺激する stop() メソッド用の単体テストです。 私は後で詳細に取得します。

単体テスト ガイドライン

コミット

適切な単体テストを作成するは難しい作業です。 単体テストを作成すると、時間がかかります。 ときに、コードに変更を加えると、通常と同様、テストを変更する必要があります。 時々、テスト コードにバグがあります。 つまり、あなたは本当にコミットする必要があります。 メリットは非常に大きい、小さなプロジェクトの場合も、彼らは無料ではありません。

懲戒処分を受ける

あなたが規律する必要があります。 一貫しています。 テストは常に成功していることを確認します。 わかっているので"know"コードは、[ok] を破られるテストさせてください。

自動化

懲戒処分をするために、単体テストを自動化する必要があります。 テストは事前にコミットまたは配置前のような重要なポイントで自動的に実行する必要があります。 理想的には、ソース コントロール管理システムは、そのすべてのテストに合格しなかったコードを拒否します。

テストされていないコードが定義によって壊れています。

あなたはそれをテストしていない場合、それが動作を言うことはできません。 これは、それが壊れているを検討する必要がありますを意味します。 場合クリティカルなコードは、生産に展開しないでください。

バック グラウンド

単位とは何ですか。

関連する関数またはクラスのセットを含むファイル/モジュール、ユニット単体テストの目的です。 複数のクラスを持つファイルがある場合は、各クラスの単体テストを書く必要があります。

TDD にしたりしないで TDD

テスト駆動開発は、コードを記述する前にテストを記述する方法です。 このアプローチにいくつかの利点がありますが、私は後で適切なテストを書くための規律があれば、それを避けることをお勧めします。

理由は、私はコードとデザインです。 私はコードを書く見て、それを書き換え、再びそれを見て、それを非常にすぐに再度書き換え。 テストを書く最初私を制限し、私を低下します。

初期の設計が終わったら、一度、システムの残りの部分と統合する前に、すぐにテストを書いていきます。 つまり、単体テストに自分自身を紹介する素晴らしい方法だ、それはすべてのコードがテスト保証されます。

単体テスト モジュール

単体テスト モジュールは、Python の標準ライブラリが付属しています。 それはあなたがあなたのクラスを派生させることができるTestCaseと呼ばれるクラスを提供します。 その後、各テストの前にテスト ・ フィクスチャを準備する setUp() メソッドおよび/または (個々 のテストの間にリセットしない) すべてのテストのテスト ・ フィクスチャを準備する classSetUp() クラスのメソッドをオーバーライドできます。 TearDown() および classTearDown() メソッドもオーバーライドできますが対応します。

ここでは、SelfDrivingCarTest クラスから関連する部分です。 テストメソッドごとに setUp() メソッドのみを使用してください。 新鮮な SelfDrivingCar のインスタンスを作成し、すべてのテストに使用できるように、self.car に格納します。

次のステップはテスト対象コードをテストするのには、特定のテスト メソッドを記述する-、SelfDrivingCar クラスこの場合-それが行うことになっていることです。 テスト メソッドの構造はかなり標準的です。

  • (省略可能) 環境を準備します。
  • 期待される結果を準備します。
  • テスト対象コードを呼び出します。
  • 実際の結果が期待どおりの結果と一致することを主張します。

メソッドの出力する結果を持っていないことに注意してください。 それはクラス、データベースに新しい行を追加する、ファイルの書き込みやメールのような副作用の状態の変更をすることができます。

たとえば、SelfDrivingCarクラスのstop() メソッドは何も返しませんが、速度を0に設定することで内部状態を変更します。ここでは、TestCase 基本クラスによって提供されるassertEqual() メソッドを使用して stop() の呼び出しを確認します。は期待通りに動作しました。

実際に 2 つのテストここであります。 最初のテストは、速度が 0 になるしする場合は車の速度が 5 と stop() が呼び出されたことを確認することです。 その後、別のテストは、何もうまくいかない場合は車が既に停止されている場合、再度 stop() を呼び出してことです。

その後、追加機能のためのいくつかのより多くのテストを紹介します。

Doctest モジュール

Doctest モジュールは非常に興味深いです。 それはあなたのドキュメンテーション文字列のインタラクティブなコード サンプルを使用して、発生した例外も含めて、結果を確認することができます。

私は使用しない、または大規模システムの doctest をお勧めします。 適切な単体テストは、作業の多くをかかります。 テスト コードは、通常、テスト対象コードよりもはるかに大きいです。 ドキュメンテーションは、右側の中の包括的なテストを書くためだけではないです。 彼らはしかし、クールされます。 docテストを伴う factorial関数は次のようになります。

あなたが見ることができる、ドキュメンテーション文字列は関数コードよりもはるかに大きいです。 それは、読みやすさを促進しません。

テストを実行します。

わかりました。 あなたは、ユニット テストを書いています。 大規模なシステムの可能性がある複数のディレクトリ数十/数百/千モジュールおよびクラスのがあります。 すべてのこれらのテストを実行するにはどうするか。

単体テスト モジュールでは、テストをグループ化し、それらをプログラムによって実行する様々 な施設を提供します。 テストのロードと実行をチェックしてください。 しかし、最も簡単な方法はテスト発見。 このオプションは、Python 2.7 で追加されました。 2.7より前では、テストを発見して実行するために nose を使うことができました。 鼻には、テスト _ ケースのクラスを作成することがなくテスト関数を実行するようないくつかの他の利点。 しかし、この記事の目的のための単体テストに固執してみましょう。

発見して単体テスト ベースのテストを実行するには、コマンドラインで入力します。

python -m unittest discover

単体テストがすべてのファイルとサブディレクトリをスキャン、検出すると、テストを実行し、素敵なレポートとしてランタイムを提供します。 どのようなテストが実行されているを表示する場合は、-v フラグを追加できます。

python -m unittest discover -v

操作を制御するフラグがいくつかあります。

テスト カバレッジ

テスト カバレッジは、しばしば無視されるフィールドです。 カバレッジは、テストで実際にテスト、コードの量を意味します。 たとえば、if-else文を含む関数があり、if分岐のみをテストする場合、else分岐が機能するかどうかはわかりません。 次のコード例では、関数 add() は、その引数の型をチェックします。 両方が整数の場合、それはちょうどそれらを加えます。

両方が文字列である場合は、それらを整数に変換しようとするし、それらを追加します。 それ以外の場合、例外が発生します。 Test_add() 関数は、両方の整数引数を持つ add() 関数をテストし引数には、浮動小数点数し、それぞれのケースで正しい動作を確認します。 しかし、テスト カバレッジが完了。 文字列引数の場合はテストされていません。 その結果、テストが正常に渡されますが、両方の文字列の引数のある支店のミスが発見されなかった (ある 'フックメソッド' を参照ですか?)。

ここでは、出力です。

実践的な単体テスト

産業強度単体テストの記述、単純な簡単ではありません。 いくつかの考慮すべきとされるデメリットがあります。

テスト容易化設計

コードがスパゲッティ コードまたは泥、異なる抽象化レベルが一緒に混合され、コードのすべての部分によって決まるあらゆるコードの大きなボール正式と呼ばれるものの場合は、つらい時をそれをテストがあります。 また、何かを変更するたびに、テストの束を更新するもよ。

良いニュースは、汎用の適切なソフトウェアの設計はまさにテスト容易化のため何が必要です。 特に、喜び良い単体テストの記述、各コンポーネントは、明確な責任があるし、明確に定義されたインターフェイスを介して他のコンポーネントと対話する、適切にファクタリングされたモジュラー コードを行います。

たとえば、SelfDrivingCar クラスは車の高度な操作に責任がある: 移動、停止、移動します。 まだ実装されていない calculate_distance_to_object_in_front() メソッドがあります。 この機能は、完全に独立したサブシステムによっておそらく実装する必要があります。 複数のカメラからの映像を分析する全マシン ビジョン スタックその他自動運転の車と対話するさまざまなセンサーからデータを読み取ることがあります。

実際にどのようにこの作品を見てみましょう。 SelfDrivingCarcalculate_distance_to_object_in_front() と呼ばれるメソッドを持つ object_detector と呼ばれる引数を受け入れ、このオブジェクトにこの機能を委任します。 さて、ユニットを必要ないため、このテスト、object_detector、(およびテストする必要があります) のでそれがあります。 まだしたいユニット、object_detector を正しく使用していることをテストします。

コスト/利点

テストに入れ努力の量は、失敗、どのように安定したコードは、それがラインの下の問題が検出された場合を修正するがいかに簡単・ コストに相関する必要があります。

たとえば、自動運転車クラスは超重要です。 Stop() メソッドは正常に動作しない、自動運転車、財産を破壊するされる、全自動運転の車市場を脱線させる人を殺す可能性があります。 自動運転車を開発する場合 stop() メソッドの単体テストは私より少し厳しくなると思います。

その一方で、誰かがそれをクリックしたときに少しあなたのメインページの下の 3 つのレベルを埋葬しているページで、web アプリケーションで 1 つのボタンがちらつく場合はそれを修正することがありますが、おそらくこのケース用の専用の単体テストを追加しません。 経済学はそれを揃えしません。

テストの考え方

テストの考え方は重要です。 私を使用して 1 つの原則は、コードのすべての部分が、少なくとも 2 人のユーザーを持っていること: それとそれをテスト、テストを使用する他のコード。 この単純なルールは、デザインと依存関係とたくさん助けます。 場合は、コードのテストを記述する必要を覚えて、テスト中に再構築することは困難の依存関係の多くは追加しません。

たとえば、コードは、何かを計算する必要があります。 そのために、それは、データベースから一部のデータをロードする構成ファイルを読み取り、最新情報のいくつかの REST API を動的に参照してください必要があります。 様々 な理由で必要がありますこれは、すべてが、単一の関数を入れているすべてのことはかなり困難になる単体テスト。 モックでまだ可能ですが、コードを適切に構築するより良い。

純粋関数

テストするための最も簡単なコードは、純粋な関数です。 純粋関数は、そのパラメーターの値のみにアクセスしてない副作用を持っている、同じ引数で呼び出されるたびに同じ結果を返す関数です。 彼らはプログラムの状態を変更しない、ファイル システム、またはネットワークにアクセスしないでください。 その利点は、ここでカウントする余りにも多く。

なぜ彼らは簡単にテストできますか。 テストする特別な環境を設定する必要はありません。 あなたは引数を渡すし、結果をテストします。 また、テスト対象のコードに変更がない限り、テストを変更する持っていないことを知っておく。

XML 構成ファイルを読み取る関数を比較します。 あなたのテストは、XML ファイルを作成し、テスト対象のコードをそのファイル名を渡す必要があります。 大したことありません。 しかし、誰かが決めた、XML が憎むべきすべての構成ファイルは、JSON である必要がありますと仮定します。 彼らは彼らのビジネスについて行くし、すべての構成ファイルを JSON に変換します。 彼らはテストを含むすべてのテストを実行し、それらが全て合格!

なぜでしょうか。 コードを変更していません。 まだ XML 構成ファイルを想定し、テストはまだそれの XML ファイルを作成します。 しかし、生産のコードの解析に失敗します JSON ファイルになります。

エラー処理のテスト

エラー処理は、テストする重要な別のものです。 また、デザインの一部です。 入力の正しさを担当しているか。 すべての関数とメソッドはそれについて明確にする必要があります。 場合関数の責任は、その入力を検証すべきしかし、呼び出し元の責任です関数できますだけビジネスについて行く、その入力が正しいと仮定します。 システムの全体的な正確性は、呼び出し元が関数に正しい入力のみが通過することを確認するためのテストを持っていることによって確保されること。

通常、あなたのコードを呼び出すために起こっているが必ずしもわからないのでコードにパブリック インターフェイスで入力を検証する場合します。 自動運転車の drive() メソッドを見てみましょう。 このメソッドは、'宛先' パラメーターを期待しています。 後のナビゲーション、'宛先' パラメーターが使用されますが、ドライブの方法では、それが正しいことを確認しません。

先が緯度と経度のタプルをすることになっていると仮定します。 それが有効なことを確認するためのテストのすべての種類がある (例えば、海の真ん中に先)。 我々 の目的だけ確認しましょう範囲 90.0 0.0 に緯度と経度の 180.0-180.0 山車組であります。

ここでは、更新された SelfDrivingCar クラス。 私は実装自明いくつか未実装のメソッドの直接または間接的 drive() メソッドはいくつかのこれらのメソッドを呼び出すため。

テストでのエラー処理をテストするには、無効な引数を渡す、彼らは拒否されます正しくことを確認してください。 これを行うには、self.assertRaises() を使用して unittest.TestCaseのメソッド。 このメソッドは、テスト対象のコードは確かに例外を発生させた場合を成功します。

アクションでそれを見てみましょう。 Test_drive() メソッドは、緯度と経度有効範囲外を通過し、drive() メソッド例外が発生するを見込みます。

Drive() メソッド引数の有効性をチェックしないし、例外が発生しないため、テストが失敗します。 あなたは、何が失敗した場所と理由の完全な情報と素敵なレポートを得る。

Let's はそれを修正に実際にその引数の範囲をチェックする drive() メソッドを更新します。

今、すべてのテストに合格します。

プライベート メソッドのテスト

すべての関数とメソッドをテストする必要がありますか。 特に、プライベート メソッドのコードによってのみ呼び出されますをテストする必要がありますか。 通常満足のいかない答えは:「依存」。

私はここで役に立つこと、それに依存を教えてみます。 まさに人は、プライベート メソッドを呼び出しを知っている-それは、独自のコード。 プライベート メソッドを呼び出すパブリック メソッドのテストが包括的な場合、既にメソッドをテストするあなた専用余すところなく。 しかし、プライベート メソッドが非常に複雑な場合は、それを個別にテストします。 あなたの判断を使用します。

単体テストを整理する方法

大型システムのそれは常に不明、テストを整理する方法です。 パッケージのすべてのテストの 1 つの大きなファイルまたは各クラスの 1 つのテスト ファイルがある必要があります? テストは、テスト対象コードと同じファイルまたは同じディレクトリにする必要があります?

ここでは、私を使用して、システムを。 テストは、テスト対象のコードから完全に分離する必要があります (したがって私は doctest を使用しないでください)。 理想的には、コードは、パッケージにする必要があります。 各パッケージのテストはあなたのパッケージの兄弟ディレクトリにする必要があります。 テスト ディレクトリに test _<module name>.というパッケージのモジュールごとに 1 つのファイルがあるはず

たとえば、あなたのパッケージに 3 つのモジュールがある場合: もらうべきである module_1.pymodule_2.pymodule_3.py、3 つのテスト ファイル: test_module_1.pytest_module_2.py、テスト ディレクトリの下の test_module_3.py

この条約には、いくつかの利点があります。 それに明確なだけでいくつかのモジュールを完全にテストするのには忘れていないディレクトリを参照します。 合理的なサイズのチャンクにテストを整理することができます。 仮定すると、あなたのモジュールは、各モジュールのテスト コードは、テスト対象のモジュールよりも少し大きいかもしれないが、独自のファイル、まだ 1 つのファイルで快適にフィットする何かになりますし、適度なサイズ。

結論

単体テストは、コードの堅牢の基盤です。 このチュートリアルでは、いくつかの原則とガイドライン ユニット テストといくつかのベスト プラクティスの後ろの推論を説明してきました。 大きいシステムを構築しているより重要なユニット テストになります。 しかし、単体テストが十分ではないです。 他の種類のテストは大規模システムにも必要な: 統合テスト、パフォーマンス テスト、ロード テスト、侵入テスト、受け入れテストなど。

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.