Session du 19 septembre 2024 à 20h00
Veille & Discussions
Qualité & Architecture
TDD en Python
Nous mettrons en place l'approche TDD
00:00:00 :Bonsoir à tous et merci d'être venu à cet événement live coding.Le but de ce soir c'est de parler de le TDD, d'accord, donc Test Driven Development avec le langage Python, d'accord.
00:00:25 :Qu'est-ce qu'on sait du TDD ?Donc TDD, en fait le principe du TDD c'est d'écrire un test qui va échouer, on sait d'emblée qu'il va échouer.
00:00:43 :Une fois que le test a échoué, on va faire en sorte qu'il passe.Il faut écrire le moins de codes possible qu'il passe le test.
00:00:53 :On ne va pas au-delà, c'est vraiment step by step, en mode vraiment pas à pas qu'on va résoudre un problème, un gros problème.C'est-à-dire que c'est un gros problème, on va le casser en petits morceaux afin de le résoudre.
00:01:12 :Donc on a un test qui va échouer, on fait en sorte en minimum de codes de le faire passer.Si c'est nécessaire, on refactorise le code et ensuite on passe à l'étape suivante.
00:01:28 :Aujourd'hui le TDD, dans beaucoup de cas, il est très mal compris.Les développeurs, qu'est-ce qu'ils font ?Ils écrivent du code et ensuite ils vont écrire les tests pour tester leur code.
00:01:44 :Alors que le TDD c'est tout l'inverse.Le TDD c'est je n'écris aucune ligne de code tant que le test ne me le dira pas.C'est ça la vraie approche, l'approche authentique du TDD.
00:02:04 :Je n'écris rien tant que mon test ne me le demandera pas.Aujourd'hui ce qu'on va faire, c'est qu'on va créer une application TodoList.Certes, je vous l'accorde, c'est toujours le TodoList.
00:02:19 :Mais vous allez voir qu'avec TodoList, on va avoir énormément de concepts autour de la programmation orientée objet,autour de l'architecture logicielle et autour du TDD.
00:02:33 :Donc je vais créer deux dossiers.Mon dossier test.Et je vais créer mon dossier TodoList.Je vais écrire un fichier, c'est un notebook.Alors lui, il n'y a rien à faire ici, mais c'est juste pour vous montrer quelques bouts de codeau cas où vous voulez, comment dire, juste pour rappel sur certains concepts de la programmation orientée objet en Python.
00:03:05 :Je vais prendre un kernel.Je vais prendre la base, voilà.Donc, je souhaite créer une application TodoList.Je ne sais pas aujourd'hui si je veux en faire une application web, une interface graphique ou une API.
00:03:30 :Tout ce dont je sais, c'est que le cœur de l'application pourrait être utilisé dans n'importe quelle infrastructure.Et avec une approche test-driven-development, TDD, comme je vous l'ai dit, je ne code que si les tests me le demandent.
00:03:49 :Je code le cœur de l'application.Et toute l'originalité dans cette approche, c'est que je n'ai pas besoin de savoir quelle infrastructure.Je n'ai pas besoin de savoir si je vais utiliser PyQt.
00:04:03 :Je n'ai pas besoin de savoir si je vais utiliser une application web ou une API.Moi, je me concentre sur le cœur de l'application.Donc, je vais en faire des modules.
00:04:15 :Donc, init.py et TodoList.Je vais en faire également des modules init.py.Alors, j'ai le chat qui est ouvert.N'hésitez pas à poser des questions et tout. Je le vois en direct et tout.
00:04:36 :Pierre, comme ça, tu n'auras pas besoin de l'ouvrir et tout.Peut-être qu'à la fin, oui.Alors, comme j'ai dit, approche TDD.Je vais créer un fichier où je vais tester ma TodoList.
00:04:58 :Alors, pour que PyTest fonctionne, vos fichiers doivent commencer par test.D'accord?Et tous les tests à l'intérieur doivent également commencer par test.D'accord?Donc, je vais faire...
00:05:14 :Alors, je vais zoomer un peu.Voilà.Je vais faire un test trou.D'accord?On va voir si ça fonctionne bien.On va voir si ça fonctionne bien.
00:05:27 :Et je m'attends à ce que ça soit vrai.Dans le terminal...Excusez-moi.Le terminal, il est où mon terminal?Il est là.Donc, dans mon terminal, je lance PyTest.
00:05:50 :Et mon test passe.D'accord?Donc, jusque-là, c'est bon.Moi, mon premier test...Mon premier test, c'est de créer une todo.D'accord?Ça, c'est mon premier test.
00:06:12 :Alors, comment je vais créer ma todo?Je vais utiliser un dictionnaire.Dans ce dictionnaire, il aura un ID UID4 comme clé et comme valeur la todo.
00:06:31 :Donc, avec son ID, son title et est-ce que la todo est donne ou pas.Donc, en fait, je réutilise les IDs qui vont être générés dans ma todo.
00:06:44 :Je les réutilise comme des clés de mon dictionnaire.D'accord?L'idée, c'est de...Maintenant, je vais me poser la question.C'est que je dois stocker mes todos et pouvoir les récupérer de quelque part.
00:07:05 :Ce quelque part, je ne sais pas encore c'est quoi.Je sais que demain, ça pourrait être une base de données.Ça pourrait être une API.
00:07:16 :Je ne sais pas si c'est une base de données MongoDB ou de base de données MySQL.Je ne sais pas.D'accord?Donc, moi, tout ce que je sais, c'est que j'ai besoin de stocker quelque part.
00:07:32 :Ce quelque part, on l'appelle dans le jargon en développement un repository.D'accord?Un repository, c'est là où on va stocker nos données.Alors, ce n'est pas exactement là où on va stocker nos données.
00:07:47 :C'est l'objet pour être plus précis.Le repository, c'est l'objet qui va communiquer avec la base de données.Moi, ne sachant pas pour l'instant où je vais le faire, où je vais stocker mes données,je vais utiliser ce qu'on appelle un in-memory todo repository.
00:08:09 :C'est en mémoire.C'est en mémoire.Donc, je vais utiliser la mémoire de la RAM pour stocker mes, comment dire, mes todos.Maintenant, je vais avoir ce qu'on appelle un cas d'utilisation, un use case.
00:08:34 :Un cas d'utilisation, c'est create use case.Donc, ce sera une instance de create todo use case.Et pour créer cette tâche, elle aura besoin de connaître le repository.
00:09:03 :Où est-ce qu'elle va créer cette tâche?Où est-ce qu'elle va stocker cette tâche?Maintenant, moi, ce que j'ai envie de faire, c'est d'utiliser cette instancecomme, en fait, j'ai envie de rendre l'objet callable.
00:09:22 :Alors, je ne sais pas si, alors si je vous parle de ces, certains d'entre vous doivent le savoir,d'autres peut-être pas.Donc, pardonnez-moi si, ne vous sentez pas offensés si j'explique des concepts qui peuvent paraîtrebateau pour vous, mais il y en a peut-être d'autres dans ceux qui sont présents qui ne connaissent pas.
00:09:42 :Si j'ai une classe Adder avec, donc, un nombre.Donc, self nombre est égal à nombre.Moi, ce que je veux, c'est, donc, une instance de Adder.
00:10:10 :Donc, je vais lui donner un nombre 5, mais je veux appeler Adder comme une fonction.D'habitude, on fait point et on appelle ses méthodes.Donc, si j'avais une méthode ici, addition, d'accord, je ne sais pas, moi, je vais mettre A,et je retourne le self nombre plus A.
00:10:42 :Donc, le Adder, je vais faire point, hop, je valide, je vais faire Adder point l'addition, d'accord.Moi, je ne veux pas. Ce que je souhaite faire, c'est invoquer le Adder directement comme une fonction, le rendre callable.
00:11:01 :Et qu'est-ce qu'il me dit ? Il me dit Object of type Adder is not callable.Il n'est pas invocable.Pour le rendre invocable, il faut que j'implémente la méthode magique underscore, underscore, call, underscore, underscore.
00:11:16 :Donc, à la place de l'addition, je vais faire underscore, underscore, call, underscore, underscore.Et là, je vais lui donner, par exemple, 6.Je valide la cellule, je valide, et voyez, il a fait 5 plus 6.
00:11:35 :Moi, qu'est-ce que je veux faire ici ?Je veux que mon create use case soit callable.Et je vais lui donner une tâche, a new todo.
00:11:48 :OK, jusque là.Maintenant, la question, c'est quoi ?C'est, une fois que j'ai mis en place tout ça, comment je vérifie que ma tâche a bien été créée ?
00:12:00 :C'est simple, il me suffit de récupérer fetched todo, donc la récupérer depuis où ?Depuis le repository.Souvenez-vous que le repository, c'est lui qui communique avec la base de données.
00:12:14 :Et lui, je vais lui demander de me renvoyer la todo grâce à son ID.Grâce à son ID.Alors, comment je peux avoir l'ID de la todo que je viens de créer ?
00:12:27 :C'est simple, le callable de create todo use case me renverra cette todo qui a été créée.Created todo.Donc, ça veut dire que je récupérais, quand il va créer ma tâche, il va me renvoyer created todo.
00:12:50 :Et depuis created todo, je vais demander son ID.Et donc, je dois m'assurer que fetched todo n'est pas non, qu'il est bien présent dans ma base de données.
00:13:09 :Et je dois m'assurer que fetched todo, le title, a a new todo.Alors, double égal.C'est bon pour vous jusque là ?Ça fait beaucoup de code, je vous l'accorde.
00:13:31 :Tout ça.C'est le principe du TDD.Le principe du TDD, avec ses lignes de code, je sais d'emblée maintenant comment coder la création de ma nouvelle tâche.
00:13:49 :Première chose, je dois avoir un in-memory todo repository.Ok, on va dans todo list.Je vais créer le in-memory todo repository.Donc, in-memory todo repository.
00:14:18 :Ellipsis.Ellipsis, c'est équivalent à ce que je mets de passe, d'accord.Donc, je l'importe.Alors, pourquoi il ne veut pas me l'importer ?In-memory todo repository.
00:14:48 :Pourquoi il ne veut pas me l'importer ?Je crois que c'est le nom du fichier.In-memory repository, je vais l'appeler.Voyons voir.Voilà, c'est le nom du fichier.
00:15:22 :En fait, c'est des endoscores, moi j'ai mis des tirées, d'accord.Donc là, il le reconnaît.Voilà, je l'ai importé.Moi, je vais étape par étape.
00:15:33 :Je ne vais pas plus vite que la musique.J'ai créé mon in-memory todo repository.Pour l'instant, il ne gueule pas.Maintenant, je dois créer quoi ?
00:15:41 :Créer todo use case.Donc, c'est ce qu'on appelle des cas d'utilisation.Je vais créer un fichier todo use cases.Je vais tous les mettre ici, parce qu'il n'y en aura pas 50 non plus.
00:15:56 :Normalement, on devrait créer un fichier par cas d'utilisation.Mais comme j'en ai, comment dire,comme j'en ai que quelques-uns, je ne vais pas tous les utiliser.
00:16:11 :Alors oui, tu disais les parenthèses dans la classe.Où sont les parenthèses dans la classe ?Ici ?C'est utenaras.Tu peux activer le micro.
00:16:37 :Quand tu cherchais pourquoi ça n'importait pas,je me demandais si c'était le fait que tu n'avais pas mis les parenthèsesquand tu avais défini ta classe.
00:16:44 :En fait, c'est vraiment les noms de fichiers.En fait, comme j'ai fait toute la journée du TypeScript,les noms de fichiers, je m'ai détiré.Mais c'est vrai qu'en Python, le standard, c'est des endoscopes.
00:17:02 :Maintenant, dans todo use case, je vais créer ma classe.Create todo.Alors bien sûr, j'ai été un peu trop vite.On parle du principe qu'il n'y a pas ça.
00:17:19 :J'ai terminé mon test.J'ai terminé mon test.Je lance myTest.Il échoue.D'accord ?Donc là, je suis arrivé à cette étape où il échoue.
00:17:33 :Je dois faire en sorte, avec le minimum de code,faire en sorte qu'il passe.OK.Donc, je réimporte.Donc, todo use case, je vais créer ma classe.
00:17:49 :Create todo use case.Je l'importe ici.Voilà.Ah, il me dit qu'il a besoin d'un répositorier dans son constructeur,dans son init.Je vais le mettre.
00:18:10 :Def init self.repository.D'accord ?self.repository est égal à repository.Bon, j'ai envie de typer.J'ai envie de typer.Ici, je vais typer en in memory todo repository.
00:18:39 :C'est ce qu'on pourrait dire.Le problème, c'est que si vous connaissez les principes solides,les principes solides, ils disent quoi ?Les principes solides, surtout le D,ils disent que c'est le dependency inversion.
00:19:01 :Ça veut dire que je dépends de l'abstraction,non pas de l'implémentation.Excusez-moi, l'implémentation.Alors, j'ai un diagramme pour vous l'expliquer.J'ai un diagramme pour vous l'expliquer.
00:19:29 :C'est celui-ci.Imaginez que j'essaie de récupérer des données de match de foot.J'essaie de récupérer des données de match de foot.Je peux les récupérer soit depuis un fichier CSV,soit depuis une API, soit depuis une base de données.
00:19:51 :Du coup, le reader, je vais utiliser de la composition,c'est-à-dire que la classe MatchReader sera composée de l'un des trois.Soit je lui donne un reader qui va appeler un CSV,soit un reader qui va appeler une API,soit un reader qui va appeler une DB.
00:20:12 :Le problème, c'est quoi ?C'est que si je mets ici un type CSV FileReader,je crée un couplage fort entre MatchReader et celui-ci.D'accord ?
00:20:29 :Ça veut dire que MatchReader ne fonctionnera qu'avec cette classe.Or, moi, je veux rendre ma classe générique,mon reader, je dois pouvoir lui passer soit une instance de CSV FileReader,soit une API, soit une DB.
00:20:46 :D'accord ?Qu'est-ce que je fais ?Je vais créer un parent commun, une interface,dont CSV FileReader, API Reader et DB Reader vont implémenter cette interface.
00:21:01 :Et moi, je dépends de l'interface.C'est pour ça qu'on dit je dépends de l'abstraction,non pas de l'implémentation.Je vais dépendre de l'interface qui est de l'abstraction,et je ne dépends pas de ceux qui ont implémenté l'interface.
00:21:21 :D'accord ?Donc ça, c'est le D de Dépendency Inversion.Du coup, moi, le problème, c'est que si je veux typer,faire un typage fort,aujourd'hui, j'utilise un InMemory,mais si demain, je vais utiliser un SQLiteAutoRepositoryou un MySQLAutoRepository,je vais devoir créer une interface qui s'appelle AutoRepository,et le useCase va dépendre de ça,
00:21:54 :non pas de ceux qui implémentent AutoRepository.D'accord ?Je dépends de l'abstraction, non pas de l'implémentation.Donc je vais créer...Alors, on ne peut pas créer d'interface,mais on peut créer des protocoles en Python.
00:22:10 :Le protocole, c'est l'équivalent d'une interface.En clair, tu dépends du traducteur universel et pas du langage utilisé.Exactement.Ça permet, toi, à ton useCase,de pouvoir recevoir n'importe quel type.
00:22:27 :Demain, tu veux changer d'un SQLite à un MySQL,tu as juste à changer l'instance,tu n'as pas à revenir sur le code.OK ?Donc, c'est ce que je vais faire.
00:22:39 :Je vais créer mon protocole.Dans TodoList, je vais créer le TodoRepository.Alors, moi, j'aime bien rajouter protocole,comme ça, ils sont faciles à retrouver.Et pour créer, donc, TodoRepository,il va hériter de protocole, protocole de typing.
00:23:04 :D'accord ?Donc, je reviens à mon useCase.Et là, je ne dépends plus de l'implémentation,je dépends de l'abstraction.TodoRepository.Et je retire celui-ci.OK ?
00:23:28 :Voyons voir mon test.Ah, il me dit quoi ?Il me dit que l'objet créé TodoUseCasen'est pas un callable.Alors, ça veut dire qu'il me suffitde mettre en place le fameux callable.
00:23:46 :Et lui va recevoir quoi ?Alors, je vais mettre ellipsis.Voyons voir TodoList.Il me dit quoi ?Il manque un argument.OK.On va mettre l'argument.
00:23:58 :C'est quoi ?C'est un title de type str.On va essayer de typer à fond.D'accord ?Donc, on revient sur le test.C'est bon.
00:24:13 :Vous voyez ?On a l'impression, en fait,si vous regardez bien,on a l'impression qu'on est en traind'éteindre les feux un peu,tous les rouges, etc. et tout.
00:24:20 :Mais c'est ça l'approche TDD.Maintenant, je dois mettre en placela création d'une tâche.Sinon, je veux dire,quand il va vouloir la récupérer,il ne la trouvera pas.
00:24:34 :Ça, on y reviendra.Ça, on y reviendra.Donc, je vais créer une tâche.Comment je crée une tâche ?J'ai besoin, en fait,de créer une Todo.
00:24:46 :Et ça va être, en fait,ben, une, comment dire ?Ça va être une entité.Todo.En fait, j'ai besoin de faire Todo.Todo n'existe pas.
00:25:01 :Je vais le créer.Je vais créer TodoEntity.Alors, on n'est pas obligéde mettre Entity,mais c'est juste pour que vous,vous puissiez bien voirles différents élémentsqui composent le projet.
00:25:19 :Alors, je vais créer une classe Todo.Moi, Todo, il me sert juste, en fait.Je ne vais pas me prendre la têteparce qu'il n'y aura pasde méthode, etc.
00:25:32 :Ce que j'aime bien,c'est utiliser Pas Identique.Pas Identique.Donc, je vais faire,je crois que je l'ai déjà,Pas Identique sur la base.Alors, pour transformer Todo en,non, je n'ai pas.
00:25:45 :OK.Donc, je vais mettrepip install Pas Identique.Pourquoi il ne me le dit pas ?Ici, je ne suis pas dans la base.OK.
00:26:05 :Maintenant, je dois être dans la base.Modèle.Voilà.Base modèle.Et en fait, ça va me permettrede créer un modèleet dire que l'ID est de type STR.
00:26:18 :D'accord ?Parce qu'en fait,si on regarde bien,si on regarde bien le Todo List,je sais d'emblée que,je sais d'emblée que ma Todo,elle aura un ID et un title.
00:26:30 :Je sais que ma Todo,elle aura un ID et un title.Donc, je vais mettre en place l'IDet le title de type STR.OK.
00:26:40 :Donc, une fois que c'est fait,je vais pouvoir revenir dans le use caseet créer ma Todo.OK.Ma Todo,je vais lui donner un ID.
00:26:55 :L'ID, je ne vais pas me prendre la tête.Pour l'instant,je vais mettre un 1.Je vais y revenir juste après.Et le title,je vais dire,c'est le title qui est juste au-dessus.
00:27:07 :Title.OK.Alors l'ID,moi, ce que je vais faire,c'est que comme vous l'avez vudans le diagramme qui est ici.Non, pas celui-ci.Excusez-moi.
00:27:21 :Celui-ci,moi, je vais utiliser un UID.D'accord.Donc,UID 4.OK.Bon,le problème, c'est queUID cannot be assignedpour un ID de type STR.
00:27:42 :Qu'est-ce qu'il me dit ?Il me dit que ma Todo Entité,mon Entité Todo,c'est de type STR.Et ici,ces UID,c'est un type UID.
00:27:51 :Moi, pour le transformer en STR,je vais prendre le EXA.EXA.Et là, ça va le transformer en STR.Bon, là, je commence à éteindre les feux.
00:28:03 :J'ai créé ma Todo.Ça veut dire quoi ?Ça veut dire quepour que le repository puisse la récupérerselon son ID,je dois la sauvegarder dans la base de donnéesdans mon repository plus exactement.
00:28:21 :Donc, je vais demander à mon repositoryde sauvegarder,alors self, excuse-moi,self repository,je vais lui demander de sauvegarder cette Todo.Et une fois qu'elle est sauvegardée,je la retourne.
00:28:41 :Bon, là, vous commencez à comprendreque le repository,il va avoir comme méthode saveet comme méthode getById.D'accord ?Donc,inMemoryTodoRepositoryaura deux méthodes.
00:29:03 :Mais inMemoryRepository,étant donné qu'il implémente le protocole,donc mon protocole,ça veut dire quetous mes repositoriesdevront avoir deux méthodesgetByIden ayant un ID de type stret ça va retourner quoi ?
00:29:26 :Soit une Todo, soit non.D'accord ?Alors, j'ai oublié le def, excusez-moi.Je vous ai dit, j'ai fait pas mal de typescriptcet après-midi.D'accord ?
00:29:44 :Voilà.Donc,il me dit quoi ?Ouais, self.Ça, qu'en fasse d'un.Donc, il renvoie soit un Todo,soit un non.Bon, le problème, c'est quoi ?
00:29:59 :C'est que je ne suis pas dans une bonne versionde Python.D'accord ? Je ne suis pas dans une bonne version de Python.En utilisant la base,qu'est-ce que je vais faire ?
00:30:09 :Je vais utiliserSelect Interpreter,une autre basequi contienttac, tac, tac, tac, tac,j'avais, j'avaisah tiens, api-env.D'accord ?api-env.Et là aussi, je vais mettredans mon terminal,conda activateapi-env.
00:30:36 :Voilà.Lui, je crois qu'il a PyTest.Ouais, c'est bon.Lui, il a PyTest.OK.Donc,il aura Get Back by ID,mais un protocole, c'est ça, un protocole.
00:30:52 :Un protocole, c'est juste une idée.C'est juste une idée.Et donc, je laisse le soin,je laisse le soin,on va dire, à ceux qui implémententTodo Repository,à ceux qui veulent ressemblerà Todo Repository,je leur laisse le soin de définircomment récupérer un ID.
00:31:13 :D'accord ?Donc, en fait,lui, c'est juste une idée,mais c'estInMemory Todo Repository,SQLite et MySQL Todo Repositoryqui, eux, vont devoirdéfinir ces différentes méthodes.
00:31:29 :C'est pour ça que j'utilise le ellipsiste.OK ?Et la deuxième méthode,c'est Save.On va sauvegarderune Todo,de type Todo,et ça n'enverra rien du tout.
00:31:44 :Non.Et là aussi, c'est juste une idée.C'est à vous d'implémenter le Save.Donc, une fois qu'on a fait ça,lui, la première chose qu'on va faire,c'est qu'on vainitjusteun self.todos.
00:32:08 :Ce sera un dictionnaire vide.N'oubliez pas queje vais utiliser un dictionnaire.Je ne vais pas utiliser une liste.Je vais utiliser un dictionnaireparce que chaque cléest une liste.
00:32:22 :Je vais utiliser un dictionnaireparce que chaque clé,ce sera l'ID.Ce sera beaucoup plus simpleaprès pour rechercher par ID, etc.Donc, on...Regardez ce qu'il me dit.
00:32:35 :Ça, c'est intéressant.Regardez.Créer Todo USECASEa besoin d'un repositoryquirespecte le protocole.Il me dit queInMemoryTodoRepositoryne peut pas être assignécomme paramètre, etc.
00:32:57 :Parce qu'en fait,GetById is not presentet Save is not present.Donc, en fait,c'est ça qui est superavec le typage.C'est qu'il me dit,en quelque sorte,attention,le InMemoryTodoRepositoryne respecte pasle protocole.
00:33:17 :Il lui manqueGetById et Save.Bon.On va le faire.On va définir, du coup,le GetById.Save.On va lui donner un IDde type STR.
00:33:34 :Et ça va renvoyerun todo,un todo,ou un non.Moi, je vais retourner quoi ?Je vais retournerSave.Todos.Et comme c'est un dictionnaire,je vais lui passerl'ID entre crochet.
00:33:56 :Donc, vous avez compris,en fait,je récupère l'ID.Et comme l'ID,c'est celui qui est en cléde mon dictionnaire,ça me permettrade récupérer toute cette tâche.
00:34:09 :Une fois que c'est fait,il me dit quoi ?Il me dit,c'est toujours pas terminé.Normalement,si j'ai fait une erreur,GetById is not present,ça veut dire qu'il y a un problème.
00:34:22 :Pourquoi il me dit ça ?GetById.Alors, attendez.Je vais juste mettrele protocole à droite.GetById.Il est là.Save.ID.Todo ou non.
00:34:39 :Ça a l'air d'être bon.On va voir après.Et la méthode Save.D'accord.Save.Elle aura besoind'une Todode type Todo.Elle n'enverra rien du tout.
00:34:54 :.todosCrée une nouvelle clé.Une nouvelle clégrâce à l'ID de la tâcheet on lui mettracette Todo.D'accord.Et là, je crois que c'est bon.
00:35:13 :Non, même pas.Qu'est-ce qu'il y a ?Qu'est-ce qu'il y a ?TodoRepository.Une fonction init.TodoRepository.Alors, pourquoi c'est pas ?Voyons voir le useCase.
00:35:32 :C'est bizarre, ça.Pourquoi il me ditque ça ne respecte pas ?C'est censé respecter.Alors, je vais rechargerCTRL-SHIFT-P.Reload.Juste pour voirsi c'est pas utile.
00:35:53 :Ça a l'air d'être bon.Ouais.En fait, des fois,il faut recharger le VSCode.Parce que là, c'est...Alors, j'enlève ça.J'enlève ça.Parce qu'en fait,ça respecte bien mon protocole.
00:36:09 :Le InMemory.Il y a bien les deux méthodes.GetByEdit.Si je lui enlève ça.Si je lui enlève ça,oui, là, il ne respecte pas.
00:36:17 :Il me dit quoi ?Il me dit, voilà,Save est manquant.D'accord ?Donc, si je remets Save,c'est bon.Il respecte.Alors,vous voyez mon test ?
00:36:26 :J'ai éteint les feux.D'accord ?J'ai éteint les feux.Maintenant,si je lance mon test,PyTest,mon test passe.D'accord ?Et c'est ça,le TDD.
00:36:42 :Le TDD,c'est quec'est mon testqui m'a drivédans l'écriture du code.Et ce n'est pas l'inverse.Ce n'est pas,j'ai écrit du codeet ensuite,je me suis amusé à écrire le testpour le faire passer.
00:36:56 :D'accord ?Parce que ça mène,comment dire,forcément,ça met un biais.Vous êtes d'accord avec moi ?Que si vous écrivez votre codeet ensuite,on vous dit,n'oubliez pas d'écrire les testsqu'on va lancerdans le CICDavant le déploiement,vous écrivez les tests,il y a un biais.
00:37:16 :Parce que vous avez écrit le code,donc,sans vous en rendre compte,sans vous en rendre compte,vous écrivez des testspour faire passervotre code.
00:37:25 :Alors que la procédé,c'est tout l'inverse.J'écris du code,j'écris le testet c'est luiqui va me guiderà l'écrituredu code.D'accord ?
00:37:40 :En fait,au lieu de partir de l'originevers le résultat,tu es parti du résultatvers l'origine.Exactement.Et ça,c'est vraimentl'esprit TDD.OK ?
00:37:53 :Alors,je vais juste rajouterun truc dans le protocole.Dans le protocole,j'aurai une listede taux d'eau.Listedetaux d'eau.Je sais que ça...
00:38:08 :Parce que je saistoutes mes...Pourquoi ?Voilà.Donc, il me ditRepositoryCe n'est pas une liste.Ce n'est pas une liste.Qu'est-ce que je dis ?
00:38:27 :Taux d'eau,ce n'est pas une liste.Excusez-moi.C'estun dictionnaire.Un dictionnaireavecun stret un taux d'eau.Voilà.OK ?Donc, mon test fonctionne.
00:38:52 :Tout est bon.Maintenant, ce que je veux faire...Maintenant, ce que je veux faire,c'est que je veux testerce qu'on appelle le toggle.Le toggle,comme vous voyez,c'est activer-désactiver.
00:39:12 :Ça veut dire, pour dire qu'une tâche,elle est terminée,j'y vais un peu comme...Vous voyez ?Un peu commemode avion.Vous tapez une fois,vous êtes en mode avion.
00:39:22 :Vous re-tapez une fois,vous n'êtes plus en mode avion.D'accord ?C'est ça, le toggle.Donc, moi, je veux toggleune taux d'eau.Je vais dans mes tests.
00:39:32 :Je vais dans mes tests.Et en fait,le dev, il est pessimiste.Le développeur, il est pessimiste.Il va commencer par voirles problèmesavant de voirque ça fonctionne bien.
00:39:47 :Moi, je sais une chose,c'est que je ne peux pastoggleune taux d'eaunot existing.Je ne peux pastoggle une taux d'eauqui n'existe pas.
00:40:01 :Ça, je le sais.Donc, je vaisOK ?Donc, je sais quela taux d'eau n'existe pas.Donc, je vais créer un.D'abord, je vais créermon repository.
00:40:17 :Repository.Donc,in memorytaux de repository.Alors, bien sûr,le refactoringpeut égalements'appliqueraux fichiers de test.C'est ce qu'on va rendreparce que là,vous allez voir qu'on va avoirbeaucoup de répétitionset on va refactoriserça plus tard.
00:40:39 :Donc, j'ai besoinde mon repository.J'ai besoinde montoggledoneuse case.Mon cas d'utilisationpourtoggle une tâche.Donc, toggledoneuse case.
00:40:56 :Il a besoindu repository.Et là, on va faire un trucintéressant.C'est quoi ?C'est queje vaistoggle done use case.OK.Un IDnonexistingID.
00:41:18 :Donc, je vais essayerde toggleun IDqui n'existe pas.Mais je sais que je vais avoirune erreur.Ça doitme direqu'il y a une erreur.
00:41:33 :Devoiressayerde toggledoneune tâchequi n'existe pas.Je vais importerPyTest.Et PyTest, en fait,il me permetje sais quewithPyTestraiseje sais qu'il va y avoirune erreur.
00:41:53 :Je vais l'appelervalueerror.Value error.Je sais qu'en essayantde faire ça,en essayantde faire ça,il doit me direqu'il y a une erreur.
00:42:05 :En fait, pour que le testpasse,il doitéchouer.Alors, c'esttricky.Parce qu'on pensequ'il doitéchouer.Non.Ça veut dire quelà,moncomment diremon toggle done use casedoit me renvoyerune erreur.
00:42:23 :Donc, lui, s'il arriveà capter une erreuren essayantde toggleune tâchequi n'existe pas,alorsle testfonctionnera.D'accord.Donc, vous avez compris.
00:42:34 :J'aijuste,pour l'instant,à créer la classe.Donc, je retournedans todo use case.Hop.Classe.Toggledoneuse case.J'aimoninit.D'accord.Donc, selfrepositoryde typetodorepository.
00:43:00 :OK.Repositoryest égalà repository.J'aije vais l'importerici.Voilà.Il me ditqu'il n'est pascallable.Vous l'avez compris.Hop.Callable.Self.Je vais lui donnerun idde type str.
00:43:25 :OK.Donc, ça,c'est bon.J'ai écritle minimumde code.J'ai écritle minimumde code.Je lancemon test.Il échoue.En effet,il s'attend,regardez bien,did not raisevalue error.
00:43:46 :Il n'a pas,il n'a paspropagé,levéune exceptionvalue error.Il n'a paslevé une exceptionvalue error.Donc,je retournedans mon use caseet je vaisfaire quoi ?
00:44:03 :Je vaisessayerde récupérerune todoen demandantà mon repositoryget by iden lui donnantcet id.OK.Et c'est làque,regardez,si todoisnone,tu propages,tu lèvesune exceptionvalue error.
00:44:31 :On va diretashnoneexistingtodo.Je lance mon test.Et là,ça c'est intéressant.Il y a un keyerror.Il y a un keyerror non existant.
00:45:01 :Donc,ça vient de là.Ça vient deget by id.Allons voirget by idet une mémorietodo repository.Get by id,il renvoie une todoou none.
00:45:14 :Or,ici,self todoid.En fait,si vous souvenez bien,si je prendsune todohopid.Je ne vais pasprendre une todoinfo.
00:45:31 :Nomde point.1,2,3.Non,1,2,3,todo.Age.23,d'accord.Si je faisinfo,j'essaye d'avoirla clénon,il fonctionne.Mais si j'essayed'avoirune cléqui n'existe pas,d'accord,il me fait unekey error.
00:46:09 :Voyez,il me fait une key error.C'est exactementce qui se passe ici.J'essaye,dans mon dictionnaire,j'essaye derécupérerun élément,une cléqui s'appellenon existingid.
00:46:23 :C'est pour ça qu'il y aune erreur.Or, pour éviter ça,et pour respectermon protocolequi dit queil renvoie soit une todosoit une non,et bien on va direà infoget.
00:46:37 :On va utiliser le get.En utilisant le get,ce qui va se passer,c'est qu'il va,bon là il ne m'affiche pasparce que c'est dûà un notebook,mais il va m'envoyerune non.
00:46:48 :Si il le trouve,voyez, regardez,get,get id,il renvoie la données'il la trouve,sinon il renvoie non.Du coup,dans lein memory todo repository,je ne vais plus utiliserles crochets,je vais utiliserget.
00:47:03 :Ça me garantitd'avoir un nondans le casoù l'id n'existe pas.Si je relancemon test,il passe.D'accord ?Mais regardez bien,je n'ai pasimplémentéle toggle.
00:47:26 :J'ai écrit le minimumde codepour faire en sorteque mon test passe.Mais pour l'instant,si vous regardez bienle use case,il n'est pas en trainde toggle la tâche.
00:47:38 :J'ai juste demandéau repositoryde retrouvercette tâcheet si elle n'existe pas,tu propagesune value l'erreur.Mais pourquoi ?Je dois faire en sorteque mon test passe.
00:47:51 :Et seulement là,je vais testerle toggledontoggletodo.D'accord ?N'oubliez pasque vos tests,comme vos fichiers,doivent commencer par test.Si vous voulez les lanceravec PyTest.
00:48:12 :Donc là,je récupèrele repositoryInMemorytodorepository.Alors là,je dois créer une tâche.D'accord ?Je dois créer une tâche.Je vais prendre ça.
00:48:27 :Après,on fera de la refactorisation.Je vais prendre ça.Donc là,j'ai ma tâche qui est créée.Je vaiscomment dire ?Je vaiscréer une instancede toggledontodo.
00:48:44 :Et là,je vaistoggledonuse casela tâchequi a été crééecreated todoen lui donnant l'ID.Je vais séparerpour une meilleure lisibilité.
00:48:56 :D'accord ?J'ai créé ma tâche.Je la récupère.Grâce à son ID,je vaistoggle.OK ?Donc,je récupèreassert.Alors,je récupère ma tâchefetidtododepuisle repositorygetByIdcreatedtodo.id
00:49:24 :Et là,je doism'attendre.Donc déjà,dans un premier temps,je dois m'attendre quefetch todois notnon.Alors,si je l'enlève,vous allez voir pourquoi.
00:49:37 :Si je l'enlève,vous allez voir pourquoi.Je vais faireassert.Donc,je dois m'assurer quefetch ittodoque je récupère depuisla base de données,il est biendone.
00:49:49 :Il est bien done.D'accord ?Que c'est bienvrai.Et pourquoi ?Alors,il me souligne parce queil faut que j'ajouteun attributdoneà ma classe,à mon entitétodo.
00:50:07 :D'accord ?Donc,je vais aller dans monentitétodo.Je vais lui ajouterun donede typeboolean.Et lui,je sais une chose,c'est que toutes les tâchessont falseà la création.
00:50:21 :D'accord ?C'est comme ça.Au moment du use casede la créationd'une todo,il ne va pas me demanderde le mettre.Même si je pourraismettre false ici,mais bon,autant utilisercomment dire,justement,les modèlespas identiqueset mettre à false.
00:50:38 :Donc,je reviens sur mondoneici.Voilà,c'est intéressant.Là,il n'est plus en blanc,il est en bleu,donc il existe,mais il est toujourssouligné.
00:50:51 :Pourquoi il est souligné ?Parce qu'il me ditque doneis nota knownattributeof none.En effet,getByIdpeut me renvoyersoit une todo,soit un none.
00:51:03 :Donc,si il me renvoieune todo,bah,done existe,mais s'il me renvoienone,il n'existe paspour none.C'est pour ça que,pour éviter d'avoircette erreur,alors,je pourrais utilisertypeignore.
00:51:19 :D'accord ?Je pourrais utilisertypeignore.Et c'est ça qui est bien,c'est qu'en évitant ça,ça me permetde m'assurerà certesque fetchedtodoisis notknown.
00:51:34 :D'abord,je m'assure,je testequefetchedtodois notknown.Et après,je demande,je m'assure que maintenantil y a trop.Je lanceles tests.
00:51:50 :Donc,deux testspassent.Le dernieréchoue.OK ?Pourquoi ?Parce qu'il est toujoursà false.OK.Là,on va dans le use case.Dans le use case,on va dire quoi ?
00:52:08 :On va prendre notretodopointdoneet pour mettrel'effettoggle,c'est-à-direquand j'appuie une fois,c'est true.Quand je rappuie dessus,c'est false.Quand je rappuie une fois,c'est true.
00:52:23 :On va faire l'inversede tododone.OK ?Une fois que c'est fait,je demande à monrepositoryde mettre à jourupdate,de mettre à jourma todo.
00:52:42 :Mais pour mettre à jourune todo,je dois lui donnerd'abord un IDetla todo.Donc,je dois lui donnerl'IDde latodo.
00:52:56 :Donc,j'ai récupéré la tododepuis le repository.S'il est non,je propageune erreur.Sinon,je changele contrairede ce que c'était.Si c'était un trou,ça devient false.
00:53:11 :Et si c'est false,ça devient un trou.Et je mets à jouren donnantl'IDet la nouvelle todo.D'accord ?Donc,le test,forcément,il est faux.
00:53:24 :Il est fauxparce que c'est à causede update.OK ?Donc,dans le nouveaurepository,je doisimplémenterupdate.Mais avant d'implémenterupdate,vous l'avez compris,je dois définirdans le protocoleque,à quoi doit ressemblerla méthodeupdate.
00:53:45 :Elle auraun IDde type str.Elle auraune todode typetodo.Ça ne renverrarien du tout.Non.Voilà.Et du coup,il ne me reste plusqu'à,dans InMemoryrepository,à l'implémenterdefupdate.
00:54:06 :D'accord ?Donc,self,il a un IDde type str.Il a une todode typetodo.Il renvoienon.Et pour mettre à jour,bah,je vais faireself.todos
00:54:26 :dans l'IDde type str.Dans l'ID,écraséavec la nouvelle todo.On peut l'appelerupdated todo,mais c'est,bon,c'est vrai quesave todo,à la limite,on peut l'appeler,voilà.
00:54:47 :On pourrait l'appelerupdatedtodo.OK ?Alors,non, ça,excusez-moi,c'est une écriture.Ce n'est pas conformeà Python.Voilà.Ça, c'est conforme à Python.
00:55:03 :D'accord ?Donc,je regarde mon test.Qu'est-ce qu'il me dit ?Repository,update,incompatible.Voyons voir pourquoi il est incompatible.IDde type str,updatetodo,todo.
00:55:19 :Est-ce que c'est le nom ?Ça serait bizarreque ce soit le nom.Ça serait bizarreque ce soit le nom.Ah ouais,c'est le nom.
00:55:30 :Je ne savais même pas que...J'apprends une chose.Je suis honnête avec vous.J'apprends une chose.Je ne savais pas que ça...Je pensais que ça devait respecterla signatured'une méthode.
00:55:40 :D'accord ?Du moment que la signature,elle était identique.Mais là,il me dit carrément le nom.Si ce n'est pas le même nom,ça, c'est bizarre.
00:55:51 :Donc,la signature,pour ceux qui ne savent pas,la signature,c'est la portée.D'accord ?Le nom,les argumentset le type de retour.C'est ce qu'on appelleune signature de méthode.
00:56:07 :Je ne savais pas que ça devaitaussi respecter le nom.Je l'apprends avec vous.D'accord ?Donc,voyons voir.Si je lance mes tests,mes trois tests fonctionnent.
00:56:19 :D'accord ?Alors,on va faireun dernieret puisje vous montreraila suiteet la finla semaine prochaine,comme c'était prévu.Donc,maintenant,je veux supprimerune tâche.
00:56:47 :D'accord ?Alors,je vais supprimerune tâche.D'accord ?Alors,déjà,je peux refactorisermes use cases.Mes use cases,en fait,ce que je peux faire,c'estcréer une classeune classeuse case.
00:57:09 :D'accord ?Use case.Il va êtreabstraite.D'accord ?Une classe abstraite.Avecun,comment ça s'appelle ?Un constructeur.Donc,repositoryde typetodorepository.
00:57:33 :Donc,ça sera toujours le même.Repositoryetrepositoryest égal àrepositoryet une méthodecallable.D'accord ?Callable.Alors,aujourd'hui,normalement,si vous regardez bien,j'ai qu'un seul argument.
00:57:54 :Title,ID,et à chaque fois,c'est de type str.Mais,peut-être que demain,j'aurai dans mon callabledeux arguments.D'accord ?Notamment,moi je pense à l'update.
00:58:06 :Pour mettre à jourune tâche,j'ai toujours besoind'un IDet d'une tâcheà mettre à jour.Du coup,pour ne pas me prendre la tête,je vais utiliser les args.
00:58:15 :D'accord ?Donc,étoile args.Et là,ça devra être redéfini.Du coup,ça je l'enlève.Ça je l'enlève.Et en fait,create,todo,et toggle,ils vont hériterde useCase.
00:58:37 :Ok ?Je vais relancer mes testspour voir si j'ai rien cassé.Ah, c'est bon.Ok ?Maintenant,pour délecter une tâche,alors,non,je crois qu'on va terminersur la refactorisation.
00:58:58 :Je vais terminer plutôtsur la refactorisationetla semaine prochaine.Ah, on verra.Bon, je vais voiren fonction du tempsparce que j'ai pas aussienvie de vous retenirplus d'une heure trente.
00:59:11 :Donc,on anos tests,ils fonctionnent.Alors,maintenant,là aussi,c'est la répétition.Pour ça,on va utiliserce qu'on appelleles fixtures.Les fixtures dans PyTest,en fait,c'est une fonctionPythonqui peut être utiliséepour initialiserdes données.
00:59:32 :Ça permet d'initialiserdes données,de configurerdes environnementsde testsou effectuerd'autres tâchesen fait de préparation.Moi,je vais créerune fixturegrâce à PyTestFixture.
00:59:46 :Donc,c'est un décorateuret je vais créermon repositorypuisque lui,c'est quasimenttout le tempsque je vais le demander.Donc,ça me permetd'initialiserun repository.
00:59:58 :Regardez,je vais retournertout simplementune instancedee-memorytodo-repository.Comme ça,ici,j'en ai pas besoin.Ici,j'en ai pas besoin.Et ici,j'en ai pas besoin.
01:00:13 :Alors,comment je fais appelà mes fixturesdans les parenthèses,demon test,la fonction test.En fait,j'appellerepository.D'accord ?Ça,c'est la première chose.
01:00:28 :Ensuite,la créationd'une todo.La créationd'une todo.J'en ai une ici,voyez ?Pour créer une todo,elle est ici.Il y a ça aussi,mais celle-ci,j'y toucherai pas.
01:00:43 :Pourquoi je touche pascelle-ci ?Dans les autres tests,je vais à chaque foisutiliserune fixtured'une nouvelle tâche.Regardez bien,je vais créerune fixtured'une nouvelle tâche.
01:01:00 :Newtodo.En fait,New todo,pour créerune nouvelle todo,regardez bien,pour créer une nouvelle todo,il a besoin d'un repository.Une fixturepeut faire appelà une fixture au-dessus.
01:01:14 :Donc,je vais utiliserla fixture qui est au-dessus.Ça va me permettrede créer,comment dire,createdtodoest égal,non,createdtodoexcusez-moi,use case,est égalàcreatedtodouse case.
01:01:40 :Il a besoin du repository,on récupérera celuide la fixture.D'accord ?Donc, comprenez bien icique ce repository,ça vient de là.Ça vient de là.
01:01:49 :Et,je vais récupérer,en fait,je vais retourner,puisque ça retourne une todo,je vais retournercreate todouse caseen lui passanta newtodo.
01:02:01 :Donc là,j'ai créé une fixtured'une nouvelle todo.Je vais la remplacerici.Alors,je l'ai appeléenewtodo.Donc,je vais appelerma fixture icinewtodo.
01:02:22 :Mais là,du coup,je doiscorriger iciet ici.Newtodo.Alors,à votre avis,je vous pose une question,vous pouvezrépondre,activer le microet répondre,pourquoije n'utilise pasla fixture ici ?
01:02:42 :Et,je vais l'utiliserdans tous les autres testsqui auront besoind'une todo.Mais,pourquoi je n'utilise pasici ?Est-ce que vous avezune idée ?
01:02:54 :Non,pourquoi pas,moi ?Parce que c'estla raison d'êtrede ce test,de testerla créationd'une todo.D'accord ?Donc,celle-ci,elle ne va pasutiliser une fixture.
01:03:11 :Donc,si vous pouvez vous dire,oui,mais Rachid,c'est pareil,en fait,c'est la même chose,mais la raison d'êtrede ce test,c'est de créerune tâche.
01:03:22 :Donc,je n'utiliserai pasde fixture.Mais,pour tous les autres,je vais utiliserune fixture.D'accord ?Donc là,on a,comment dire,on a refactorisé,on a refactoriséet là,ça a l'air d'être bon.
01:03:37 :On n'aura pasnon plusde fixture.On n'aura pasnon plus tropde trucs à faire et tout.Je vais mettre en placele test,alors,pour supprimer,pour supprimerune tâche.
01:03:57 :Là aussi,je suis pessimiste.Je sais une chose,c'est que je ne peux pas,je ne peux pasdélèguerune todonotexisting.D'accord ?
01:04:15 :J'aurai besoinde la fixturerepository.Je vais créerun use casedeletetodouse case.Donc,deletetodousecase.Il aura besoindu repository.
01:04:33 :Ensuite,la même chose.Comme je ne peux passupprimer une tâchequi n'existe pas,je m'attendspour que le test passe,je m'attendsà ce qu'il échoue.
01:04:45 :Donc,withpytestraisevalueerror.D'accord ?Ça veut direque quand je vaisessayerde supprimerune tâchequi n'existe pas,elle ditil doitpropagerune valueerror.
01:05:10 :Donc,danstodo use case,ça c'est bon,ça c'est bon,ça c'est bon.Je vais créerma classedeletetodousecase.Comme ça,j'ai juste à écrirele colDonc,il a besoind'un IDde type str.
01:05:43 :Je vaisd'abordrécupérerla todoen demandantau repositorygetByIdcet ID.N'oubliez pas,je dois faire en sorteque le testpasse.Alors,je l'ai importé.
01:06:03 :Pour que le testpasse,je me dis quoi ?Si la todouse casenull,tu propagesune valueerrortodonotfound.Et là,mon test,il va passer.
01:06:22 :Je commence à comprendre.Il passe.Ensuite,alors je croisqu'il y a quelqu'unqui a son microd'activé.Ensuite,je sais une chose,c'est queje dois supprimerune todonotfound,cette fois-ci,qui n'est pas terminée.
01:06:43 :Je ne peux pas la supprimer.Donc,repository,hop,la même chose,je peux copier ça,mais c'est,d'accord,alors non,je ne peux pas,ouais,je peux copier ça,ça,je peux le copier,ctrl-c,ctrl-v,et cette fois-ci,je vais récupérerma nouvelle todoet j'ai la chance,ma nouvelle todo
01:07:05 :n'a pas été donnée.C'est une new todoqui esta false.Donc,là,cette fois-ci,je vais lui direnew todopointid.D'accord.Donc,là,je lance mon test.
01:07:28 :Il échoue en disantqu'il n'a paslevé une exception.Je vais dansuse caseet cette fois-ci,vous voyez,je fais juste en sorteque mes tests passent.
01:07:42 :Je n'ai pas implémentéla totalitéde commentdélèterune tâche.Juste mes tests passent.Si la todoif nottododone,si elle n'est pas done,alors,je propageune valueerrordisant quela todois notdone.
01:08:05 :Et mon testva passer.Et là, enfin,là, enfin,je teste.Il y a quelqu'unqui a le microd'allumer ?Là, je testedeletetododone.
01:08:27 :J'aile repository.OK.J'ai manew todo.Avantavant de laavant de lasupprimer,avant de la supprimer,new todo doit êtredone.Alors, j'ai deux possibilités.
01:08:47 :Soit je metsen place ça.Je mets en place çaici,CTRL-C,CTRL-V.D'accord ?Soitje vaiscréer une fixture.Je vais créerune fixture.
01:09:06 :I testfixtureavec une nouvelletododone,qui est déjà donedirectement.Repository.Alors,j'ai besoin,c'est ça qui est superavec les fixtures,c'est que je peuxles imbriquer.
01:09:24 :Je vais prendrema new todoqui est juste au-dessus.New todo.Roberto,Roberto,tu as ton microd'allumé ?Je ne peux pasmuter.C'est bon.
01:09:51 :Excusez-moi.J'ai réussi à le muter.Donc,ce qui est bien,c'est que je peuxutiliser la fixtured'au-dessus.Comme ça,j'ai juste à mettreen place,en fait,letoggleCTRL-CCTRL-VD'accord ?
01:10:11 :On toggledone news case.Ok ?Une fois,une fois qu'elle est done,je peux retournercette new todo.Je crois qu'elle sera done.Donc,là,j'ai créé une fixture,mais c'est facile pour une todoqui est done.
01:10:31 :Et là,je vais utilisernew tododone.Je peux créerCTRL-CCTRL-VEt là,je vais lancerle news caseennew tododone.id
01:10:51 :Je vais récupérerlatododepuismabase de données,le repository,doncgetby iden faisantnewtododone.idEt là,comme elle est suppriméede ma base de données,je m'attendsà ce quefetched todois done.
01:11:18 :Si je lance mon test,il est chaud.D'accord ?Il est chaudparce qu'il a bien récupéréune todo.Il a bien récupéré une todo.
01:11:30 :Ça veut direqu'il ne me reste plusqu'à mettre en placela suppression.Donc,si la tâche existeet sielle est done,là,je peux demanderà mon repository,selfrepositorydedeletefetchedtodo.
01:11:49 :Et là,j'ai donctodo.D'accord ?Fetched todo.Vous l'avez compris,je dois définirau protocoledelete,doncdefdeleteself.On auraun idde typestrnonellipsiset je vaisdansmon in-memory.
01:12:18 :Pour in-memory,j'implémentedeletegrâceà l'idde typestr.Alors,ça envoienonet en fait,je vais utiliserdelselftodosl'id.Tout simplement.
01:12:42 :Je vais dans mon use case.Qu'est-ce qu'il me dit ?C'est ce qu'il me dit.Todo,ah, il a besoin de l'id.En effet,je vais lui passerl'id.
01:12:52 :Si je vais dans mes tests,mes testspassent.D'accord ?Voyez,c'est ça l'idéequ'il y a derrière le TDD.C'est quedepuis tout à l'heure,la seule chose qui drive,qui me faitécrire du code,ce sont mes tests.
01:13:17 :Rien d'autre.Quand je dis,quand je testela suppression d'une tâchequi n'existe pas,tout ce que j'écriscomme code,c'est ces lignes-là.Je n'ai pas été au-delà.
01:13:28 :Alors, bien sûr,bien sûr,il y a des chosesque vous allezdeviner.En effet,j'aurais pudirectement codertoutes ces lignes-là.Mais,pour vous dire que demain,ce n'est pas des TDDque vous aurezcomme problématique,comme applicationà coder.
Aucune occurrence trouvée pour « ».
00:45:15
Key Error
00:47:18
Key Error
00:47:24
Key Error
00:47:39
Toggle