From e2e73cbf5dd2eb565da3ea45a8aa6d061bca0a1d Mon Sep 17 00:00:00 2001 From: Jan Vlcinsky Date: Thu, 26 Apr 2018 22:47:11 +0200 Subject: [PATCH] tests/test_transactions.py refactored --- tests/conftest.py | 47 ++++++++++++++++++++++++++ tests/test_transactions.py | 67 +++++++++++++++++++++++++------------- tox.ini | 4 +-- 3 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..37128f2 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,47 @@ +"""Shared pytest fixtures. + +""" +import pytest + +import records + + +@pytest.fixture(params=[ + # request: (sql_url_id, sql_url_template) + + ('sqlite_memory', 'sqlite:///:memory:'), + ('sqlite_file', 'sqlite:///{dbfile}'), + # ('psql', 'postgresql://records:records@localhost/records') +], + ids=lambda r: r[0]) +def db(request, tmpdir): + """Instance of `records.Database(dburl)` + + Ensure, it gets closed after being used in a test or fixture. + + Parametrized with (sql_url_id, sql_url_template) tuple. + If `sql_url_template` contains `{dbfile}` it is replaced with path to a + temporary file. + + Feel free to parametrize for other databases and experiment with them. + """ + id, url = request.param + # replace {dbfile} in url with temporary db file path + url = url.format(dbfile=str(tmpdir / "db.sqlite")) + db = records.Database(url) + yield db # providing fixture value for a test case + # tear_down + db.close() + + +@pytest.fixture +def foo_table(db): + """Database with table `foo` created + + tear_down drops the table. + + Typically applied by `@pytest.mark.usefixtures('foo_table')` + """ + db.query('CREATE TABLE foo (a integer)') + yield + db.query('DROP TABLE foo') diff --git a/tests/test_transactions.py b/tests/test_transactions.py index f2d5e92..c9255b3 100644 --- a/tests/test_transactions.py +++ b/tests/test_transactions.py @@ -1,19 +1,43 @@ +"""Test manipulating database table in various transaction scenarios. + +Varying conditions: + +- db for different database backends (see `db` fixture) +- query run via + + - `db=records.Database(); db.query() + - `conn=db.get_connection(); conn.query()` + +- transaction + - not used at all + - used and created in different ways + - transaction succeeds + - transaction fails or raise +""" import pytest -import records -db = records.Database('sqlite:///:memory:') +@pytest.mark.usefixtures('foo_table') +def test_plain_db(db): + """Manipulate database by `db.query` without transactions. + """ + db.query('INSERT INTO foo VALUES (42)') + db.query('INSERT INTO foo VALUES (43)') + assert db.query('SELECT count(*) AS n FROM foo')[0].n == 2 -@pytest.fixture -def table_setup(request): - db.query('CREATE TABLE foo (a integer)') - def drop_table(): - db.query('DROP TABLE foo') - request.addfinalizer(drop_table) +@pytest.mark.usefixtures('foo_table') +def test_plain_conn(db): + """Manipulate database by `conn.query` without transactions. + """ + conn = db.get_connection() + conn.query('INSERT INTO foo VALUES (42)') + conn.query('INSERT INTO foo VALUES (43)') + assert conn.query('SELECT count(*) AS n FROM foo')[0].n == 2 -def test_failing_transaction_self_managed(table_setup): +@pytest.mark.usefixtures('foo_table') +def test_failing_transaction_self_managed(db): conn = db.get_connection() tx = conn.transaction() try: @@ -22,14 +46,15 @@ def test_failing_transaction_self_managed(table_setup): raise ValueError() tx.commit() conn.query('INSERT INTO foo VALUES (44)') - except: + except ValueError: tx.rollback() finally: conn.close() assert db.query('SELECT count(*) AS n FROM foo')[0].n == 0 -def test_failing_transaction(table_setup): +@pytest.mark.usefixtures('foo_table') +def test_failing_transaction(db): with db.transaction() as conn: conn.query('INSERT INTO foo VALUES (42)') conn.query('INSERT INTO foo VALUES (43)') @@ -38,21 +63,19 @@ def test_failing_transaction(table_setup): assert db.query('SELECT count(*) AS n FROM foo')[0].n == 0 -def test_passing_transaction_self_managed(table_setup): +@pytest.mark.usefixtures('foo_table') +def test_passing_transaction_self_managed(db): conn = db.get_connection() tx = conn.transaction() - try: - conn.query('INSERT INTO foo VALUES (42)') - conn.query('INSERT INTO foo VALUES (43)') - tx.commit() - except: - tx.rollback() - finally: - conn.close() - assert db.query('SELECT count(*) AS n FROM foo')[0].n == 2 + conn.query('INSERT INTO foo VALUES (42)') + conn.query('INSERT INTO foo VALUES (43)') + tx.commit() + conn.close() + assert db.query('SELECT count(*) AS n FROM foo')[0].n == 2 -def test_passing_transaction(table_setup): +@pytest.mark.usefixtures('foo_table') +def test_passing_transaction(db): with db.transaction() as conn: conn.query('INSERT INTO foo VALUES (42)') conn.query('INSERT INTO foo VALUES (43)') diff --git a/tox.ini b/tox.ini index df57c06..4e93a8b 100644 --- a/tox.ini +++ b/tox.ini @@ -3,11 +3,11 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py33, py34, py35, py36 +envlist = py27, py34, py35, py36 [testenv] commands = pytest tests deps = pytest - + # psycopg2-binary