0

django のテストに関するいくつかのプレゼンテーションを見た後、django のテストをスキップし、テスト用により優れたパッケージ構造を作成するために、独自の TestRunner をコーディングしたいと考えています。

問題は、プロジェクト構造を変更したため、テスト ランナーがテスト検出を行うための正しいパスを見つけられないことです。これは私のプロジェクトがどのように見えるかです:

project/
  -src/
    - project_name/
      - apps/
      - test/ # Not a good name, i know, will change it
         - some_app/

           - test_models.py
    - manage.py
    - development.db

さて、テストするために、test_models.pyこれを行いたいです:

$ cd project/src/
$ python manage.py test some_app.test_models

some_app問題は、テスト ランナーがそのパッケージ ( ) とモジュール ( ) を見つけられないことですtest_models.py。テスト ランナーで名前をハードコードすると変更されますが、私はそうしたくありません。これを機能させるために私が行うことは次のとおりです。

test_labels = ["%s.%s" % ("project_name.test", l)
                           for l in test_labels
                           if not l.startswith("project_name.test")]

だから、あなたがするなら

$ python manage.py test some_app.test_models

次のように書き換えられます。

$ python manage.py test project_name.test.some_app.test_models

そして、それはうまくいきます。

やってみsys.path.append("(...)/project_name/test)ましたが、どちらもうまくいきません。

これは私の TestRunner のコードです:

class DiscoveryDjangoTestSuiteRunner(DjangoTestSuiteRunner):
    """A test suite runner that uses unittest2 test discovery.
    It's better than the default django test runner, becouse it
    doesn't run Django tests and let you put your tests in different
    packages, modules and classes.

    To test everything in there:
        $ ./manage.py test

    To test a single package/module:

        $ ./manage.py test package
        $ ./manage.py test package.module

    To test a single class:

        $ ./manage.py test package.module.ClassName
    """
    def build_suite(self, test_labels, extra_tests=None, **kwargs):
        suite = None
        discovery_root = settings.TEST_DISCOVERY_ROOT
        if test_labels:
            # This is where I append the path
            suite = defaultTestLoader.loadTestsFromNames(test_labels)
            # if single named module has no tests, do discovery within it
            if not suite.countTestCases() and len(test_labels) == 1:
                suite = None
                discovery_root = import_module(test_labels[0]).__path__[0]

        if suite is None:
            suite = defaultTestLoader.discover(
                discovery_root,
                top_level_dir=settings.BASE_PATH,
                )

        if extra_tests:
            for test in extra_tests:
                suite.addTest(test)

        return reorder_suite(suite, (TestCase,))
4

2 に答える 2

2

カスタムTestRunnerにさらに時間を費やす前に、ぜひ をご覧になることをお勧めしますdjango-nose

django-noseimplementsのテスト ランナーによって提供されるカスタム テスト ランナーnoseは、非常に柔軟で、テストを実行するための多くのオプションを提供します。デフォルトの管理コマンドをシームレスにオーバーライドし、プロジェクトのモジュールtestでデフォルトのテスト オプションを構成できるようにします。settings

いくつかの理由から、私は本当にそれをお勧めします:

  • コマンドのオプションtestは完全に文書化されています (出力を見てください) 。
  • 鼻はテスト発見のための多くのアプローチを提供します
  • あなたの同僚はすでにベテランの鼻のユーザーである可能性があります
  • TestRunner自分でクラスを書く必要はありませんでした
于 2012-05-04T19:45:16.160 に答える
2

Python インポート階層のルートはproject/srcです。したがって、test_modelsモジュールの正しい Python インポート パスはproject_name.test.some_app.test_modelsであるため、これをテスト ラベルとして渡すことが期待されます。

project_name.testしかし、特定のテスト モジュールを実行するたびにプレフィックスを入力するのは好きではありません。すべてのテストがそこに配置されるからです。それは問題ありません。利便性と引き換えに、暗黙の非自明な動作を導入することを選択しています。これを実現するためには、絶対に何も追加しないsys.pathでください。Python インポートの健全性を確保するための鍵は、特定のコードベースのインポート階層を 1 つの場所にルート化することです。重複する sys.path エントリは、同じモジュールを異なる名前で二重にインポートするなどの問題を引き起こします。

本当に欲しいのはUIの便利さだけです。私には、あなたが示すテストラベル変更コードがその便利さを実装する明白な方法であるように見えます。接頭辞をハードコーディングするのは好きではありませんが、project_name.testどこかにハードコーディングする必要があります。テスト ランナーが魔法のように、テスト ラベルの先頭にproject_name.test. より一般的なものにしたい場合はTestRunner、設定のようなものに引き出してBASE_TEST_MODULE、その設定の値を各テストラベルの前に追加できます。

于 2012-05-05T22:27:35.070 に答える