より良い単位テストを書くための5つのチップス



どのような単位テストですか?
ユニットテストは、プログラムの個々の部品またはコンポーネントのテストです.単体テストの目的は、単一のコンポーネントの機能をテストし、その動作を他のコンポーネントとは独立に検証することです.単位テストの単位は、テストされることができる機能性の最も小さな部分を含みます.ユニットテストの主な目的は、プログラムの最小部分を分離し、各部分の機能をテストすることです.単体テストの基本構造は、指定されたコードブロックの出力が与えられた条件に合致するかどうかを調べるように設計されています.たとえば、関数をテストするときに、以下のように関数が予期した出力を返す場合、入力引数とテストのセットを指定します.
ファンク.パイ
# ==== Function ==== #
class Calculations:

  # Function to Test
    def calculate_total(value1, value2):
        return int(value1 + value2)
テスト.パイ
# ==== Unit Test ==== #
import unittest
from func import Calculations

# Test Class
class TestingFunctions(unittest.TestCase):

    # Test Case
    def test_calculation(self):
        input_one = 4
        input_two = 6
        total = Calculations.calculate_total(input_one, input_two)
        # Identify if output is equal to zero
        self.assertEqual(total, 10)

if __name__ == '__main__': 
    unittest.main()


複雑なセットアップを避ける
単体テスト中に最も簡単なテスト可能なユニットの機能をテストしているので、できるだけ簡単にテストを維持する方が良いです.ユニットテスト中に大きな困難な開発者の1つが直面しているテストケースは、それらを不必要に複雑にするために理解し、変更するのは難しいとなっています.
AAAルールは、できるだけ多くのユニットテストを維持するための良いガイドラインを提供します.ユニットテストでは、AAAは手配、行為、主張する.最初のステップは、入力された変数、プロパティ、および条件を使用してテストケースを配置することです.次の手順は、メソッドまたは関数を呼び出すことによってあなたの手配を行うことです.アサーションである最終段階では、テストフレームワークを使用して期待される出力を検証することをアサートできます.このメソッドはテストケースのコードベースを読みやすく理解しやすくします.
import unittest

# AAA Methodology
class TestingStringFunctions(unittest.TestCase):

    def test_string_manipulation(self):
        # Arrange
        text = "Hello World"

        # Act
        new_text = ''.join(reversed(text))

        # Assert
        self.assertEqual(new_text, 'dlroW olleH')
単体テストを実行するときに考慮するもう一つの重要なことはテスト依存です.テストケースが別のテストケースに依存する場合、単一のテストケースを変更すると、他のテストケースに影響を与える可能性があります.

徹底性はゴールではない
それは常にあなたのプログラムの包括的な単体テストを実行する良いアイデアです.ただし、各シナリオごとにテストケースを書くべきではない.すべてのエッジケースを考慮すると、貴重な開発時間の無駄です.
テストはあなたのコードブロックの共通の流れをカバーするためにまっすぐ進むべきです.単純なテストが通過されると、エッジケースを含めると、複数の境界をカバーするテストのカバレッジを増やすことができます.バグが開発サイクルで発見されると、そのバグを含むテストカバレッジを展開できます.これは、バグに取り組むために別のテストケースを作成することなく、最新のテストケースを維持します.

バグの修正時に最初にテストを書く
バグを発見するときの開発者の最初の意図は、試してみて、どうにかそれを修正することです.彼女はその時バグを修正することができるでしょうが、バグの彼女の理解は制限されるかもしれません、そして、将来のパイプラインの下で新しい問題を引き起こすかもしれません.
したがって、バグを引き起こすコンポーネントを含む発見されたバグのテストを作成するのは、常に良い習慣です.このように、バグが指定されたコンポーネントに関連しているか、外部要因によって引き起こされるかどうかを確認できます.簡単で簡単なテストをすることは、すぐに問題を公開することによって、より簡単なバグ修正につながります.
テストを書くときは、バグを修正する前に実行し、テストが失敗したことを確認してください.さもなければ、実際にバグをカプセル化しないテストを書くかもしれません.
バグが修正されると、そのユニットのテストを破棄する必要はありません.また、これらのテストは、プログラムの全体的な機能をテストするために、回帰テストで使用することができます.同様のバグが発見されたときに、将来の出来事でそのテストの失敗と通過条件の両方を知っているので、それは余分の利益です.また、どこでフィックスを適用するかを知ることが容易になります.

注意を払う
モッキングは、人工のオブジェクト(モックオブジェクト)をそれに似て作成することによって制御された方法で実際のオブジェクトの動作をシミュレートする方法です.MOCKオブジェクトは、開発者が関数を呼び出すことなく複雑な関数の動作を模擬することができます.これは、これらのサービスを必要とする外部サービスを扱う場合に便利です.
モックは、テストケースの速度と効率を高めるのに便利です.mocksがない場合、外部ライブラリや関数をテストする場合は、その関数が完了してテストを継続するのを待つ必要があります.これにより、テスト実行時間が遅くなり、テストケース内で不要なエラーや動作を導入することもできます.たとえば、ファイルシステムとネットワーク機能を扱う場合、テストのコア機能に焦点を当てながら、効果的にテストを高速化する、それらの動作をシミュレートするために模擬オブジェクトを使用することができます.
import unittest
from unittest import mock
from func import delete_file

class TestFunctions(unittest.TestCase):

    # Mock the os module
    @mock.patch('func.os')
    def test_file_delete(self, mockobj):
        file_name = "test.txt"
        delete_file(str(file_name))
        # Verify the parameters were passed correctly to the function
        mockobj.remove.assert_called_with(str(file_name))
Mocksを使用するときに最も重要なことは、テストケースの機能を模擬することではありません.データベースクエリ、API呼び出し、または全体的なテストに直接影響を与えるすべての機能をテストしている場合は、MCKを使用しないでください.

テスト独立
テストは、互いに直交する必要があります一度に単一の機能をテストするために使用されます.テストクラスは独立してテストされるべきであり、テストフレームワーク以外の何にも依存してはいけません.
ユニットテストを実行するために順序が必要な場合は、テストフレームワークの作り付けのセットアップとティアダウンメソッドを使用してテストケースを分離できます.良いテストケースは実装変更によって影響を受けるべきではありません.APIの変更に対処するとき、正しく実装された個々のユニットテストを備えたソリッドコードベースを持つプログラムは、エラーを特定し、プログラムを再起動し実行するために重要です.
さらに、独立テストを作成すると、簡単に他のテストに副作用を引き起こすことなく、テストスペクトルを増加させながら、各テストケースを簡単に変更することができます.テストオートメーション環境では、独立したテストは、CI/CDパイプラインと統合するための好ましい方法です.

次のステップ
ユニットテストは発見し、ユニットのバグを解決するために、プログラムのすべての単一の部分がうまく動作するように最適な方法です.ただし、プログラムのさまざまな部分をテストしたい場合は、実際の環境では、統合テストまたはエンドツーエンドを実行する必要があります.テスト階層hereの詳細については、こちらをご覧ください.
統合テストは、複数のユニットまたはモジュール間を横断するコードパスで、単体テスト、実行、アサートからレベルを抽象化しました.今、我々はアプリケーションとは、お互いと相互作用の異なる部分を確保するために開始している.
さらに遠いエンドツーエンド(E 2 E)テストです.これらのテストは、上から下にアプリケーションの全体の表面積をカバーすることを目的としています.これらは一般的にエンドユーザから期待されるコードパスに従うべきです.
ユニットテストを超えて次のステップを取る簡単な方法をお探しですか?walrus.aiをチェックしてください
  • 試験は平易な英語で書かれることができます-難しいセットアップは、
  • を必要としませんでした
  • テストあなたの最も挑戦的なユーザー体験-電子メール、マルチユーザフロー、サードパーティの統合
  • ゼロメンテナンス-セイウチ.AIはあなたのためのテストのメンテナンスを処理するので、フレーク
  • を経験することはありません