Aller au contenu
English

Travail final

  • Après le module 6
  • environ 4 h

Ce que vous saurez faire

Montrez que vous pouvez modifier un vrai projet Python de façon sûre, sans aide. Le changement apporte de nouvelles données, de nouvelles règles et de nouvelles sorties. Les tests, les journaux (logs) et le README rendent le projet fiable. Vous travaillez sur votre projet ticket-cleaner et vous gardez des preuves de chaque partie.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 240 minutes
  • Vous avez terminé les modules 1 à 6. Chaque partie ci-dessous nomme les leçons qu’elle utilise.
  • ticket-cleaner se trouve dans ~/projects/ticket-cleaner, comme à la fin de Qualité et passation : il s’exécute avec python -m ticket_cleaner, et python -m pytest et ruff check . réussissent.
  • Vous pouvez faire le travail en plusieurs séances. Avancez par petites étapes et exécutez les tests après chacune.
  • Si vous utilisez Git, faites un commit (enregistrement des modifications) avant de commencer, pour pouvoir comparer et revenir en arrière. Ce n’est pas obligatoire.

Le service de soutien a changé de système. Le nouvel export contient deux colonnes de plus :

Colonne Signification Valeurs permises
channel Comment le client a contacté le service de soutien email (courriel), phone (téléphone), chat (clavardage)
subject Le titre court du billet de soutien Tout texte qui n’est pas vide

La personne responsable du service de soutien demande quatre changements :

  1. Vérifier les nouvelles colonnes. Un billet sans canal connu ou sans sujet n’est pas valide. Les anciennes règles restent.
  2. Produire un rapport par canal. Le rapport contient un nouveau champ, by_channel : le nombre de billets sélectionnés par canal, comme by_category.
  3. Un mode strict. Une tâche nocturne exécute ticket-cleaner et doit savoir quand les données posent problème. Avec l’option --strict, le programme écrit le rapport comme d’habitude. Cependant, il termine avec le code de sortie 3 si au moins un enregistrement a été rejeté.
  4. Un court résumé dans les journaux. Au niveau INFO (information), le programme consigne aussi une ligne avec les nombres, par exemple INFO ticket_cleaner: 20 rows: 12 valid, 8 rejected (20 lignes : 12 valides, 8 rejetées).

Les fichiers dans l’ancien format, sans les nouvelles colonnes, ne sont plus pris en charge. Le programme rejette leurs enregistrements, comme prévu.

Téléchargez les deux fichiers du nouvel export dans votre dossier data. Ils contiennent les mêmes 20 billets : l’un vient d’un tableur (CSV), l’autre du service Web de soutien (JSON).

Fenêtre de terminal
curl -o data/tickets-v2.csv https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C02/data/tickets-v2.csv
curl -o data/tickets-v2.json https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C02/data/tickets-v2.json

Lisez tickets-v2.csv avant de modifier le code. Prédisez quelles lignes sont valides et pourquoi les autres ne le sont pas. Notez votre prédiction : vous la comparerez au résultat de votre programme dans la partie 2.

  • Faites un seul changement à la fois. Après chaque changement, exécutez python -m pytest. Ne commencez pas le changement suivant tant qu’un test échoue.
  • Pour chaque nouvelle règle, écrivez d’abord un test qui échoue. Modifiez ensuite le code jusqu’à ce que le test réussisse, comme pour le test de régression dans Des tests ciblés.
  • Avant de terminer une partie, exécutez ruff format . et ruff check .. Les deux doivent réussir.
  • Gardez la structure : validation dans parsing.py, types dans records.py, calculs dans report.py, commande dans cli.py.
  • Créez un fichier evidence.md à l’extérieur du dossier du projet, par exemple ~/projects/c02-evidence.md. Après chaque partie, copiez-y les sorties demandées.

Utilise Les enregistrements structurés, Le contrat d’une fonction et Des tests ciblés.

  1. Dans records.py, ajoutez les canaux permis, ajoutez channel et subject aux champs obligatoires, puis ajoutez ces deux champs à Ticket.
  2. Exécutez les tests. Plusieurs échouent maintenant, car ils créent des enregistrements et des billets sans les nouveaux champs. C’est normal : voyez l’erreur fréquente à la fin. Mettez à jour les données de test.
  3. Écrivez des tests pour les nouvelles règles. Un canal connu est valide, même avec des majuscules et des espaces. Un canal inconnu, comme fax, pose problème. Un sujet vide pose problème. Incluez les cas limites : un sujet contenant seulement des espaces et une clé channel absente.
  4. Modifiez find_problems et to_ticket jusqu’à ce que tous les tests réussissent. Le texte du problème pour un canal inconnu suit le modèle du statut : unknown channel 'fax' (canal inconnu « fax »).

Preuves pour la partie 1 :

  • Les nouveaux tests (copiez les fonctions de test).
  • La sortie de python -m pytest, avec tous les tests réussis.

Utilise Lire et écrire des fichiers et L’interface en ligne de commande.

  1. Ajoutez une fonction count_by_channel à report.py, avec un test, et ajoutez by_channel au résumé.

  2. Ajoutez l’option --strict à cli.py, avec son texte d’aide. Ajoutez des tests pour le code de sortie 3 avec des enregistrements rejetés, et 0 avec --strict et des données valides.

  3. Exécutez le programme sur le fichier CSV :

    Fenêtre de terminal
    python -m ticket_cleaner data/tickets-v2.csv --output reports/v2.json --strict
  4. Vérifiez votre résultat avec ces nombres. La sortie indique 20 lignes : 12 valides, 8 rejetées. Les lignes rejetées sont 5, 6, 8, 9, 10, 11, 16 et 17. Le code de sortie est 3. Pour les billets open (ouverts), selected (sélectionnés) vaut 7. Si un nombre diffère, utilisez la méthode de Lire les erreurs avant de modifier le code.

  5. Comparez avec votre prédiction de la section Obtenir les données. Pour chaque ligne où vous vous êtes trompé, écrivez une phrase : qu’a vu le programme que vous n’aviez pas vu?

  6. Exécutez le programme sur le fichier JSON, avec un autre fichier de sortie. Les deux rapports doivent être identiques. Ajoutez un test qui le prouve.

Preuves pour la partie 2 :

  • reports/v2.json de l’étape 3.
  • La sortie du terminal de l’étape 3 et le code de sortie.
  • Votre prédiction et les phrases de l’étape 5.

Utilise Exceptions et journalisation et Configuration et secrets.

  1. Ajoutez la ligne de résumé INFO de la demande 4 du responsable. Exécutez avec LOG_LEVEL=info et vérifiez qu’elle apparaît. Exécutez sans cette variable et vérifiez qu’elle n’apparaît pas.
  2. Exécutez le programme dans chacune des situations suivantes. Avant chaque exécution, prédisez la sortie et le code de sortie. Notez les deux, ainsi que le résultat réel :
    1. Un fichier qui n’existe pas.
    2. Un fichier JSON tronqué (créez-en un, comme dans Exceptions et journalisation).
    3. remote (distant) avec une valeur de TICKETS_URL qui renvoie 404.
    4. --status unknown.
    5. data/tickets-v2.csv sans --strict.
  3. Vérifiez qu’aucune sortie, ligne de journal ou fichier du projet ne contient de secret. Si vous avez testé avec un jeton (token), il était seulement dans une variable d’environnement.

Preuves pour la partie 3 :

  • Un tableau avec les cinq situations : votre prédiction, la dernière ligne réelle et le code de sortie.
  • La sortie avec LOG_LEVEL=info pour data/tickets-v2.json.

Utilise Isoler les dépendances et Qualité et passation.

  1. Mettez à jour le README : les nouvelles colonnes, l’option --strict, le code de sortie 3, la commande et la sortie d’exemple avec data/tickets-v2.csv.
  2. Si vous avez modifié requirements.txt, recréez le fichier de verrouillage dans un nouvel environnement.
  3. Faites le test sur une nouvelle copie : une copie sans .venv ni reports, un nouveau terminal et seulement le README. Ajoutez chaque étape manquante au README, puis recommencez jusqu’à ce que cela fonctionne.
  4. Dans la nouvelle copie, exécutez le programme selon le README, puis python -m pytest et ruff check ..

Preuves pour la partie 4 :

  • Le README.
  • La sortie des trois commandes dans la nouvelle copie.
  • La liste des étapes ajoutées au README à l’étape 3. « Aucune » est une réponse valide seulement si tout a fonctionné au premier essai.

Ce cours n’a pas encore de réviseur. Examinez vos propres preuves avec ce tableau, ou demandez à un collègue de l’utiliser. Marquez chaque élément comme démontré, partiellement démontré ou pas encore démontré, avec une raison. Le cours est terminé quand chaque élément est démontré. Vous pouvez améliorer un élément et le réexaminer aussi souvent que nécessaire.

Preuve requise Démontré quand
Installation reproductible Une nouvelle copie fonctionne avec seulement le README. Le fichier de verrouillage contient seulement les paquets de requirements.txt et leurs dépendances. Le projet ne contient aucun secret.
Traitement correct des enregistrements valides et invalides Les résultats correspondent aux nombres de la partie 2 pour les deux fichiers. Chaque enregistrement rejeté a son numéro de ligne et toutes les raisons du rejet. Valides + rejetés = toutes les lignes. Rien n’est supprimé sans indication.
Code modulaire et tests ciblés Chaque nouvelle règle et fonction a un test qui compare une valeur exacte, y compris les cas limites et les chemins d’erreur. Vous avez vu chaque test échouer avant que son code existe. Le code reste dans le module qui correspond à son rôle. ruff check . réussit.
Journaux utiles et README permettant l’exécution Les erreurs prévues donnent une ligne claire et le code de sortie 1, et les commandes incorrectes donnent 2. --strict donne 3. Un défaut affiche toujours sa trace d’appels. Le README répond aux questions de Qualité et passation, avec les commandes et la sortie attendue.

Un parcours sans erreur qui fonctionne ne suffit pas. Des enregistrements invalides peuvent être perdus, ou un chemin d’erreur de la partie 3 peut donner un mauvais code de sortie. L’élément est alors pas encore démontré, même si le rapport semble correct.

Erreur courante

Plusieurs tests échouent après un petit changement

Symptôme : après l’ajout de channel et subject à Ticket, beaucoup de tests échouent avec :

TypeError: Ticket.__init__() missing 2 required positional arguments: 'channel' and 'subject'

Cause : les tests créent des objets Ticket et des enregistrements bruts avec les anciens champs. Le contrat de Ticket a changé. Chaque endroit qui en crée un doit donc changer aussi. Les tests ont trouvé tous ces endroits pour vous. C’est leur rôle.

Correction :

  1. Mettez d’abord à jour les données de test partagées : la fixture (données préparées pour les tests) valid_raw et la fixture tickets dans test_report.py. Plusieurs tests les utilisent, donc plusieurs échecs disparaissent ensemble.
  2. Exécutez les tests de nouveau et corrigez ceux qui échouent encore, un à la fois, depuis le début de la sortie.
  3. Ne supprimez pas un test qui échoue pour rendre la sortie verte. Si un test vérifie quelque chose qui n’est plus vrai, modifiez ce qu’il vérifie et expliquez pourquoi dans vos preuves.

Récapitulatif

Dans ce cours, vous êtes passé d’un terminal et d’un premier script à un projet qu’une autre personne peut installer et utiliser avec confiance :

  • Environnement : un dossier de projet, un environnement virtuel et un fichier de verrouillage qui recrée le même environnement partout.
  • Code : valeurs, collections, conditions et boucles, organisées en fonctions avec des contrats, en modules et en dataclasses (classes de données).
  • Données : fichiers CSV et JSON et service Web, avec une validation qui rejette les enregistrements incorrects avec une raison, sans suppression silencieuse.
  • Fiabilité : traces d’appels et points d’arrêt pour trouver les causes, exceptions pour les erreurs prévues, journaux avec contexte et tests des cas normaux, des cas limites et des chemins d’erreur.
  • Passation : une interface en ligne de commande avec des codes de sortie, du formatage et de l’analyse statique (linting), et un README testé sur une nouvelle copie.

Tous les cours suivants du programme utilisent ces habitudes : SQL et préparation des données, création d’une API et cours sur les applications d’IA.