Writting py test for sqlalchemy app

假如想象 提交于 2020-01-23 01:00:08

问题


I am trying convert unit test into py test. I am using the unit test example

class TestCase(unittest.TestCase):
    def setUp(self):
        app.config['TESTING'] = True
        app.config['CSRF_ENABLED'] = False
        app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 
        'test.db')
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()

I am not sure, What should be its py test version.


回答1:


I searched high and low for a well explained solution to use SqlAlchemy without Flask-SQLAlchemy and run tests with Pytest, so here's how i have achieved this:

  1. Set up your engine & Session objects as per the docs. (I have opted for sessionmaker as i want to check in my app if the session is still available in the Flask's request thread pool, see: https://dev.to/nestedsoftware/flask-and-sqlalchemy-without-the-flask-sqlalchemy-extension-3cf8

  2. Import your Base object from wherever you've created it in your app. This will create all the tables in your database defined by the engine.

  3. Now we want to Yield a Session back to your unit tests. The idea is to setup before calling Yield & teardown after. Now, in your test you can create a table and populate it with some rows of data etc.

  4. Now we must close the Session, this is important!

  5. Now by calling Base.metadata.drop_all(bind=engine) we drop all the tables in the database ( we can define a table(s) to drop if required, default is: tables=None)

    engine = create_engine(create_db_connection_str(config), echo=True)
    Session = scoped_session(sessionmaker(bind=engine))
    
    @pytest.fixture(scope="function")
    def db_session():
        Base.metadata.create_all(engine)
        yield Session()
        Session.close_all()
        Base.metadata.drop_all(bind=engine)
    
  6. Now we can pass the function scoped fixture to each unit test:

    class TestNotebookManager:
        """
            Using book1.mon for this test suite
        """
        book_name = "book1"
    
        def test_load(self, client: FlaskClient, db_session) -> None:
            notebook = Notebook(name=self.book_name)
            db_session.add(book)
            db_session.commit()
            rv = client.get(f"/api/v1/manager/load?name={self.name}")
            assert "200" in rv.status
    



回答2:


First off, py.test should just run the existing unittest test case. However the native thing to do in py.test is use a fixture for the setup and teardown:

import pytest

@pytest.fixture
def some_db(request):
    app.config['TESTING'] = True
    app.config['CSRF_ENABLED'] = False
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'test.db')
    db.create_all()
    def fin():
        db.session.remove()
        db.drop_all()
    request.addfinalizer(fin)

def test_foo(some_db):
    pass

Note that I have no idea about SQLAlchemy and whether there are better ways of handling it's setup and teardown. All this example demonstrates is how to turn the setup/teardown methods into a fixture.



来源:https://stackoverflow.com/questions/23325669/writting-py-test-for-sqlalchemy-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!