2013-05-13 45 views
12

Tôi đang thử nghiệm một ứng dụng Flask (Flask 0.9), và đặc biệt tôi có một phiên đấu giá mà tôi muốn chạy theo cách được ghi thành tài liệu, giống như thế này (như tôi hiểu nó):Đơn vị kiểm tra phiên Flask - không thể tạo lại lỗi với session_transaction

from flask import Flask, session 
app = Flask(__name__) 

@app.route('/', methods=['POST']) 
def m(): 
    logging.error(session) # expect {'x': 1} 
    return "" 

with app.test_request_context() as trc: 
    with app.test_client() as c: 
    with c.session_transaction() as sess: 
     sess['x'] = 1 
    c.post() 

này hoạt động như mong đợi, với sản lượng là một cái gì đó như thế này:

ERROR:root:<SecureCookieSession {'x': 1}> 

Đáng tiếc là tôi đang gặp phải một kết quả bất ngờ nơi dữ liệu phiên không được thiết lập trong các thiết bị đầu cuối chức năng, tức là đầu ra là một cái gì đó như thế này:

ERROR:root:<SecureCookieSession {}> 

Sự cố này chỉ hiển thị khi chạy từ khung kiểm tra đơn vị của tôi. Khi nó đứng, tôi không thể tái tạo vấn đề này với một trường hợp thoái hóa, mặc dù tôi đã thực hiện một nỗ lực khá đáng kể with a gist of some of this effort here. Các điểm nổi bật là tôi đã bao gồm itsdangerousGoogle App Engine testbed, hy vọng có thể một trong số đó là nguyên nhân.

Trên hệ thống của riêng tôi, tôi đã đi xa hơn gist và gần như hoàn toàn nhân rộng khung thử nghiệm đơn vị của tôi đang cố gắng cách ly này. Tương tự như vậy, tôi đã xóa số lượng ngày càng tăng của mã có liên quan khỏi khuôn khổ thử nghiệm của mình. Đến mức này, tôi không thể nghĩ ra sự khác biệt giữa trường hợp thoái hóa và khuôn khổ bị loại bỏ của tôi có thể ảnh hưởng đến kết quả. Tôi đã vượt qua cuộc gọi c.post() trong pdb để thử eek ra nguyên nhân của sự ác tính này, nhưng vẫn chưa thu thập bất kỳ thông tin chi tiết hữu ích nào.

Tất cả điều để nói, tôi sẽ biết ơn về một hướng hoặc gợi ý nhỏ về vấn đề có thể xảy ra. Điều gì có thể ảnh hưởng đến bối cảnh Werkzeug theo cách mà session_transaction không được tôn trọng?

+0

Tôi biết đã một năm rồi, nhưng bản thân tôi cũng gặp phải vấn đề này. Bạn đã bao giờ có thể hình dung ra điều này? Theo những gì tôi đã đọc trực tuyến và trong tài liệu, điều này sẽ hoạt động hoàn hảo. Nhưng nó không. –

+0

@IanHunter Hãy xem câu trả lời của tôi, bên dưới. Nó sẽ giúp. –

Trả lời

0

Đây là những gì tôi đã kết thúc thực hiện:

# Code that modifies the current `session`; we must be in a test context already. 
headers = {} 
with self.client.session_transaction(): 
    # Get the cookie that is sent to the browser to establish a connection 
    # via a fake request. 
    response = make_response() 
    self.app.session_interface.save_session(self.app, session, response) 
    headers['Cookie'] = response.headers.get('Set-Cookie', '') 
self.client.post(..., headers=headers) # also works for .get, .put, etc. 
0

Nếu không có một testcase thực sự thất bại, thật khó để nói nhiều điều. Tất cả những gì tôi có thể nghĩ là trường hợp TestClient bạn đang sử dụng để tạo yêu cầu khác với yêu cầu bạn sử dụng để thiết lập phiên. Ví dụ. bạn có thể làm cho ý chính thất bại như mong đợi với điều này:

with self.app.test_client() as c: 
    with c.session_transaction() as sess: 
     sess['d'] = 1 
    self.client.post() 

Nhưng vì đây không phải là trường hợp ở đây hoặc ý chính, hãy xem.

+0

Cảm ơn. Tôi đang gặp một chút rắc rối khi hiểu những gì bạn đang cố gắng thêm vào đây, Tommi. Nếu bạn nhận thấy rằng vấn đề là khó khăn, tôi chắc chắn đồng ý –– vì thế tiền thưởng! ;) –

+1

Như tôi đã thấy, lý do chính là khó vì mã bạn đăng * không thành công * như được mô tả. Vì vậy, cho mã làm việc tất cả những gì tôi có thể làm là làm cho một dự đoán được giáo dục về cách làm cho nó thất bại như bạn đã mô tả, và mẫu tôi đăng có vẻ tốt như mọi cách. Chỉ cần không làm điều đó trong mã thực sự và bạn nên gần gũi hơn để có được một cái gì đó làm việc. –

3

Trong trường hợp của tôi, tôi đã tự động hạn chế cookie cho một miền cụ thể bằng cách tải tệp cấu hình. Bằng cách cập nhật cấu hình khi đang di chuyển, tôi có thể lấy cookie để làm việc trong khi kiểm tra đơn vị. Đặt thuộc tính SESSION_COOKIE_DOMAIN thành None, tất cả các miền (cụ thể là localhost) đều có thể đặt phiên.

app.config.update(              
    SESSION_COOKIE_DOMAIN = None             
) 

Bạn có thể muốn tìm hiểu các cài đặt cấu hình được mô tả trong Configuration Handling trong tài liệu.

1

Tôi ghét để hồi sinh một câu hỏi cũ, nhưng tôi tin rằng tôi đã tìm ra giải pháp cho vấn đề này. Để thử nghiệm, hãy thử cài đặt tên máy chủ của bạn để localhost:

app.config['SERVER_NAME'] = 'localhost' 

tôi ban đầu được sử dụng Hack Brian, nhưng điều này đã giải quyết được vấn đề đối với tôi.