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

Configure GH Actions for running tests before merging into development branch #237

Merged
merged 15 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/webapp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Django application

#on: [push]
on:
push:
branches:
- gh-test
- development
pull_request:
- development

jobs:
build:

runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backend


services:
postgres:
image: postgres:latest
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: github_actions
ports:
- 5432:5432
# needed because the postgres container does not provide a healthcheck
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5


steps:
- uses: actions/checkout@v2
- name: Set up Python 3.10
uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest-django
- name: Run migrations
run: |
python manage.py makemigrations authentication
python manage.py makemigrations eventposts
python manage.py migrate
- name: Run tests
run: py.test
5 changes: 4 additions & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ RUN pip install -r requirements.txt
ADD . /
WORKDIR /

CMD python manage.py makemigrations authentication && python manage.py makemigrations eventposts && python manage.py migrate && python manage.py runserver 0.0.0.0:9000
## POSTGRES WAIT SCRIPT FROM https://github.com/ufoscout/docker-compose-wait
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.9.0/wait /wait
RUN chmod +x /wait
CMD /wait && python manage.py makemigrations authentication && python manage.py makemigrations eventposts && python manage.py migrate && python manage.py test eventposts && python manage.py runserver 0.0.0.0:9000
KeremZaman marked this conversation as resolved.
Show resolved Hide resolved

EXPOSE 9000
16 changes: 16 additions & 0 deletions backend/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,25 @@

'PORT': '5432',

'TEST': {
'NAME': 'mytestdatabase'
}

}
}

if os.environ.get('GITHUB_WORKFLOW'):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'github_actions',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}


# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
Expand Down
5 changes: 3 additions & 2 deletions backend/eventposts/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db import models
from authentication.models import User
from django.contrib.postgres.fields import ArrayField
from datetime import datetime

def empty_list():
return list([])
Expand All @@ -12,15 +13,15 @@ class Post(models.Model):
content = models.TextField(default="")
title = models.TextField(default="")

creation_date = models.DateTimeField(auto_now_add=True)
creation_date = models.DateTimeField(default=datetime.now())
location = models.TextField(default="")

class Meta:
abstract = True


class EventPost(Post):
date = models.DateTimeField(auto_now_add=True)
date = models.DateTimeField(default=datetime.now())
duration = models.IntegerField(default=60)

sport = models.CharField(max_length=30)
Expand Down
2 changes: 1 addition & 1 deletion backend/eventposts/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from rest_framework import serializers
from .models import EventPost, Post
from eventposts.models import EventPost, Post

class EventSerializer(serializers.ModelSerializer):
class Meta:
Expand Down
168 changes: 167 additions & 1 deletion backend/eventposts/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,169 @@
from django.test import TestCase
from rest_framework.test import force_authenticate
from rest_framework.test import APITestCase, APIRequestFactory
from rest_framework import status
from eventposts.models import EventPost
from authentication.models import User
from eventposts.serializers import EventSerializer
from django.urls import reverse
from django.db.models import Q
from datetime import datetime, timedelta


class EventPostTests(APITestCase):
def setUp(self):
# create user and get auth token
self.user = User.objects.create_user(email="user@user.com", password="1234567", username="user")
resp = self.client.post(reverse('token_create'), {'username': 'user', 'password': '1234567'})
self.token = resp.data['access']

# create additional users for spectators and players
self.user2 = User.objects.create_user(email="user2@user.com", password="1234567", username="user2")
self.user3 = User.objects.create_user(email="user3@user.com", password="1234567", username="user3")

# create mock events for testing
self.event_01 = EventPost.objects.create(owner=self.user, title='Football Event',
content='We are organizing a football match with FC Barcelona fans.',
location='Madrid', date=datetime(2021, 9, 3), sport='Football',
min_age=13, max_age=45, player_capacity=14, spec_capacity=20,
min_skill_level=3, max_skill_level=4, latitude=40.43103333341609,
longitude=-3.705507357022727, duration=90, players=[self.user.id],
spectators=[self.user2.id, self.user3.id])

self.event_02 = EventPost.objects.create(owner=self.user, title='basketball event',
content='We are organizing a basketball match with Anadolu Efes fans.',
location='levent', date=datetime(2022, 5, 5), sport='Basketball',
min_age=20, max_age=33, player_capacity=6, spec_capacity=10,
min_skill_level=0, max_skill_level=5, latitude=41.08204996728227,
longitude=29.016445404346598, duration=120,
spectators=[self.user.id, self.user2.id, self.user3.id])

self.event_03 = EventPost.objects.create(owner=self.user, title="Let's show some NBA skillz",
content='Guys, today we are gathering to play basketball, join us!',
location='Washington', date=datetime(2022, 4, 4), sport='Basketball',
min_age=18, max_age=30, player_capacity=8, spec_capacity=10,
min_skill_level=3, max_skill_level=5, latitude=38.90785448747658,
longitude=-77.04329853399994, duration=120)

self.event_04 = EventPost.objects.create(owner=self.user, title="Tek kale aylık",
content='hep maç olmaz bu sefer tek kale aylık ayarlıyoruz,'
' katılım sınırlıdır',
location='etiler', date=datetime(2021, 1, 13), sport='Football',
min_age=13, max_age=17, player_capacity=5, spec_capacity=18,
min_skill_level=3, max_skill_level=4, latitude=41.13274943188016,
longitude=29.105688623416825, duration=60,
players=[self.user.id, self.user2.id], spectators=[self.user3.id])

self.basketball_games = EventSerializer(EventPost.objects.filter(sport="Basketball"), many=True).data

self.football_games = EventSerializer(EventPost.objects.filter(sport="Football"), many=True).data

self.player_capacity_between_6_10_games = EventSerializer(
EventPost.objects.filter(Q(player_capacity=6) | Q(player_capacity=8)), many=True).data

self.spec_capacity_between_15_25_games = self.football_games

self.age_between_18_35_games = self.basketball_games

self.in_turkey_games = EventSerializer(EventPost.objects.filter(
Q(location="levent") | Q(location="etiler")), many=True).data

self.date_inside_2022_games = self.basketball_games

self.duration_between_45_100_games = self.football_games
self.games_created_by_user = EventSerializer(EventPost.objects.all(), many=True).data
self.creation_date_today = EventSerializer(EventPost.objects.all(), many=True).data
self.num_players_between_1_5_games = self.football_games
self.num_spectators_between_3_5_games = EventSerializer(EventPost.objects.filter(title="basketball event"),
many=True).data

self.skill_between_2_4 = self.football_games

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test coverage looks great, I see pretty exhaustive tests here.

def test_filter_by_query(self):
response = self.client.get(reverse('eventpost-list'), {'query': 'basketball'}, HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.basketball_games)

def test_filter_by_date(self):
response = self.client.get(reverse('eventpost-list'), {'min_date': datetime(2021, 12, 12),
'max_date': datetime(2023, 1, 1)},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.date_inside_2022_games)

def test_filter_by_creation_date(self):
response = self.client.get(reverse('eventpost-list'), {'min_creation_date': (datetime.today() - timedelta(3)),
'max_creation_date': (datetime.today() + timedelta(1))},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.creation_date_today)

def test_filter_by_player_capacity(self):
response = self.client.get(reverse('eventpost-list'), {'min_player_capacity': 6, 'max_player_capacity': 10},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.player_capacity_between_6_10_games)

def test_filter_by_spec_capacity(self):
response = self.client.get(reverse('eventpost-list'), {'min_spectator_capacity': 15, 'max_spectator_capacity': 25},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.spec_capacity_between_15_25_games)

def test_filter_by_location(self):
response = self.client.get(reverse('eventpost-list'), {'location': 'le'},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.in_turkey_games)

def test_filter_by_duration(self):
response = self.client.get(reverse('eventpost-list'), {'min_duration': 45, 'max_duration': 100},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.duration_between_45_100_games)

def test_filter_by_sport(self):
response = self.client.get(reverse('eventpost-list'), {'sport': 'Basketball'},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.basketball_games)

def test_filter_by_owner(self):
response = self.client.get(reverse('eventpost-list'), {'owner_id': self.user.id},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.games_created_by_user)

def test_filter_by_age(self):
response = self.client.get(reverse('eventpost-list'), {'min_age': 18, 'max_age': 35},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.age_between_18_35_games)

def test_filter_by_coordinates(self):
response = self.client.get(reverse('eventpost-list'), {'min_latitude': 36.23763062438484,
'max_latitude': 42.01901802424485,
'min_longitude': 26.732105369671633,
'max_longitude': 44.3513027746188},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.in_turkey_games)

def test_filter_by_player_numbers(self):
response = self.client.get(reverse('eventpost-list'), {'min_players': 1, 'max_players': 5},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.num_players_between_1_5_games)

def test_filter_by_spectator_numbers(self):
response = self.client.get(reverse('eventpost-list'), {'min_spectators': 3, 'max_spectators': 5},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.num_spectators_between_3_5_games)

def test_filter_by_skill(self):
response = self.client.get(reverse('eventpost-list'), {'min_skill_level': 2, 'max_skill_level': 4},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.skill_between_2_4)

# Create your tests here.
Loading