1. ホーム
  2. python

[解決済み] PyCharm Community Editionでマウスの右クリックコンテキストメニューからDjangoアプリケーションのUnitTestsを実行/デバッグしますか?

2022-02-18 14:40:39

質問

を強調しなければなりません。 PyCharm コミュニティ エディション を行うものです。 がない ジャンゴ 統合 ( v 2016.3.2 質問時)。

私は グーグル もちろん、回答がある可能性を排除するものではありませんが、私が見逃していただけなのです。

質問は簡単です。 PyCharm を実行(デバッグ)することができます。 テストケース またはそのメソッドの1つ)を、下の画像のようにマウスの右クリック(コンテキストメニューから)で簡単に実行することができます。

残念ながら、例外が発生します。

Traceback (most recent call last):
    File "C:\Install\PyCharm Community Edition\2016.3.2\helpers\pycharm\utrunner.py", line 254, in <module>
        main()
    File "C:\Install\PyCharm Community Edition\2016.3.2\helpers\pycharm\utrunner.py", line 232, in main
        module = loadSource(a[0])
    File "C:\Install\PyCharm Community Edition\2016.3.2\helpers\pycharm\utrunner.py", line 65, in loadSource
        module = imp.load_source(moduleName, fileName)
    File "E:\Work\Dev\Django\Tutorials\proj0\src\polls\tests.py", line 7, in <module>
        from polls.models import Question
    File "E:\Work\Dev\Django\Tutorials\proj0\src\polls\models.py", line 9, in <module>
        class Question(models.Model):
    File "E:\Work\Dev\Django\Tutorials\proj0\src\polls\models.py", line 10, in Question
        question_text = models.CharField(max_length=200)
    File "E:\Work\Dev\VEnvs\py2713x64-django\lib\site-packages\django\db\models\fields\__init__.py", line 1043, in __init__
        super(CharField, self).__init__(*args, **kwargs)
    File "E:\Work\Dev\VEnvs\py2713x64-django\lib\site-packages\django\db\models\fields\__init__.py", line 166, in __init__
        self.db_tablespace = db_tablespace or settings.DEFAULT_INDEX_TABLESPACE
    File "E:\Work\Dev\VEnvs\py2713x64-django\lib\site-packages\django\conf\__init__.py", line 53, in __getattr__
        self._setup(name)
    File "E:\Work\Dev\VEnvs\py2713x64-django\lib\site-packages\django\conf\__init__.py", line 39, in _setup
        % (desc, ENVIRONMENT_VARIABLE))
    django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

備考 : 誰かの役に立つかもしれない答えを提供するために、質問を追加しただけです。

解決方法を教えてください。

1. 背景情報

  • のみで作業しています。 Django 3ヶ月間
  • について PyCharm 私は何年かそれを使って仕事をしてきましたが、IDEとしてのみ(例えば PyCharm for dummies そのため、高度な内容には触れていません。

以上のことを考えると、一部(または全部)の解決策は、一部の上級ユーザにとっては面倒/バカバカしいと思われるかもしれませんので、ご容赦ください。この解決策に付加価値を与えてくれるようなコメントがあれば、それを取り入れるつもりです。

質問に戻ります。私は、次のようなプロジェクトでテスト/調査を行いました。 Djangoチュートリアル ( [DjangoProject]です。最初の Django アプリを書く ) + の一部と Django Rest フレームワーク チュートリアル ( [DRF]: クイックスタート ). 例として、次のような実行を試みます。 polls/tests.py : QuestionViewTests.test_index_view_with_no_questions()

メモとして 設定 django_settings_module 例外の指示通り もう1つのトリガー などなど.

2. を作成する パイソン コンフィギュレーション

これは質問に対する答えではありませんが(遠隔的に関連しているだけです)、とりあえず投稿しておきます(すでに多くの人がやっていることでしょう)。

  • メニューをクリック 実行 -> 設定を編集する...
  • について 実行/デバッグ設定 ダイアログを表示します。
    • タイプを持つ新しいコンフィギュレーションを追加します。 パイソン
    • を設定します。 作業ディレクトリ をプロジェクトのルートパスに設定します(私の場合、" E:∕Work∕Dev∕Django∕Tutorials∕proj0src ")。デフォルトでは、このパスは Python のモジュール検索パス
    • を設定します。 スクリプト を指定します。 Django プロジェクト起動スクリプト ( manage.py )
    • を設定します。 スクリプトのパラメータ をテストパラメータに設定します ( test QuestionViewTests.test_index_view_with_no_questions )
    • 設定に名前を付け(任意)、次のようにクリックします。 OK . これで、このテストを実行できるようになります。

もちろん、すべてのテストケース(とそのメソッド)に対してこれを行わなければならないのは、(本当に迷惑な話ですが)この方法はスケーラブルではありません。

3. 調整する PyCharm を実行することができます。

ただ、これは真の解決策とはいえず、むしろ(いい加減な)回避策のようなものだということは指摘しておきます ( ゲイナーリー )であり、しかも押し付けがましい。

まずは、次のようなことが起こるのかを見てみましょう。 Rクリック の上に テスト (この用語は一般的に使用するつもりで、特に指定しない限り、テストケース、メソッド、テストファイル全体を意味することがあります)。私の場合は、以下のコマンドを実行しています。

"E:\Work\Dev\VEnvs\py2713x64-django\Scripts\python.exe" "C:\Install\PyCharm Community Edition\2016.3.2\helpers\pycharm\utrunner.py" E:\Work\Dev\Django\Tutorials\proj0\src\polls\tests.py::QuestionViewTests::test_index_view_with_no_questions true

ご覧のように、"を起動しています。 C:\InstallPyCharm Community Edition2016.3.2版helpers "(以下、こう呼ぶことにします。 utrunner )を引数の束で指定します(1 st は、テスト仕様なので、私たちには重要です)。 ユートランナー を気にしないテスト実行フレームワークを使用しています。 Django (実際には、いくつかの Django を処理するコードですが、それは私たちの助けにはなりません)。

について一言。 PyCharm `s 実行/デバッグの設定 :

  • いつ Rクリック -をクリックすると テスト , PyCharm を自動的に作成します。 実行設定 (保存できるようになります)。 実行/デバッグ設定 ダイアログを表示します。アン 重要 であるコンフィギュレーションタイプに注意する必要があります。 Pythonテスト/Unittests (これは自動的に ユートランナー )
  • を作成する場合 実行設定 を一般的に使用します。 PyCharm そのコンフィギュレーションタイプの設定をコピーします。 既定値 (で見ることができます)。 実行/デバッグ設定 を新しいコンフィギュレーションに追加し、その他の部分を特定のデータで埋めます。について重要なことが一つあります。 デフォルトの設定 は、それらが プロジェクトベース に存在する。 .アイデア フォルダー ( ワークスペース.xml そのため、それらを変更しても、他のプロジェクトに影響を与えることはありません(最初に心配したとおりです)。

以上を踏まえて、進めていきましょう。

最初のこと を実行する必要があります。 実行/デバッグ設定 ダイアログ(メニュー。 実行 -> 設定を編集する... を編集してください。 デフォルト/Pythonテスト/Unittests の設定を行います。

  • を設定します。 作業ディレクトリ 先ほどの方法と同じように
  • での 環境変数 という名前の新しいものを追加してください。 django_test_mode_gainarie という文字列を設定し、それを任意の文字列(空/ ヌル )

2つ目 そして、より厄介なのは(侵入を伴う)、パッチを当てることです。 ユートランナー .

utrunner.patch :

--- utrunner.py.orig    2016-12-28 19:06:22.000000000 +0200
+++ utrunner.py 2017-03-23 15:20:13.643084400 +0200
@@ -113,7 +113,74 @@
   except:
     pass

-if __name__ == "__main__":
+
+def fileToMod(filePath, basePath):
+  if os.path.exists(filePath) and filePath.startswith(basePath):
+    modList = filePath[len(basePath):].split(os.path.sep)
+    mods = ".".join([os.path.splitext(item)[0] for item in modList if item])
+    return mods
+  else:
+    return None
+
+
+def utrunnerArgToDjangoTest(arg, basePath):
+  if arg.strip() and not arg.startswith("--"):
+    testData = arg.split("::")
+    mods = fileToMod(testData[0], basePath)
+    if mods:
+      testData[0] = mods
+      return ".".join(testData)
+    else:
+      return None
+  else:
+    return None
+
+
+def flushBuffers():
+  sys.stdout.write(os.linesep)
+  sys.stdout.flush()
+  sys.stderr.write(os.linesep)
+  sys.stderr.flush()
+
+
+def runModAsMain(argv, codeGlobals):
+  with open(argv[0]) as f:
+    codeStr = f.read()
+  sys.argv = argv
+  code = compile(codeStr, os.path.basename(argv[0]), "exec")
+  codeGlobals.update({
+    "__name__": "__main__",
+    "__file__": argv[0]
+    })
+  exec(code, codeGlobals)
+
+
+def djangoMain():
+  djangoTests = list()
+  basePath = os.getcwd()
+  for arg in sys.argv[1: -1]:
+    djangoTest = utrunnerArgToDjangoTest(arg, basePath)
+    if djangoTest:
+      djangoTests.append(djangoTest)
+  if not djangoTests:
+    debug("/ [DJANGO MODE] Invalid arguments: " + sys.argv[1: -1])
+  startupTestArgs = [item for item in os.getenv("DJANGO_STARTUP_TEST_ARGS", "").split(" ") if item]
+  startupFullName = os.path.join(basePath, os.getenv("DJANGO_STARTUP_NAME", "manage.py"))
+  if not os.path.isfile(startupFullName):
+    debug("/ [DJANGO MODE] Invalid startup file: " + startupFullName)
+    return
+  djangoStartupArgs = [startupFullName, "test"]
+  djangoStartupArgs.extend(startupTestArgs)
+  djangoStartupArgs.extend(djangoTests)
+  additionalGlobalsStr = os.getenv("DJANGO_STARTUP_ADDITIONAL_GLOBALS", "{}")
+  import ast
+  additionalGlobals = ast.literal_eval(additionalGlobalsStr)
+  flushBuffers()
+  runModAsMain(djangoStartupArgs, additionalGlobals)
+  flushBuffers()
+
+
+def main():
   arg = sys.argv[-1]
   if arg == "true":
     import unittest
@@ -186,3 +253,10 @@

   debug("/ Loaded " + str(all.countTestCases()) + " tests")
   TeamcityTestRunner().run(all, **options)
+
+
+if __name__ == "__main__":
+  if os.getenv("DJANGO_TEST_MODE_GAINARIE"):
+    djangoMain()
+  else:
+    main()

上記は 差分 ( [man7]を参照してください。DIFF(1) ) (または パッチ - は連結して使用することができます。 パッチ ): の違いを示しています。 utrunner.py.orig (元のファイル - 修正を始める前に保存しておいたものです。 utrunner.py (変更を含む現在のバージョン)。私が使用したコマンドは diff --binary -uN utrunner.py.orig utrunner.py (当然ながら ユートランナー のフォルダ)。個人的な感想として パッチ を変更するのに適した形式です。 rd パーティーのソースコードです(変更を管理下に置き、分離するため)。

のコードは何ですか? パッチ は何をするのか(おそらく、プレーンな Python のコード)。

  • の下にあるものはすべて メイン ブロック ( if __name__ == "__main__": という関数に移動されました。 メイン (分離して、間違って変更しないようにするため)
  • は、その メイン ブロックが修正され、もし env var が django_test_mode_gainarie が定義されている場合(そして空でない場合)、新しい実装に従います ( djangoMain 関数)、それ以外の場合は 通常 . 新しい実装です。
    • ファイルトモッド 減算 ベースパス から ファイルパス に変換し、その差分を パイソン パッケージのスタイルです。例 fileToMod("E:\Work\Dev\Django\Tutorials\proj0\src\polls\tests.py", "E:\Work\Dev\Django\Tutorials\proj0\src") を返します。 polls.tests
    • utrunnerArgToDjangoTest : 前の関数を使用し、クラス名 ( QuestionViewTests ) と (オプションで) メソッド名 ( テストインデックス_ビュー_質問なし に変換され、最後にテスト仕様が ユートランナー 形式( E:\Work\Dev\Django\Tutorials\proj0\src\polls\tests.py::QuestionViewTests::test_index_view_with_no_questions ) から manage.py フォーマット ( polls.tests.QuestionViewTests.test_index_view_with_no_questions )
    • フラッシュバッファ を書き込む。 eoln を生成し、それをフラッシュします。 標準出力 標準エラー バッファを使用する必要があります。 PyCharm Django が交錯し、最終的にぐちゃぐちゃになる)
    • RunModAsMain : 通常、関連するすべての manage.py のコードは if __name__ == "__main__": . この関数 "tricks"。 パイソン と思わせる manage.py は、その1として実行されました。 st 引数

パッチング ユートランナー :

  • これらの改造は自分でやりました(以下のようなバージョンを検索していません)。 Django を統合し、そこからインスパイアする)
  • ユートランナー は次の製品に含まれます PyCharm . なぜ JetBrains を入れなかったのは 任意の ジャンゴ を統合しています。 コミュニティ版 を買わせるためのものです。 プロフェッショナル版 . これは、彼らのつま先を踏んでいるようなものです。を変更することが法的にどのような意味を持つのか、私は知りません。 ユートランナー が、とにかくパッチを当てれば 自分の責任とリスクでやってください。
  • コーディングスタイル:最悪です(少なくともネーミング/インデントから POV しかし、ファイルの他の部分と一貫性があります(コーディングスタイルが最悪であることが許される唯一のケースです)。 [Python]: PEP 8 -- Pythonコードのためのスタイルガイド のコーディングスタイルガイドラインが含まれています。 Python
  • パッチは、元のファイル( utrunner.py ) で、以下のようなプロパティがあります (このプロパティはまだ v 2019.2.3 (最終確認済み。 20190930 )):
    • の大きさを指定します。 5865
    • sha256sumです。 db98d1043125ce2af9a9c49a1f933969678470bd863f791c2460fe090c2948a0
  • を適用する。 パッチ :
    • ユートランナー は"にあります。 ${PYCHARM_INSTALL_DIR}/helpers/pycharm "です。
    • 典型的な例です。 pycharm_install_dir} を指定します。 を指しています。
      • ニックス : /usr/lib/pycharm-community
      • 勝利 : " C:\Program Files (x86)\JetBrains PyCharm 2016.3 "(お使いのバージョン番号に合わせます)
    • を保存します。 パッチ のコンテンツ(例えば、次のようなファイル)を作成します。 utrunner.patch の下にあると仮定します。 /tmp )
    • ニックス - は簡単で、ただ ( cd utrunner のフォルダで)実行する patch -i /tmp/utrunner.patch . [man7]を参照してください。PATCH(1) は、デフォルトでインストールされるユーティリティです( パッチ でのdpkg ユーブツ ). なお utrunner.py が所有する ルート この手順で必要なのは sudo
    • 勝つ - と同じような手順を踏みますが、ネイティブの パッチ ユーティリティを使用します。ただし、回避策はあります。
      • 使用する Cygwin . のように ニックス ( Lnx ) の場合です。 パッチ ユーティリティが利用可能ですが デフォルトではインストールされません。 . その パッチ pkgは必ず 明示的に からインストールされます。 Cygwinのセットアップ . これを試したところ 動作する
      • 代替品がある(試していない)。
      • のように ニックス の場合、ファイルのパッチは (ほとんどの場合) 管理者 . また、ファイルのパスに注意して、必ず (ダブル)クォート スペースが含まれている場合
    • を元に戻す パッチ :
      • バックアップは有害ではありません(ただし、ディスクの空き容量の POV とか、溜まってくると管理が面倒になるとか)。私たちの場合は必要ありません。変更を戻すには、変更したファイルに対してこのコマンドを実行すればよい。 patch -Ri /tmp/utrunner.patch そうすると、元のコンテンツに切り替わります。 utrunner.py.orig ファイルを変更します。 .py .py.orig ファイル)を作成します。
        とはいえ いつもバック3 rd -パーティーのファイルを変更する前にアップする (特にツールやインストーラによって追跡されている場合)、変更中に何か問題が発生しても、元の状態に戻す方法が常にあるようにします。
    • 今回のケースとは異なりますが、変更が別の形で行われた場合、例えばファイルに パッチ を適用した(例えば ギットハブ ) の場合、明らかにファイル全体を取得し (ファイルが多数ある場合、それらをすべて追跡するのは面倒になります)、自分のを上書きすることができます。しかし、もう一度言います。 最初にバックアップを取る !

この方法について一言 :

  • コードが(オプションの)envバーを扱うことができる。 django_test_mode_gainarie - これは必須です)。

    • django_startup_name : 万が一 manage.py が別の名前を持っていたり (何らかの理由で?)、あるいは他のフォルダーにあったりした場合、そのフォルダーは 作業ディレクトリ . について 重要 ファイルパスを指定するときは、プラットフォーム固有のパスセパレータを使用することです。 スラッシュ ( / ) のために ニックス , bkslash ( \ ) のために 勝利
    • django_startup_test_args の追加引数です。 manage.py test を受け付ける(実行 manage.py test --help で全リストを取得します)。ここで、私が主張しなければならないのは -k / --keepdb で、テスト用データベースを保持する ( test_${REGULAR_DB_NAME} とします。 で設定されています。 設定 の下にある TEST ディクショナリ)を実行する間に 単一のテストを実行する場合 DB (そしてすべてのマイグレーションを適用する)そしてそれを破棄するのは時間がかかる(そして非常に迷惑でもある)場合がある。このフラグは DB は最後に削除されず、次のテスト実行時に再利用されます。
    • django_startup_additional_globals : これは文字列表現が必要です。 Pythonのディクショナリ . 何らかの理由で manage.py に存在する必要があります。 globals() ディクショナリーをここに配置する必要があります。
  • を修正する場合 デフォルト設定 の場合、それを継承する以前に作成されたすべてのコンフィギュレーションは、それを継承します。 は更新されません。 そのため、手動で 削除 (そして、新しい Rクリック テスト )

Rクリック を同じテストに使用し (以前の設定を削除した後:d)、そして さあ :

E:\Work\Dev\VEnvs\py2713x64-django\Scripts\python.exe "C:\Install\PyCharm Community Edition\2016.3.2\helpers\pycharm\utrunner.py" E:\Work\Dev\Django\Tutorials\proj0\src\polls\tests.py::QuestionViewTests::test_index_view_with_no_questions true
Testing started at 01:38 ...


Using existing test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.390s

OK

Preserving test database for alias 'default'...


Process finished with exit code 0

デバッグも動作します(ブレークポイントなど・・・)。

注意事項 (今のところ2つ確認しました)。

  • これは良性で、ただの UI の問題です。 ユートランナー (ほとんどの場合)いくつかの初期化で PyCharm が行われることを期待しているのですが、今回のケースでは明らかにそうではありません。そのため、テストが正常に終了しても PyCharm 's PoV ということで 出力 のウィンドウに警告が表示されます。 テストフレームワークが予期せず終了した となります。
  • これは厄介なもので、私は(まだ)真相を知ることができませんでした。どうやら、である。 ユートランナー 任意 input ( raw_input ) の呼び出しはあまりうまく処理されません。プロンプトテキスト: " テストデータベース 'test_tut-proj0' を削除する場合は 'yes' を、キャンセルする場合は 'no' を入力してください。 "(前回のテスト実行がクラッシュした場合に表示され、その時の DB が最後に破棄されない)が表示されず、プログラムがフリーズしてしまう(これは ユートランナー ) 、ユーザーにテキストを入力させることはできません (スレッドが混在しているのかも?)。復旧するには、テスト実行を停止して DB を実行し、再度テストを実行します。ここでもまた manage.py test -k この問題を回避するためのフラグ

私は以下のように作業/テストしてきました。 環境 :

  • ニックス ( Lnx ):
    • Ubtu 16.04 x64
    • PyCharm コミュニティ版 2016.3.3
    • Python 3.4.4 ( VEnv )
    • Django 1.9.5
  • 勝利 :
    • W10 x64
    • PyCharm コミュニティ版 2016.3.2
    • Python 2.7.13 ( VEnv )
    • Django 1.10.6

備考 :

  • 現在の問題点(少なくとも2つの nd 1)
  • A クリーン の中で何らかの形で上書きすることです。 PyCharm を実行するデフォルトの設定(私がコードから行ったこと)ですが、私は設定ファイルを見つけることができませんでした(おそらく、それは PyCharm を使用します)。
  • に固有のファイル/フォルダーがたくさんあることに気づきました。 Django の中にある ヘルパー ( ユートランナー の親)フォルダも使えるかもしれないので、確認が必要です。

冒頭で述べたように、どんな提案でも大歓迎です!

EDIT0 :

  • Udiさんのコメントにも返信しましたが、これは、「Software」の「Software」を支払う余裕がない人(あるいは、その気がない会社)のための代替案です。 PyCharm プロフェッショナル版 ライセンス料(ざっと見た感じでは ~100$-200$ / 各インスタンスの1年分)