From 943b705a9ed3dc1ed3de147a2da808b27895ab89 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Thu, 25 Oct 2018 16:32:50 +0200 Subject: [PATCH 3/3] tests: add real ones with fixtures (fixes #27482) --- tests/conftest.py | 65 ++++++++++- tests/fixtures/schema1/01_schema.sql | 64 +++++++++++ tests/fixtures/schema1/schema.json | 158 +++++++++++++++++++++++++++ tests/test_schema1.py | 29 +++++ tox.ini | 2 + 5 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/schema1/01_schema.sql create mode 100644 tests/fixtures/schema1/schema.json create mode 100644 tests/test_schema1.py diff --git a/tests/conftest.py b/tests/conftest.py index c431b27..48bbb32 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,11 +1,25 @@ +import os +import glob +import json +from contextlib import closing + import pytest import django_webtest + +import sqlparse + +import psycopg2 + + +from django.db import connection from django.contrib.auth.models import User @pytest.fixture -def app(request): +def app(settings, request): + settings.TEMPLATE_DEBUG = True + settings.DEBUG = True wtm = django_webtest.WebTestMixin() wtm._patch_settings() request.addfinalizer(wtm._unpatch_settings) @@ -29,3 +43,52 @@ def admin(db): u.is_staff = True u.save() return u + +SCHEMA_PATHS = os.path.join(os.path.dirname(__file__), 'fixtures/') + + +def load_schema(settings, tmpdir, schema): + import random + + database_name = 'db%s' % random.getrandbits(20) + try: + with closing(psycopg2.connect('')) as conn: + conn.set_isolation_level(0) + with conn.cursor() as cursor: + cursor.execute('CREATE DATABASE %s' % database_name) + + schema_dir = tmpdir.mkdir('schemas') + SCHEMA_DIR = os.path.join(SCHEMA_PATHS, schema) + + # copy schemas and set pg_dsn + for schema_path in glob.glob(os.path.join(SCHEMA_DIR, '*.json')): + with open(schema_path) as f: + schema = json.load(f) + schema['pg_dsn'] = 'dbname=%s' % database_name + new_schema_path = schema_dir.join(os.path.basename(schema_path)) + new_schema_path.write(json.dumps(schema)) + + settings.BIJOE_SCHEMAS = [str(schema_dir.join('*.json'))] + with closing(psycopg2.connect(database=database_name)) as conn: + conn.set_isolation_level(0) + with conn.cursor() as cursor: + for sql_path in sorted(glob.glob(os.path.join(SCHEMA_DIR, '*.sql'))): + with open(sql_path) as sql_file: + sql = sql_file.read() + statements = sqlparse.split(sql) + for statement in statements: + if not statement.strip(';').strip(): + continue + cursor.execute(statement.rstrip(';')) + yield + finally: + with closing(psycopg2.connect('')) as conn: + conn.set_isolation_level(0) + with conn.cursor() as cursor: + cursor.execute('DROP DATABASE IF EXISTS %s' % database_name) + + +@pytest.fixture +def schema1(db, settings, tmpdir): + for _ in load_schema(settings, tmpdir, 'schema1'): + yield _ diff --git a/tests/fixtures/schema1/01_schema.sql b/tests/fixtures/schema1/01_schema.sql new file mode 100644 index 0000000..3a2eacd --- /dev/null +++ b/tests/fixtures/schema1/01_schema.sql @@ -0,0 +1,64 @@ +DROP SCHEMA IF EXISTS schema1 cascade; + +CREATE SCHEMA schema1; + +SET search_path = schema1; + +CREATE TABLE category ( + id serial primary key, + ord integer default(0) not null, + label varchar not null); + +CREATE TABLE subcategory ( + id serial primary key, + category_id integer not null references schema1.category(id), + ord integer default(0) not null, + label varchar not null); + +CREATE TABLE facts ( + id serial primary key, + date date, + datetime timestamp with time zone, + integer integer, + cnt integer default(1), + innersubcategory_id integer references schema1.subcategory(id), + leftsubcategory_id integer references schema1.subcategory(id), + rightsubcategory_id integer references schema1.subcategory(id), + outersubcategory_id integer references schema1.subcategory(id) +); + +INSERT INTO category (ord, label) VALUES + (1, 'caté1'), + (0, 'caté2'), + (0, 'caté3'); + +INSERT INTO subcategory (category_id, ord, label) VALUES + (1, 1, 'subé1'), + (1, 0, 'subé2'), + (1, 0, 'subé3'), + (2, 0, 'subé4'), + (2, 0, 'subé5'), + (2, 0, 'subé6'), + (3, 1, 'subé7'), + (3, 0, 'subé8'), + (3, 0, 'subé9'); + + +INSERT INTO facts (date, datetime, integer, cnt, innersubcategory_id, leftsubcategory_id, rightsubcategory_id, outersubcategory_id) VALUES + ('2017-01-01', '2017-01-01 10:00', 1, 10, 1, 1, 1, 1), + ('2017-01-02', '2017-01-02 10:00', 1, 10, 3, 3, 3, 3), + ('2017-01-03', '2017-01-03 10:00', 1, 10, NULL, NULL, NULL, NULL), + ('2017-01-04', '2017-01-04 10:00', 1, 10, 1, 1, 1, 1), + ('2017-01-05', '2017-01-05 10:00', 1, 10, 1, 1, 1, 1), + ('2017-01-06', '2017-01-06 10:00', 1, 10, 1, 1, 1, 1), + ('2017-01-07', '2017-01-07 10:00', 1, 10, 1, 1, 1, 1), + ('2017-01-08', '2017-01-08 10:00', 1, 10, 1, 1, 1, 1), + ('2017-01-09', '2017-01-09 10:00', 1, 10, 1, 1, 1, 1), + ('2017-01-10', '2017-01-10 10:00', 1, 10, 1, 1, 1, 1), + ('2017-02-01', '2017-02-01 10:00', 1, 10, 1, 1, 1, 1), + ('2017-03-01', '2017-03-01 10:00', 1, 10, 1, 1, 1, 1), + ('2017-04-01', '2017-04-01 10:00', 1, 10, 1, 1, 1, 1), + ('2017-05-01', '2017-05-01 10:00', 1, 10, 1, 1, 1, 1), + ('2017-06-01', '2017-06-01 10:00', 1, 10, 1, 1, 1, 1), + ('2017-07-01', '2017-07-01 10:00', 1, 10, 1, 1, 1, 1), + ('2017-08-01', '2017-08-01 10:00', 1, 10, 1, 1, 1, 1); diff --git a/tests/fixtures/schema1/schema.json b/tests/fixtures/schema1/schema.json new file mode 100644 index 0000000..caaaea7 --- /dev/null +++ b/tests/fixtures/schema1/schema.json @@ -0,0 +1,158 @@ +{ + "name": "schema1", + "label": "test schema1", + "pg_dsn": "fixme", + "search_path": ["schema1"], + "cubes": [ + { + "name": "facts1", + "label": "Facts 1", + "fact_table": "facts", + "key": "id", + "joins": [ + { + "name": "innersubcategory", + "table": "subcategory", + "master": "innersubcategory_id", + "detail": "id", + "kind": "inner" + }, + { + "name": "leftsubcategory", + "table": "subcategory", + "master": "leftsubcategory_id", + "detail": "id", + "kind": "left" + }, + { + "name": "rightsubcategory", + "table": "subcategory", + "master": "rightsubcategory_id", + "detail": "id", + "kind": "right" + }, + { + "name": "outersubcategory", + "table": "subcategory", + "master": "outersubcategory_id", + "detail": "id", + "kind": "full" + }, + { + "name": "innercategory", + "table": "category", + "master": "innersubcategory.category_id", + "detail": "id", + "kind": "inner" + }, + { + "name": "leftcategory", + "table": "category", + "master": "leftsubcategory.category_id", + "detail": "id", + "kind": "left" + }, + { + "name": "rightcategory", + "table": "category", + "master": "rightsubcategory.category_id", + "detail": "id", + "kind": "right" + }, + { + "name": "outercategory", + "table": "category", + "master": "outersubcategory.category_id", + "detail": "id", + "kind": "full" + } + ], + "dimensions": [ + { + "name": "innersubcategory", + "label": "Inner SubCategory", + "type": "integer", + "join": ["innercategory", "innersubcategory"], + "value": "innersubcategory.id", + "value_label": "innersubcategory.label" + }, + { + "name": "leftsubcategory", + "label": "Left SubCategory", + "type": "integer", + "join": ["leftcategory", "leftsubcategory"], + "value": "leftsubcategory.id", + "value_label": "leftsubcategory.label" + }, + { + "name": "rightsubcategory", + "label": "Right SubCategory", + "type": "integer", + "join": ["rightcategory", "rightsubcategory"], + "value": "rightsubcategory.id", + "value_label": "rightsubcategory.label" + }, + { + "name": "outersubcategory", + "label": "Outer SubCategory", + "type": "integer", + "join": ["outercategory", "outersubcategory"], + "value": "outersubcategory.id", + "value_label": "outersubcategory.label" + }, + { + "name": "innercategory", + "label": "Inner Category", + "type": "integer", + "join": ["innersubcategory", "innercategory"], + "value": "innercategory.id", + "value_label": "innercategory.label" + }, + { + "name": "leftcategory", + "label": "Left Category", + "type": "integer", + "join": ["leftsubcategory", "leftcategory"], + "value": "leftcategory.id", + "value_label": "leftcategory.label" + }, + { + "name": "rightcategory", + "label": "Right Category", + "type": "integer", + "join": ["rightsubcategory", "rightcategory"], + "value": "rightcategory.id", + "value_label": "rightcategory.label" + }, + { + "name": "outercategory", + "label": "Outer Category", + "type": "integer", + "join": ["outersubcategory", "outercategory"], + "value": "outercategory.id", + "value_label": "outercategory.label" + } + ], + "measures": [ + { + "name": "simple_count", + "label": "number of rows", + "type": "integer", + "expression": "count({fact_table}.id)" + }, + { + "name": "aggregated_count", + "label": "sum of cnt", + "type": "integer", + "expression": "sum(cnt)" + }, + { + "name": "percent", + "label": "pourcentage des demandes", + "type": "percent", + "expression": "case (select count({fact_table}.id) from {table_expression} where {where_conditions}) when 0 then null else count({fact_table}.id) * 100. / (select count({fact_table}.id) from {table_expression} where {where_conditions}) end" + } + ] + } + ] +} diff --git a/tests/test_schema1.py b/tests/test_schema1.py new file mode 100644 index 0000000..fbec6f9 --- /dev/null +++ b/tests/test_schema1.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +from utils import login + +def get_table(response): + table = [] + + for tr in response.pyquery('table tr'): + row = [] + table.append(row) + for td in tr.findall('td'): + row.append(td.text.strip()) + return table + +def test_simple(schema1, app, admin): + login(app, admin) + response = app.get('/').follow() + response = response.click('Facts 1') + assert 'big-msg-info' in response + form = response.form + form.set('representation', 'table') + form.set('measure', 'simple_count') + form.set('drilldown_x', 'innersubcategory') + response = form.submit('visualize') + assert 'big-msg-info' not in response + assert get_table(response) == [ + [u'Inner SubCategory', u'subé1', u'subé3'], + ['number of rows', '15', '1'], + ] diff --git a/tox.ini b/tox.ini index d843d92..01e26c7 100644 --- a/tox.ini +++ b/tox.ini @@ -26,6 +26,8 @@ deps = pytest-django WebTest django-webtest<1.9.3 + sqlparse + pyquery commands = dj111: py.test {posargs: --junitxml=test_{envname}_results.xml --cov-report xml --cov-report html --cov=bijoe --random tests/} dj18: py.test {posargs: --junitxml=test_{envname}_results.xml --random tests/} -- 2.18.0