diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2022-06-28 14:04:27 +0200 | 
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2022-06-28 14:04:27 +0200 | 
| commit | 77ac79f1b29e8b07c74852e3c5be83abf6424c7a (patch) | |
| tree | e5653ce152d39c066423d3dec9992c4e225a243f /tests | |
| download | fietsboek-77ac79f1b29e8b07c74852e3c5be83abf6424c7a.tar.gz fietsboek-77ac79f1b29e8b07c74852e3c5be83abf6424c7a.tar.bz2 fietsboek-77ac79f1b29e8b07c74852e3c5be83abf6424c7a.zip  | |
Initial commit
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/__init__.py | 0 | ||||
| -rw-r--r-- | tests/conftest.py | 132 | ||||
| -rw-r--r-- | tests/test_functional.py | 13 | ||||
| -rw-r--r-- | tests/test_views.py | 23 | 
4 files changed, 168 insertions, 0 deletions
diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/__init__.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..5251b35 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,132 @@ +import alembic +import alembic.config +import alembic.command +import os +from pyramid.paster import get_appsettings +from pyramid.scripting import prepare +from pyramid.testing import DummyRequest, testConfig +import pytest +import transaction +import webtest + +from fietsboek import main +from fietsboek import models +from fietsboek.models.meta import Base + + +def pytest_addoption(parser): +    parser.addoption('--ini', action='store', metavar='INI_FILE') + +@pytest.fixture(scope='session') +def ini_file(request): +    # potentially grab this path from a pytest option +    return os.path.abspath(request.config.option.ini or 'testing.ini') + +@pytest.fixture(scope='session') +def app_settings(ini_file): +    return get_appsettings(ini_file) + +@pytest.fixture(scope='session') +def dbengine(app_settings, ini_file): +    engine = models.get_engine(app_settings) + +    alembic_cfg = alembic.config.Config(ini_file) +    Base.metadata.drop_all(bind=engine) +    alembic.command.stamp(alembic_cfg, None, purge=True) + +    # run migrations to initialize the database +    # depending on how we want to initialize the database from scratch +    # we could alternatively call: +    # Base.metadata.create_all(bind=engine) +    # alembic.command.stamp(alembic_cfg, "head") +    alembic.command.upgrade(alembic_cfg, "head") + +    yield engine + +    Base.metadata.drop_all(bind=engine) +    alembic.command.stamp(alembic_cfg, None, purge=True) + +@pytest.fixture(scope='session') +def app(app_settings, dbengine): +    return main({}, dbengine=dbengine, **app_settings) + +@pytest.fixture +def tm(): +    tm = transaction.TransactionManager(explicit=True) +    tm.begin() +    tm.doom() + +    yield tm + +    tm.abort() + +@pytest.fixture +def dbsession(app, tm): +    session_factory = app.registry['dbsession_factory'] +    return models.get_tm_session(session_factory, tm) + +@pytest.fixture +def testapp(app, tm, dbsession): +    # override request.dbsession and request.tm with our own +    # externally-controlled values that are shared across requests but aborted +    # at the end +    testapp = webtest.TestApp(app, extra_environ={ +        'HTTP_HOST': 'example.com', +        'tm.active': True, +        'tm.manager': tm, +        'app.dbsession': dbsession, +    }) + +    return testapp + +@pytest.fixture +def app_request(app, tm, dbsession): +    """ +    A real request. + +    This request is almost identical to a real request but it has some +    drawbacks in tests as it's harder to mock data and is heavier. + +    """ +    with prepare(registry=app.registry) as env: +        request = env['request'] +        request.host = 'example.com' + +        # without this, request.dbsession will be joined to the same transaction +        # manager but it will be using a different sqlalchemy.orm.Session using +        # a separate database transaction +        request.dbsession = dbsession +        request.tm = tm + +        yield request + +@pytest.fixture +def dummy_request(tm, dbsession): +    """ +    A lightweight dummy request. + +    This request is ultra-lightweight and should be used only when the request +    itself is not a large focus in the call-stack.  It is much easier to mock +    and control side-effects using this object, however: + +    - It does not have request extensions applied. +    - Threadlocals are not properly pushed. + +    """ +    request = DummyRequest() +    request.host = 'example.com' +    request.dbsession = dbsession +    request.tm = tm + +    return request + +@pytest.fixture +def dummy_config(dummy_request): +    """ +    A dummy :class:`pyramid.config.Configurator` object.  This allows for +    mock configuration, including configuration for ``dummy_request``, as well +    as pushing the appropriate threadlocals. + +    """ +    with testConfig(request=dummy_request) as config: +        yield config diff --git a/tests/test_functional.py b/tests/test_functional.py new file mode 100644 index 0000000..6102063 --- /dev/null +++ b/tests/test_functional.py @@ -0,0 +1,13 @@ +from fietsboek import models + +def test_my_view_success(testapp, dbsession): +    model = models.MyModel(name='one', value=55) +    dbsession.add(model) +    dbsession.flush() + +    res = testapp.get('/', status=200) +    assert res.body + +def test_notfound(testapp): +    res = testapp.get('/badurl', status=404) +    assert res.status_code == 404 diff --git a/tests/test_views.py b/tests/test_views.py new file mode 100644 index 0000000..08347b6 --- /dev/null +++ b/tests/test_views.py @@ -0,0 +1,23 @@ +from fietsboek import models +from fietsboek.views.default import my_view +from fietsboek.views.notfound import notfound_view + + +def test_my_view_failure(app_request): +    info = my_view(app_request) +    assert info.status_int == 500 + +def test_my_view_success(app_request, dbsession): +    model = models.MyModel(name='one', value=55) +    dbsession.add(model) +    dbsession.flush() + +    info = my_view(app_request) +    assert app_request.response.status_int == 200 +    assert info['one'].name == 'one' +    assert info['project'] == 'fietsboek' + +def test_notfound_view(app_request): +    info = notfound_view(app_request) +    assert app_request.response.status_int == 404 +    assert info == {}  | 
