mutmutの学習-Python変異テストツール

変異テストでは、従来のテストではカバーされていないバグを特定できます。



あらゆる場面でのテストはありますか?または、プロジェクトリポジトリに「約100%のテストカバレッジ」ヘルプが含まれている場合もありますか?しかし、すべてが実生活でとてもシンプルで達成可能ですか?







ユニットテストでは、すべてが多かれ少なかれ明確です。それらは書かれなければなりません。期待どおりに機能しない場合があります。誤検知やエラーのあるテストがあり、コードを変更せずに「はい」と「いいえ」を返します。ユニットテストで見つけることができる小さなバグは価値がありますが、多くの場合、開発者はコミットする前にそれらを修正します。しかし、私たちはしばしば見えなくなるそれらの間違いについて本当に心配しています。そして何よりも悪いことに、彼らは製品がユーザーの手に渡ったときに自分の名前を付けることを決定することがよくあります。



これは、ある突然変異検査あなたはそのような陰湿なバグに対処することができます。あらかじめ決められた方法でソースコードを変更し(特別なバグ、いわゆる「ミュータント」を導入)、これらのミュータントが他のテストで生き残るかどうかをチェックします。ユニットテストを生き延びた変異体は、標準テストではエラーを含む対応する変更されたコードが見つからなかったという結論に至ります。



Pythonでは、mutmutは突然変異テストの主要なツールです



アナログ時計で時針と分針の間の角度を計算するコードを書く必要があると想像してください。



def hours_hand(hour, minutes):
    base = (hour % 12 ) * (360 // 12)
    correction = int((minutes / 60) * (360 // 12))
    return base + correction

def minutes_hand(hour, minutes):
    return minutes * (360 // 60)

def between(hour, minutes):
    return abs(hours_hand(hour, minutes) - minutes_hand(hour, minutes))


基本的なユニットテストを書いてみましょう。



import angle

def test_twelve():
    assert angle.between(12, 00) == 0


コードにifはありませんそのようなユニットテストがすべての可能な状況をどの程度カバーしているかを確認しましょう。



$ coverage run `which pytest`
============================= test session starts ==============================
platform linux -- Python 3.8.3, pytest-5.4.3, py-1.8.2, pluggy-0.13.1
rootdir: /home/moshez/src/mut-mut-test
collected 1 item                                                              

tests/test_angle.py .                                                    [100%]

============================== 1 passed in 0.01s ===============================


優れた! 100%のカバレッジのように。しかし、突然変異テストを行うとどうなりますか?







大野! 21のうち、16もの変異体が生き残った。どうして?



突然変異テストごとに、潜在的なエラーをシミュレートするソースコードの一部を変更する必要があります。このような変更の例は、比較演算子 ">"を "> ="に変更することです。この境界条件のユニットテストがない場合、このミュータントバグは存続します。これは、通常のテストでは検出されない潜在的なバグです。



はい。すべて明確です。より良いユニットテストを書く必要があります。次に、resultsコマンドを使用して、どのような特定の変更が行われたかを確認しましょう。



$ mutmut results
<snip>
Survived :( (16)

---- angle.py (16) ----

4-7, 9-14, 16-21
$ mutmut apply 4
$ git diff
diff --git a/angle.py b/angle.py
index b5dca41..3939353 100644
--- a/angle.py
+++ b/angle.py
@@ -1,6 +1,6 @@
 def hours_hand(hour, minutes):
     hour = hour % 12
-    base = hour * (360 // 12)
+    base = hour / (360 // 12)
     correction = int((minutes / 60) * (360 // 12))
     return base + correction


これは、mumutがどのように機能するかの典型的な例です。ソースコードを分析し、一部の演算子を他の演算子に置き換えます。たとえば、減算による加算、またはこの場合のように除算による乗算です。ユニットテストは、一般的に言って、ステートメントを変更するときにエラーをキャッチする必要があります。そうしないと、プログラムの動作を効果的にテストできません。これは、特定の変更を行うときにmutmutが準拠するロジックです。生き残ったミュータントに対して



mutmutapplyコマンド使用できます。わあ、時間パラメータが正しく使用されているかどうかを確認しなかったことがわかりました。これを修正しましょう:



$ git diff
diff --git a/tests/test_angle.py b/tests/test_angle.py
index f51d43a..1a2e4df 100644
--- a/tests/test_angle.py
+++ b/tests/test_angle.py
@@ -2,3 +2,6 @@ import angle
 
 def test_twelve():
     assert angle.between(12, 00) == 0
+
+def test_three():
+    assert angle.between(3, 00) == 90


以前は、12のみをチェックしていました。値3のチェックを追加すると、1日節約できますか?







この新しいテストは、2つの変異体を殺すことができました。以前よりも優れていますが、さらに多くの作業を行う必要があります。アイデアはすでに明確であるため(すべてのミュータントを自分で殺すことができますか?)、残りの14のケースのそれぞれについて、現時点ではソリューションを作成しません。



ミューテーションテストでは、カバレッジの測定に加えて、テストの包括性を評価することもできます。このようにして、テストを改善できます。生き残った変異体は、開発者が犯した可能性のある間違いであり、製品の潜在的な欠陥でもあります。だから、もっとミュータントを殺してほしい!






広告



VDSina、LinuxおよびWindows用の仮想サーバーを提供します。プリインストールされているOSのいずれかを選択するか、イメージからインストールします。






All Articles