Speed up tests (#638)

This commit is contained in:
thomas girod 2023-05-02 11:00:23 +02:00 committed by GitHub
parent 66fcb76cb5
commit 96dede5077
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 191 additions and 200 deletions

View File

@ -0,0 +1,8 @@
name: "Compile messages"
description: "Compile the gettext translation messages"
runs:
using: composite
steps:
- name: Setup project
run: poetry run ./manage.py compilemessages
shell: bash

View File

@ -0,0 +1,53 @@
name: "Setup project"
description: "Setup Python and Poetry"
runs:
using: composite
steps:
- name: Install apt packages
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: gettext libxapian-dev libgraphviz-dev
version: 1.0 # increment to reset cache
- name: Install dependencies
run: |
sudo apt update
sudo apt install gettext libxapian-dev libgraphviz-dev
shell: bash
- name: Set up python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Load cached Poetry installation
id: cached-poetry
uses: actions/cache@v3
with:
path: ~/.local
key: poetry-0 # increment to reset cache
- name: Install Poetry
if: steps.cached-poetry.outputs.cache-hit != 'true'
shell: bash
run: curl -sSL https://install.python-poetry.org | python3 -
- name: Check pyproject.toml syntax
shell: bash
run: poetry check
- name: Load cached dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Install dependencies
run: poetry install -E testing -E docs
shell: bash
- name: Compile gettext messages
run: poetry run ./manage.py compilemessages
shell: bash

10
.github/actions/setup_xapian/action.yml vendored Normal file
View File

@ -0,0 +1,10 @@
name: "Setup xapian"
description: "Setup the xapian indexes"
runs:
using: composite
steps:
- name: Setup xapian index
run: |
mkdir -p /dev/shm/search_indexes
ln -s /dev/shm/search_indexes sith/search_indexes
shell: bash

43
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Sith 3 CI
on:
push:
branches:
- master
- taiste
pull_request:
branches:
- master
- taiste
jobs:
black:
name: Black format
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Setup Project
uses: ./.github/actions/setup_project
- run: poetry run black --check .
tests:
name: Run tests and generate coverage report
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
- uses: ./.github/actions/setup_project
- uses: ./.github/actions/setup_xapian
- uses: ./.github/actions/compile_messages
- name: Run tests
run: poetry run coverage run ./manage.py test
- name: Generate coverage report
run: |
poetry run coverage report
poetry run coverage html
- name: Archive code coverage results
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: coverage_report

View File

@ -1,83 +0,0 @@
name: Sith3 CI
on:
pull_request:
branches: [ master, taiste ]
push:
branches: [ master, taiste ]
jobs:
unittests:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v3
# Skip unit testing if no diff on .py files
- name: Check file diff
uses: technote-space/get-diff-action@v6
id: git-diff
with:
PATTERNS: |
**/*.py
- name: Set up python
if: steps.git-diff.outputs.diff
uses: actions/setup-python@v4
with:
python-version: '3.8'
- name: Install dependencies
if: steps.git-diff.outputs.diff
run: |
sudo apt-get update
sudo apt-get install gettext libxapian-dev libgraphviz-dev
- name: Install poetry
if: steps.git-diff.outputs.diff
run: |
python -m pip install --upgrade pip
python -m pip install poetry
- name: Checking pyproject.toml syntax
if: steps.git-diff.outputs.diff
run: poetry check
- name: Install project
if: steps.git-diff.outputs.diff
run: poetry install -E testing
- name: Setup xapian index
if: steps.git-diff.outputs.diff
run: |
mkdir -p /dev/shm/search_indexes
ln -s /dev/shm/search_indexes sith/search_indexes
- name: Setup project
if: steps.git-diff.outputs.diff
run: poetry run ./manage.py compilemessages
- name: Launch tests and generate coverage report
if: steps.git-diff.outputs.diff
run: |
poetry run coverage run ./manage.py test
poetry run coverage report
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up python
uses: actions/setup-python@v4
with:
python-version: '3.8'
- name: Install black
run: |
python -m pip install --upgrade pip
python -m pip install black==23.3.0
- name: Check linting
run: black --check .

View File

@ -31,7 +31,6 @@ from accounting.models import (
class RefoundAccountTest(TestCase):
def setUp(self):
call_command("populate")
self.skia = User.objects.filter(username="skia").first()
# reffil skia's account
self.skia.customer.amount = 800
@ -73,7 +72,6 @@ class RefoundAccountTest(TestCase):
class JournalTest(TestCase):
def setUp(self):
call_command("populate")
self.journal = GeneralJournal.objects.filter(id=1).first()
def test_permission_granted(self):
@ -101,7 +99,6 @@ class JournalTest(TestCase):
class OperationTest(TestCase):
def setUp(self):
call_command("populate")
self.tomorrow_formatted = (date.today() + timedelta(days=1)).strftime(
"%d/%m/%Y"
)

View File

@ -33,7 +33,6 @@ from sith.settings import SITH_BAR_MANAGER
class ClubTest(TestCase):
def setUp(self):
call_command("populate")
self.skia = User.objects.filter(username="skia").first()
self.rbatsbak = User.objects.filter(username="rbatsbak").first()
self.guy = User.objects.filter(username="guy").first()
@ -379,7 +378,6 @@ class MailingFormTest(TestCase):
"""Perform validation tests for MailingForm"""
def setUp(self):
call_command("populate")
self.skia = User.objects.filter(username="skia").first()
self.rbatsbak = User.objects.filter(username="rbatsbak").first()
self.krophil = User.objects.filter(username="krophil").first()
@ -699,7 +697,6 @@ class ClubSellingViewTest(TestCase):
"""
def setUp(self):
call_command("populate")
self.ae = Club.objects.filter(unix_name="ae").first()
def test_page_not_internal_error(self):

View File

@ -26,9 +26,6 @@ from core.models import User, RealGroup
class ComAlertTest(TestCase):
def setUp(self):
call_command("populate")
def test_page_is_working(self):
self.client.login(username="comunity", password="plop")
response = self.client.get(reverse("com:alert_edit"))
@ -37,9 +34,6 @@ class ComAlertTest(TestCase):
class ComInfoTest(TestCase):
def setUp(self):
call_command("populate")
def test_page_is_working(self):
self.client.login(username="comunity", password="plop")
response = self.client.get(reverse("com:info_edit"))
@ -48,14 +42,16 @@ class ComInfoTest(TestCase):
class ComTest(TestCase):
def setUp(self):
call_command("populate")
self.skia = User.objects.filter(username="skia").first()
self.com_group = RealGroup.objects.filter(
@classmethod
def setUpTestData(cls):
cls.skia = User.objects.filter(username="skia").first()
cls.com_group = RealGroup.objects.filter(
id=settings.SITH_GROUP_COM_ADMIN_ID
).first()
self.skia.groups.set([self.com_group])
self.skia.save()
cls.skia.groups.set([cls.com_group])
cls.skia.save()
def setUp(self):
self.client.login(username=self.skia.username, password="plop")
def test_alert_msg(self):

View File

@ -22,9 +22,6 @@ from django.core.management import call_command
class Command(BaseCommand):
help = "Set up a new instance of the Sith AE"
def add_arguments(self, parser):
parser.add_argument("--prod", action="store_true")
def handle(self, *args, **options):
root_path = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
@ -40,7 +37,4 @@ class Command(BaseCommand):
except Exception as e:
repr(e)
call_command("migrate")
if options["prod"]:
call_command("populate", "--prod")
else:
call_command("populate")
call_command("populate")

View File

@ -30,11 +30,9 @@ to run these tests :
class UserRegistrationTest(TestCase):
def setUp(self):
try:
Group.objects.create(name="root")
except Exception as e:
print(e)
@classmethod
def setUpTestData(cls):
User.objects.all().delete()
def test_register_user_form_ok(self):
"""
@ -282,19 +280,8 @@ class MarkdownTest(TestCase):
class PageHandlingTest(TestCase):
def setUp(self):
self.root_group = Group.objects.create(name="root")
u = User(
username="root",
last_name="",
first_name="Bibou",
email="ae.info@utbm.fr",
date_of_birth="1942-06-12",
is_superuser=True,
is_staff=True,
)
u.set_password("plop")
u.save()
self.client.login(username="root", password="plop")
self.root_group = Group.objects.get(name="Root")
def test_create_page_ok(self):
"""
@ -321,12 +308,20 @@ class PageHandlingTest(TestCase):
"""
Should create a page correctly
"""
# remove all other pages to make sure there is no side effect
Page.objects.all().delete()
self.client.post(
reverse("core:page_new"), {"parent": "", "name": "guy", "owner_group": "1"}
reverse("core:page_new"),
{"parent": "", "name": "guy", "owner_group": str(self.root_group.id)},
)
page = Page.objects.first()
response = self.client.post(
reverse("core:page_new"),
{"parent": "1", "name": "bibou", "owner_group": "1"},
{
"parent": str(page.id),
"name": "bibou",
"owner_group": str(self.root_group.id),
},
)
response = self.client.get(
reverse("core:page", kwargs={"page_name": "guy/bibou"})
@ -392,9 +387,6 @@ http://git.an
class UserToolsTest(TestCase):
def setUp(self):
call_command("populate")
def test_anonymous_user_unauthorized(self):
response = self.client.get(reverse("core:user_tools"))
self.assertEqual(response.status_code, 403)
@ -432,13 +424,12 @@ class UserToolsTest(TestCase):
class FileHandlingTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.subscriber = User.objects.get(username="subscriber")
def setUp(self):
try:
call_command("populate")
self.subscriber = User.objects.filter(username="subscriber").first()
self.client.login(username="subscriber", password="plop")
except Exception as e:
print(e)
self.client.login(username="subscriber", password="plop")
def test_create_folder_home(self):
response = self.client.post(

View File

@ -30,13 +30,13 @@ from sith.settings import SITH_MAIN_CLUB
class CounterTest(TestCase):
def setUp(self):
call_command("populate")
self.skia = User.objects.filter(username="skia").first()
self.sli = User.objects.filter(username="sli").first()
self.krophil = User.objects.filter(username="krophil").first()
self.mde = Counter.objects.filter(name="MDE").first()
self.foyer = Counter.objects.get(id=2)
@classmethod
def setUpTestData(cls):
cls.skia = User.objects.filter(username="skia").first()
cls.sli = User.objects.filter(username="sli").first()
cls.krophil = User.objects.filter(username="krophil").first()
cls.mde = Counter.objects.filter(name="MDE").first()
cls.foyer = Counter.objects.get(id=2)
def test_full_click(self):
self.client.post(
@ -161,9 +161,7 @@ class CounterTest(TestCase):
class CounterStatsTest(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
call_command("populate")
def setUpTestData(cls):
cls.counter = Counter.objects.filter(id=2).first()
cls.krophil = User.objects.get(username="krophil")
cls.skia = User.objects.get(username="skia")
@ -171,10 +169,7 @@ class CounterStatsTest(TestCase):
cls.root = User.objects.get(username="root")
cls.subscriber = User.objects.get(username="subscriber")
cls.old_subscriber = User.objects.get(username="old_subscriber")
cls.counter.sellers.add(cls.sli)
cls.counter.sellers.add(cls.root)
cls.counter.sellers.add(cls.skia)
cls.counter.sellers.add(cls.krophil)
cls.counter.sellers.add(cls.sli, cls.root, cls.skia, cls.krophil)
barbar = Product.objects.get(code="BARB")
@ -368,7 +363,7 @@ class CounterStatsTest(TestCase):
class BillingInfoTest(TestCase):
@classmethod
def setUpClass(cls):
def setUpTestData(cls):
cls.payload_1 = {
"first_name": "Subscribed",
"last_name": "User",
@ -385,8 +380,6 @@ class BillingInfoTest(TestCase):
"city": "Sète",
"country": "FR",
}
super().setUpClass()
call_command("populate")
def test_edit_infos(self):
user = User.objects.get(username="subscriber")
@ -596,7 +589,6 @@ class BillingInfoTest(TestCase):
class BarmanConnectionTest(TestCase):
def setUp(self):
call_command("populate")
self.krophil = User.objects.get(username="krophil")
self.skia = User.objects.get(username="skia")
self.skia.customer.account = 800
@ -662,7 +654,6 @@ class StudentCardTest(TestCase):
"""
def setUp(self):
call_command("populate")
self.krophil = User.objects.get(username="krophil")
self.sli = User.objects.get(username="sli")

View File

@ -41,7 +41,6 @@ from eboutic.models import Basket
class EbouticTest(TestCase):
@classmethod
def setUpTestData(cls):
call_command("populate")
cls.barbar = Product.objects.filter(code="BARB").first()
cls.refill = Product.objects.filter(code="15REFILL").first()
cls.cotis = Product.objects.filter(code="1SCOTIZ").first()

View File

@ -9,8 +9,6 @@ from election.models import Election
class MainElection(TestCase):
def setUp(self):
call_command("populate")
self.election = Election.objects.all().first()
self.public_group = Group.objects.get(id=settings.SITH_GROUP_PUBLIC_ID)
self.subscriber_group = Group.objects.get(name=settings.SITH_MAIN_MEMBERS_GROUP)

View File

@ -31,7 +31,6 @@ from galaxy.models import Galaxy
class GalaxyTest(TestCase):
def setUp(self):
call_command("populate")
self.root = User.objects.get(username="root")
self.skia = User.objects.get(username="skia")
self.sli = User.objects.get(username="sli")

View File

@ -83,12 +83,12 @@ class UVCreation(TestCase):
Test uv creation
"""
def setUp(self):
call_command("populate")
self.bibou = User.objects.filter(username="root").first()
self.tutu = User.objects.filter(username="tutu").first()
self.sli = User.objects.filter(username="sli").first()
self.guy = User.objects.filter(username="guy").first()
@classmethod
def setUp(cls):
cls.bibou = User.objects.get(username="root")
cls.tutu = User.objects.get(username="tutu")
cls.sli = User.objects.get(username="sli")
cls.guy = User.objects.get(username="guy")
def test_create_uv_admin_success(self):
self.client.login(username="root", password="plop")
@ -157,9 +157,6 @@ class UVListTest(TestCase):
Test guide display rights
"""
def setUp(self):
call_command("populate")
def test_uv_list_display_success(self):
# Display for root
self.client.login(username="root", password="plop")
@ -192,9 +189,6 @@ class UVDeleteTest(TestCase):
Test UV deletion rights
"""
def setUp(self):
call_command("populate")
def test_uv_delete_root_success(self):
self.client.login(username="root", password="plop")
self.client.post(
@ -250,7 +244,6 @@ class UVUpdateTest(TestCase):
"""
def setUp(self):
call_command("populate")
self.bibou = User.objects.filter(username="root").first()
self.tutu = User.objects.filter(username="tutu").first()
self.uv = UV.objects.get(code="PA00")
@ -341,13 +334,13 @@ class UVCommentCreationAndDisplay(TestCase):
Display and creation are the same view
"""
def setUp(self):
call_command("populate")
self.bibou = User.objects.filter(username="root").first()
self.tutu = User.objects.filter(username="tutu").first()
self.sli = User.objects.filter(username="sli").first()
self.guy = User.objects.filter(username="guy").first()
self.uv = UV.objects.get(code="PA00")
@classmethod
def setUpTestData(cls):
cls.bibou = User.objects.get(username="root")
cls.tutu = User.objects.get(username="tutu")
cls.sli = User.objects.get(username="sli")
cls.guy = User.objects.get(username="guy")
cls.uv = UV.objects.get(code="PA00")
def test_create_uv_comment_admin_success(self):
self.client.login(username="root", password="plop")
@ -473,7 +466,6 @@ class UVCommentDeleteTest(TestCase):
"""
def setUp(self):
call_command("populate")
comment_kwargs = create_uv_comment_template(
User.objects.get(username="krophil").id
)
@ -533,11 +525,11 @@ class UVCommentUpdateTest(TestCase):
Test UVComment update rights
"""
@classmethod
def setUpTestData(cls):
cls.krophil = User.objects.get(username="krophil")
def setUp(self):
call_command("populate")
self.krophil = User.objects.get(username="krophil")
# Prepare a comment
comment_kwargs = create_uv_comment_template(self.krophil.id)
comment_kwargs["author"] = self.krophil
@ -624,7 +616,6 @@ class UVSearchTest(TestCase):
"""
def setUp(self):
call_command("populate")
call_command("update_index", "pedagogy")
def test_get_page_authorized_success(self):
@ -794,8 +785,6 @@ class UVModerationFormTest(TestCase):
"""
def setUp(self):
call_command("populate")
self.krophil = User.objects.get(username="krophil")
# Prepare a comment
@ -1023,8 +1012,6 @@ class UVCommentReportCreateTest(TestCase):
"""
def setUp(self):
call_command("populate")
self.krophil = User.objects.get(username="krophil")
self.tutu = User.objects.get(username="tutu")

View File

@ -18,6 +18,7 @@ from datetime import date, timedelta
from django.core.management import call_command
from django.test import TestCase
from django.urls import reverse
from django.utils.timezone import localtime, now
from club.models import Club
from core.models import User, RealGroup
@ -27,22 +28,21 @@ from subscription.models import Subscription
class MergeUserTest(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
call_command("populate")
def setUpTestData(cls):
cls.ae = Club.objects.get(unix_name="ae")
cls.eboutic = Counter.objects.get(name="Eboutic")
cls.barbar = Product.objects.get(code="BARB")
cls.barbar.selling_price = 2
cls.barbar.save()
cls.root = User.objects.get(username="root")
cls.to_keep = User.objects.create(
username="to_keep", password="plop", email="u.1@utbm.fr"
)
cls.to_delete = User.objects.create(
username="to_del", password="plop", email="u.2@utbm.fr"
)
def setUp(self) -> None:
super().setUp()
self.to_keep = User(username="to_keep", password="plop", email="u.1@utbm.fr")
self.to_delete = User(username="to_del", password="plop", email="u.2@utbm.fr")
self.to_keep.save()
self.to_delete.save()
self.client.login(username="root", password="plop")
def test_simple(self):

View File

@ -113,6 +113,8 @@ MIDDLEWARE = (
"core.middleware.SignalRequestMiddleware",
)
TEST_RUNNER = "sith.testrunner.SithTestRunner"
ROOT_URLCONF = "sith.urls"
TEMPLATES = [

9
sith/testrunner.py Normal file
View File

@ -0,0 +1,9 @@
from django.core.management import call_command
from django.test.runner import DiscoverRunner
class SithTestRunner(DiscoverRunner):
def setup_databases(self, **kwargs):
res = super().setup_databases(**kwargs)
call_command("populate")
return res

View File

@ -102,9 +102,9 @@ class SubscriptionUnitTest(TestCase):
class SubscriptionIntegrationTest(TestCase):
def setUp(self):
call_command("populate")
self.user = User.objects.filter(username="public").first()
@classmethod
def setUp(cls):
cls.user = User.objects.filter(username="public").first()
def test_duration_one_month(self):
s = Subscription(