2016-12-10 2 views
0

私が構築していフラスコアプリケーションのためのいくつかのユニットテストを書くしようとしているに始まった、これはフラスコのアプリケーションに終了する方法をフラスコプロセスはunittestの

app.pyを含むファイルです

from flask import Flask 

app = Flask(__name__) 


@app.route('/') 
def home(): 
    return 'hello world' 

、その後、私が思いついた

tests.py

from unittest import TestCase, main 
from app import app 
from multiprocessing import Process 
import requests 


class Test(TestCase): 

    @classmethod 
    def setUpClass(cls): 
     cls.hostname = 'http://localhost:8000' 

     with app.app_context(): 
      p = Process(target=app.run, kwargs={'port': 8000}) 
      p.start() 
      cls.p = p 

    def test_options(self): 
     # print(self.p.is_alive()) # returns True but requests doesn't connect 
     result = requests.post(self.hostname).text 
     self.assertEqual(result, 'hello world') 

    @classmethod 
    def tearDownClass(cls): 
     cls.p.terminate() # works fine if i comment it out 
     pass 


if __name__ == '__main__': 
    main() 

テストを含むファイルフラスコに付属のtest_clientの代わりにrequestsモジュールを使用してアプリケーションをテストすることを考えました。ユニットテストモジュールの私の理解から、

setUpClassメソッドが新しいプロセスを作成し、アプリケーションを起動すること、一度呼び出されます。

その後、request.postまたはrequest.getでさまざまなテストを無料で実行できます。

その後、すべてのテストが実行された日の終わりに、tearDownClassが処理を終了するはずです。

私はテストを実行しようとすると、これは私が得るものです(スタックトレースは、実際にこれより長いですが、それはすべてこれに沸く)

requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=5000): Max retries exceeded with url:/(Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7faeeba183c8>: Failed to establish a new connection: [Errno 111] Connection refused',)) 

フラスコのプロセスが起動し、要求されていないため

cls.p.terminateすべてが正しく動作し、テストに合格した場合、唯一の問題はフラスコプロセスを再び殺すことができなくなることです。

私はプロセスが鬼神の作るか、またはこのようなtest_client使用することができます知っている:

class Test(TestCase): 

    @classmethod 
    def setUpClass(cls): 
     cls.hostname = 'http://localhost:8000' 

     with app.app_context(): 
      app.config['TESTING'] = True 
      cls.app = app.test_client() 

    def test_options(self): 
     # print(self.p.is_live()) 
     result = self.app.get().data 
     self.assertEqual(result, b'hello world') 

をし、ちょうど私の生活に移動するが、私は本当に私のコードは動作しませんなぜ私がしようとすると理解したいです私がテストスイートを破っているときにプロセスを殺すために。

私はデバッグにpdbを使用しようとしましたが、pdbプロンプトに何か入力しようとすると端末が壊れてしまうのを知らない(何らかの文字が端末に表示されませんI型、私はエンターキーを押したときに、私は文字が実際にあったが、見えなかったことを発見し、例)私はそれらを押したとき

+0

この時点では、テストハーネスはアプリより複雑で壊れやすく、機能していてもそのままになる可能性があります。フックのドキュメントに記載されているテストの設定に進む必要がある場合は、ちょうど嘲笑で始める方がよいでしょう。 – pvg

+0

ええ、私は知っています...しかし、一方で、 'test_client'はREST APIのテストにはあまり適していませんが、Responseオブジェクトはバイトを返します(自分で他のデータ型に変換する必要があります)。私の質問は「質問」よりも「なぜ質問なのですか」 – danidee

+0

これは、フラスコのアプリが実際に完全に初期化されていないために引き裂かれている可能性があります。基本的な印刷ロギングを追加して、一連の操作を確認する必要があります。あなたはp.startの後に5〜10秒の睡眠をとって(バンダイの尺度としてチェックして)、ティアダウンをコメントなしで残しておくことができます - それは簡単にその理論をチェックできるようになります。 – pvg

答えて

1

Iを表示することを拒否prrrinnntttrためとt私が持っ終わるかもしれないprintを入力しますあなたのケースで何が起こっているのか分かりませんが、私のプロジェクトの1つでは、このようなbashスクリプトを使ってテストします:

#!/bin/bash 

set -eux 

python app.py & 
sleep 3 

set +e 

python tests.py 
result=$? 
kill $(ps aux | grep app.py | grep -v grep | awk '{print $2}') 
exit $result 

これは、サーバーの起動、テストの実行、サーバーの強制終了を処理するため、Pythonテストでサーバーを処理することは記述されていません。

+0

ありがとう@AlexHall、私もbashスクリプトでこれを扱うことができたことを知っていた、私はちょうどそれがすべてPythonからやったかった、私は今できるようになった(テストクラスからプロセスの作成を移動することによって、スクリプトとそれをデーモンにする)。ですから、問題はunitTestsメソッドとは何か、内部的にはどのように働いているのかと思います。 – danidee

関連する問題