Session du 26 septembre 2024 à 20h00
Veille & Discussions
Qualité & Architecture
TDD en Python
Nous mettrons en place l'approche TDD
00:00:00 :Et voilà, je me disais que c'est ok, pour moi c'est bon.Donc vous voyez mon écran, c'est bon pour vous ?Ouais on voit ton écran.
00:00:17 :Bonsoir à tous et merci d'être revenu pour ceux qui étaient là la semaine dernièreet pour ceux qui viennent de reprendre en cours, merci d'être là et tout.
00:00:33 :Donc nous ce qu'on avait fait la semaine dernière, on avait initié un projet,donc une todo list en tdd.Donc l'approche du tdd c'était vraiment donc d'écrire nos testset les tests ont driver l'écriture de notre code.
00:00:53 :D'accord ?Je mets en vide, voilà.Donc on avait à partir de là, on avait donc testé la création d'une todoet qu'on ne pouvait pas toggle une todo qui n'existe pas.
00:01:11 :Ensuite on pouvait la toggle, c'est à dire de false à true, elle a été faite la tâche.Ensuite on avait testé qu'on ne pouvait pas supprimer une todo qui n'existe pas,on ne pouvait pas supprimer une todo qui n'était pas encore terminéeet enfin on a implémenté la suppression de la todo.
00:01:34 :Donc en fait le plus gros effet, vous l'avez compris, il nous reste à mettre à jour notre todo.Mais juste avant ce que j'ai envie de faire, c'est,valueError c'est pas significatif, c'est pas aussi explicite de l'erreur que je souhaite lever.
00:01:54 :Moi ce que je souhaite lever c'est une todo not found exception.Donc ça va être une exception comme quoi ma todo n'existe pas.Ici je ne peux pas supprimer une todo qui n'existe pas la même chose.
00:02:15 :Donc todo not found exception.Je ne peux pas supprimer une todo qui n'est pas terminée,du coup je vais mettre une exception todo not done exception.
00:02:29 :Et je crois que c'est tout.Du coup je vais devoir créer ces exceptions.Pour ça dans todo list je vais créer todo exception.On n'a pas 50, du coup je vais les regrouper dans le même fichier.
00:02:45 :Donc je vais créer la classe todo not found exception.Je vais zoomer un peu.Exception qui, pour pouvoir avoir le même comportement qu'une erreur, qu'une exception,celle-ci va hériter de exception.
00:03:08 :Quand je vais appeler le init, ce init va invoquer le super,donc va invoquer le constructeur, la méthode magique init de l'exception.Moi je ne vais pas lui passer des arguments, je vais juste lui mettre todo not found.
00:03:30 :Je vais faire la même chose.Je vais faire la même chose avec, donc, todo not done.todo not done.Je vais lancer, alors je préfère toujours un terminal à part.
00:03:51 :Tu y arrives, ok.Je ne sais plus où que je l'ai mis.Bon, je vais utiliser ce terminal parce que je ne sais plus où que je l'ai mis.
00:04:07 :Ah ouais, je l'ai mis dans desktop dev, ok.Donc, top, desktop, dev, string, todo listed, voilà.Et donc je vais lancer pytest.Du coup, il y a une erreur.
00:04:30 :Il y a une erreur, pourquoi ? Parce que je n'ai pas importé mes exceptions.Et todo not done exception.Qu'est-ce qu'il me dit ?Un supported operand type, un type, c'est où le problème ?
00:05:01 :C'est où le problème ?C'est dans todo list, un not type.C'est bizarre ça.Alors, déjà je vais aller dans mes use case, je verrai juste après.
00:05:25 :Dans mes use case, là ce que je propage, quand il n'y a pas de todo,je ne vais plus propager une value error non existing todo,je vais propager du coup todo not done exception, d'accord.
00:05:43 :Et je vais propager ici également la todo not done exception.Et ici, je vais propager la todo not done exception.Maintenant, pourquoi mon test ne s'y passe pas ?
00:06:01 :Ah, c'est parce que je ne suis pas dans la bonne version de Python.Je vais prendre API Env, lui sera bon lui.Pytest, voilà.Donc mes six tests passent, d'accord.
00:06:23 :Il me reste un dernier cas à faire, vous l'avez compris.Je vais mettre à jour une todo.Nous, on commence toujours par gérer les exceptions.
00:06:33 :Je sais que je ne peux pas update todo not existing.Je ne peux pas faire ça.J'aurai besoin d'un repository.Le repository, souvenez-vous, qui provient de ma fixture.
00:06:53 :Les fixtures vont me permettre d'initialiser des objets ou des réglages.Donc la repository me renvoie un objet repository.New todo va utiliser la fixture juste au-dessus pour m'envoyer une nouvelle tâche.
00:07:11 :Et new todo done, je vais utiliser la todo qui est juste au-dessus.Je vais la toggle pour avoir une todo qui est done, d'accord.Donc là, j'ai besoin du repository et j'ai besoin d'une nouvelle todo.
00:07:27 :D'accord.Donc update todo use case.Donc update todo use case.Il a besoin d'un repository.Et je sais que j'aurai une erreur.Donc pytest doit lever l'erreur todo not found.
00:07:55 :Quand je vais essayer de mettre à jour la todo sur une ID qui n'existe pas.Non existing ID.Et je vais lui donner un nouveau titre, new title.
00:08:10 :Donc bien sûr, si on suit le principe de TDD, on lance.Mon test échoue.Je vais devoir créer le use case.Hop, dans todo use case.
00:08:28 :Qui hérite de l'abstraction, la classe abstraite use case.Et j'ai juste à définir le code.Donc cette fois-ci, il aura un ID et il aura un new title.
00:08:50 :D'accord.L'ID, il est de type str.Et new title, il est de type str.Ok.Je vais, j'en vois rien ici.Alors vous savez, pour info, si vous allez dans open user settings json.
00:09:15 :Ici on a le tag checking mode.Donc python analysis tag checking mode.Moi je l'ai mis en basique.Si je le mets en strict, ça va s'allumer de partout.
00:09:28 :Pourquoi ? Parce que vraiment il s'attend à ce que je type tous les éléments.D'accord.Moi je vais le mettre en basique pour avoir vraiment un typage basique.
00:09:39 :Mais sachez que si vraiment vous voulez vous challenger, vous le mettez en strict.Et là vous allez voir, ça va s'allumer de partout et vous devez justement typer tous les éléments pour éviter que ça gueule.
00:09:52 :Donc je vais récupérer une todo grâce à mon repository getById en lui donnant l'ID.Si je n'ai pas de todo, donc si todo is none, alors je propage une todo not foundException.
00:10:13 :D'accord.Dans le test todo list, je mets hop, je l'importe.Donc il faut bien comprendre que comme je vous l'avais dit la dernière fois, le but c'est de faire passer nos tests.
00:10:28 :Donc c'est vraiment step by step.Je dois faire passer ce test.Je n'ai pas implémenté toute la logique de mise à jour.J'ai juste écrit assez de code pour faire passer mon test.
00:10:43 :C'est vraiment ça l'esprit TDD.J'écris un minimum de code pour faire passer mon test.D'accord.Une fois que mon test passe, je vais du coup mettre en place le test qui va mettre à jour update todo.
00:11:04 :D'accord.Donc on aura toujours notre repository.On aura notre nouvelle new todo.Je vais aller chercher ça.D'accord.Je vais update todo use case.Je vais utiliser le new todo l'id de new todo.
00:11:29 :Et je lui donne un nouveau titre, new title.Pour vérifier qu'il a bien mis à jour mon titre, je vais récupérer la todo depuis le repository.
00:11:47 :Get my id, la nouvelle todo id.Et je m'assure dans un premier temps que je vérifie que fetch todo is not null.Et je m'assure que fetched todo title est bien égal à new title.
00:12:18 :Donc si je lance mon test, il échoue.D'accord.Pourquoi ? Parce que j'ai un new todo, mais là j'ai new title.D'accord.Donc je dois mettre en place la logique.
00:12:37 :Pour mettre en place la logique, une fois que j'ai récupéré la todo, je modifie le title qui sera égal au new title.Et je demande à mon repository de mettre à jour ma todo.
00:12:58 :Il a besoin de l'id.D'accord.Alors là il a besoin d'une todo.Ouais c'est bon parce que je l'ai modifié, excusez-moi.Donc je vais modifier le titre et je lui passe la nouvelle todo.
00:13:12 :D'accord.Donc si tout se passe bien, tous mes tests passent.D'accord.Donc sachez une chose, déjà quelques notions.A use case c'est quoi ?A use case on a tendance à croire que c'est une feature.
00:13:38 :On a tendance à croire que c'est une feature, une fonctionnalité.Non.A use case c'est beaucoup plus précis qu'une fonctionnalité.A use case par exemple c'est, en tant que nouveau client, je veux créer un nouveau compte.
00:13:53 :En tant que déjà client, je veux créer un deuxième compte.En tant que client, je voudrais créer un compte conjoint.En fait les use case c'est toutes les possibilités, ça va être toutes les possibilités en fait.
00:14:08 :C'est plus qu'une fonctionnalité, c'est vraiment les différents cas que vous pouvez faire sur une fonctionnalitéquand vous allez ouvrir un compte dans une application style Conto ou N26.
00:14:24 :En fait vous avez la fonctionnalité de créer un compte,mais les use case ça va être les différentes possibilités de créer un compte.D'accord.Donc maintenant qu'on a terminé en fait, parce qu'on a vraiment terminé ici le projet,on a projeté l'idée, vous avez remarqué une chose, c'est qu'à aucun moment, il n'y a pas de print.
00:14:50 :Il n'y a aucun print dans mon code pour vérifier si en effet ça se passe bien, j'ai bien la donnée, j'ai bien la todo.Pourquoi ? Parce que mes tests me suffisent.
00:15:01 :Pas besoin de print.Je n'ai pas de main, un fichier main qui va venir tester ces différentes possibilités pour voir si ça fonctionne bien.Je n'en ai pas besoin.
00:15:10 :D'accord.Maintenant, on a le cœur de notre application qui est ici.On va créer un dossier, je vais créer un dossier qu'on appelle dans le jargon de la clean architecture,on va appeler ça l'infrastructure.
00:15:34 :Ce qui est bien c'est que ma todo list fonctionne.Mes tests me disent qu'elle fonctionne ma todo list.Pas besoin de vérifier qu'on se soit.
00:15:45 :Maintenant, ce cœur de todo list, je vais l'utiliser où ?Je peux l'utiliser par exemple dans une application API.Par exemple.Je peux l'utiliser dans un GUI.
00:16:04 :Par exemple, pas Qt.Je peux l'utiliser dans une application web style Django.D'accord.Je n'en ai pas besoin.En fait, on va séparer vraiment le cœur de notre projet avec l'infrastructure, comment il va être utilisé.
00:16:23 :D'accord.Je vais vous faire un exemple.On va rester sur une API, ça va être plus rapide.Dans l'API, alors on a l'infrastructure, on va créer un dossier data base.
00:16:39 :D'accord.Ici, je vais créer le mail.py.D'accord.Au niveau de la base de données, on va créer une connexion à notre base de données.On ne va pas se prendre la tête.
00:17:02 :On va utiliser SQLite.D'accord.Et SQLichemie.Dans SQLichemie, on va importer CreateEngine.Et depuis SQLichemie.org, on va importer SessionMaker.Ma DB URL, comme je l'ai dit, je ne vais pas me prendre la tête.
00:17:27 :Ça va être un SQLite.Je vais rentrer dans l'infrastructure, dans le dossier data base et je vais mettre ma todo list.db.Je vais créer GetEngine.
00:17:47 :D'accord.Pour récupérer le moteur.Je vais retourner CreateEngine en lui passant le DB URL.Et je vais récupérer GetSession.J'ai besoin du moteur.J'ai de la chance qu'il est juste au-dessus.
00:18:09 :GetEngine.Alors, SessionMaker, lui, il crée une classe.C'est pour ça qu'on met Session en majuscule.Parce que SessionMaker, on va le bind.Pas besoin, je peux mettre directement le engine.
00:18:30 :En fait, SessionMaker va créer une classe Session.Du coup, moi, ce que je retourne, c'est une instance de cette session.D'accord.Donc là, la collection de ma base de données, elle est fonctionnelle.
00:18:46 :Maintenant, il y a un truc qui est...Parce qu'on est dans du typage.Il faut bien garder à l'esprit qu'on est en mode typage.Si on n'avait pas de type, on ne se prendrait pas autant la tête.
00:18:58 :Quelqu'un qui a son micro allumé ?Excusez-moi.Donc.Euh...Moi, ce que je vais faire, c'est que je vais créer un modèle.Alors, il y a une différence.
00:19:24 :Vous pourriez vous dire, ouais, il y a une entité et il y a un modèle.En fait, l'entité, c'est ce qui me permet de typer mes todos à l'intérieur de TodoList.
00:19:39 :Alors que le modèle, c'est ce qui va me permettre de créer des objets.En fait, de créer des objets et ensuite de les enregistrer dans ma base de données.
00:19:51 :D'accord.Donc ça, c'est le todomodel, on l'appelle.todomodel.py.D'accord.Le todomodel, en fait, on va...Alors, comme je vous l'ai dit, c'est assez rapide.Alors, comme je vous l'ai dit, c'est assez rapide.
00:20:07 :Parce que c'est...Moi, le but, c'est vraiment de vous montrer comment, après avoir utilisé le TDD et mis en place justement le cœur, comment l'utiliser.
00:20:22 :D'accord.Comment l'utiliser sans avoir à modifier quoi que ce soit.D'accord.Vraiment, on ne va même plus toucher à notre TodoList.Alors, à part une petite chose légère, mais on ne va même plus y toucher.
00:20:35 :On va importer...Alors, est-ce qu'il y a la chimie.ext ?Non.C'est pareil, en fait.On va importer déclarative.Déclarative base.Donc, on va créer notre base.
00:20:57 :Déclarative base.Donc, elle aussi, elle crée une classe.D'accord.On va récupérer notre moteur.On en aura besoin pour créer nos tables.Notre table, parce qu'il n'y en a qu'une seule.
00:21:14 :Donc, là, on a TodoModel.Donc, qui va hériter de base.Donc, la base qui vient de déclarative base.Le nom de ma table, tableName, va s'appeler Todo.
00:21:31 :A l'intérieur, j'ai un ID.Donc, c'est une colonne de type chaînes de caractères.N'oubliez pas que notre quantité, c'est quoi ?C'est un ID de type chaînes de caractères.
00:21:45 :Un title, chaînes de caractères et donne booléens.D'accord.Donc, c'est ce qu'on lui dit.Donc, c'est de type string.Non.Z, c'est pas celui-ci.C'est celui de H.Q.H.I.B.
00:21:57 :Et ça va être notre primarie qui...Donc, notre clé primaire.Le title, donc, c'est une colonne, lui aussi, de type string.Par contre, nullable, nullable, false.
00:22:16 :Et enfin, le don, le don,c'est une colonne de type booléen,qu'on va récupérer de...et nullable, false,mais par défaut, on peut lui mettre une valeur par défaut,ça va être un false.
00:22:37 :Et ensuite, je dis à ma base,metadata,create,create, all,en utilisant le moteur.D'accord ?Maintenant, la seule modification qu'on va fairedans notre entité,dans notre entité,c'est...
00:23:02 :En fait, que ce soit...En fait, le souci, c'est quej'ai besoin...On est dans le typage, d'accord ?Et, en fait, on va rajoutermodèle config, ici.
00:23:22 :Donc, config.dict,depuis,rendAttribute,on.D'accord ?Maintenant,pour créerpour créer une todo,pour créer une todo, je n'ai pas besoin de l'id,puisqu'il est généré automatiquement.
00:23:45 :Pour créer une todo, je n'ai pas besoin de l'id.Et pour...Et je n'ai pas besoin du don,parce qu'il est par défaut.Pour créer une todo, j'ai besoin juste de lui donner un title.
00:23:57 :Et comme on est dans du typage,comme on est dans du typage,je vais créer un modèletodo,create,base, modèle,dont lui aura juste un title,de type str.
00:24:14 :Et vous allez voir qu'on va l'utiliser,en fait, dans FastAPI.Voilà.Donc,maintenant, c'est quoi le souci ?C'est que,pour envoyer des donnéesdepuis mon applicationvers une base de données,et que je suis en typage,c'est vraiment comme je le disais, c'est parce qu'on est en typage
00:24:40 :qu'on se prend un peu la tête, ici.Je dois convertir un objetde type todoen un objetde type todo modèle.D'accord ?Parce que je suis dans du typage,fort,pour envoyer des donnéesvers la base de données,je vais devoir convertirun objet todoen un objet todo modèle.
00:25:08 :Comme ça, ensuite, j'ai juste à lancer...Comme ça, vous connaissez,ça va créer directementune nouvelle tâche dans la base de données.Et l'inverse,quand je voudrais récupérer depuisma base de données,je vais devoir convertir un todomodèle en un,en une entité todo.
00:25:28 :D'accord ?Alors, je ne sais pas si vous avez compris, c'est vraiment...C'est parce qu'on est en modetypage. S'il n'y avait pas de typage,
00:25:36 :comme je vous l'ai dit, je ne me prendrais pas la tête.Donc, du coup, dans ma basede données, database, je vaiscréer ce qu'on appelle un todoconverteur.
00:25:46 :Ok ?Ça va être une classequi s'appelle todo converteur.Et je vais en faire un helper.Ça veut dire queje vais en faire des méthodes statiques.
00:26:00 :Lui,il va transformer un modèleen entité.Donc, modèlede typetodo modèle.Il va renvoyerune todo.Alors, il faut que je l'apporte.Ça va être simple.
00:26:20 :C'est que je retourne regardertodo.Alors, c'est du pas identique.Donc, je peux utilisermodèlevalidate.Et je lui donne le modèle.Donc, lui, il va me transformerce que je récupère de la basede données en une entité.
00:26:42 :Et ma deuxième méthode statique,elle, elle va me transformerune entitéen modèle.Donc, je lui donne une entitéde typetodo.Et ça me renvoie un todo modèle.
00:27:00 :Alors, c'est quand on l'utilisera que vous allez voirpourquoi c'est intéressant d'avoirmis un todo converteur.Donc là, je vais retournerun todo modèle.Et un todo modèle,l'id seraégal àentity.id
00:27:20 :Le titlesera égalàentity.titleEt enfin,le don seraégal à entity.donD'accord?Ok.Ça, c'est bon.Maintenant, regardons nos use case.
00:27:48 :Nos use case,ils doivent recevoirun répositoryd'accord?De type todo repository.Et vous vous souvenezde ce qu'on avait vu la dernière fois.Il est où?
00:28:04 :Il est là.Vous vous souvenez de ce que j'avais dit?J'avais dit quele fait d'avoir créé un protocolele fait d'avoir créé un protocoletodo repository va me permettrede passer d'unrepository facilement.
00:28:20 :Moi, je vais créer quoi? Le SQLitetodo repository.Donc, je peux le mettredans l'infrastructure. On peut séparer.Il y en a, ils disent, dans le database.
00:28:30 :Alors, c'est sujet à discussion.La structure,on peut trouver mieux que ça et tout.Moi, je vais créerun nouveau dossierqui s'appelle repositories.Si demain, j'ai envie de changerde repositories,là, je vais créerSQLitetodo repository.
00:28:54 :.py.pyD'accord?Donc,je vais créer du coup ma classeSQLitetodorepository.OK.Alors,mainitpour construire, j'ai besoind'uneen fait, d'une sessionde typesession.
00:29:32 :Alors, session, il nele détecte pas.Donc,en fait, il vient depuisSQLalchimie. On va importernon, c'estSQLalchimie.orgsi je ne dis pas de bêtises. On va
00:29:50 :importer la session.D'accord?Donc, on va faireself.sessionest égalà session.Alors,maintenant,je vais mettre ça à droite.Il est où mon protocole?
00:30:12 :Mon protocole,il estlà.Voyez?Pour queSQLite todo repositorypuisse être acceptépar mes use case,je dois implémentertout ça. D'accord?Je dois implémenter tout ça.
00:30:34 :Donc,je vaisle getby ID.Donc, pour récupérer,j'ai besoin d'un IDde type str.Ok?Et en fait,j'ai ma todo.Je vais dire à ma sessionde faire une queryde faire une querysur todo modelen filtrantfilteurtodo model.id doit être
00:31:10 :égal à l'ID que je lui passe.Je lui demande de me passerle premier élément.Et c'est là que ça va être intéressant.Parce quelà,ce que je récupère, vous l'avez compris,je récupère un todo model.
00:31:26 :D'accord?Je récupère un todo model.Moi, ce que je veux pour mon application,ce n'est pas un todo model, c'est une entité.Du coup, je vais retourneren utilisant le todoconverteur, lui dire,transforme-moi le modèle en entité.
00:31:42 :Voici le modèle.Si, bien sûr,il y a une todo.Sinon, tu me mets non.Pourquoi? Parce que, regardez bien quefirstAh, qu'est-ce qu'il fait?
00:31:56 :Ouais, bon, todome dit que, voilà, c'est dû à first.Todo, c'est soitil a trouvé quelque chose, soit il n'a rien trouvé.D'accord?Ok?
00:32:10 :Active.Donc, le save pour sauvegarderune todo.Donc, savetodo de type todo.Ok?Bon, pour sauvegarder,d'abord,n'oubliez pas que ça, c'est une entité.
00:32:32 :D'abord, je vais créerle modèleavec mon todo converteur.Je lui dis, convertis cette fois-cidepuis une entitéen un modèle, la todoque je te donne.
00:32:46 :Et là, je vais pouvoir demanderà ma sessiond'ajouter cetodo modèle.Et je commit.Ah, il faut session.Je commit.D'accord?Pour le update,pour le update,save IDde type str,todo depuistodo.
00:33:16 :Je vais demanderà la sessionde querysur le todo modèlede filtrer.Filter.Donc,todo modèle.id doit êtreégal à l'ID.Et je vais en profiter pour mettreà jour update tout de suitepourle titleen le récupérantdepuis le todo.title
00:33:48 :etle dondepuistodo.don.L'ID, je n'y touche pas.Une fois que c'est fait, je commit.Toujours,j'oublie session.OK?Enfin,le delete.D'accord?Donc, self.
00:34:18 :Self.Pour delete, j'ai besoind'un ID de type str.Et là, c'est simple. Je demandeà la session query.Donc, je récupère, comme d'habitude,modèle.
00:34:32 :Je filtre.Filter.Todo.model.idest égal à l'ID.Et je supprime.Et je n'oublie pasde commit.Alors, moi, ce que je vais faire,ce que je vais faire,parce que j'en aurai besoin,c'est que je vais monter dans mon protocoledef.getAll.
00:35:02 :D'accord?Qui va me renvoyer, en fait,qui va me renvoyertoutes les tâches.D'accord?Donc, en fait, il va me renvoyerune liste detous les todos.
00:35:20 :D'accord?Alors, j'en profite vite fait,parce que sinon mes tests,ils risquent d'échouer.Parce que dans todoinMemory,dans leinMemory,inMemorytodoRepository,je dois mettrele getAll.
00:35:50 :Sinon, il ne respecte pasmon, comment dire,il ne respecte pasmon protocole.Et lui, en fait, ce que je vais retourner,ce que je vais retourner,c'est une listede toutesles valuesde todo.
00:36:10 :Voilà.C'est terminé, il ne va pas gueuler.Donc, le getAllici,getAllself,qui varenvoyer, donc on a une listede todo.Hop.Donc, alors ça, ça va être intéressantparce que je vais récupérer tous mes todosen demandant à la sessionde faire une querysur todo
00:36:46 :modèleall. Donc, je vais tous les récupérer.Mais ce que je récupère,ce sont des modèles.D'accord? Moi, ce que je veux,ce sont des entités. Donc, ce que je vais
00:36:58 :retourner, c'est un autreERAY avec une liste de compréhensionoù je demande àtodoConverter de modifiertous les modèles en entitéde chaque todoqui trouvera,chaque todo qui trouveraà l'intérieur detodos. OK?
00:37:18 :Etici,d'accord,je crois quec'est bon. Je pense qu'il va gueulersur ça.On attendpour voir, mais je pense qu'il va gueuler.Bon.
00:37:36 :Maintenant,tout est prêt.D'accord? Tout est prêt.Ce que je vais faire, c'estdans main, ici,dans main,je vais créermon API. Donc,FastAPI.
00:37:54 :Je vais créermon Repository.Donc, c'estune DB.Donc, depuissqlchemy.org,je vais importersession.Donc, ma DB,ma DB ou ma session,d'accord? Moi, je préfère
00:38:16 :l'appeler DB.C'est juste pour donner l'idée que je suis dansune base de données, mais en vrai, c'est une session.D'accord?Elle, elle va dépendre. Donc, on va utiliser
00:38:26 :dépense deFastAPI. Elle va dépendrede get session.D'accord?Et ça doit renvoyer, si je fais du typagefort, ça doitrenvoyer. Alors,souvenez-vous, on ne dépend pas del'augmentation, on dépend de l'abstraction.
00:38:44 :D'accord? Je ne vais pas dire que ça renvoieun sqlitetodo repositoryparce que demain, je peux très bien changerde base de données. Donc, je vais dire
00:38:54 :que ça renvoie comme type todorepository.Et là, ce que je vais faire, c'est que je vais retournerune instancede sqlite todorepository. D'accord?
00:39:06 :Alors, qu'est-ce qu'il me demande?Missingla session, oui, la sessioncdb. Voilà.Et qu'est-ce qu'il me dit encore?sqlite is not aAh, voilà, vous voyez, il y a un problème, c'esttodos. D'accord?
00:39:22 :Donc, todosc'est dans mon protocolej'ai un dictionnairetodoDonc là, forcément, dans sqlite,je dois le déclarer.D'accord?HumBonLà, ça a l'air d'être bonsi je vais voir dans le mail, voilà.
00:39:50 :Donc,première chose,première chose,mon API, doncapp.getje veux récupérertoutes les tâches.D'accord?get todoLà, je ne vais pas me prendre la têterepositoryLà, je ne fais pas appel à mes use cases.
00:40:14 :D'accord? Pour l'instant, c'est juste pour tester.Doncet dégageexcusez-moi, dépenseexcusez-moic'est-à-dire simuler le creuxdansdans sqlite todoc'est exactement ça, ouais, pour simulerAlors, dans le in-memorytodo repository, en effet, j'ai simuléun creux. D'accord?
00:40:46 :La question c'est, en fait, tu viens de faireles méthodes pour simuler le creuxDoncau début, tant que je suis dans mestests et qu'il n'y a pas d'infrastructuretant que je suis dans mes tests et qu'il n'y a pas d'infrastructurej'ai pas envie de mettre en place
00:41:00 :une base de donnéeson utilise ce qu'on appelle un in-memorypour simuler, comme tu as ditune connexion à une base de données et mettreles différentes méthodes pour sauvegardermettre à jour des lettres, etc.
00:41:12 :Et maintenantque je crée l'infrastructureune API avec FastAPIcette fois-ci je dois mettre en placeune vraie base de données, sqlite todorepository, et là c'est un vraicru celui-ci. D'accord? C'est pas une
00:41:26 :simulation, ça va être un vrai cruD'accord?Donc dans le mailj'ai une basede repositoryOkEt là je vais pas me prendre la têtecomme je vous ai dit, je vais juste dire à repositoryde get all, juste pour voirsi mon API fonctionneDoncpour lancer
00:41:54 :mes tests c'est bonpour lanceron va utiliser uvcornuvcorn, tiens il est làFastAPInon je l'ai appeléapp-apiapp-apimain, reloadapp, normalement, voilà c'est bonmon API, voyezmon API est lancéet tout de suitema base de données a été crééeD'accord? Alors pour ça
00:42:26 :on va utiliserdata-server-clienthopje vais créer une nouvelle collectionSQLite, je vais aller la chercherelle estdansnon c'est pas ça, desktopdevdocstreamtodo list, infrastructuresdatabase, todo listdb, je me connecteje sauvegardedonc ça c'estdatabase clientdonc voyez ma todo elle est là
00:43:02 :avec un id, un titleet donedonc ma table a bien été créée, c'est que la chimie a fait le tafmaintenant pour testerpour tester mon APImoije vais utiliser un autreune autre extensionqui s'appelle rest-clientd'accord, je ne vais pas ouvrir un postmanparce que c'est assez basique
00:43:24 :ce qu'on est en train de faire et toutdonc je ne vais pas ouvrir un postman, voici rest-clientça, ça fait super bien le tafce que vous allez faire c'est que vous allez créeren fait un fichier qui s'appellerequest.http
00:43:36 :et c'est làque vous allez mettre vospar exempleJSvous mettez GetAllpour récupérer toutes les tâchesdonc c'est une méthode Getsur le http...
00:43:54 :localhostil me le propose, c'est bienle port 8000d'accord, et là vous voyez vous avez un petit boutonici send requestil me récupère toutes mes tâches, il n'y en a aucuned'accord, donc ça fonctionne correctementmaintenantje vais créer une tâchedonc je vais créer le chemin
00:44:14 :et c'est là qu'on va utiliserle use casehopil est où ?il est làdoncapppostpour créer quelque chosedonc slash tododonc createtodookon a toujours besoindu repositorybonmais cette fois-ci en plus du repositoryje vais avoirle body de la requête
00:44:57 :d'accord, pourquoi ?parce que je vais créericihop, createtododonc c'est avec une méthodepost http...localhost todomais cette fois-ci je vais avoirun bodyje vais avoir un bodymais juste ici je vais préciserle content typeapplicationque je les ai et là je vais avoir un body
00:45:29 :et mon body c'est seulement un titlevous voyeza new tododoncce bodyet on le récupère où ? on le récupère làtodoet lui il est de quel type ?
00:45:45 :alors là c'est intéressantlà il est de quel type ? en faitdansmes entités je vous avais dit quepour créer une tâchej'ai besoin justedu titleparce que tout le resteest par défautdonc done et false par défautet il a dit c'est pas moi qui le gère
00:46:07 :du coup je vais dire que c'esttodocreate le typeon appelle ça aussides schémas ça dépend dujargonhopdonclàje vais créer mon use casecreate todouse casequi est égal àcreatetodo use caseil a besoin durepositoryet je demande au create
00:46:51 :todo use casede créer du coupma tâche grâceavec le titreque je récupère du jsondonc que je vais récupérer iciavec le titreça il va me renvoyera new todod'accordje vais l'appeler create todoet moi ce que je vais faire c'estque je vais retourner
00:47:17 :createcreate todookje lance ma requesthopqu'est ce qu'il me ditil me dit que j'ai oubliéj'ai oublié quelque chosec'est quoi que j'ai oubliéhopon va voirparce qu'il ne faut pas coller en faitquand tu as une tag et voyezj'ai créé une nouvelle todo
00:47:47 :l'id a bien été généréd'accordnew todoet si je vais voir dans ma base de donnéesje peux voir que ma todoa bien été créé avec l'id etcle use case s'est chargéde toutle use case s'est chargé de toutvoyezalors je sais ce que vous pourriez me dire
00:48:09 :mais Rachid Repository t'aurais pucréer une todooui mais mon use case il prépare toutil y a toute une logiqueaujourd'hui c'est simplec'est une tododonc mon use case forcément il est simpled'accordil y a deux lignesmais demainvotre use case peut contenirbeaucoup de code
00:48:33 :c'est ce qu'on appelle la séparation des préoccupationsj'ai un use case qui se chargede chose et j'ai un repositoryqui se charge de sauvegardermon repository ne va pas tout faireon ne peut pas demander à un repositoryde faire çale repository se charge de sauvegarderséparation des préoccupations
00:48:53 :d'accorddonc si je créesi je demandeget allvous voyez j'ai un arrêtexcusez moi j'ai une listequand vous avez fait du tab script toute l'après midivous appelez ça des arrêtsj'ai une listequi contient l'objetque je viens de créernew todo numéro 2par exemple
00:49:19 :je crée, je redemande à avoirça fonctionne bienc'est bon pour vousdoncce que je peux fairec'est vraimentmettre le point sur noscomment dire, là il y a un truc intéressantregardezpour que vous compreniez bien en faitpourquoi nos use casepourquoi on a mis nos use case
00:49:49 :pourquoi on a codé avec cette approche làregardez je vais dansje commence à m'hyper làici je vaisappalorsquelqu'un pose la questiondans le chatest-ce qu'au niveau des idest-ce qu'au niveau des idest-ce qu'ils seront uniquesou est-ce que je peux avoir des doublons
00:50:15 :alorsdansici en fait je génèreje crée un id avec uid4d'accorddonc uid4ça génère un idqui est costaud quand mêmemais rien ne garantitrien ne garantit que tu n'auras pas des doublonsrien ne garantit que tu n'auras pas des doublonsmais ça va être très très dur
00:50:41 :ça va être vraiment très très durmoi c'est vraiment parce que j'ai démarré sur du uidmais j'aurais pu faireun auto-incrémentet tu ne vas pas me prendre la tête et toutet puis ça fait 1, 2, 3 etcça pour avoir des doublons il faut y aller
00:50:55 :vraiment y allerparce qu'en plus tu peux choisir la taillele nombre de bitstu voisdoncon va togglealors pour toggleon va utiliser putparce qu'on est en train de modifier une tâchen'oubliez pas queen fait on est en train de modifieret put c'est la méthode qui permet de modifier
00:51:21 :doncsur le todotoggletoggleet làun id spécialdonc togglealors c'est surtout pour vous montrerles exceptions que tout çaça a été bien pensé donc toggle doneon va récupérerl'idici donc c'est un idde type strun repositoryd'accord toujours la même chose
00:51:53 :on récupère çaalors je ne suis pas un spécialistedeje ne suis pas un spécialiste de FastAPIpeut être qu'il y abeaucoup plus efficace que toujours répéter çad'accord je pensequ'il doit y avoir un truc mais bon je ne sais pasaujourd'hui c'est pas le propos
00:52:11 :d'accord donc toggledone use caseon va aller chercher notretoggle done use caseon va lui passer le repositoryet on va lui direde toggle doneuse case avecl'id qu'on a récupéré d'accorddoncon va dans notrehop on va dans notrerequestdans notre request on va créer
00:52:43 :une troisièmepoint toggledone tododonc làforcément on va aller récupérerun idil est làok mais moi je saisd'embléece que je vais faire c'est quece qui est bien avec le reste c'est que je peuxcréer une variable idet lui mettre cette valeur là
00:53:09 :comme ça à chaque foisj'appelle cette id au lieu de copier toujours la mêmeid là je vaisfaire un puthttp2.5 slashlocalhosttodo slash et làon va aller chercher l'idil le met directement en doubledouble à colladedoncvoyons voircette hache elle est
00:53:37 :falseok si je lancedétail not foundalors pourquoi détail not foundpourquoi détail not foundmaintogglerepositoryidquoi c'était peut-être l'id le problèmeattendezoù est-ce qu'on le met entre guillemetsdétail not foundhttp localhost8000 todoça c'est une bonne questionça c'est une bonne question
00:54:39 :ouais tu voisvariablealors attendezoh merdec'est du croissantah mais c'est normalparce que j'ai oublié togglevoilà c'est pour çavoyez c'est pas si expliciteje trouvej'aurais bien voulu un message beaucoup plusle end point n'existe pas c'est vrai quenot foundvoilà localhostn'existe pas
00:55:15 :alors là j'ai un internal servervoyons voirqu'est-ce qu'il me ditvoyeztodo not foundah ça c'est intéressantbon en fait il faut enlever les guillemets icivoilà et là ça va fonctionnervoyez nulça va fonctionnervoilà si je vais redemanderallet ça c'est intéressantça c'est intéressant parce que je voulais tester
00:55:43 :justement qu'une todo n'existe paset toutdonc par exemple je vais mettreun idnonexistingidd'accord en mettantje sais pas moi 5 5 5 5et si je refaisdoncuntoggledonetodonot existingd'accord existingdoncje copie ça ctrl cctrl vet là je vais mettre
00:56:27 :non existing iddonc là en effetinternal server errordonc ça c'est super parce quedéjà je peux voir que mon use case fonctionne très bienregardez bientodo not found exceptiond'accorddonc c'est juste à moi de gérer du côté de FastAPIdu côté de FastAPIde gérer cette erreur
00:56:51 :donc comment je vais faireen fait je vais lui direje vais lui dire d'essayertryetexceptalors tout ce que je peux récupérercommetout ce que je peux récupérer comme erreurça va être untodo not found exceptiond'accordasmsget en fait moi je vais retourner
00:57:19 :un json responsede FastAPIavecun statut code404et un contentqui sera égalà messageavec ce messageet là c'estsuper parce que maintenantmon request je le lanceinternalqu'est ce qu'il me ditalorsça c'est intéressantil me dit quoiil me dit que object of type todo not
00:57:57 :en faitcomment direil me dit que object of type todo not exceptionis not json serializabledonc en fait il ne peut pastransformer c'est dû à çac'est simple en faitc'est que le messageon va juste le convertir en stret là normalementon devrait être bon
00:58:21 :on a récupéré le messagede notre erreur de notre exceptionet il s'affiche icid'accordvoilàje pense que vous avez comprispour le reste comment mettre en placelele delete, le updateetc.
00:58:43 :je pense qu'on n'a pas besoin d'allerau delà et toutle but c'était vraiment de vous montrerl'approche tddet que comme vous avez puconstater moitout mon codea été driverpar ces tests làd'accordà chaque fois je faisais en sorted'écrire que lestrict minimum pour que mon test
00:59:09 :passealors sachez quesur un projet comme celui-ci vous l'avez comprisc'est assez bateaufacileà mettre en placevous avez dans des trèstrès gros projetsils vont créer vraiment un fichierà côtéun fichier je sais pas moitest.md
00:59:33 :et ils vontvraiment lister tous lestests qu'il doit fairevraiment tous les testsvous pouvez vous retrouver avec desune cinquantaine de lignesetc. et tout
Aucune occurrence trouvée pour « ».