IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Analyse d'un projet Python


Sujet :

Python

  1. #1
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 64
    Par défaut Analyse d'un projet Python
    Bonjour à tous...
    Je suis à la recherche d'un outil, qui devrait exister, mais dont j'ignore le nom.
    Cela s'apparenterait à un outil de test dont j'attends le résultat suivant :
    Je veux tester un projet composé de plusieurs modules, de plusieurs imports également et bien entendu d'un script initial qui intègre tout ce beau monde.
    Ce dont je rêve existe dans d'autres langages : on configure l'outil, on lance le script (disons celui qui contient le main-loop())
    on l' exécute ... ou on l'analyse.
    Dans le premier cas : exécution. Le test retourne alors le nom des fonctions par où il est passé. Ce qui n'est déjà pas trop mal.
    Dans le second cas : analyse. Alors là c'est le reve absolu, Le test vous sortirait un fichier texte qui serait une version texte d'un organigramme. Idéalement il ne serait même pas nécessaire de l'exécuter.
    J'avoue être assez brouillon, et parfois, je m' aperçois en modifiant quelque chose que j'ai fait une grosse bêtise et qu'une fonction est appelée plusieurs fois. Et même si cela ne porte pas à conséquence, j'aimerais l'éviter. Ne serait-ce pour ne pas passer pour un crétin, quand je donnerais le produit fini à ceux de mes amis qui pourraient être intéressés.
    Si donc cela existe, et que ça peut être utilisé relativement simplement, merci de m'indiquer le ou les noms de ces saints graal que je recherche.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Citation Envoyé par azad2b Voir le message
    Si donc cela existe, et que ça peut être utilisé relativement simplement, merci de m'indiquer le ou les noms de ces saints graal que je recherche.
    Les mots clefs pour chercher des outils sont "call graph" et "static code analysis".
    Les bons outils sont payants et les sorties intéressantes pour tapisser un bureau et impressionner les chefs... mais comme aujourd'hui on bosse en open space, ça ne va pas être coton.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 64
    Par défaut
    Bonsoir
    Pour avoir posé sur ce forum quelques questions dignes du débutant que je suis, et avoir souvent obtenu de wistricks des réponses toujours appréciées, je vais faire les recherches indiquées. Mais me fiant à son savoir, je pars perdant. Merci de votre réponse et bonne soirée.
    Ha, pour la petite histoire, dans les années 80 Apple utilisait un langage appelé APW qui permettait d'approcher mon rêve de façon assez naïve. Mais vous avez sans doute raison. Dans mon cas la solution la plus bébète est encore de copier/coller dans toutes mes fonctions un print('bien le bonjour de la fonction xxx) de ranger tout cela proprement dans un dictionnaire et ainsi de (peut-être) réussir à faire de mon rêve, une réalité.
    Merci encore Monsieur wistricks...

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Citation Envoyé par azad2b Voir le message
    Dans mon cas la solution la plus bébète est encore de copier/coller dans toutes mes fonctions un print('bien le bonjour de la fonction xxx) de ranger tout cela proprement dans un dictionnaire et ainsi de (peut-être) réussir à faire de mon rêve, une réalité.
    Il y a des bibliothèques qui font déjà çà. Si vous cherchiez un peu avec les mots clefs indiqués vous trouveriez quelque chose d'intéressant (il faut tester, voir si ce que çà sort répond aux attentes, passer à autre chose,...).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Bonjour,

    Pour des erreurs d'inattention, cherchez du côté des linters
    • black
    • pylint
    • flake8
    • ...


    Attention tout de même à ne pas les mélanger, certains peuvent entrer en conflits sur des détails de la PEP8.

    @wiztricks a déjà parlé de "static code analysis", les plus connus me concernant sont,
    • SonarQube
    • MyPy


    Pour tester, on fait des tests unitaires et fonctionnels,
    • pytest
    • selenium
    • unittest
    • ...


    Bref il y a l'embarras du choix

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 831
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 831
    Billets dans le blog
    1
    Par défaut
    Bonjour

    En cherchant "call graph" mentionné par wiztricks, je suis rapidement tombé sur cette page.

    Le truc étant dispo sous Linux (Ubuntu), je l'ai installé directement (aptitude install python3-pycallgraph) et l'ai testé sur un petit code que j'avais en stock
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #!/usr/bin/env python3
    # coding: utf-8
     
    class cComplex:
    	def __init__(self, reel=0, img=0):
    		(self.reel, self.img)=(reel, img)
    	# __init__()
     
    	def __str__(self):
    		return "%s, %si" % (self.reel, self.img)
    	# __str__()
     
    	def __add__(self, other):
    		if isinstance(other, (int, float)): other=self.__class__(other, 0)
    		elif isinstance(other, self.__class__): pass
    		else: raise TypeError(
    			"on ne peut pas additionner un complexe avec un {}".format(type(other).__name__)
    		)
     
    		return self.__class__(self.reel + other.reel, self.img + other.img)
    	# ___add__()
     
    	def __radd__(self, n): return self+n
    # cComplex()
     
    a=cComplex(5, 2)
    print(a)
    print(a+1)
    print(1+a+1)
    print(a+cComplex(2, 2))
    print(a+"toto")

    Résultat
    Nom : pycallgraph.png
Affichages : 289
Taille : 30,7 Ko

    Attention, si le programme se complexifie, le graphe se complexifie de façon exponentielle
    Exemple
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    #!/usr/bin/env python3
    # coding: utf-8
     
    import random
    from collections import Counter
     
    # Objet qui gère le jeu
    class cGame:
    	RCK=0x01
    	PPR=0x02
    	SCS=0x03
    	pieces={
    		RCK : {
    			"label" : "Caillou",
    			"win" : (SCS,),
    		},
    		PPR : {
    			"label" : "Papier",
    			"win" : (RCK,),
    		},
    		SCS : {
    			"label" : "Ciseaux",
    			"win" : (PPR,),
    		},
    	}
     
    	def __init__(self, p1, p2, rnd):
    		super().__init__()
    		self.__p1=p1
    		self.__p2=p2
    		self.__rnd=rnd
    	# __init__()
     
    	def debug_rules(self):
    		for v in cGame.pieces.values():
    			yield "%s éclate %s" % (
    				v["label"],
    				", ".join(cGame.pieces[x]["label"] for x in v["win"]),
    			)
    		# for
    	# debug_rules()
     
    	# Evaluation résultat
    	def __evaluate(self, m1, m2):
    		if m2 in cGame.pieces[m1]["win"]: return m1
    		if m1 in cGame.pieces[m2]["win"]: return m2
    		return 0
    	# __evaluate()
     
    	def play_round(self):
    		move1 = self.__p1.move()
    		move2 = self.__p2.move()
    		self.__p1.learn(move1, move2)
    		self.__p2.learn(move2, move1)
    		print("Player1 played : %s" % cGame.pieces[move1]["label"])
    		print("Player2 played : %s" % cGame.pieces[move2]["label"])
    		e=self.__evaluate(move1, move2)
    		if e == move1:
    			print("Player1 win")
    			self.__p1.win()
    		elif e == move2:
    			print("Player2 win")
    			self.__p2.win()
    		else:
    			print("Draw")
    		print("Player 1: %d" % self.__p1.score)
    		print("Player 2: %d" % self.__p2.score)
    	# play_round()
     
    	# Function for playing multiple games
    	def play_game(self):
    		print("\nGame start! \n")
    		for rnd in range(1, self.__rnd + 1):
    			print("\nRound %d/%d:" % (rnd, self.__rnd))
    			self.play_round()
    		# for
    		print("Game over! \n")
    		print("Score p1 : %d" % self.__p1.score)
    		print("Score p2 : %d" % self.__p2.score)
    	# play_game()
    # class Game
     
    # Objet qui gère un joueur
    class cJoueur:
    	score=property(lambda self: self.__score)
    	moves=property(lambda self: tuple(self.__moves))
    	def __init__(self):
    		super().__init__()
    		self.__score=0
    		self.__moves=list()
     
    	def win(self):
    		self.__score+=1
     
    	def learn(self, m1, m2):
    		self.__moves.append((m1, m2))
    # class cJoueur()
     
    # Objet qui joue aléatoirement
    class cJoueurRandom(cJoueur):
    	def move(self):
    		return random.choice(tuple(cGame.pieces.keys()))
    # class cJoueurRandom()
     
    # Objet qui joue le dernier coup de son adversaire
    class cJoueurReflect(cJoueurRandom):
    	def move(self):
    		return self.moves[-1][1] if self.moves else super().move()
    # class cJoueurReflect()
     
    # Objet qui joue la pièce qui battra la plus jouée par son adversaire
    class cJoueurFindMax(cJoueurRandom):
    	def move(self):
    		if not self.moves:
    			return super().move()
     
    		# Compteur des pièces jouées par l'adversaire
    		c=Counter(x[1] for x in self.moves)
     
    		# Récupération de la pièce la plus jouée par l'adversaire
    		pieceM=random.choice(tuple(k for (k, v) in c.items() if v == max(c.values())))
     
    		# Récupération des pièces pouvant battre la pièce la plus jouée
    		m=tuple(k for (k, v) in cGame.pieces.items() if pieceM in v["win"])
     
    		# Choix d'une pièce au hasard parmis celles-là
    		return random.choice(m)
    	# move()
    # class cJoueurFindMax
     
    # Objet qui joue la pièce qui battra la moins jouée par son adversaire
    class cJoueurFindMin(cJoueurRandom):
    	def move(self):
    		if not self.moves:
    			return super().move()
     
    		# Compteur des pièces jouées par l'adversaire
    		c=Counter(x[1] for x in self.moves)
     
    		# Récupération de la pièce la moins jouée par l'adversaire
    		pieceM=random.choice(tuple(k for (k, v) in c.items() if v == min(c.values())))
     
    		# Récupération des pièces pouvant battre la pièce la moins jouée
    		m=tuple(k for (k, v) in cGame.pieces.items() if pieceM in v["win"])
     
    		# Choix d'une pièce au hasard parmis celles-là
    		return random.choice(m)
    	# move()
    # class cJoueurFindMin
     
    # Objet qui joue la pièce qui battra la pièce qui battra la plus jouée par son adversaire
    class cJoueurFindMaxInv(cJoueurFindMax):
    	def move(self):
    		# Récupération de la pièce qui battra la plus jouée
    		pieceM=super().move()
     
    		if not self.moves:
    			return pieceM
     
    		# Récupération des pièces pouvant battre cette pièce
    		m=tuple(k for (k, v) in cGame.pieces.items() if pieceM in v["win"])
     
    		# Choix d'une pièce au hasard parmis celles-là
    		return random.choice(m)
    	# move()
    # class cJoueurFindMaxInv
     
    # Objet qui joue la pièce qui battra la pièce qui battra la moins jouée par son adversaire
    class cJoueurFindMinInv(cJoueurFindMin):
    	def move(self):
    		# Récupération de la pièce qui battra la moins jouée
    		pieceM=super().move()
     
    		if not self.moves:
    			return pieceM
     
    		# Récupération des pièces pouvant battre cette pièce
    		m=tuple(k for (k, v) in cGame.pieces.items() if pieceM in v["win"])
     
    		# Choix d'une pièce au hasard parmis celles-là
    		return random.choice(m)
    	# move()
    # class cJoueurFindMinInv
     
    # Programme principal
    import sys
    g=cGame(cJoueurFindMin(), cJoueurRandom(), int(sys.argv[1]))
    g.play_game()

    Résultat
    Nom : pycallgraph.png
Affichages : 277
Taille : 210,6 Ko
    On peut toutefois obtenir aussi une version de type "listing".
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    bonjour

    Existe aussi beaucoup d'outils (pas exactement la demande) comme

    cprofile
    pprofile
    line-profiler
    memory-profiler
    ...
    pyheat
    perfplot
    palanteer
    pyinstrument
    py-spy
    ...

  8. #8
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 603
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 603
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Bonjour,

    Pour des erreurs d'inattention, cherchez du côté des linters
    • black
    • pylint
    • flake8
    • ...


    Attention tout de même à ne pas les mélanger, certains peuvent entrer en conflits sur des détails de la PEP8.
    On peut les mélanger sans soucis. black et flake8 sont des prérequis dans mon pôle de devs pour tout nouveau projet. Avec mypy, pytest et pytest-mock car nous bossons en Test Driven Development (TDD).

    pylint, personnellement je l'utilise, même si notre techlead n'aime pas trop (M'en fous ).

    Citation Envoyé par fred1599 Voir le message
    Pour tester, on fait des tests unitaires et fonctionnels,
    • pytest
    • selenium
    • unittest
    • ...
    Je plussois pour les tests, unitaires à minima, fonctionnels et d'intégration lorsque nécessaire.

    Et pourtant, j'ai mis à temps fou à penser "test" avant de penser "code". Gymnastique compliquée au début (faire volontairement planter un test sur une méthode n'existant pas encore, puis coder la méthode jusqu'à ce que le test passe au vert).

    Mais quand on y prend gout, difficile de s'en passer après.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 831
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 831
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Arioch Voir le message
    Gymnastique compliquée au début (faire volontairement planter un test sur une méthode n'existant pas encore, puis coder la méthode jusqu'à ce que le test passe au vert).
    Bizarre. Généralement je code une méthode parce que j'ai besoin d'un travail... puis je teste si la méthode effectue correctement ledit travail...

    Ou alors tu parles de méthodes un peu génériques (exemple tous tes objets doivent posséder une méthode "affich()" donc ton test appelle systématiquement ".affich()" sur tous les objets existants...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 603
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 603
    Par défaut
    Non non, je parle de TDD : le codage d'une appli mené par les tests.

    Par tests, j'entends : en utilisant pytest, les mocks, monkeypatch.

    Pour chacun de nos projets, nous procédons comme ceci :

    - besoin de créer une méthode à une classe ? On crée d'abord un test et on s'assure en premier lieu que tous les résultats possibles traités/retournés par la méthode (non encore créée) seront présents dans le test (la fixture parametrize de pytest est excellente pour ça).
    - on exécute pytest. La méthode n'existant pas encore, il se plaint : on crée la méthode.
    - tant que le test ne passe pas au vert, on peaufine la méthode.
    - maintenant que le test passe au vert (pytest ne se plaint plus), on passe au test suivant.

    Un exemple tout bête et simpliste : écrire le test pour une méthode n'existant pas encore et qui va additionner deux nombres.

    Le test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    import pytest
    from my_class import MyClass # la classe contenant la future méthode d'addition, add_values()
     
     
    class TestMyClass:
        def test_add_values_is_ok(self) -> None:
            assert MyClass().add_values(1, 2) == 3
    En exécutant pytest, il beugle : pas trouvé de méthode add_values dans la classe MyClass.

    Ok, alors go to the code !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class MyClass:
        def add_values(self, a: int, b: int) -> int:
            return a + b
    On exécute pytest : il est content.

    Maintenant, la méthode n'est pas tip top, question sécurisation. 1+1 == 2, mais a+1 ?

    Alors on se rajoute un test dans TestClass :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    def test_add_bad_values(self) -> None:
            with pytest.raises(MyClassError):
                MyClass().add_values(1, "deux")
    Ici, je veux que le résultat de l'addition de 1 + deux lève une exception MyClassError (exception personnalisée). Pytest se plaint encore : MyClassError n'existe pas.

    Alors je rajoute l'exception dans le fichier de ma classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class MyClassError(Exception):
        """MyClass errors exception."""
     
     
    class MyClass:
         # voir code plus haut
    Je relance pytest mais il se plaint toujours. L'exception levée n'est pas MyClassError mais TypeError et le test reste au rouge.

    Logique : je n'ai pas géré le cas où le user me demanderai d'additionner un entier avec une chaîne. Go dans la classe et la méthode add_values() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MyClassError(Exception):
        """MyClass errors exception."""
     
     
    class MyClass:
        def add_values(self, a: int, b: int) -> int:
            try:
                return a + b
            except TypeError as err:
                raise MyClassError from err
    Je relance pytest : le test s'assurant que l'exception est levée en additionnant 1 + "deux" passe au vert.

    Alors certes : l'exemple ici est simpliste, puéril, débile ? Mais il illustre notre manière de fonctionner : pas de code sans avoir produit le ou les tests qui s'assurent que le code sera bon.

    Et quand il faut mocker le retour d'une méthode de classe, pytest-mock rentre en action. Ci-dessous, on mocke add_values() de manière à ce que, quels que soient les deux entiers qui lui sont fournis, le résultat de l'addition donnera toujours 10 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    import pytest_mock
     
    def test_add_values_returns_ten(self, mocker: pytest_mock) -> None:
            mocker.patch.object(MyClass, "add_values", return_value=10)
            assert MyClass().add_values(1, 2) == 10
    Le test (qui ne sert strictement à rien, on est d'accord) passe au vert puisqu'on a forcé la méthode add_values de MyClass à retourner 10.

    On mocke beaucoup de choses, comme par exemple une base de données. On mocke la méthode connect() pour éviter d'avoir à se connecter pour de vrai. Certaines méthodes sont chiantes à mocker (faut aller dans le code source de la méthode, voir ce que la méthode fait, ce qu'elle attend pour dire si c'est ok ou pas, etc). Quand ça devient trop complexe, on "espionne" l'appel à la méthode que l'on teste. Si notre test fait appel à la méthode 3 fois, on place un espion (pytest-spy) dessus, on joue notre test et on s'assure que l'appel à la fonction == 3.

    C'est mon quotidien dans le se(r)vice ou je bosse. Et à chaque évolution de code, tous les tests sont joués lorsque nous "pushons" le code dans le repo car nous travaillons en CI/CD : on pushe en dev, les tests sont joués et si validés, le code est automatiquement pushé en recette. Là, intervention manuelle du recetteur qui valide les évolutions, puis déclenche le push d'après vers la pré-prod, etc etc.

  11. #11
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    On peut les mélanger sans soucis. black et flake8 sont des prérequis dans mon pôle de devs pour tout nouveau projet
    Mon expérience me dit que non, mais tant que la problématique n'est pas arrivée, je comprends que continuer de cette manière est logique.

    Avec mypy, pytest et pytest-mock car nous bossons en Test Driven Development (TDD).
    J'aime bien la TDD, c'est une manière de voir le développement... c'est mon avis, mais ça ne veut pas dire que d'autres manières de développer un projet sont mauvaises pour autant.
    Par exemple, dans une start-up où les changements sont courants, peut rendre difficile le développement en "mode TDD".

  12. #12
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 603
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 603
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Mon expérience me dit que non, mais tant que la problématique n'est pas arrivée, je comprends que continuer de cette manière est logique.
    Ah ce n'était point une critique à ton encontre hein

    Je dis juste qu'on se sert quotidiennement de ces modules et que nous n'avons jamais eu de surprise désagréable en les utilisant.

    Citation Envoyé par fred1599 Voir le message
    J'aime bien la TDD, c'est une manière de voir le développement... c'est mon avis, mais ça ne veut pas dire que d'autres manières de développer un projet sont mauvaises pour autant.
    Par exemple, dans une start-up où les changements sont courants, peut rendre difficile le développement en "mode TDD".
    Ah ça, c'est notre manière de développer et je suis heureux de savoir qu'ailleurs, l'herbe est plus verte.

    Là où un dev est capable de coder un programme en une journée mais sans tests, nous il nous faut entre 2 et 3 * plus de temps.

    Nous avons des impératifs de temps, comme pour beaucoup de devs, mais notre impératif n°1 est que ça fonctionne du premier coup et qu'il n'y ait pas de mauvaises surprises une fois en production.

  13. #13
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Nous avons des impératifs de temps, comme pour beaucoup de devs, mais notre impératif n°1 est que ça fonctionne du premier coup et qu'il n'y ait pas de mauvaises surprises une fois en production.
    On en perd encore plus en essayant de stabiliser une application avec des tests unitaires. Mieux vaut soit,

    • écrire les tests suite à son développement
    • écrire les tests avant de développer ses fonctionnalités (TDD)


    Là où un dev est capable de coder un programme en une journée mais sans tests, nous il nous faut entre 2 et 3 * plus de temps.
    ça me paraît beaucoup, pour en avoir fait sur un sujet très bien défini. La TDD demande à avoir une idée très précise des fonctionnalités, pour les tester via des tests unitaires et vérifier que les fonctionnalités attendues sont présentes.

    Ah ce n'était point une critique à ton encontre hein
    Je ne l'ai absolument pas pris de cette manière, au contraire, je trouve toujours intéressant de parler de nos expériences respectives.

    Je dis juste qu'on se sert quotidiennement de ces modules et que nous n'avons jamais eu de surprise désagréable en les utilisant.
    Et je maintiens que tu as raison de continuer de cette manière, et qu'il sera toujours temps quand tu rencontreras ce type de problème ou un autre, de résoudre cela.

  14. #14
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 64
    Par défaut
    Hé bien merci à tous de vos essais et remarques.. Je suis resté longtemps sans participer, mais j'ai fait énormément de test. Mais hélas aucun n'a été concluant. J'arrive à des choses sympa, avec les différents produits que vous m'avez conseillés, mais je ne peux traiter que les fonctions une par une. Cela est probablement dû à la stucture (si j'ose dire) de mon projet.
    Bref je baisse les bras. Merci beaucoup, je vais repartir sur une autre piste.

Discussions similaires

  1. Devellopeur pour Projet Python
    Par ju_bicycle dans le forum Général Python
    Réponses: 0
    Dernier message: 24/03/2010, 16h36
  2. [WD12] Plusieurs Analyses dans un projet
    Par J0r_x dans le forum WinDev
    Réponses: 11
    Dernier message: 27/08/2009, 11h56
  3. Analyse d'impact projet J2EE
    Par isaacgaye dans le forum Intégration Continue
    Réponses: 3
    Dernier message: 01/04/2009, 11h58
  4. packager un projet python
    Par ad1lux dans le forum Déploiement/Installation
    Réponses: 1
    Dernier message: 22/04/2008, 12h17
  5. taille d'un projet Python
    Par planeur2007 dans le forum Général Python
    Réponses: 4
    Dernier message: 05/06/2007, 15h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo