mirror of
				https://github.com/ae-utbm/sith.git
				synced 2025-11-03 18:43:04 +00:00 
			
		
		
		
	En réorganisant les requêtes à la db, on diminue par 100 le temps d'exécution de la commande `rule_galaxy` (~6h => ~2min)
		
			
				
	
	
		
			204 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#
 | 
						|
# Copyright 2023
 | 
						|
# - Skia <skia@hya.sk>
 | 
						|
#
 | 
						|
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
 | 
						|
# http://ae.utbm.fr.
 | 
						|
#
 | 
						|
# This program is free software; you can redistribute it and/or modify it under
 | 
						|
# the terms of the GNU General Public License a published by the Free Software
 | 
						|
# Foundation; either version 3 of the License, or (at your option) any later
 | 
						|
# version.
 | 
						|
#
 | 
						|
# This program is distributed in the hope that it will be useful, but WITHOUT
 | 
						|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
						|
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
						|
# details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU General Public License along with
 | 
						|
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
 | 
						|
# Place - Suite 330, Boston, MA 02111-1307, USA.
 | 
						|
#
 | 
						|
#
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
from core.models import User
 | 
						|
from galaxy.models import Galaxy
 | 
						|
 | 
						|
 | 
						|
# @pytest.mark.skip(reason="Galaxy is disabled for now")
 | 
						|
class TestGalaxyModel(TestCase):
 | 
						|
    @classmethod
 | 
						|
    def setUpTestData(cls):
 | 
						|
        cls.root = User.objects.get(username="root")
 | 
						|
        cls.skia = User.objects.get(username="skia")
 | 
						|
        cls.sli = User.objects.get(username="sli")
 | 
						|
        cls.krophil = User.objects.get(username="krophil")
 | 
						|
        cls.richard = User.objects.get(username="rbatsbak")
 | 
						|
        cls.subscriber = User.objects.get(username="subscriber")
 | 
						|
        cls.public = User.objects.get(username="public")
 | 
						|
        cls.com = User.objects.get(username="comunity")
 | 
						|
 | 
						|
    def test_user_self_score(self):
 | 
						|
        """Test that individual user scores are correct."""
 | 
						|
        with self.assertNumQueries(1):
 | 
						|
            scores = Galaxy.compute_individual_scores()
 | 
						|
            expected = {
 | 
						|
                self.root.id: 9,
 | 
						|
                self.skia.id: 10,
 | 
						|
                self.sli.id: 8,
 | 
						|
                self.krophil.id: 2,
 | 
						|
                self.richard.id: 10,
 | 
						|
                self.subscriber.id: 8,
 | 
						|
                self.public.id: 8,
 | 
						|
                self.com.id: 1,
 | 
						|
            }
 | 
						|
            assert scores.items() >= expected.items()
 | 
						|
 | 
						|
    def test_users_score(self):
 | 
						|
        """Test on the default dataset generated by the `populate` command
 | 
						|
        that the relation scores are correct.
 | 
						|
        """
 | 
						|
        expected_scores = {
 | 
						|
            "krophil": {
 | 
						|
                "comunity": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "public": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "rbatsbak": {"clubs": 100, "family": 0, "pictures": 0, "score": 100},
 | 
						|
                "subscriber": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
            },
 | 
						|
            "public": {
 | 
						|
                "comunity": {"clubs": 0, "family": 0, "pictures": 0, "score": 0}
 | 
						|
            },
 | 
						|
            "rbatsbak": {
 | 
						|
                "comunity": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "public": {"clubs": 0, "family": 366, "pictures": 0, "score": 366},
 | 
						|
                "subscriber": {"clubs": 0, "family": 366, "pictures": 0, "score": 366},
 | 
						|
            },
 | 
						|
            "root": {
 | 
						|
                "comunity": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "krophil": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "public": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "rbatsbak": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "skia": {"clubs": 0, "family": 732, "pictures": 0, "score": 732},
 | 
						|
                "sli": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "subscriber": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
            },
 | 
						|
            "skia": {
 | 
						|
                "comunity": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "krophil": {"clubs": 114, "family": 0, "pictures": 2, "score": 116},
 | 
						|
                "public": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "rbatsbak": {"clubs": 100, "family": 0, "pictures": 0, "score": 100},
 | 
						|
                "sli": {"clubs": 0, "family": 366, "pictures": 4, "score": 370},
 | 
						|
                "subscriber": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
            },
 | 
						|
            "sli": {
 | 
						|
                "comunity": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "krophil": {"clubs": 17, "family": 0, "pictures": 2, "score": 19},
 | 
						|
                "public": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "rbatsbak": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "subscriber": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
            },
 | 
						|
            "subscriber": {
 | 
						|
                "comunity": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
                "public": {"clubs": 0, "family": 0, "pictures": 0, "score": 0},
 | 
						|
            },
 | 
						|
        }
 | 
						|
        computed_scores = {}
 | 
						|
        users = [
 | 
						|
            self.root,
 | 
						|
            self.skia,
 | 
						|
            self.sli,
 | 
						|
            self.krophil,
 | 
						|
            self.richard,
 | 
						|
            self.subscriber,
 | 
						|
            self.public,
 | 
						|
            self.com,
 | 
						|
        ]
 | 
						|
 | 
						|
        with self.assertNumQueries(44):
 | 
						|
            while len(users) > 0:
 | 
						|
                user1 = users.pop(0)
 | 
						|
                family_scores = Galaxy.compute_user_family_score(user1)
 | 
						|
                picture_scores = Galaxy.compute_user_pictures_score(user1)
 | 
						|
                club_scores = Galaxy.compute_user_clubs_score(user1)
 | 
						|
                for user2 in users:
 | 
						|
                    u1 = computed_scores.get(user1.username, {})
 | 
						|
                    u1[user2.username] = {
 | 
						|
                        "score": (
 | 
						|
                            family_scores[user2.id]
 | 
						|
                            + picture_scores[user2.id]
 | 
						|
                            + club_scores[user2.id]
 | 
						|
                        ),
 | 
						|
                        "family": family_scores[user2.id],
 | 
						|
                        "pictures": picture_scores[user2.id],
 | 
						|
                        "clubs": club_scores[user2.id],
 | 
						|
                    }
 | 
						|
                    computed_scores[user1.username] = u1
 | 
						|
 | 
						|
        self.maxDiff = None  # Yes, we want to see the diff if any
 | 
						|
        self.assertDictEqual(expected_scores, computed_scores)
 | 
						|
 | 
						|
    def test_rule(self):
 | 
						|
        """Test on the default dataset generated by the `populate` command
 | 
						|
        that the number of queries to rule the galaxy is stable.
 | 
						|
        """
 | 
						|
        galaxy = Galaxy.objects.create()
 | 
						|
        with self.assertNumQueries(39):
 | 
						|
            galaxy.rule(0)  # We want everybody here
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.slow
 | 
						|
# @pytest.mark.skip(reason="Galaxy is disabled for now")
 | 
						|
class TestGalaxyView(TestCase):
 | 
						|
    @classmethod
 | 
						|
    def setUpTestData(cls):
 | 
						|
        """Generate a plausible Galaxy once for every test."""
 | 
						|
        call_command("generate_galaxy_test_data", "-v", "0")
 | 
						|
        galaxy = Galaxy.objects.create()
 | 
						|
        galaxy.rule(26)  # We want a fast test
 | 
						|
        cls.root = User.objects.get(username="root")
 | 
						|
 | 
						|
    def test_page_is_citizen(self):
 | 
						|
        """Test that users can access the galaxy page of users who are citizens."""
 | 
						|
        self.client.force_login(self.root)
 | 
						|
        user = User.objects.get(last_name="n°500")
 | 
						|
        response = self.client.get(reverse("galaxy:user", args=[user.id]))
 | 
						|
        self.assertContains(
 | 
						|
            response,
 | 
						|
            f'<a onclick="window.focusNode(window.getNodeFromId({user.id}))">Reset on {user}</a>',
 | 
						|
            status_code=200,
 | 
						|
        )
 | 
						|
 | 
						|
    def test_page_not_citizen(self):
 | 
						|
        """Test that trying to access the galaxy page of non-citizen users return a 404."""
 | 
						|
        self.client.force_login(self.root)
 | 
						|
        user = User.objects.get(last_name="n°1")
 | 
						|
        response = self.client.get(reverse("galaxy:user", args=[user.id]))
 | 
						|
        assert response.status_code == 404
 | 
						|
 | 
						|
    def test_full_galaxy_state(self):
 | 
						|
        """Test with a more complete galaxy.
 | 
						|
 | 
						|
        This time, the test is done on
 | 
						|
        the more complex dataset generated by the `generate_galaxy_test_data`
 | 
						|
        command that the relation scores are correct,
 | 
						|
        and that the view exposes the right data.
 | 
						|
        """
 | 
						|
        self.client.force_login(self.root)
 | 
						|
        response = self.client.get(reverse("galaxy:data"))
 | 
						|
        state = response.json()
 | 
						|
 | 
						|
        galaxy_dir = Path(__file__).parent
 | 
						|
 | 
						|
        # 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())
 |