2009-03-11 5 views
3

나는 이와 같은 몇 가지 기능을 가지고 있습니다.() s.handle_request 요청을 대기 때문에 설치에서사용 wsgiref.simple_server는


from wsgiref.simple_server import make_server 
def app_200_hello(environ,start_response): 
    stdout = StringIO('Hello world') 
    start_response("200 OK", [('Content-Type','text/plain')]) 
    return [stdout.getvalue()] 

s = make_server('localhost', 8080, app_200_hello) 

class TestFunc(unittest.TestCase): 
    def setUp(self): 
     s.handle_request() 

    def test1(self): 
     r = func() 
     assert r, something 

if __name__ == '__main__': 
    unittest.main() 

이() 내 테스트를 중지 :

나는 이런 일을했다. 나는 그걸 어떻게 피할 수 있니? 다른 스레드에서 s.handle_request()를 실행 하시겠습니까? 다른 솔루션이 있습니까?

편집 : 나는 당신이 WSGI 응용 프로그램을 테스트하는 경우 없습니다 "app_200_hello"

답변

7

, 나는 강하게 서버없이 응용 프로그램 자체를 테스트하여 이러한 문제를 해결 도착 werkzeug.test을 추천 할 수 있습니다 "FUNC"기능을 테스트 할 :

from werkzeug.test import Client 

# then in your test case 
def test1(self): 
    client = Client(app_200_hello) 
    appiter, status, headers = client.open() 
    assert ''.join(appiter) == 'Hello World' 
    assert status == '200 OK' 

이 접근 방식은 WSGI 서버에 대한 필요성을 완전히 제거합니다.

물론 서버를 시작하려면 별도의 스레드 나 프로세스를 사용해야하지만 이후에는 프로세스를 중지해야합니다. 그러나 실제 서버로 테스트하고 싶은 유일한 시간은 프로덕션 통합 테스트를위한 것이며,이 경우 서버가 wsgiref가 아니며 시작할 필요가없는 실제 서버가됩니다 이런 식으로.

+0

감사합니다. 그것은 내가 원하는 것처럼 보입니다. 그러나 werkzeug가 너무 큽니다. 클라이언트 클래스는 http://dev.pocoo.org/projects/werkzeug/browser/werkzeug/test.py#L551 werkzeug 패키지의 다른 부분과 독립적입니까? –

+0

아니요 독립적이지는 않지만 개발에만 큰 의존성이 없습니다. 사실 그것은 아주 작습니다. –

+0

오. 나는 얽힌. app_200_hello을 테스트하고 싶지 않습니다. 나는 "func"를 테스트하고 싶다 –

3

서버는 별도의 프로세스 여야합니다.

당신은 파이썬 2.6을 사용하는 경우, 당신은 다음의 tearDown 동안 서브 프로세스를 죽일 수 subprocess.Popen()

와 함께 시작하는 것이 좋습니다

.

def setUp(self): 
    self.server= subprocess.Popen("python","myserver","etc.") 
def tearDown(self): 
    self.server.kill() 

파이썬 2.6을 사용하고 있지 않다면 서버를 죽이는 것이 좋지 않을 수 있습니다.

+0

나는 그것이 좋은 생각이라고 생각하지 않는다. 나에 관해서는 각 테스트 후에 시스템이 파이썬을 시작/정지하는 것이 매우 어려울 것이다. 그리고 나는 복잡한 wsgi 응용 프로그램에 대한 테스트를 작성하고 싶지 않습니다. 많은 상황에서 많은 간단한 wsgi 응용 프로그램을 작성하고 싶습니다. –

+0

tearDown은 WSGI 서버를 중지하므로 Python은 정상적으로 종료됩니다. 시스템이 파이썬을 멈추게하는 것은 매우 쉽다. –

+0

wsgiref.simple_server는 유용한 별도의 프로세스로 시작되어야합니다. –

0

내 솔루션 :

 

URL = 'http://localhost:8085' 
def func(): 
    response = urlopen(URL) 
    return response.read() 

import unittest 
from wsgiref.simple_server import WSGIServer, WSGIRequestHandler 
import threading 
from urllib2 import urlopen 
from cStringIO import StringIO 

def app_200_hello(environ,start_response): 
    stdout = StringIO('Hello world') 
    start_response("200 OK", [('Content-Type','text/plain')]) 
    return [stdout.getvalue()] 

server = WSGIServer(('localhost', 8085), WSGIRequestHandler) 
server.set_app(app_200_hello) 

t = threading.Thread(target=server.serve_forever) 
t.start() 

class TestFunc(unittest.TestCase): 
    def setUp(self): 
     pass 

    def test1(self): 
     r = func() 
     self.assertEqual(r, 'Hello world') 

    def __del__(self): 
     server.shutdown() 

if __name__ == '__main__': 
    unittest.main() 

 

나는 TestFunc 소멸자에서 다른 thread 종료를에서 "서버"를 시작합니다.

+0

당신은 그렇지 않습니까? 각 테스트 후에 서버 상태가 나빠지는 것에 대해 걱정하고 테스트에 영향을 미치는가? 어떻게하면 쿠키를 테스트 할 수 있습니까? 이 작업을 수행해야하는 경우 프로세스를 사용하고 요청별로 처리하는 것이 좋습니다. –

2

실제로 서버를 실행하지 않는 urlopen 모의 버전을 제공 할 수도 있습니다.

당신이 뭔가를 할 거라고 테스트 코드에서, 원래의 코드가 mycode.py이었다 가정 :



import mycode 

class TestFunc(unittest.TestCase): 
    def setUp(self): 
     # patch mycode, to use mock version of urlopen 
     self._original_urlopen = mycode.urlopen 
     mycode.urlopen=self.mock_urlopen 

    def tearDown(self): 
     # unpatch urlopen 
     mycode.urlopen=self._original_urlopen 

    def mock_urlopen(self,url): 
     # return whatever data you need urlopen to return 

    def test1(self): 
     r = func() 
     assert r, something 

if __name__ == '__main__': 
    unittest.main() 


이가 "원숭이 패치"에 따라 약간의 찌푸린 얼굴로하지만 할 수있는 코드를 테스트 알려져있다 원래 코드를 변경하여 테스트 할 수있게 만들 필요가 없으므로보다 쉽게 ​​작업 할 수 있습니다.

다음
self.port = 8000 
server = make_server('', self.port, make_my_wsgi_ap()) 
self.server_process = multiprocessing.Process(target=server.serve_forever) 
self.server_process.start() 

의 tearDown에서 할 :

4

를 사용하여 멀티는

설정에서

같은 것을 할 별도의 프로세스에서 서버를 시작합니다

self.server_process.terminate() 
self.server_process.join() 
del(self.server_process) 

나는 것으로 나타났습니다 당신 경우 명시 적으로 del()을 두지 않으면 후속 서버 인스턴스가 이미 사용중인 포트에 문제가있을 수 있습니다.

+0

이것이 IMO를 수행하는 가장 좋은 방법입니다. – vangheem