31

私はpython Command-Line-Interfaceプログラムに取り組んでいますが、テストを行うと退屈だと思います。たとえば、プログラムのヘルプ情報は次のとおりです。

usage: pyconv [-h] [-f ENCODING] [-t ENCODING] [-o file_path] file_path

Convert text file from one encoding to another.

positional arguments:
  file_path

optional arguments:
  -h, --help            show this help message and exit
  -f ENCODING, --from ENCODING
                        Encoding of source file
  -t ENCODING, --to ENCODING
                        Encoding you want
  -o file_path, --output file_path
                        Output file path

プログラムに変更を加えて何かをテストしたいときは、ターミナルを開き、(オプションと引数を指定して) コマンドを入力し、Enter を入力して、実行中にエラーが発生するかどうかを確認する必要があります。エラーが実際に発生した場合は、エディターに戻ってコードを最初から最後までチェックし、バグの位置を推測し、小さな変更を加え、print行を書き、ターミナルに戻り、コマンドを再度実行する必要があります...

再帰的に。

だから私の質問は、CLI プログラムでテストを行うための最良の方法は何ですか? 通常の Python スクリプトを使用した単体テストと同じくらい簡単にできますか?

4

10 に答える 10

15

プログラム全体のレベルで機能をテストするのはまったく問題ないと思います。テストごとに1つのアスペクト/オプションをテストすることは引き続き可能です。このようにして、プログラムが実際に全体として機能することを確認できます。単体テストを作成するということは、通常、テストをより迅速に実行できるようになり、失敗は通常、解釈/理解しやすくなることを意味します。ただし、単体テストは通常​​、プログラム構造とより密接に関連しているため、内部で変更を行う場合は、より多くのリファクタリング作業が必要になります。

とにかく、py.testを使用して、pyconvのlatin1からutf8への変換をテストするための小さな例を次に示します。

# content of test_pyconv.py

import pytest

# we reuse a bit of pytest's own testing machinery, this should eventually come
# from a separatedly installable pytest-cli plugin. 
pytest_plugins = ["pytester"]

@pytest.fixture
def run(testdir):
    def do_run(*args):
        args = ["pyconv"] + list(args)
        return testdir._run(*args)
    return do_run

def test_pyconv_latin1_to_utf8(tmpdir, run):
    input = tmpdir.join("example.txt")
    content = unicode("\xc3\xa4\xc3\xb6", "latin1")
    with input.open("wb") as f:
        f.write(content.encode("latin1"))
    output = tmpdir.join("example.txt.utf8")
    result = run("-flatin1", "-tutf8", input, "-o", output)
    assert result.ret == 0
    with output.open("rb") as f:
        newcontent = f.read()
    assert content.encode("utf8") == newcontent

pytest( "pip install pytest")をインストールした後、次のように実行できます::

$ py.test test_pyconv.py
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.4.5dev1
collected 1 items

test_pyconv.py .

========================= 1 passed in 0.40 seconds =========================

この例では、pytestのフィクスチャメカニズムを活用して、pytest独自のテストの内部機構を再利用しています。http://pytest.org/latest/fixture.htmlを参照してください。詳細を少し忘れた場合は、テストの準備と実行を支援するために「run」と「tmpdir」が提供されているという事実から作業できます。再生したい場合は、失敗したassertステートメントを挿入するか、単に「assert 0」を挿入してから、トレースバックを確認するか、「py.test--pdb」を発行してPythonプロンプトを入力します。

于 2012-11-21T19:08:35.530 に答える
5

だから私の質問は、CLI プログラムでテストを行うための最良の方法は何ですか? 通常の Python スクリプトを使用した単体テストと同じくらい簡単にできますか?

唯一の違いは、Python モジュールをスクリプトとして実行すると、その__name__属性が に設定されること'__main__'です。したがって、一般的に、コマンド ラインからスクリプトを実行する場合は、次の形式にする必要があります。

import sys

# function and class definitions, etc.
# ...
def foo(arg):
    pass

def main():
    """Entry point to the script"""

    # Do parsing of command line arguments and other stuff here. And then
    # make calls to whatever functions and classes that are defined in your
    # module. For example:
    foo(sys.argv[1])


if __name__ == '__main__':
    main()

スクリプトまたはモジュールとして使用する方法に違いはありません。したがって、単体テスト コード内では、foo関数をインポートして呼び出し、必要なアサーションを行うことができます。

于 2012-11-21T12:59:51.030 に答える
2

簡単な答えは「はい」です。単体テストを使用できます。コードが適切に構造化されている場合は、各コンポーネントを個別にテストするのは非常に簡単です。必要な場合はsys.argv、さまざまな引数を使用して実行をシミュレートするために、いつでもモックを作成できます。

于 2012-11-21T12:33:47.707 に答える
0

これは特にPython向けではありませんが、コマンドラインスクリプトをテストするために私が行うことは、さまざまな事前定義された入力とオプションを使用してスクリプトを実行し、正しい出力をファイルに保存することです。次に、変更を加えたときにそれらをテストするために、新しいスクリプトを実行し、出力をにパイプしますdiff correct_output -。ファイルが同じ場合、何も出力されません。それらが異なる場合、それはあなたにどこを示します。これは、LinuxまたはOSXを使用している場合にのみ機能します。Windowsでは、MSYSを入手する必要があります。

例:

python mycliprogram --someoption "some input" | diff correct_output -

さらに簡単にするために、これらすべてのテスト実行を「maketest」Makefileターゲットに追加できます。これはすでに持っていると思います。;)

これらの多くを一度に実行している場合は、失敗タグを追加することで、それぞれがどこで終了するかをもう少し明確にすることができます。

python mycliprogram --someoption "some input" | diff correct_output - || tput setaf 1 && echo "FAILED"

于 2012-11-21T12:33:18.150 に答える
-1

標準の unittest モジュールを使用できます。

# python -m unittest <test module>

または、ノーズをテスト フレームワークとして使用します。従来の unittest ファイルを別のディレクトリに書き込んで実行するだけです。

# nosetests <test modules directory>

単体テストを書くのは簡単です。単体テストのオンラインマニュアルに従ってください

于 2012-11-21T13:18:47.373 に答える
-3

プログラム全体をテストするつもりはありませんが、これは良いテスト戦略ではなく、エラーの実際の場所を実際に把握できない可能性があります。CLI インターフェイスは、API の単なるフロント エンドです。単体テストを介して API をテストし、特定の部分に変更を加えると、その変更を実行するためのテスト ケースが作成されます。

したがって、アプリケーション自体ではなく API をテストするように、アプリケーションを再構築してください。ただし、完全なアプリケーションを実際に実行し、出力が正しいことを確認する機能テストを行うことはできます。

つまり、コードをテストすることは、他のコードをテストすることと同じですが、変更によってすべてが壊れないように、全体としての組み合わせではなく、個々の部分をテストする必要があります。

于 2012-11-21T14:39:44.213 に答える