Skip to content

Commit

Permalink
CELE-17 chore: Merge with develop
Browse files Browse the repository at this point in the history
  • Loading branch information
afonsobspinto committed Apr 24, 2024
2 parents 79743f6 + ff7026e commit 124054a
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 2 deletions.
18 changes: 17 additions & 1 deletion applications/visualizer/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ backend
├── openapi
│   └── openapi.json # The openapi.json generated from the routes defined in "api.py"
├── populate-db.bash # the script to populate the DB
├── tests/** # The directory that contains the tests
└── visualizer
├── asgi.py
├── models.py
Expand Down Expand Up @@ -45,4 +46,19 @@ If you also want to see the SQL commands that are sent to the DB, you can start
```bash
# from inside the "backend" folder
python manage.py shell_plus --print-sql
```
```

## Run tests

The tests are written with `pytest` and `pytest-django`.
To run the test, simply execute in the `backend` folder one of the following command:

```bash
python -m pytest
# or simply
pytest
```

The data in the test are paritally generated.
Some of the fields are manually set and the ones that we don't want to write and/or test are generated (e.g: the field is marked `not null` in the django model, so it has to be here).
The value generation is done with [`model-bakery`](https://model-bakery.readthedocs.io/), which offers a nice level of flexibility and customization.
24 changes: 24 additions & 0 deletions applications/visualizer/backend/api/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from ninja import NinjaAPI, Router, Schema
from ninja.pagination import paginate, PageNumberPagination
from django.shortcuts import aget_object_or_404
from django.db.models import Q


from .schemas import Dataset, FullDataset, Neuron, Connection, ConnectionRequest
Expand Down Expand Up @@ -74,6 +75,29 @@ async def get_dataset(request, dataset: str):
return await aget_object_or_404(DatasetModel, id=dataset)


@api.get(
"/datasets/{dataset}/neurons",
response={200: list[Neuron], 404: ErrorMessage},
tags=["datasets"],
)
async def get_dataset_neurons(request, dataset: str):
"""Returns all the neurons of a dedicated dataset"""
return await to_list(
NeuronModel.objects.filter(
Q(
name__in=ConnectionModel.objects.filter(
dataset__id=dataset
).values_list("pre", flat=True)
)
| Q(
name__in=ConnectionModel.objects.filter(
dataset__id=dataset
).values_list("post", flat=True)
)
)
)


@api.get("/cells", response=list[Neuron], tags=["neurons"])
@paginate(PageNumberPagination, page_size=50)
def get_all_cells(request):
Expand Down

This file was deleted.

3 changes: 3 additions & 0 deletions applications/visualizer/backend/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
DJANGO_SETTINGS_MODULE = visualizer.settings
django_debug_mode = keep
2 changes: 2 additions & 0 deletions applications/visualizer/backend/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ django_extensions
ipdb
pytest
pytest-django
pytest-asyncio
model-bakery
black
Empty file.
25 changes: 25 additions & 0 deletions applications/visualizer/backend/tests/test_connections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import pytest

from api.models import Connection
from .utils import generate_instance


# Some test data
connections = [
{"id": "1", "dataset": {"id": "ds3", "name": "Dr. Seuss"}},
]


@pytest.fixture(scope="module")
def django_db_setup(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
generate_instance(Connection, connections)


@pytest.mark.django_db
def test__fk_creation():
o = Connection.objects.get(id=1)

assert o.dataset
assert o.dataset.id == "ds3"
assert o.dataset.name == "Dr. Seuss"
75 changes: 75 additions & 0 deletions applications/visualizer/backend/tests/test_datasets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from ninja.testing import TestAsyncClient
import pytest


from api.api import api as celegans_api
from api.models import Dataset
from .utils import generate_instance


# Some test data
datasets = [
{
"id": "ds1",
"name": "Dataset 1",
},
{
"id": "gg",
"name": "Gamma Goblin",
},
{
"id": "ds3",
"name": "Dr. Seuss",
},
]


# Setup the db for this module with some data
# Data are baked with "baker", it allows to create dummy values automatically
# and also to specify some fields. It is used here to "fill" the fields which are
# marked as "non-null" in the model which we don't want to manually fill.
@pytest.fixture(scope="module")
def django_db_setup(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
generate_instance(Dataset, datasets)


# Fixture to access the test client in all test functions
@pytest.fixture
def api_client():
client = TestAsyncClient(celegans_api.default_router)
return client


# Test function
@pytest.mark.django_db # required to access the DB
@pytest.mark.asyncio # required as we access a async function
async def test__get_nonexisting_dataset(api_client):
response = await api_client.get("/datasets/nonexisting")
assert response.status_code == 404


@pytest.mark.django_db
@pytest.mark.asyncio
async def test__get_existing_dataset(api_client):
response = await api_client.get("/datasets/ds3")
assert response.status_code == 200

dataset = response.json()
assert dataset["id"] == "ds3"
assert dataset["name"] == "Dr. Seuss"


@pytest.mark.django_db
@pytest.mark.asyncio
async def test__get_all_datasets(api_client):
response = await api_client.get("/datasets")
assert response.status_code == 200

datasets = response.json()
assert len(datasets) == 3

datasets_id = [dataset["id"] for dataset in datasets]
assert "ds1" in datasets_id
assert "ds3" in datasets_id
assert "gg" in datasets_id
18 changes: 18 additions & 0 deletions applications/visualizer/backend/tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from model_bakery import baker


def flat_dict(d):
res = {}
for key, value in d.items():
if isinstance(value, dict):
subdict = flat_dict(value)
for subk, subv in subdict.items():
res[f"{key}__{subk}"] = subv
else:
res[key] = value
return res


def generate_instance(cls, instance_list):
for instance in instance_list:
baker.make(cls, **flat_dict(instance))
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
"TEST": {"NAME": BASE_DIR / "tests" / "testdb.sqlite3"},
}
}

0 comments on commit 124054a

Please sign in to comment.