2013-01-10 29 views
10

Gần đây tôi đã phải viết lại api còn lại của mình và chuyển đổi từ Flask sang Cherrypy (chủ yếu là do khả năng tương thích Python 3). Nhưng bây giờ tôi đang cố gắng để viết các bài kiểm tra đơn vị của mình, Flask có một ứng dụng thử nghiệm tích hợp thực sự tiện lợi, bạn có thể sử dụng để gửi các yêu cầu giả mạo tới ứng dụng của mình (mà không cần khởi động máy chủ). cho Cherrypy, là có chức năng như vậy, hoặc tôi bị mắc kẹt bắt đầu từ một máy chủ và thực hiện các yêu cầu thực tế chống lại nó?Unittesting cherrypy webapp

Trả lời

18

Theo như tôi biết, CherryPy không thực sự cung cấp một cơ sở cho loại thử nghiệm này (không có máy chủ đang chạy). Nhưng nó khá dễ dàng để làm điều đó dù sao (mặc dù nó dựa trên một số bên trong của CherryPy).

Dưới đây là một giới thiệu đơn giản:

from StringIO import StringIO 
import unittest 
import urllib 

import cherrypy 

local = cherrypy.lib.httputil.Host('127.0.0.1', 50000, "") 
remote = cherrypy.lib.httputil.Host('127.0.0.1', 50001, "") 

class Root(object): 
    @cherrypy.expose 
    def index(self): 
     return "hello world" 

    @cherrypy.expose 
    def echo(self, msg): 
     return msg 

def setUpModule(): 
    cherrypy.config.update({'environment': "test_suite"}) 

    # prevent the HTTP server from ever starting 
    cherrypy.server.unsubscribe() 

    cherrypy.tree.mount(Root(), '/') 
    cherrypy.engine.start() 
setup_module = setUpModule 

def tearDownModule(): 
    cherrypy.engine.exit() 
teardown_module = tearDownModule 

class BaseCherryPyTestCase(unittest.TestCase): 
    def webapp_request(self, path='/', method='GET', **kwargs): 
     headers = [('Host', '127.0.0.1')] 
     qs = fd = None 

     if method in ['POST', 'PUT']: 
      qs = urllib.urlencode(kwargs) 
      headers.append(('content-type', 'application/x-www-form-urlencoded')) 
      headers.append(('content-length', '%d' % len(qs))) 
      fd = StringIO(qs) 
      qs = None 
     elif kwargs: 
      qs = urllib.urlencode(kwargs) 

     # Get our application and run the request against it 
     app = cherrypy.tree.apps[''] 
     # Let's fake the local and remote addresses 
     # Let's also use a non-secure scheme: 'http' 
     request, response = app.get_serving(local, remote, 'http', 'HTTP/1.1') 
     try: 
      response = request.run(method, path, qs, 'HTTP/1.1', headers, fd) 
     finally: 
      if fd: 
       fd.close() 
       fd = None 

     if response.output_status.startswith('500'): 
      print response.body 
      raise AssertionError("Unexpected error") 

     # collapse the response into a bytestring 
     response.collapse_body() 
     return response 

class TestCherryPyApp(BaseCherryPyTestCase): 
    def test_index(self): 
     response = self.webapp_request('/') 
     self.assertEqual(response.output_status, '200 OK') 
     # response body is wrapped into a list internally by CherryPy 
     self.assertEqual(response.body, ['hello world']) 

    def test_echo(self): 
     response = self.webapp_request('/echo', msg="hey there") 
     self.assertEqual(response.output_status, '200 OK') 
     self.assertEqual(response.body, ["hey there"]) 

     response = self.webapp_request('/echo', method='POST', msg="hey there") 
     self.assertEqual(response.output_status, '200 OK') 
     self.assertEqual(response.body, ["hey there"]) 

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

Chỉnh sửa, tôi đã mở rộng câu trả lời này như một CherryPy recipe.

+0

Cảm ơn, sẽ cung cấp cho một thử này ngày hôm nay. – Blubber

+0

Làm việc như một nét duyên dáng, cảm ơn lần nữa :). – Blubber

+0

@Sylvain: có cần gì đặc biệt cho '@ cherrypy.tools.json_in()' hỗ trợ không? 'cherrypy.request.json' trong testcases khiến đối tượng' AttributeError: 'Request' không có thuộc tính 'json'' – user1338062

2

Dường như có một cách thay thế để thực hiện unittest. Tôi chỉ tìm thấy và kiểm tra các công thức sau đây hoạt động tốt với cherrypy 3.5.

http://docs.cherrypy.org/en/latest/advanced.html#testing-your-application

import cherrypy 

    from cherrypy.test import helper 

    class SimpleCPTest(helper.CPWebCase): 
     def setup_server(): 
      class Root(object): 
       @cherrypy.expose 
       def echo(self, message): 
        return message 

      cherrypy.tree.mount(Root()) 
     setup_server = staticmethod(setup_server) 

     def test_message_should_be_returned_as_is(self): 
      self.getPage("/echo?message=Hello%20world") 
      self.assertStatus('200 OK') 
      self.assertHeader('Content-Type', 'text/html;charset=utf-8') 
      self.assertBody('Hello world') 

     def test_non_utf8_message_will_fail(self): 
      """ 
      CherryPy defaults to decode the query-string 
      using UTF-8, trying to send a query-string with 
      a different encoding will raise a 404 since 
      it considers it's a different URL. 
      """ 
      self.getPage("/echo?message=A+bient%F4t", 
         headers=[ 
          ('Accept-Charset', 'ISO-8859-1,utf-8'), 
          ('Content-Type', 'text/html;charset=ISO-8859-1') 
         ] 
      ) 
      self.assertStatus('404 Not Found') 
+0

Điều này chắc chắn là cách kiểm tra CherryPy được viết nội bộ. Nhưng điều đó có nghĩa là bắt đầu một máy chủ thực tế. Đó là tự động nhưng công thức của tôi đã cố gắng để cho thấy bạn có thể kiểm tra trình xử lý của bạn mà không cần một máy chủ đang chạy. Câu trả lời của bạn không chính xác hơn một chút về khía cạnh tích hợp mà tôi muốn nói. –