6

Python の組み込みunittestモジュールを使用していますが、重要ではないいくつかのテストを作成したいと考えています。

つまり、私のプログラムがそのようなテストに合格した場合、それは素晴らしいことです! ただし、合格しなくても問題はなく、プログラムは引き続き動作します。

たとえば、私のプログラムはカスタム タイプ "A" で動作するように設計されています。「A」で動作しない場合は、壊れています。ただし、便宜上、そのほとんどは別のタイプ「B」でも動作するはずですが、これは必須ではありません。「B」で機能しない場合でも、壊れていません (主な目的である「A」で引き続き機能するため)。「B」で作業できないことは重大ではありません。「ボーナス機能」を見逃してしまうだけです。

もう 1 つの (仮説的な) 例は、OCR を書き込む場合です。アルゴリズムは、テストからほとんどの画像を認識する必要がありますが、それらの一部が失敗しても問題ありません。(いいえ、OCR を書いているわけではありません)

unittest (または他のテスト フレームワーク) で重要でないテストを作成する方法はありますか?

4

11 に答える 11

8

実際問題として、私はおそらく print ステートメントを使用して、その場合の失敗を示します。より正しい解決策は、警告を使用することです。

http://docs.python.org/library/warnings.html

ただし、ロギング機能を使用して、テスト結果のより詳細な記録を生成できます (つまり、「B」クラスの失敗をログに警告を書き込むように設定します)。

http://docs.python.org/library/logging.html

編集:

Django でこれを処理する方法は、失敗することが予想されるいくつかのテストと、環境に基づいてスキップする他のテストがあることです。一般に、テストが失敗するか合格するかを予測できるため (つまり、特定のモジュールをインポートできない場合、システムにはそれがなく、テストは機能しません)、失敗したテストを賢くスキップできます。これは、合格するすべてのテストを引き続き実行し、合格する可能性のあるテストがないことを意味します。単体テストは、予測どおりに動作する場合に最も役立ちます。テストを実行する前に、テストに合格する必要があるかどうかを検出できるため、これが可能になります。

于 2009-09-10T17:16:11.973 に答える
4

単体テストでのアサートは二者択一です。動作するか失敗するかで、中間テストはありません。

そのため、これらの「重要ではない」テストを作成するために、テストを失敗させたくない場合はアサーションを使用しないでください。テストの「有用性」を損なわないように、これは慎重に行う必要があります。

OCR の例に対する私のアドバイスは、何かを使用してテスト コードで成功率を記録し、「assert success_rate > 8.5」のような 1 つのアサーションを作成することです。これにより、希望する効果が得られるはずです。

于 2009-09-10T17:27:20.130 に答える
3

リンクする単体テストのドキュメントから:

unittest.main() の代わりに、より細かく制御でき、出力が簡潔で、コマンド ラインから実行する必要がないテストを実行する方法が他にもあります。たとえば、最後の 2 行は次のように置き換えることができます。

suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
unittest.TextTestRunner(verbosity=2).run(suite)

あなたの場合、TestSuite重要なテストと重要でないテスト用に別々のインスタンスを作成できます。コマンドライン引数を使用して、どのスイートをテスト ランナーに渡すかを制御できます。テスト スイートには他のテスト スイートを含めることもできるため、必要に応じて大きな階層を作成できます。

于 2009-09-10T20:16:41.317 に答える
3

素晴らしい答えをありがとう。本当に完全な回答は 1 つだけではなかったので、役に立ったすべての回答を組み合わせてここに書いています。この回答が気に入ったら、これを担当した人に投票してください。

結論

単体テスト (または少なくともunittestモジュール内の単体テスト) はバイナリです。Guilherme Chapiewski が言うように、それらは機能するか失敗するかであり、中期はありません。

したがって、私の結論は、単体テストはこの仕事に適したツールではないということです。単体テストは「すべてが機能し続けること、失敗は予想されないこと」にもっと関心があるようです。したがって、非バイナリテストを行うことはできません(または簡単ではありません)。

したがって、アルゴリズムまたは実装を改善しようとしている場合、単体テストは適切なツールではないようです。単体テストでは、あるバージョンが他のバージョンと比較してどの程度優れているかがわからないためです (両方が正しく実装されていると仮定します)。 、両方ともすべての単体テストに合格します)。

私の最終的な解決策

私の最終的な解決策は、 wcoenen answerに示されているryber のアイデアとコードに基づいています。私は基本的にデフォルトを拡張し、冗長性を減らしています。次に、私のメイン コードは 2 つのテスト スイートを呼び出します。重要なものは standard を使用し、重要でないものは私自身のあまり冗長でないバージョンを使用します。TextTestRunnerTextTestRunner

class _TerseTextTestResult(unittest._TextTestResult):
    def printErrorList(self, flavour, errors):
        for test, err in errors:
            #self.stream.writeln(self.separator1)
            self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
            #self.stream.writeln(self.separator2)
            #self.stream.writeln("%s" % err)


class TerseTextTestRunner(unittest.TextTestRunner):
    def _makeResult(self):
        return _TerseTextTestResult(self.stream, self.descriptions, self.verbosity)


if __name__ == '__main__':
    sys.stderr.write("Running non-critical tests:\n")
    non_critical_suite = unittest.TestLoader().loadTestsFromTestCase(TestSomethingNonCritical)
    TerseTextTestRunner(verbosity=1).run(non_critical_suite)

    sys.stderr.write("\n")

    sys.stderr.write("Running CRITICAL tests:\n")
    suite = unittest.TestLoader().loadTestsFromTestCase(TestEverythingImportant)
    unittest.TextTestRunner(verbosity=1).run(suite)

可能な改善

Kathy Van Stone が提案したように、非バイナリ テストを含むテスト フレームワークがあるかどうかを知ることは、依然として有用です。おそらく、この単純な個人的なプロジェクトでは使用しませんが、将来のプロジェクトで役立つ可能性があります。

于 2009-09-14T19:42:08.257 に答える
3

単体テストがどのように機能するかは完全にはわかりませんが、ほとんどの単体テスト フレームワークには、カテゴリに似たものがあります。そのようなテストを分類し、無視するようにマークを付けて、興味がある場合にのみ実行することができると思います。しかし、私は経験上、テストを無視するとすぐに、誰も実行しないテストを無視するようになることを知っています。

私のアドバイスは、あなたのアプリがやるかやらないかです。試してはいけません。

于 2009-09-10T17:17:30.217 に答える
2

Python 2.7 (および 3.1) では、一部のテスト メソッドまたはテスト ケースをスキップし、一部のテストを予期された失敗としてマークするサポートが追加されました。

http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures

予想される失敗としてマークされたテストは、TestResult で失敗としてカウントされません。

于 2010-10-22T18:41:31.357 に答える
0

鼻を見てください:http ://somethingaboutorange.com/mrl/projects/nose/0.11.1/

実行するテストを選択するためのコマンドラインオプションはたくさんあり、既存の単体テストテストを保持できます。

于 2009-09-10T18:33:06.743 に答える
0

もう1つの可能性は、「B」ブランチを作成し(ある種のバージョン管理を使用していますよね?)、そこで「B」の単体テストを行うことです。そうすれば、リリースバージョンの単体テストをクリーンに保つことができますが(見て、すべてのドット!)、Bのテストはまだあります。gitやmercurial(私はmercurialに部分的です)などの最新のバージョン管理システムを使用している場合は、分岐します。 / cloneingとmergingは簡単な操作なので、それをお勧めします。

しかし、私はあなたが彼らがすることを意図されていない何かのためにテストを使用していると思います。本当の質問は、「「B」が機能することはあなたにとってどれほど重要ですか?」です。テストスイートには、合格か不合格かを気にするテストのみが含まれている必要があるためです。それらが失敗した場合、それはコードが壊れていることを意味することをテストします。そのため、「B」機能を開発しているブランチになるため、「B」ブランチで「B」のみをテストすることを提案しました。

必要に応じて、ロガーまたは印刷コマンドを使用してテストできます。しかし、ユニットテストでフラグが立てられるほど壊れていることを気にしないのであれば、テストするのに十分気にかけているかどうかを真剣に疑問に思います。その上、それは不必要な複雑さを追加します(デバッグレベルを設定するための余分な変数、互いに完全に独立しているが同じ空間内で動作する複数のテストベクトル、潜在的な衝突やエラーなどを引き起こします)。「Hello、World!」を開発している場合を除きます。アプリ、私はあなたの問題セットが追加の、不必要な複雑さを追加することなく十分に複雑であると思います。

于 2009-09-10T20:36:18.890 に答える
-1

成功率をカウントするようにテストを作成できます。OCR を使用すると、コード 1000 の画像をスローして、95% が成功する必要があります。

プログラムがタイプ A で動作する必要がある場合、これが失敗するとテストは失敗します。B で作業する必要がない場合、そのようなテストを行う価値は何ですか?

于 2009-09-10T17:19:34.393 に答える