単体テストと抽象テスト

参加する代わりに



Unittestは、おそらくPythonで最も有名なテスト作成フレームワークです。 プロジェクトで簡単に習得でき、使い始めることができます。 しかし、完璧なものはありません。 この投稿では、私が個人的に(1つではなく、私が)ユニットテストに欠けている1つの機能についてお話したいと思います。



ユニットテストについて少し



テストフレームワークについて議論(および非難)する前に、テスト全般について少し話す必要があると思います。 「ユニットテスト」という言葉を初めて聞いたとき、ソフトウェアモジュールが要件に準拠しているかどうかをチェックするのは、品質管理サービスの責任だと思いました。 これらの同じテストがプログラマーによって書かれるべきだとわかったとき、私の驚きを想像してください。 最初はテストを作成しませんでした...まったく。 朝起きて、ユーザーから「プログラムは動作しません。 急を要することがあります。」 最初は、エラーを発見した最初の単体テストを作成するまで、これは完全に正常なプロセスであるように思われました。 ユニットテストは一般に、問題を検出するまでまったく役に立たないようです。 今では、テストを書かずに新しい関数をコミットすることはできません。

ただし、テストは、コードの正しいスペルを検証するだけではありません。 私の意見では、テストを実行する関数のリストは次のとおりです。





ある意味では、テストはプログラムの構造を繰り返します。 プログラム構築の原則はテストに適用可能ですか? はい-これは同じプログラムですが、別のプログラムをテストしています。



問題の説明



ある時点で、抽象的なテストを書くというアイデアを得ました。 それはどういう意味ですか? これは、それ自体は実行されませんが、相続人で定義されたパラメーターに依存するメソッドを宣言するテストです。 そして、私はユニットテストでこれを人間的に行うことができないことを発見しました。 以下に例を示します。



class SerializerChecker(TestCase): model = None serializer = None def test_fields_creation(self): props = TestObjectFactory.get_properties_for_model(self.model) obj = TestObjectFactory.create_test_object_for_model(self.model) serialized = self.serializer(obj) self.check_dict(serialized.data, props)
      
      





TestObjectFactoryとcheck_dictメソッドの実装を知らなくても、propsはオブジェクトのプロパティのディクショナリであり、objはシリアライザをチェックするオブジェクトであることは明らかです。 check_dictは、一致する辞書を再帰的にチェックします。 unittestに精通している多くの人が、このテストは抽象の私の定義を満たさないとすぐに言うと思います。 なんで? test_fields_creationメソッドはこのクラスから実行されるため、絶対に必要ではありません。 情報を検索したところ、TestCaseからSerializerCheckerを継承するのではなく、何らかの方法で相続人を実装することが最も適切なオプションであるという結論に達しました。



 class VehicleSerializerTest(SerializerChecker, RecursiveTestCase): model = Vehicle serializer = VehicleSerialize
      
      





RecursiveTestCaseは、check_dictメソッドを実装するTestCaseの子孫です。



このソリューションは、いくつかの位置から一度にいです:





画像



開発環境がスローするエラー



check_dictのスタブを追加するだけで、すべての問題が解決されたように見えるかもしれません。



 class SerializerChecker: model = None serializer = None def check_dict(self, data, props): raise NotImplementedError def test_fields_creation(self): props = TestObjectFactory.get_properties_for_model(self.model) obj = TestObjectFactory.create_test_object_for_model(self.model) serialized = self.serializer(obj) self.check_dict(serialized.data, props)
      
      





しかし、これは問題の完全な解決策ではありません。





まとめると



Unittestには、TestCaseから継承したクラスを「切断」するための健全な機能はありません。 このような機能がフレームワークに追加されたら、とてもうれしいです。 この問題をどのように解決しますか?



All Articles