Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sql test setup #2903

Merged
merged 16 commits into from Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/run-sql-tests.yml
@@ -0,0 +1,32 @@
name: Run SQL tests
on:
push:
paths:
- '**.sql'
pull_request:
paths:
- '**.sql'


jobs:
tests:
runs-on: ubuntu-latest
# We only want to run on external PRs, since internal PRs are covered by "push"
# This prevents this from running twice on internal PRs
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
steps:
- uses: actions/checkout@v2

- name: Copy env file
run: cp .env.example .env

# The code is checked out under uid 1001 - reset this to 1000 for the
# container to run tests successfully
- name: Fix permissions
run: sudo chown -R 1000:1000 .

- name: Build the test DB
run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d dev-db

- name: Run tests with pg_prove
run: docker exec mathesar_dev_db /bin/bash /sql/run_tests.sh
12 changes: 9 additions & 3 deletions DEVELOPER_GUIDE.md
Expand Up @@ -65,19 +65,25 @@ See our [API guide](./mathesar/api/README.md) for more information on API usage

We use [pytest](https://docs.pytest.org) for our backend tests.

- Run all backend tests:
- Run all python backend tests:

```
docker exec mathesar_service_dev pytest mathesar/ db/
```

- Run a specific test, by name:
- Run a specific python test, by name:

```
docker exec mathesar_service_dev pytest -k "test_name"
```

- See the [pytest documentation](https://docs.pytest.org/en/latest/how-to/usage.html), or run pytest with the `--help` flag to learn about more options for running tests.

- See the [pytest documentation](https://docs.pytest.org/en/latest/how-to/usage.html), or run pytest with the `--help` flag to lear about more options for running tests.
- Run all SQL tests:

```
docker exec mathesar_dev_db /bin/bash sql/run_tests.sh
```

## Front end development

Expand Down
4 changes: 4 additions & 0 deletions Dockerfile.devdb
@@ -0,0 +1,4 @@
FROM postgres:13

RUN apt update
RUN apt install -y postgresql-13-pgtap && rm -rf /var/lib/apt/lists/*
16 changes: 16 additions & 0 deletions db/sql/run_tests.sh
@@ -0,0 +1,16 @@
#!/bin/bash
for i in {1..50}; do
pg_isready -U mathesar -d postgres && break || sleep 0.5
done

if [[ $BASH_SOURCE = */* ]]; then
sql=${BASH_SOURCE%/*}/
else
sql=./
fi

psql -q -U mathesar -d postgres -f "$sql"/test_startup.sql
pg_prove --runtests -U mathesar -d mathesar_testing
exit_code=$?
psql -q -U mathesar -d postgres -f "$sql"/test_shutdown.sql
exit $exit_code
140 changes: 140 additions & 0 deletions db/sql/test_0_msar.sql
@@ -0,0 +1,140 @@
DROP EXTENSION IF EXISTS pgtap CASCADE;
CREATE EXTENSION IF NOT EXISTS pgtap;

CREATE OR REPLACE FUNCTION setup_drop_columns() RETURNS SETOF TEXT AS $$
BEGIN
CREATE TABLE atable (dodrop1 integer, dodrop2 integer, dontdrop text);
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION setup_drop_tables() RETURNS SETOF TEXT AS $$
BEGIN
CREATE TABLE dropme (id SERIAL PRIMARY KEY, col1 integer);
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_columns_oid() RETURNS SETOF TEXT AS $$
DECLARE
rel_id oid;
BEGIN
rel_id := 'atable'::regclass::oid;
PERFORM msar.drop_columns(rel_id, 1, 2);
RETURN NEXT has_column(
'atable', 'dontdrop', 'Keeps correct columns'
);
RETURN NEXT hasnt_column(
'atable', 'dodrop1', 'Drops correct columns 1'
);
RETURN NEXT hasnt_column(
'atable', 'dodrop2', 'Drops correct columns 2'
);
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_columns_names() RETURNS SETOF TEXT AS $$
BEGIN
PERFORM msar.drop_columns('public', 'atable', 'dodrop1', 'dodrop2');
RETURN NEXT has_column(
'atable', 'dontdrop', 'Dropper keeps correct columns'
);
RETURN NEXT hasnt_column(
'atable', 'dodrop1', 'Dropper drops correct columns 1'
);
RETURN NEXT hasnt_column(
'atable', 'dodrop2', 'Dropper drops correct columns 2'
);
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_table_oid() RETURNS SETOF TEXT AS $$
DECLARE
rel_id oid;
BEGIN
rel_id := 'dropme'::regclass::oid;
PERFORM msar.drop_table(tab_id => rel_id, cascade_ => false, if_exists => false);
RETURN NEXT hasnt_table('dropme', 'Drops table');
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_table_oid_if_exists() RETURNS SETOF TEXT AS $$
DECLARE
rel_id oid;
BEGIN
rel_id := 'dropme'::regclass::oid;
PERFORM msar.drop_table(tab_id => rel_id, cascade_ => false, if_exists => true);
RETURN NEXT hasnt_table('dropme', 'Drops table with IF EXISTS');
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_table_oid_restricted_fkey() RETURNS SETOF TEXT AS $$
DECLARE
rel_id oid;
BEGIN
rel_id := 'dropme'::regclass::oid;
CREATE TABLE
dependent (id SERIAL PRIMARY KEY, col1 integer REFERENCES dropme);
RETURN NEXT throws_ok(
format('SELECT msar.drop_table(tab_id => %s, cascade_ => false, if_exists => true);', rel_id),
'2BP01',
'cannot drop table dropme because other objects depend on it',
'Table dropper throws for dependent objects'
);
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_table_oid_cascade_fkey() RETURNS SETOF TEXT AS $$
DECLARE
rel_id oid;
BEGIN
rel_id := 'dropme'::regclass::oid;
CREATE TABLE
dependent (id SERIAL PRIMARY KEY, col1 integer REFERENCES dropme);
PERFORM msar.drop_table(tab_id => rel_id, cascade_ => true, if_exists => false);
RETURN NEXT hasnt_table('dropme', 'Drops table with dependent using CASCADE');
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_table_name() RETURNS SETOF TEXT AS $$
BEGIN
PERFORM msar.drop_table(
sch_name => 'public',
tab_name => 'dropme',
cascade_ => false,
if_exists => false
);
RETURN NEXT hasnt_table('dropme', 'Drops table');
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_table_name_missing_if_exists() RETURNS SETOF TEXT AS $$
BEGIN
PERFORM msar.drop_table(
sch_name => 'public',
tab_name => 'dropmenew',
cascade_ => false,
if_exists => true
);
RETURN NEXT has_table('dropme', 'Drops table with IF EXISTS');
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION test_drop_table_name_missing_no_if_exists() RETURNS SETOF TEXT AS $$
BEGIN
RETURN NEXT throws_ok(
'SELECT msar.drop_table(''public'', ''doesntexist'', false, false);',
'42P01',
'table "doesntexist" does not exist',
'Table dropper throws for missing table'
);
END;
$$ LANGUAGE plpgsql;
1 change: 1 addition & 0 deletions db/sql/test_shutdown.sql
@@ -0,0 +1 @@
DROP DATABASE mathesar_testing WITH (FORCE);
4 changes: 4 additions & 0 deletions db/sql/test_startup.sql
@@ -0,0 +1,4 @@
CREATE DATABASE mathesar_testing;
\c mathesar_testing
\ir 0_msar.sql
\ir test_0_msar.sql
29 changes: 0 additions & 29 deletions db/tests/columns/operations/test_drop.py

This file was deleted.

58 changes: 0 additions & 58 deletions db/tests/tables/operations/test_drop.py

This file was deleted.

26 changes: 23 additions & 3 deletions docker-compose.dev.yml
Expand Up @@ -4,10 +4,27 @@ services:
# Mathesar App built with the same configurations as the production image
# but with additional testing dependencies.
# It is used to run automated test cases to verify if the app works as intended
dev-db:
container_name: mathesar_dev_db
build:
context: .
dockerfile: Dockerfile.devdb
environment:
- POSTGRES_DB=mathesar_django
- POSTGRES_USER=mathesar
- POSTGRES_PASSWORD=mathesar
ports:
- "5432:5432"
volumes:
- dev_postgres_data:/var/lib/postgresql/data
- ./db/sql:/sql/
test-service:
extends:
file: docker-compose.yml
service: service
environment:
- DJANGO_DATABASE_URL=postgres://mathesar:mathesar@mathesar_dev_db:5432/mathesar_django
- MATHESAR_DATABASES=(mathesar_tables|postgresql://mathesar:mathesar@mathesar_dev_db:5432/mathesar)
container_name: mathesar_service_test
image: mathesar/mathesar-test:latest
build:
Expand All @@ -16,7 +33,7 @@ services:
args:
PYTHON_REQUIREMENTS: requirements-dev.txt
depends_on:
- db
- dev-db
# On testing, the HTTP port is exposed to other containers, and the host.
ports:
- "8000:8000"
Expand All @@ -40,16 +57,19 @@ services:
- DJANGO_ALLOW_ASYNC_UNSAFE=true
- DJANGO_SUPERUSER_PASSWORD=password
- DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE-config.settings.development}
entrypoint: dockerize -wait tcp://mathesar_db:5432 -timeout 30s ./dev-run.sh
- DJANGO_DATABASE_URL=postgres://mathesar:mathesar@mathesar_dev_db:5432/mathesar_django
- MATHESAR_DATABASES=(mathesar_tables|postgresql://mathesar:mathesar@mathesar_dev_db:5432/mathesar)
entrypoint: dockerize -wait tcp://mathesar_dev_db:5432 -timeout 30s ./dev-run.sh
volumes:
- .:/code/
- ui_node_modules:/code/mathesar_ui/node_modules/
depends_on:
- db
- dev-db
# On dev, following ports are exposed to other containers, and the host.
ports:
- "8000:8000"
- "3000:3000"
- "6006:6006"
volumes:
ui_node_modules:
dev_postgres_data: