faster tests

This commit is contained in:
thomas girod 2024-07-04 10:19:24 +02:00
parent 47fec973bc
commit aa07fa9207
11 changed files with 75 additions and 49 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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"]

View File

@ -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
-----------------------------------

View File

@ -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)

View File

@ -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)
@ -381,28 +381,15 @@ class Command(BaseCommand):
u1.godchildren.add(u3)
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)

View File

@ -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
View File

@ -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"

View File

@ -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"]

View File

@ -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

View File

@ -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