Skip to content
Snippets Groups Projects
Commit 7ad79d39 authored by Victor Löfgren's avatar Victor Löfgren
Browse files

Resolve "Testing for competitions and teams"

parent db431571
No related branches found
No related tags found
1 merge request!168Resolve "Testing for competitions and teams"
Pipeline #47043 passed
......@@ -2,7 +2,7 @@ System overview
===============
This is a brief overview of how the entire system works.
There is then more detail about the client and the server.
There is then more detail about the client, the server and the database.
.. toctree::
:maxdepth: 2
......@@ -10,3 +10,4 @@ There is then more detail about the client and the server.
overview/overview
overview/client
overview/server
overview/database
# Database overview
......@@ -49,15 +49,15 @@ def db_add(item):
db.session.refresh(item)
except (exc.IntegrityError):
db.session.rollback()
abort(http_codes.CONFLICT, message=f"Kunde inte lägga objektet")
abort(http_codes.CONFLICT, message=f"Kunde inte lägga till objektet")
except (exc.SQLAlchemyError, exc.DBAPIError):
db.session.rollback()
# SQL errors such as item already exists
abort(http_codes.INTERNAL_SERVER_ERROR, message=f"Kunde inte lägga objektet")
abort(http_codes.INTERNAL_SERVER_ERROR, message=f"Kunde inte lägga till objektet")
except:
db.session.rollback()
# Catching other errors
abort(http_codes.INTERNAL_SERVER_ERROR, message=f"Kunde lägga till objektet")
abort(http_codes.INTERNAL_SERVER_ERROR, message=f"Kunde inte lägga till objektet")
return item
......@@ -254,14 +254,18 @@ def question(name, total_score, type_id, slide_id, correcting_instructions=None)
return db_add(Question(name, total_score, type_id, slide_id, correcting_instructions))
def question_alternative(alternative, correct, question_id):
def question_alternative(question_id, alternative="", alternative_order=None, correct="", correct_order=None):
"""
Adds a question alternative to the specified
question using the provided arguments.
"""
order = dbc.utils.count(QuestionAlternative, {"question_id": question_id})
return db_add(QuestionAlternative(alternative, order, correct, order, question_id))
alternative_order = alternative_order if alternative_order is not None else order
correct_order = correct_order if correct_order is not None else order
return db_add(QuestionAlternative(alternative_order, correct_order, question_id, alternative, correct))
def question_score(score, question_id, team_id):
......
......@@ -12,7 +12,13 @@ def _alternative(item_alternative_old, question_id):
Internal function. Makes a copy of the provided question alternative.
"""
return add.question_alternative(item_alternative_old.alternative, item_alternative_old.correct, question_id)
return add.question_alternative(
question_id,
item_alternative_old.alternative,
item_alternative_old.alternative_order,
item_alternative_old.correct,
item_alternative_old.correct_order,
)
def _question(item_question_old, slide_id):
......
......@@ -196,10 +196,10 @@ class Slide(db.Model):
__table_args__ = (db.UniqueConstraint("order", "competition_id"),)
id = db.Column(db.Integer, primary_key=True)
order = db.Column(db.Integer, nullable=False)
title = db.Column(db.String(STRING_SIZE), nullable=False, default="")
body = db.Column(db.Text, nullable=False, default="")
title = db.Column(db.String(STRING_SIZE), nullable=False, default="") # Unused. TODO: Delete
body = db.Column(db.Text, nullable=False, default="") # Unused. TODO: Delete
timer = db.Column(db.Integer, nullable=True)
settings = db.Column(db.Text, nullable=False, default="{}")
settings = db.Column(db.Text, nullable=False, default="{}") # Unused. TODO: Delete
competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
background_image_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=True)
......@@ -255,7 +255,7 @@ class QuestionAlternative(db.Model):
correct_order = db.Column(db.Integer)
question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
def __init__(self, alternative, alternative_order, correct, correct_order, question_id):
def __init__(self, alternative_order, correct_order, question_id, alternative="", correct=""):
self.alternative = alternative
self.alternative_order = alternative_order
self.correct = correct
......
......@@ -7,13 +7,6 @@ DISABLE_TESTS = False
@pytest.fixture
def app():
app, _ = create_app("configmodule.TestingConfig")
"""
with app.app_context():
db.drop_all()
db.create_all()
yield app
"""
app.app_context().push()
db.drop_all()
db.create_all()
......
......@@ -9,7 +9,7 @@ from app.apis import http_codes
from app.core import sockets
from tests import DISABLE_TESTS, app, client, db
from tests.test_helpers import add_default_values, change_order_test, delete, get, post, put
from tests.test_helpers import add_default_values, assert_dict_has_values, change_order_test, delete, get, post, put
@pytest.mark.skipif(DISABLE_TESTS, reason="Only run when DISABLE_TESTS is False")
......@@ -392,43 +392,80 @@ def test_slide_api(client):
def test_question_api(client):
add_default_values()
COMPETITION_ID = 3
SLIDE_ID = 6
# Login in with default user
response, body = post(client, "/api/auth/login", {"email": "test@test.se", "password": "password"})
assert response.status_code == http_codes.OK
headers = {"Authorization": "Bearer " + body["access_token"]}
num_questions = 3
# Get number of questions before
response, questions = get(
client, f"/api/competitions/{COMPETITION_ID}/slides/{SLIDE_ID}/questions", headers=headers
)
assert response.status_code == http_codes.OK
num_questions_before = len(questions)
# Add question
name = "Nytt namn"
type_id = 2
slide_order = 6
response, item_question = post(
data = {
"name": "Nytt namn",
"type_id": 2,
}
response, question = post(
client,
f"/api/competitions/{3}/slides/{slide_order}/questions",
{"name": name, "type_id": type_id},
f"/api/competitions/{COMPETITION_ID}/slides/{SLIDE_ID}/questions",
data=data,
headers=headers,
)
assert response.status_code == http_codes.OK
assert item_question["name"] == name
assert item_question["type_id"] == type_id
num_questions += 1
assert_dict_has_values(question, data)
"""
# Delete question
response, _ = delete(client, f"/api/competitions/{CID}/slides/{slide_order}/questions/{QID}", headers=headers)
num_questions -= 1
assert response.status_code == http_codes.NO_CONTENT
# Get number of questions after
response, questions = get(
client, f"/api/competitions/{COMPETITION_ID}/slides/{SLIDE_ID}/questions", headers=headers
)
assert response.status_code == http_codes.OK
assert question["id"] == questions[-1]["id"] # Last question is same as the one we added
assert len(questions) == num_questions_before + 1 # One more question than before
# Checks that there are fewer questions
response, body = get(client, f"/api/competitions/{CID}/questions", headers=headers)
question_id = question["id"]
# Edit question
data = {
"correcting_instructions": "Rätt så här",
"type_id": 2,
"name": "Ännu ett nytt namn",
"total_score": 5,
}
response, edited_question = put(
client,
f"/api/competitions/{COMPETITION_ID}/slides/{SLIDE_ID}/questions/{question_id}",
data=data,
headers=headers,
)
assert response.status_code == http_codes.OK
assert_dict_has_values(edited_question, data)
# Get question
response, edited_question_from_get = get(
client, f"/api/competitions/{COMPETITION_ID}/slides/{SLIDE_ID}/questions/{question_id}", headers=headers
)
assert response.status_code == http_codes.OK
assert body["count"] == num_questions
assert edited_question == edited_question_from_get
# Delete question
response, _ = delete(
client, f"/api/competitions/{COMPETITION_ID}/slides/{SLIDE_ID}/questions/{question_id}", headers=headers
)
assert response.status_code == http_codes.NO_CONTENT
# Tries to delete question again
response, _ = delete(client, f"/api/competitions/{CID}/slides/{NEW_slide_order}/questions/{QID}", headers=headers)
response, _ = delete(
client, f"/api/competitions/{COMPETITION_ID}/slides/{SLIDE_ID}/questions/{question_id}", headers=headers
)
assert response.status_code == http_codes.NOT_FOUND
"""
@pytest.mark.skipif(DISABLE_TESTS, reason="Only run when DISABLE_TESTS is False")
......@@ -494,3 +531,88 @@ def test_authorization(client):
# Also get antoher teams answers
response, body = get(client, f"/api/competitions/{competition_id}/teams/{team_id+1}/answers", headers=headers)
assert response.status_code == http_codes.OK
@pytest.mark.skipif(DISABLE_TESTS, reason="Only run when DISABLE_TESTS is False")
def test_team_api(client):
add_default_values()
# Login in with default user
response, body = post(client, "/api/auth/login", {"email": "test@test.se", "password": "password"})
assert response.status_code == http_codes.OK
headers = {"Authorization": "Bearer " + body["access_token"]}
# Get no teams for empty competition
CID = 2
response, body = get(client, f"/api/competitions/{CID}/teams", headers=headers)
assert response.status_code == http_codes.OK
assert len(body) == 0
# Get teams in competition
CID = 1
response, body = get(client, f"/api/competitions/{CID}/teams", headers=headers)
num_teams = 4
assert response.status_code == http_codes.OK
assert len(body) == num_teams
assert body[0]["name"] == "Lag 1"
assert body[1]["name"] == "Lag 2"
assert body[2]["name"] == "Lag 3"
assert body[3]["name"] == "Lag 4"
# Post new team
name = "Testlag"
response, body = post(client, f"/api/competitions/{CID}/teams", {"name": name}, headers=headers)
num_teams += 1
assert response.status_code == http_codes.OK
assert body["name"] == name
assert body["competition_id"] == CID
# Get teams in competition
response, body = get(client, f"/api/competitions/{CID}/teams", headers=headers)
assert response.status_code == http_codes.OK
assert len(body) == num_teams
assert body[0]["name"] == "Lag 1"
assert body[1]["name"] == "Lag 2"
assert body[2]["name"] == "Lag 3"
assert body[3]["name"] == "Lag 4"
assert body[4]["name"] == name
# Gets a specific team
TID = 5
response, body = get(client, f"/api/competitions/{CID}/teams/{TID}", {"name": name}, headers=headers)
assert response.status_code == http_codes.OK
assert body["name"] == name
assert body["competition_id"] == CID
assert body["id"] == TID
# Edits team
name = "Nytt lagnamn"
assert body["name"] != name
response, body = put(client, f"/api/competitions/{CID}/teams/{TID}", {"name": name}, headers=headers)
assert response.status_code == http_codes.OK
assert body["name"] == name
assert body["competition_id"] == CID
# Tries to edit team
response, _ = put(client, f"/api/competitions/{CID}/teams/{-1}", {"name": name}, headers=headers)
assert response.status_code == http_codes.NOT_FOUND
# Get teams in competition
response, body = get(client, f"/api/competitions/{CID}/teams", headers=headers)
assert response.status_code == http_codes.OK
assert len(body) == num_teams
assert body[4]["name"] == name
# Deletes team
response, _ = delete(client, f"/api/competitions/{CID}/teams/{TID}", {"name": name}, headers=headers)
num_teams -= 1
assert response.status_code == http_codes.NO_CONTENT
# Get teams in competition
response, body = get(client, f"/api/competitions/{CID}/teams", headers=headers)
assert response.status_code == http_codes.OK
assert len(body) == num_teams
# Tries to delete team
response, _ = delete(client, f"/api/competitions/{CID}/teams/{TID}", {"name": name}, headers=headers)
assert response.status_code == http_codes.NOT_FOUND
......@@ -4,10 +4,30 @@ This file tests the database controller functions.
import app.database.controller as dbc
import pytest
from app.database.models import City, Code, Competition, Media, MediaType, Role, Slide, User
from app.database.models import (
City,
Code,
Competition,
Media,
MediaType,
Question,
QuestionAlternative,
QuestionAlternativeAnswer,
QuestionScore,
Role,
Slide,
Team,
User,
)
from tests import DISABLE_TESTS, app, client, db
from tests.test_helpers import add_default_values, assert_all_slide_orders, assert_should_fail, assert_slide_order
from tests.test_helpers import (
add_default_values,
assert_all_slide_orders,
assert_insert_fail,
assert_should_fail,
assert_slide_order,
)
@pytest.mark.skipif(DISABLE_TESTS, reason="Only run when DISABLE_TESTS is False")
......@@ -238,134 +258,79 @@ def test_move_slides(client):
assert_slide_order(item_comp, [0, 6, 1, 8, 3, 4, 5, 7, 2, 9])
"""
@pytest.mark.skipif(DISABLE_TESTS, reason="Only run when DISABLE_TESTS is enabled")
def test_question(client):
add_default_values()
item_user = User.query.filter_by(email="test@test.se").first()
# Get image type
image_type = MediaType.query.filter_by(name="Image").first()
# Add image
db.session.add(Media("bild.png", image_type.id, item_user.id))
db.session.commit()
item_media = Media.query.filter_by(filename="bild.png").first()
# Add competition
item_city = City.query.filter_by(name="Linköping").first()
dbc.add.competition("teknik8", 2020, item_city.id)
dbc.add.competition("teknik9", 2020, item_city.id)
item_competition = Competition.query.filter_by(name="teknik8").first()
item_competition_2 = Competition.query.filter_by(name="teknik9").first()
assert item_competition is not None
assert item_competition.id == 4
assert item_competition.city.name == "Linköping"
# Add teams
dbc.add.team("Lag1", item_competition)
dbc.add.team("Lag2", item_competition)
assert_insert_fail(Team, "Lag1", item_competition.id)
dbc.add.team("Lag1", item_competition_2)
assert Team.query.filter((Team.competition_id == item_competition.id) & (Team.name == "Lag1")).count() == 1
assert Team.query.filter((Team.competition_id == item_competition.id) & (Team.name == "Lag2")).count() == 1
assert Team.query.filter((Team.competition_id == item_competition_2.id) & (Team.name == "Lag1")).count() == 1
assert Team.query.filter(Team.name == "Lag1").count() == 2
assert Team.query.filter(Team.competition_id == item_competition.id).count() == 2
assert Team.query.count() == 3
# Add slides
dbc.add.slide(item_competition)
dbc.add.slide(item_competition)
dbc.add.slide(item_competition)
# Try add slide with same order
assert_insert_fail(Slide, 1, item_competition.id)
assert_exists(Slide, 3, order=1)
item_slide1 = Slide.query.filter_by(order=0).first()
item_slide2 = Slide.query.filter_by(order=1).first()
item_slide3 = Slide.query.filter_by(order=2).first()
assert item_slide1 is not None
assert item_slide2 is not None
assert item_slide3 is not None
# Add questions
question_type_bool = QuestionType.query.filter_by(name="Boolean").first()
question_type_multiple = QuestionType.query.filter_by(name="Multiple").first()
dbc.add.question("Fråga1", 10, question_type_bool.id, item_slide2)
dbc.add.question("Fråga2", 10, question_type_multiple.id, item_slide3)
assert question_type_bool is not None
assert question_type_multiple is not None
item_q1 = Question.query.filter_by(name="Fråga1").first()
item_q2 = Question.query.filter_by(name="Fråga2").first()
assert item_q1.type.name == "Boolean"
assert item_q2.type.name == "Multiple"
# Get question
CID = 3
QID = 4
item_q1 = dbc.get.question(CID, QID)
assert item_q1.id == QID
item_slide = dbc.get.slide(CID, item_q1.slide_id)
assert item_q1.slide_id == item_slide.id
# Edit question
print(item_q1.type_id)
print(item_q1.slide_id)
name = "Nytt namn"
total_score = 44
type_id = 2
slide_id = 4
dbc.edit.question(item_q1, name=name, total_score=total_score, type_id=type_id, slide_id=slide_id)
item_q1 = Question.query.filter_by(name=name).first()
assert item_q1.name == name
assert item_q1.total_score == total_score
assert item_q1.type_id == type_id
assert item_q1.slide_id == slide_id
# Search for question
item_q2, _ = dbc.get.search_questions(
name=name, total_score=total_score, type_id=type_id, slide_id=slide_id, competition_id=CID
)
assert item_q1 == item_q2[0]
dbc.add.competition("Tävling 1", 2021, 1)
item_competition = Competition.query.filter(Competition.name == "Tävling 1").one()
# Add two teams
dbc.add.team("Lag 1", item_competition.id)
dbc.add.team("Lag 2", item_competition.id)
item_team_1 = Team.query.filter(Team.name == "Lag 1").one()
item_team_2 = Team.query.filter(Team.name == "Lag 2").one()
# Get default slide
item_slide_1 = Slide.query.filter((Slide.competition_id == item_competition.id) & (Slide.order == 0)).one()
# Add question to default slide
dbc.add.question("Fråga 1", 10, 1, item_slide_1.id)
item_question_1 = Question.query.filter(Question.name == "Fråga 1").one()
dbc.edit.default(item_question_1, name="Ny fråga 1", correcting_instructions="Rättningsinstruktioner")
# Add alternatives
dbc.add.question_alternative(item_question_1.id)
item_alterantive_1 = QuestionAlternative.query.filter(QuestionAlternative.question_id == item_question_1.id).one()
# Add answers
dbc.add.question_alternative_answer("Lag 1 svar 1", item_alterantive_1.id, item_team_1.id)
dbc.add.question_alternative_answer("Lag 2 svar 1", item_alterantive_1.id, item_team_2.id)
item_answer_1 = QuestionAlternativeAnswer.query.filter(QuestionAlternativeAnswer.answer == "Lag 1 svar 1").one()
dbc.edit.default(item_answer_1, answer="5")
# Add scores
dbc.add.question_score(10, item_question_1.id, item_team_1.id)
dbc.add.question_score(5, item_question_1.id, item_team_2.id)
item_score_1 = QuestionScore.query.filter(
(QuestionScore.question_id == item_question_1.id) & (QuestionScore.team_id == item_team_1.id)
).one()
dbc.edit.default(item_score_1, score=5)
assert_all_slide_orders()
def test_slide(client):
@pytest.mark.skipif(DISABLE_TESTS, reason="Only run when DISABLE_TESTS is enabled")
def test_team(client):
add_default_values()
# Get all slides
slides = Slide.query.all()
item_slides = dbc.get.search_slide()
assert slides == item_slides[0]
# Search using all parameters
item_comp = Competition.query.filter(Competition.name == "Tävling 1").first()
aux = dbc.get.search_slide(slide_order=1, title="Title 1", body="Body 1", competition_id=item_comp.id)
item_slide = aux[0][0]
assert item_comp.slides[1] == item_slide
# Edit all parameters of a slide
title = "Ändrad titel"
timer = 42
slide_id = item_slide.id
dbc.edit.slide(item_slide, title=title, timer=timer)
aux = dbc.get.search_slide(slide_order=1, title=title, body="Body 1", competition_id=item_comp.id)
item_slide = aux[0][0]
assert item_slide.id == slide_id
assert item_slide.title == title
assert item_slide.timer == timer
# Delete slide
aux = dbc.get.search_slide(slide_order=1, competition_id=item_comp.id)
item_slide = aux[0][0]
dbc.delete.slide(item_slide)
"""
# All teams were added
teams = Team.query.all()
assert len(teams) == 4
# Get team
item_team1 = dbc.get.team(1, 1)
assert item_team1.id == 1
assert item_team1.name == "Lag 1"
assert item_team1.competition.id == 1
# Add team
item_comp = Competition.query.filter(Competition.id == 2).one()
no_teams = len(Team.query.all())
item_team1 = dbc.add.team("Nytt lag", item_comp.id)
no_teams += 1
assert len(Team.query.all()) == no_teams
item_team2 = dbc.get.team(2, item_team1.id)
assert item_team1 == item_team2
# Try to add same team again
assert_insert_fail(Team, "Nytt lag", item_comp.id)
assert len(Team.query.all()) == no_teams
# Edit team
name = "Helt nytt lag"
item_team2 = dbc.edit.default(item_team1, name=name)
assert item_team2.name == name
assert item_team1 == item_team2
# Delete team
item_team = dbc.get.team(1, 1)
dbc.delete.team(item_team)
......@@ -41,7 +41,10 @@ def add_default_values():
# Add competitions
item_competition = dbc.add.competition("Tom tävling", 2012, item_city.id)
item_team1 = dbc.add.team("Hej lag 3", item_competition.id)
item_team1 = dbc.add.team("Lag 1", item_competition.id)
item_team2 = dbc.add.team("Lag 2", item_competition.id)
item_team3 = dbc.add.team("Lag 3", item_competition.id)
item_team4 = dbc.add.team("Lag 4", item_competition.id)
db.session.add(Code("111111", 1, item_competition.id, item_team1.id)) # Team
db.session.add(Code("222222", 2, item_competition.id)) # Judge
......@@ -69,8 +72,10 @@ def add_default_values():
# Add question to competition
item_question = dbc.add.question(name=f"Q{i+1}", total_score=i + 1, type_id=1, slide_id=item_slide.id)
for k in range(3):
dbc.add.question_alternative(f"Alternative {k}", f"Correct {k}", item_question.id)
for k in range(6):
dbc.add.question_alternative(
item_question.id, f"Alternative {k}", k + 5 % 6, f"Correct {k}", k + 2 % 6
)
# Add text component
dbc.add.component(1, item_slide.id, 1, i, 2 * i, 3 * i, 4 * i, text="Text")
......@@ -189,3 +194,9 @@ def assert_should_fail(func, *args):
pass # Assert failed, as it should
else:
assert False # Assertion didn't fail
def assert_dict_has_values(dict_to_check, dict_values_to_have):
""" Assert that dict_to_check has keys equal to values in dict_values_to_have. """
for key, value in dict_values_to_have.items():
assert dict_to_check[key] == value
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment