unittestにおける各種外部依存の制御と孤立

7949 ワード

一、外部依存


テストの過程でよくある外部依存を伴い、以下のように列挙される.
  • は、データベースからデータをロード、保存する必要がある場合があります
  • .
  • は、特定の時間
  • に依存する可能性がある.
  • は、ウェブ上からデータ
  • を取得することができる.

    二、隔離方式


    2.1データソース


    ほとんどの実際のテストでは、さまざまな形式のデータが必要です.通常、データはデータベースから読み込まれます.次に、データ・ソース依存関係を制御するテクノロジーを示します.
  • データベース
  • の代わりにローカルファイルを使用
  • メモリ内のデータベース
  • を使用
  • テストデータベース
  • を使用

    2.2リソースの仮想化


    システム外のリソースの動作を制御するために、仮想化、すなわち別のバージョンのリソースを構築することができ、新しいバージョンは、内部実装を必要とせずに既存のリソースのAPIをシミュレートすることができる.次のような技術があります.
  • スタブ
  • テスト中の関数呼び出しの基準に対応
  • 模造(mock)
  • 実際のオブジェクトのAPIを模倣して置き換える
  • 偽造(fake)
  • 非常に軽量な実装が可能

    三、模倣技術


    本文はまず模倣(mock)技術を説明して、その他の方式は後続して補充します!

    モックって何?


    unittest.mockはPythonでユニットテストを行うためのライブラリで、Mockが翻訳するとシミュレーションの意味で、その名の通りこのライブラリの主な機能はいくつかのものをシミュレートすることです.その主な機能は、指定したPythonオブジェクトの代わりにmockオブジェクトを使用して、シミュレーションオブジェクトの動作を達成することです.

    mockは何ができるの?

  • 前後エンドコール、フロントエンドページ開発の場合は、機能
  • を開発する必要があります.
    次の注文、支払いページのインタフェース、支払い結果に基づいて、支払い成功、支払い成功ページ、支払い失敗ページ、支払い失敗ページを表示します.この機能を完了するには、バックエンドのインタフェースを呼び出し、返された結果に基づいて異なるページを表示する必要があります.この时、バックエンドインタフェースはまだ开発されていません.フロントエンドとして开発するには、他の人が开発するのを待つことはできません.あなたが开発するには、残业の命しかありません.開発完了タスクを同期するために、インタフェースドキュメントの規定に従って、インタフェースのアドレスと入力を転送し、自分のmockインタフェースの違いをインタフェースに戻して、フロントエンドの開発タスクを完了することができます.
  • ユニットテスト
  • ユニットテストの目的は、ある小さなユニットの機能をテストすることですが、現実に開発された関数や方法には依存関係があります.例えば、b関数のパラメータは、a関数の戻り結果を呼び出す必要がありますが、私は前にa関数をテストしました.この場合、a関数をもう一度測定する必要はありません.この場合、mockモジュールで呼び出しの部分をシミュレートし、戻り結果を与えることができます.
  • サードパーティインタフェース依存
  • インタフェースの自動化を行う時、時には第三者のインタフェースを呼び出す必要がありますが、他の人の会社のインタフェースサービスはあなたの制御を受けません.他の人が提供するテスト環境が今日サービスを開いている可能性があります.他の人はオフになって、自動化インタフェースのテストに多くの面倒をもたらします.この時、自分でmock-serverを書いてインタフェースの戻りデータをシミュレートすることができます.

    mock環境準備

  • python2.xのバージョン、mockは独立したモジュールで、pipで
  • をインストールする必要があります.
        pip install -U mock
  • Python 3.3以降のバージョンmockはunittestモジュールに統合されており、unittestユニットテストの一部であり、直接インポートすればよい
  •      from unittest import mock

    使用方法1


     
    datetimehelper.pyコードは次のとおりです.
    # Code Listing #3
    
    """ Module datetime helper - Contains the class DateTimeHelper providing
    some helpful methods for working with date and datetime objects """
    
    import datetime
    
    class DateTimeHelper(object):
        """ A class which provides some convenient date/time
        conversion and utility methods """
    
        def today(self):
            """ Return today's datetime """
            return datetime.datetime.now()
    
        def date(self):
            """ Return today's date in the form of DD/MM/YYYY """
            return self.today().strftime("%d/%m/%Y")
    
        def weekday(self):
            """ Return the full week day for today """
            return self.today().strftime("%A")
    
        def us_to_indian(self, date):
            """ Convert a U.S style date i.e mm/dd/yy to Indian style i.e dd/mm/yyyy """
    
            # Split it
            mm, dd, yy = date.split('/')
            yy = int(yy)
            # Check if year is >16, else add 2000 to it
            if yy <= 16:
                yy += 2000
            # Create a date object from it
            date_obj = datetime.date(year=yy, month=int(mm), day=int(dd))
            # Return it in correct format
            return date_obj.strftime("%d/%m/%Y")
    

     
     
    テストコードは次のとおりです.
    # Code Listing #5
    
    """ Module test_datetimehelper -  Unit test module for testing datetimehelper module """
    
    # Note - This is the second version of test_datetimehelper module so named as test_datetimehelper2.py
    
    import unittest
    import datetime
    import datetimehelper
    
    from unittest.mock import patch
    
    
    class DateTimeHelperTestCase(unittest.TestCase):
        """ Unit-test testcase class for DateTimeHelper class """
        
        def setUp(self):
            self.obj = datetimehelper.DateTimeHelper()
    
        def test_date(self):
            """ Test date() method """
    
            # Put a specific date to test
            my_date = datetime.datetime(year=2016, month=8, day=16)
    
            # Patch the 'today' method with a specific return value
            with patch.object(self.obj, 'today', return_value=my_date):
                response = self.obj.date()
                self.assertEqual(response, '16/08/2016')
    
        def test_weekday(self):
            """ Test weekday() method """
    
            # Put a specific date to test
            my_date = datetime.datetime(year=2016, month=8, day=21)
    
            # Patch the 'today' method with a specific return value
            with patch.object(self.obj, 'today', return_value=my_date):
                response = self.obj.weekday()
                self.assertEqual(response, 'Sunday')            
                              
        def test_us_india_conversion(self):
            """ Test us=>india date format conversion """
    
            # Test a few dates
            d1 = '08/12/16'
            d2 = '07/11/2014'
            d3 = '04/29/00'
            self.assertEqual(self.obj.us_to_indian(d1), '12/08/2016')
            self.assertEqual(self.obj.us_to_indian(d2), '11/07/2014')
            self.assertEqual(self.obj.us_to_indian(d3), '29/04/2000')
    
    
    if __name__ == "__main__":
        unittest.main()
    

      

    使用方法2

    #  temple.py
    
    # coding:utf-8
    #  : -  QQ :588402570
    
    def zhifu():
        ''' , 
         :{"result": "success", "reason":"null"}
         :{"result": "fail", "reason":" "}
        reason 
        '''
        pass
    
    def zhifu_statues():
        ''' success or fail, '''
        result = zhifu()
        print(result)
        try:
            if result["result"] == "success":
                return " "
            elif result["result"] == "fail":
                print(" :%s" % result["reason"])
                return " "
            else:
                return " "
        except:
            return "Error,  !"
    

     
    ユニットテスト用例設計
    # coding:utf-8
    from unittest import mock
    import unittest
    import temple
    #  : -  QQ :588402570
    
    class Test_zhifu_statues(unittest.TestCase):
        ''' '''
        def test_01(self):
            ''' '''
            # mock 
            temple.zhifu = mock.Mock(return_value={"result": "success", "reason":"null"})
            #  
            statues = temple.zhifu_statues()
            print(statues)
            self.assertEqual(statues, " ")
    
        def test_02(self):
            ''' '''
            # mock 
            temple.zhifu = mock.Mock(return_value={"result": "fail", "reason": " "})
            #  
            statues = temple.zhifu_statues()
            self.assertEqual(statues, " ")
    
    if __name__ == "__main__":
        unittest.main()
    

      
    参照ドキュメント:https://www.cnblogs.com/yoyoketang/p/9346660.html