mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-22 15:51:19 +00:00
commit
79a6d9e771
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -21,6 +21,10 @@ jobs:
|
||||
tests:
|
||||
name: Run tests and generate coverage report
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false # don't interrupt the other test processes
|
||||
matrix:
|
||||
pytest-mark: [slow, not slow]
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
@ -28,7 +32,7 @@ jobs:
|
||||
- uses: ./.github/actions/setup_xapian
|
||||
- uses: ./.github/actions/compile_messages
|
||||
- name: Run tests
|
||||
run: poetry run coverage run -m pytest
|
||||
run: poetry run coverage run -m pytest -m "${{ matrix.pytest-mark }}"
|
||||
- name: Generate coverage report
|
||||
run: |
|
||||
poetry run coverage report
|
||||
|
@ -6,7 +6,7 @@ from django.utils.translation import activate
|
||||
@pytest.fixture(scope="session")
|
||||
def django_db_setup(django_db_setup, django_db_blocker):
|
||||
with django_db_blocker.unblock():
|
||||
call_command("setup")
|
||||
call_command("populate")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
|
@ -1098,8 +1098,10 @@ Welcome to the wiki page!
|
||||
n = News(
|
||||
title="Repas barman",
|
||||
summary="Enjoy la fin du semestre!",
|
||||
content="Viens donc t'enjailler avec les autres barmans aux "
|
||||
"frais du BdF! \o/",
|
||||
content=(
|
||||
"Viens donc t'enjailler avec les autres barmans aux "
|
||||
"frais du BdF! \\o/"
|
||||
),
|
||||
type="EVENT",
|
||||
club=bar_club,
|
||||
author=subscriber,
|
||||
|
@ -19,7 +19,8 @@ import base64
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
from datetime import date, datetime, timedelta
|
||||
from datetime import timezone as tz
|
||||
from typing import Tuple
|
||||
|
||||
from dict2xml import dict2xml
|
||||
@ -549,7 +550,7 @@ class Counter(models.Model):
|
||||
if since is None:
|
||||
since = get_start_of_semester()
|
||||
if isinstance(since, date):
|
||||
since = datetime(since.year, since.month, since.day, tzinfo=timezone.utc)
|
||||
since = datetime(since.year, since.month, since.day, tzinfo=tz.utc)
|
||||
return (
|
||||
self.sellings.filter(date__gte=since)
|
||||
.annotate(
|
||||
@ -583,7 +584,7 @@ class Counter(models.Model):
|
||||
if since is None:
|
||||
since = get_start_of_semester()
|
||||
if isinstance(since, date):
|
||||
since = datetime(since.year, since.month, since.day, tzinfo=timezone.utc)
|
||||
since = datetime(since.year, since.month, since.day, tzinfo=tz.utc)
|
||||
total = self.sellings.filter(date__gte=since).aggregate(
|
||||
total=Sum(F("quantity") * F("unit_price"), output_field=CurrencyField())
|
||||
)["total"]
|
||||
|
@ -207,6 +207,29 @@ Pour lancer les tests il suffit d'utiliser la commande intégrée à django.
|
||||
# Lancer une méthode en particulier de cette même classe
|
||||
pytest core.tests.UserRegistrationTest.test_register_user_form_ok
|
||||
|
||||
.. note::
|
||||
|
||||
Certains tests sont un peu longs à tourner.
|
||||
Pour ne faire tourner que les tests les plus rapides,
|
||||
vous pouvez exécutez pytest ainsi :
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -m "not slow"
|
||||
|
||||
# vous pouvez toujours faire comme au-dessus
|
||||
pytest core -m "not slow"
|
||||
|
||||
A l'inverse, vous pouvez ne faire tourner que les tests
|
||||
lents en remplaçant `-m "not slow"` par `-m slow`.
|
||||
|
||||
De cette manière, votre processus de développement
|
||||
devrait être un peu plus fluide.
|
||||
Cependant, n'oubliez pas de bien faire tourner
|
||||
tous les tests avant de push un commit.
|
||||
|
||||
|
||||
|
||||
Vérifier les dépendances Javascript
|
||||
-----------------------------------
|
||||
|
||||
|
@ -220,10 +220,11 @@ class EbouticTest(TestCase):
|
||||
self.client.get(reverse("eboutic:command"))
|
||||
response = self.client.get(et_answer_url)
|
||||
assert response.status_code == 500
|
||||
assert (
|
||||
"Basket processing failed with error: SuspiciousOperation('Basket total and amount do not match'"
|
||||
in response.content.decode("utf-8"),
|
||||
msg = (
|
||||
"Basket processing failed with error: "
|
||||
"SuspiciousOperation('Basket total and amount do not match'"
|
||||
)
|
||||
assert msg in response.content.decode("utf-8")
|
||||
|
||||
def test_buy_simple_product_with_credit_card(self):
|
||||
self.client.force_login(self.subscriber)
|
||||
|
@ -128,7 +128,7 @@ class Command(BaseCommand):
|
||||
self.clubs.append(Club(unix_name=f"galaxy-club-{i}", name=f"club-{i}"))
|
||||
# We don't need to create corresponding groups here, as the Galaxy doesn't care about them
|
||||
Club.objects.bulk_create(self.clubs)
|
||||
self.clubs = Club.objects.filter(unix_name__startswith="galaxy-").all()
|
||||
self.clubs = list(Club.objects.filter(unix_name__startswith="galaxy-").all())
|
||||
|
||||
def make_users(self):
|
||||
"""
|
||||
@ -147,20 +147,20 @@ class Command(BaseCommand):
|
||||
self.logger.info(f"Creating {u}")
|
||||
self.users.append(u)
|
||||
User.objects.bulk_create(self.users)
|
||||
self.users = User.objects.filter(username__startswith="galaxy-").all()
|
||||
self.users = list(User.objects.filter(username__startswith="galaxy-").all())
|
||||
|
||||
# now that users are created, create their subscription
|
||||
subs = []
|
||||
for i in range(self.NB_USERS):
|
||||
u = self.users[i]
|
||||
self.logger.info(f"Registering {u}")
|
||||
end = Subscription.compute_end(duration=2)
|
||||
for i, user in enumerate(self.users):
|
||||
self.logger.info(f"Registering {user}")
|
||||
subs.append(
|
||||
Subscription(
|
||||
member=u,
|
||||
member=user,
|
||||
subscription_start=Subscription.compute_start(
|
||||
self.now - timedelta(days=self.NB_USERS - i)
|
||||
),
|
||||
subscription_end=Subscription.compute_end(duration=2),
|
||||
subscription_end=end,
|
||||
)
|
||||
)
|
||||
Subscription.objects.bulk_create(subs)
|
||||
@ -175,20 +175,22 @@ class Command(BaseCommand):
|
||||
Then it will take 14 other citizen among the previous 200
|
||||
(godfathers are usually older), and apply another
|
||||
heuristic to determine whether they should have a family link
|
||||
It will result in approximately 40% of users having at least one godchild
|
||||
and 70% having at least one godfather.
|
||||
"""
|
||||
if self.users is None:
|
||||
raise RuntimeError(
|
||||
"The `make_users()` method must be called before `make_families()`"
|
||||
)
|
||||
godfathers = []
|
||||
for i in range(200, self.NB_USERS):
|
||||
godfathers = []
|
||||
for j in range(i - 200, i, 14): # this will loop 14 times (14² = 196)
|
||||
if (i / 10) % 10 == (i + j) % 10:
|
||||
if (i // 10) % 10 == (i + j) % 10:
|
||||
u1 = self.users[i]
|
||||
u2 = self.users[j]
|
||||
godfathers.append(User.godfathers.through(from_user=u1, to_user=u2))
|
||||
self.logger.info(f"Making {u2} the godfather of {u1}")
|
||||
godfathers.append(u2)
|
||||
u1.godfathers.set(godfathers)
|
||||
User.godfathers.through.objects.bulk_create(godfathers)
|
||||
|
||||
def make_club_memberships(self):
|
||||
"""
|
||||
@ -295,7 +297,7 @@ class Command(BaseCommand):
|
||||
self.picts[i].compressed.name = self.picts[i].name
|
||||
self.picts[i].thumbnail.name = self.picts[i].name
|
||||
Picture.objects.bulk_create(self.picts)
|
||||
self.picts = Picture.objects.filter(name__startswith="galaxy-").all()
|
||||
self.picts = list(Picture.objects.filter(name__startswith="galaxy-").all())
|
||||
|
||||
def make_pictures_memberships(self):
|
||||
"""
|
||||
@ -377,32 +379,24 @@ class Command(BaseCommand):
|
||||
u1 = self.users[uid]
|
||||
u2 = self.users[uid - 100]
|
||||
u3 = self.users[uid + 100]
|
||||
u1.godfathers.add(u2)
|
||||
u1.godchildren.add(u3)
|
||||
User.godfathers.through.objects.bulk_create(
|
||||
[
|
||||
User.godfathers.through(from_user=u1, to_user=u2),
|
||||
User.godfathers.through(from_user=u3, to_user=u2),
|
||||
],
|
||||
ignore_conflicts=True, # in case a relationship has already been created
|
||||
)
|
||||
self.logger.info(f"{u1} will be important and close to {u2} and {u3}")
|
||||
pictures_tags = []
|
||||
for p in range( # Mix them with other citizen for more chaos
|
||||
uid - 400, uid - 200
|
||||
):
|
||||
# users may already be on the pictures
|
||||
if not self.picts[p].people.filter(user=u1).exists():
|
||||
pictures_tags.append(
|
||||
PeoplePictureRelation(user=u1, picture=self.picts[p])
|
||||
)
|
||||
if not self.picts[p].people.filter(user=u2).exists():
|
||||
pictures_tags.append(
|
||||
PeoplePictureRelation(user=u2, picture=self.picts[p])
|
||||
)
|
||||
if not self.picts[p + self.NB_USERS].people.filter(user=u1).exists():
|
||||
pictures_tags.append(
|
||||
PeoplePictureRelation(
|
||||
user=u1, picture=self.picts[p + self.NB_USERS]
|
||||
)
|
||||
)
|
||||
if not self.picts[p + self.NB_USERS].people.filter(user=u2).exists():
|
||||
pictures_tags.append(
|
||||
PeoplePictureRelation(
|
||||
user=u2, picture=self.picts[p + self.NB_USERS]
|
||||
)
|
||||
)
|
||||
PeoplePictureRelation.objects.bulk_create(pictures_tags)
|
||||
for p in range(uid - 400, uid - 200):
|
||||
# Mix them with other citizen for more chaos
|
||||
pictures_tags += [
|
||||
PeoplePictureRelation(user=u1, picture=self.picts[p]),
|
||||
PeoplePictureRelation(user=u2, picture=self.picts[p]),
|
||||
PeoplePictureRelation(user=u1, picture=self.picts[p + self.NB_USERS]),
|
||||
PeoplePictureRelation(user=u2, picture=self.picts[p + self.NB_USERS]),
|
||||
]
|
||||
# users may already be on the pictures.
|
||||
# In this case the conflict will just be ignored
|
||||
# and nothing will happen for this entry
|
||||
PeoplePictureRelation.objects.bulk_create(pictures_tags, ignore_conflicts=True)
|
||||
|
File diff suppressed because one or more lines are too long
@ -25,6 +25,7 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from django.core.management import call_command
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
@ -147,6 +148,7 @@ class GalaxyTestModel(TestCase):
|
||||
galaxy.rule(0) # We want everybody here
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
class GalaxyTestView(TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
@ -196,6 +198,4 @@ class GalaxyTestView(TestCase):
|
||||
# Dump computed state, either for easier debugging, or to copy as new reference if changes are legit
|
||||
(galaxy_dir / "test_galaxy_state.json").write_text(json.dumps(state))
|
||||
|
||||
assert (
|
||||
state == json.loads((galaxy_dir / "ref_galaxy_state.json").read_text()),
|
||||
)
|
||||
assert state == json.loads((galaxy_dir / "ref_galaxy_state.json").read_text())
|
||||
|
10
poetry.lock
generated
10
poetry.lock
generated
@ -573,17 +573,17 @@ test = ["testfixtures"]
|
||||
|
||||
[[package]]
|
||||
name = "djangorestframework"
|
||||
version = "3.15.1"
|
||||
version = "3.15.2"
|
||||
description = "Web APIs for Django, made easy."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "djangorestframework-3.15.1-py3-none-any.whl", hash = "sha256:3ccc0475bce968608cf30d07fb17d8e52d1d7fc8bfe779c905463200750cbca6"},
|
||||
{file = "djangorestframework-3.15.1.tar.gz", hash = "sha256:f88fad74183dfc7144b2756d0d2ac716ea5b4c7c9840995ac3bfd8ec034333c1"},
|
||||
{file = "djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20"},
|
||||
{file = "djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
django = ">=3.0"
|
||||
django = ">=4.2"
|
||||
|
||||
[[package]]
|
||||
name = "docutils"
|
||||
|
@ -76,6 +76,7 @@ select = ["I", "F401"]
|
||||
[tool.pytest.ini_options]
|
||||
DJANGO_SETTINGS_MODULE = "sith.settings"
|
||||
python_files = ["tests.py", "test_*.py", "*_tests.py"]
|
||||
markers = ["slow"]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
@ -72,7 +72,7 @@ class MergeUserTest(TestCase):
|
||||
assert "B'ian" == self.to_keep.nick_name
|
||||
assert "Jerusalem" == self.to_keep.address
|
||||
assert "Rome" == self.to_keep.parent_address
|
||||
assert (3, self.to_keep.groups.count())
|
||||
assert self.to_keep.groups.count() == 3
|
||||
groups = sorted(self.to_keep.groups.all(), key=lambda i: i.id)
|
||||
expected = sorted([subscribers, mde_admin, sas_admin], key=lambda i: i.id)
|
||||
assert groups == expected
|
||||
|
@ -696,6 +696,17 @@ if DEBUG:
|
||||
|
||||
if TESTING:
|
||||
CAPTCHA_TEST_MODE = True
|
||||
PASSWORD_HASHERS = [ # not secure, but faster password hasher
|
||||
"django.contrib.auth.hashers.MD5PasswordHasher",
|
||||
]
|
||||
STORAGES = { # store files in memory rather than using the hard drive
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.InMemoryStorage",
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||
},
|
||||
}
|
||||
|
||||
if SENTRY_DSN:
|
||||
# Connection to sentry
|
||||
|
Loading…
Reference in New Issue
Block a user