Skip to content

Commit

Permalink
Add initial testing (#26)
Browse files Browse the repository at this point in the history
* try get initial tests working

* add in env file

* fix names and rename file

* fix

* fix again

* move to ci file

* Revert "move to ci file"

This reverts commit 73a9418.

* collapse to one file

* fix indents

* try some stuff

* add ci to correct path

* fix TTY issues

* try waiting

* try with healthcheck instead

* try making sure service is healthy

* add initial testing

* add updates

* make model tests work

* make tests even better

* improve again

* get tests partially working

* try

* inject OE license

* fix settings stuff

* HOLY GUACAMOLE it was the OE version

* fix wf

* gix path?

* Update ci.yaml

* Update ci.yaml

* Update test_views.py

* Update test_views.py

* Update test_views.py
  • Loading branch information
hmacdope authored Feb 11, 2024
1 parent f03bc65 commit 1077518
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 22 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: ci

on:
push:
branches:
- "main"
pull_request:
branches:
- "main"
schedule:
# Nightly tests run on main by default:
# Scheduled workflows run on the latest commit on the default or base branch.
# (from https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule)
- cron: "0 0 * * *"
workflow_dispatch:

concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true

defaults:
run:
shell: bash -l {0}

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Install docker-compose
run: |
sudo apt-get update
sudo apt-get install -y docker-compose
- name: Copy example env file
run: |
cp devtools/deployment/.env.example .env
- name: Make OpenEye directory
run: |
mkdir -p ~/.OpenEye
- name: Copy OpenEye license file
env:
OE_LICENSE: ${{ secrets.OE_LICENSE }}
run: |
echo "$OE_LICENSE" > ~/.OpenEye/oe_license.txt
- name: Build containers
run: |
docker-compose -f docker-compose-dev.yml build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)
docker container ls
docker-compose -f docker-compose-dev.yml up -d
- name: Chown volume
run: |
ls -alsh
ls -alsh argos
sudo chown -R $(id -u):$(id -g) argos/pdb_data
- name: Run tests
run: |
docker-compose -f docker-compose-dev.yml exec -T web bash -c "cd argos && /opt/conda/bin/python manage.py test --no-input"
17 changes: 15 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Use the conda-forge base image with Python
FROM mambaorg/micromamba:jammy


ARG USER_ID
ARG GROUP_ID

USER root

RUN addgroup --gid $GROUP_ID user
RUN adduser --disabled-password --gecos '' --uid $USER_ID --gid $GROUP_ID user
USER user


# set environment variables
ENV PYTHONUNBUFFERED 1

Expand All @@ -13,15 +24,17 @@ COPY . /argos
RUN micromamba config append channels conda-forge
RUN micromamba config append channels openeye

COPY --chown=$MAMBA_USER:$MAMBA_USER devtools/conda-envs/argos-ubuntu-latest.yml /tmp/env.yaml
COPY --chown=user:user devtools/conda-envs/argos-ubuntu-latest.yml /tmp/env.yaml

RUN micromamba install -y -n base git -f /tmp/env.yaml && \
micromamba clean --all --yes

USER root
RUN mkdir /openeye
RUN chown -R user:user /openeye
RUN mkdir /argos/pdb_data
USER $MAMBA_USER
RUN chown -R user:user /argos/pdb_data
USER user
ENV OE_LICENSE=/openeye/oe_license.txt


Expand Down
17 changes: 17 additions & 0 deletions argos/argos/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_cleanup.apps.CleanupConfig',
'argos_viewer.apps.ArgosViewerConfig',

]
Expand Down Expand Up @@ -89,6 +90,7 @@

DATABASES = {
'default': env.db(),

}


Expand Down Expand Up @@ -146,3 +148,18 @@

# Redirect to home URL after login (Default redirects to /accounts/profile/)
LOGIN_REDIRECT_URL = '/'


LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {"class": "logging.StreamHandler"},
},
"loggers": {
"django": {
"handlers": ["console"],
"level": "INFO",
},
}
}
16 changes: 15 additions & 1 deletion argos/argos_viewer/models.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
from typing import Any
from django.db import models
from django.core.validators import FileExtensionValidator

import os

class PDBFile(models.Model):
file = models.FileField(validators=[FileExtensionValidator(['pdb'])], upload_to="pdb_data")

def delete(self, *args, **kwargs):
# Delete the file when the instance is deleted
if self.file:
if os.path.isfile(self.file.path):
os.remove(self.file.path)
super(PDBFile, self).delete(*args, **kwargs)

class TargetPDBFile(models.Model):
pdb_file = models.ForeignKey(PDBFile, on_delete=models.CASCADE)
target = models.CharField(max_length=200)
upload_date = models.DateTimeField(auto_now_add=True)


def delete(self, *args, **kwargs):
# Delete the associated PDBFile instance, which should trigger its delete method
if self.pdb_file:
self.pdb_file.delete()
super(TargetPDBFile, self).delete(*args, **kwargs)

This file was deleted.

3 changes: 0 additions & 3 deletions argos/argos_viewer/tests.py

This file was deleted.

Empty file.
43 changes: 43 additions & 0 deletions argos/argos_viewer/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from django.test import TestCase
from argos_viewer.models import PDBFile, TargetPDBFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils import timezone
import os

class PDBFileModelTest(TestCase):
def setUp(self):
self.file = SimpleUploadedFile("test.pdb", b"pdb file content")
self.pdb_file = PDBFile.objects.create(file=self.file)


def test_pdb_file_created(self):
self.assertTrue(os.path.exists(self.pdb_file.file.path))

def test_file_extension(self):
self.assertEqual(self.pdb_file.file.name.split(".")[-1], "pdb")

class TargetPDBFileModelTest(TestCase):
def setUp(self):
self.file = SimpleUploadedFile("test.pdb", b"pdb file content")
self.pdb_file = PDBFile.objects.create(file=self.file)
self.target_pdb_file = TargetPDBFile.objects.create(pdb_file=self.pdb_file, target="test_target", upload_date=timezone.now())

def tearDown(self):
if os.path.exists(self.target_pdb_file.pdb_file.file.path):
os.remove(self.target_pdb_file.pdb_file.file.path)

def test_target_pdb_file_created(self):
self.assertTrue(TargetPDBFile.objects.exists())

def test_target(self):
self.assertEqual(self.target_pdb_file.target, "test_target")

def test_upload_date(self):
self.assertIsNotNone(self.target_pdb_file.upload_date)

def test_pdb_file_deletion_on_target_pdb_file_deletion(self):
self.target_pdb_file.delete()
self.assertFalse(os.path.exists(self.pdb_file.file.path))



6 changes: 6 additions & 0 deletions argos/argos_viewer/tests/test_oe_license.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.test import TestCase

class OELicenseTests(TestCase):
def test_oechem_is_licensed(self):
from asapdiscovery.data.openeye import oechem
self.assertTrue(oechem.OEChemIsLicensed())
28 changes: 28 additions & 0 deletions argos/argos_viewer/tests/test_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from django.test import SimpleTestCase
from django.urls import reverse, resolve
from argos_viewer.views import home, upload_sucessful, TargetPDBListView, target_pdb_detail_view, failed, no_fitness_data

class TestUrls(SimpleTestCase):
def test_home_url_resolves(self):
url = reverse('home')
self.assertEqual(resolve(url).func, home)

def test_upload_sucessful_url_resolves(self):
url = reverse('upload_sucessful')
self.assertEqual(resolve(url).func, upload_sucessful)

def test_pdb_files_url_resolves(self):
url = reverse('pdb_files')
self.assertEqual(resolve(url).func.view_class, TargetPDBListView)

def test_detail_url_resolves(self):
url = reverse('detail', args=[1]) # assuming pk=1
self.assertEqual(resolve(url).func, target_pdb_detail_view)

def test_failed_url_resolves(self):
url = reverse('failed')
self.assertEqual(resolve(url).func, failed)

def test_no_fitness_data_url_resolves(self):
url = reverse('no_fitness_data', args=['target_name'])
self.assertEqual(resolve(url).func, no_fitness_data)
55 changes: 55 additions & 0 deletions argos/argos_viewer/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from django.test import TestCase, Client, RequestFactory
from django.urls import reverse
from argos_viewer.models import PDBFile, TargetPDBFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils import timezone
from django.contrib.auth.models import User
from asapdiscovery.data.testing.test_resources import fetch_test_file


class ViewTests(TestCase):
def setUp(self):
self._test_file = fetch_test_file("Mpro-P2660_0A_bound.pdb")
with open(self._test_file, "r") as f:
self._file_contents = f.read()
# Create a user
self.user = User.objects.create_user(username='testuser', password='12345')
self.file = SimpleUploadedFile("test.pdb", self._file_contents.encode())
self.pdb_file = PDBFile.objects.create(file=self.file)
self.target_pdb_file = TargetPDBFile.objects.create(pdb_file=self.pdb_file, target="SARS-CoV-2-Mpro", upload_date=timezone.now())

def test_index_view(self):
response = self.client.get(reverse('index'))
self.assertEqual(response.status_code, 302) # Redirects to home

def test_home_view_GET(self):
self.client.force_login(self.user)
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'argos_viewer/home.html')

def test_upload_successful_view(self):
self.client.force_login(self.user)
response = self.client.get(reverse('upload_sucessful'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'upload worked!')


def test_target_pdb_detail_view_GET(self):
self.client.force_login(self.user)
response = self.client.get(reverse('detail', args=[self.target_pdb_file.pk]), follow=True)
self.assertEqual(response.status_code, 200)

def test_failed_view_GET(self):
self.client.force_login(self.user)
response = self.client.get(reverse('failed'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'argos_viewer/failed.html')

def test_no_fitness_data_view_GET(self):
self.client.force_login(self.user)
response = self.client.get(reverse('no_fitness_data', args=['target_name']))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'argos_viewer/no_fitness_data.html')

# Add tests for POST requests as well if necessary
13 changes: 8 additions & 5 deletions argos/argos_viewer/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
from asapdiscovery.data.fitness import target_has_fitness_data
import tempfile

import logging

logger = logging.getLogger('django')

def index(request):
context = {}
return redirect("home")
Expand Down Expand Up @@ -74,14 +78,13 @@ def target_pdb_detail_view(request, pk):
target_kwargs={"target_name": "unknown"},
)

tf = tempfile.NamedTemporaryFile()
tf = tempfile.NamedTemporaryFile()
html_viz = HTMLVisualizer(
[c.ligand.to_oemol()], [tf], obj.target, c.target.to_oemol(), color_method="fitness", align=False
)
# align=True is broken, see https://github.com/choderalab/asapdiscovery/issues/709
[c.ligand.to_oemol()], [tf], obj.target, c.target.to_oemol(), color_method="fitness", align=True)
html = html_viz.make_poses_html()[0]
logger.debug("Made pose html")
except Exception as e:
print(f"rendering failed with exception {e}")
logger.error(f"rendering failed with exception {e}")
return redirect("failed")

return HttpResponse(html)
Expand Down
15 changes: 11 additions & 4 deletions devtools/conda-envs/argos-ubuntu-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,27 @@ dependencies:

# Base depends
- pip
- python =3.10
- git
- python >=3.10,<3.11


# argos deps
- django
- gunicorn
- django-cleanup


# Testing
- pytest
- pytest-cov
- pooch

# asapdiscovery deps

# Others
- appdirs
- openeye-toolkits
- openeye-toolkits <2023.2.3
- pydantic >=1.10.8,<2.0.0a0


# data
- requests
- boto3
Expand Down
2 changes: 1 addition & 1 deletion devtools/deployment/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ DATABASE_URL=postgresql://django_traefik:django_traefik@db:5432/django_traefik
HOST_DOMAIN=localhost
POSTGRES_USER=django_traefik
POSTGRES_PASSWORD=django_traefik
POSTGRES_DB=django_traefik
POSTGRES_DB=django_traefik
Loading

0 comments on commit 1077518

Please sign in to comment.