2013-07-22 16 views
14

Tôi có một ứng dụng web hoạt động trên Flask với SqlAlchemy để kiểm duyệt tin tức, nó có một số phương pháp api để xử lý yêu cầu kiểm duyệt, chẳng hạn như phê duyệt, từ chối tin tức hiện đang được chọn, danh sách chúng, vv. kiểm thử đơn vị cho các phương thức này và tôi đã làm cho chúng hoạt động, nhưng tôi không hiểu, cách triển khai thực hiện tất cả các yêu cầu mà tôi làm từ các trường hợp thử nghiệm trong một phiên db, để tôi có thể xóa tất cả các thay đổi đối với cơ sở dữ liệu. Hoặc là có cách nào khác sạch hơn hoặc thích hợp để làm điều này? Tôi đã phát hiện ra rằng có lẽ tất cả những gì tôi cần là "scoped_session" trong SqlAlchemy, nhưng tất cả các ý tưởng của tôi để thực hiện nó đã thất bại. Nếu đó là cách chính xác, xin vui lòng, cho tôi biết nơi để sử dụng dòng mã này (trong cài đặt, hoặc trong phương pháp set_up trường hợp thử nghiệm).test flask sql alchemy

from sqlalchemy.orm import scoped_session 
from sqlalchemy.orm import sessionmaker 
session_factory = sessionmaker() 
Session = scoped_session(session_factory) 
+0

bạn đang sử dụng sqlalchemy trực tiếp hoặc mở rộng bình phương sqlalchemy? – codegeek

+0

sqlalchemy trực tiếp –

Trả lời

12

Tôi đề nghị bạn sử dụng phần mở rộng Flask-Testing. Đây là một tiện ích mở rộng được chấp thuận cho phép bạn thực hiện kiểm tra đơn vị theo ý muốn. Nó cũng có một phần cụ thể cho SQLAlchemy.

Testing với SQLAlchemy

này đề cập đến một vài điểm nếu bạn đang sử dụng Flask-Testing với SQLAlchemy. Giả sử rằng bạn đang sử dụng phần mở rộng Flask-SQLAlchemy, nhưng nếu không phải là các ví dụ không quá khó để thích ứng với thiết lập cụ thể của riêng bạn.

Đầu tiên, đảm bảo bạn đặt URI cơ sở dữ liệu thành một thứ khác với cơ sở dữ liệu sản xuất của bạn! Thứ hai, bạn nên tạo và thả các bảng của mình với mỗi lần chạy thử, để đảm bảo các thử nghiệm rõ ràng: "

from flask.ext.testing import TestCase 

from myapp import create_app, db 

class MyTest(TestCase): 

    SQLALCHEMY_DATABASE_URI = "sqlite://" 
    TESTING = True 

    def create_app(self): 

     # pass in test configuration 
     return create_app(self) 

    def setUp(self): 

     db.create_all() 

    def tearDown(self): 

     db.session.remove() 
     db.drop_all() 
+10

Tôi phải thiếu một cái gì đó cho upvotes về câu hỏi này, nhưng không phải là việc thực hiện 'create_app' khá quan trọng ở đây? Tài liệu được liên kết không giải thích 'myapp.create_app' được cho là phải làm gì (ví dụ, liên quan đến db). – ForeverWintr

+0

create_app Tôi cho rằng chỉ cần trả lại ứng dụng như trong app.py của bạn - ví dụ: app = Flask (__ name__). Bởi vì tôi không muốn một cấu hình khác để thử nghiệm và cho sản xuất, tôi chỉ cần nhập ứng dụng từ không gian tên chính của tôi và sau đó trả về nó trong create_app, và nó hoạt động tốt. –

9

Đây là cách tôi đã chạy thử nghiệm đơn vị gần đây. Tôi giả sử vì bạn đang sử dụng SQLAlchemy mà bạn đang sử dụng các lớp mô hình. tôi cũng giả định rằng tất cả các bảng của bạn được định nghĩa là lớp mô hình SQLAlchemy.

from flask import Flask 
import unittest 

from app import db 
from app.models import Log 
from constants import test_logs 

class appDBTests(unittest.TestCase): 

    def setUp(self): 
     """ 
     Creates a new database for the unit test to use 
     """ 
     self.app = Flask(__name__) 
     db.init_app(self.app) 
     with self.app.app_context(): 
      db.create_all() 
      self.populate_db() # Your function that adds test data. 

    def tearDown(self): 
     """ 
     Ensures that the database is emptied for next unit test 
     """ 
     self.app = Flask(__name__) 
     db.init_app(self.app) 
     with self.app.app_context(): 
      db.drop_all() 

vì bạn đang sử dụng cùng một DB thiết lập như ứng dụng của bạn này cho phép bạn xây dựng và phá hủy cơ sở dữ liệu thử nghiệm với mọi thử nghiệm đơn vị bạn chạy.

+1

'LimboDBTests' ở đây là gì? – avichalp

+0

Tên dự án là Limbo và tôi có vẻ xấu khi phát hiện tên cũ. – AlexLordThorsen

+2

Tại sao 'self.app = Flask (__ name __)' trong tearDown() một lần nữa? Tôi không nghĩ rằng bạn cần phải làm điều đó một lần nữa sau khi thiết lập nó trong setUp(). – Houman

4

Về câu trả lời của codegeek bằng cách sử dụng Flask-Testing, tôi gặp khó khăn khi hiểu những gì createapp() thực hiện. Flask-SqlAlchemy Introduction into Contexts cung cấp cho tôi một số con trỏ về cách liên kết đối tượng SQLAlchemy động với ứng dụng của bạn. Trong trường hợp này, ràng buộc với ứng dụng thử nghiệm.

Về cơ bản:

  1. Tạo một đối tượng bình SQLAlchemy nhưng không vượt qua trong đối tượng ứng dụng
  2. Trong chức năng create_app, tạo ra ứng dụng thử nghiệm của bạn, và tự động ràng buộc SQLAlchemy.

bạn myapp.py:

# don't pass in the app object yet 
db = SQLAlchemy() 

def create_test_app(): 
    app = Flask(__name__) 
    app.config['TESTING'] = True 
    app.config["SQLALCHEMY_DATABASE_URI"] = "xxxxxxtestdatabasexxx" 
    # Dynamically bind SQLAlchemy to application 
    db.init_app(app) 
    app.app_context().push() # this does the binding 
    return app 

# you can create another app context here, say for production 
def create_production_app(): 
    app = Flask(__name__) 
    app.config["SQLALCHEMY_DATABASE_URI"] = "xxxxxxproductionxxxx" 
    # Dynamically bind SQLAlchemy to application 
    db.init_app(app) 
    app.app_context().push() 
    return app 

Sau đó bạn có thể làm theo giải pháp codegeek của như được nêu trong Tài liệu Flask-Test

from flask.ext.testing import TestCase 
from myapp import create_app, db 

class MyTest(TestCase): 

    # I removed some config passing here 
    def create_app(self): 
     return create_test_app() 

    def setUp(self): 

     db.create_all() 

    def tearDown(self): 

     db.session.remove() 
     db.drop_all() 

Những điều tốt đẹp về giải pháp này là bạn có thể tạo các ứng dụng khác nhau và tự động ràng buộc đối tượng SQLAlchemy bằng cách sử dụng một hàm. Mỗi ứng dụng có thể phục vụ các mục đích khác nhau. Ví dụ, một cho sản xuất và một cho thử nghiệm đơn vị.Trong trường hợp sản xuất, bạn có thể gọi hàm create_production_application() trong ứng dụng bình cấp cao nhất của bạn.