[{"data":1,"prerenderedAt":3635},["ShallowReactive",2],{"navigation":3,"\u002Fnsi-tale\u002Fta-structures-donnees\u002Fcontrat-tests-assertions":140,"\u002Fnsi-tale\u002Fta-structures-donnees\u002Fcontrat-tests-assertions__counterpart":2906,"\u002Fnsi-tale\u002Fta-structures-donnees\u002Fcontrat-tests-assertions__slides":2825,"annexes-memo:\u002Fnsi-tale\u002Fta-structures-donnees\u002Fcontrat-tests-assertions":3309,"annexes-slides:\u002Fnsi-tale\u002Fta-structures-donnees\u002Fcontrat-tests-assertions":2825},[4,24,112],{"title":5,"path":6,"stem":7,"children":8},"SNT · Seconde","\u002Fsnt-2nde","0.snt-2nde\u002F0.index",[9,10],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13,"children":14},"Photographie numérique","\u002Fsnt-2nde\u002Fsg-photo-numerique","0.snt-2nde\u002Fsg-photo-numerique\u002F0.index",[15,16,20],{"title":11,"path":12,"stem":13},{"title":17,"path":18,"stem":19},"Photosites, pixels et résolution","\u002Fsnt-2nde\u002Fsg-photo-numerique\u002Fpixels-resolution","0.snt-2nde\u002Fsg-photo-numerique\u002F1.pixels-resolution",{"title":21,"path":22,"stem":23},"Traiter une image en Python","\u002Fsnt-2nde\u002Fsg-photo-numerique\u002Ftraitement-rgb","0.snt-2nde\u002Fsg-photo-numerique\u002F4.traitement-rgb",{"title":25,"path":26,"stem":27,"children":28},"NSI · Première","\u002Fnsi-1ere","1.nsi-1ere\u002F0.index",[29,30,52,82],{"title":25,"path":26,"stem":27},{"title":31,"path":32,"stem":33,"children":34},"Représentation des données : types construits","\u002Fnsi-1ere\u002Fpc-types-construits","1.nsi-1ere\u002Fpc-types-construits\u002F0.index",[35,36,40,44,48],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39},"Tableaux et listes","\u002Fnsi-1ere\u002Fpc-types-construits\u002Ftableaux-listes","1.nsi-1ere\u002Fpc-types-construits\u002F1.tableaux-listes",{"title":41,"path":42,"stem":43},"Listes en compréhension","\u002Fnsi-1ere\u002Fpc-types-construits\u002Fcomprehension","1.nsi-1ere\u002Fpc-types-construits\u002F2.comprehension",{"title":45,"path":46,"stem":47},"Tuples et p-uplets nommés","\u002Fnsi-1ere\u002Fpc-types-construits\u002Ftuples","1.nsi-1ere\u002Fpc-types-construits\u002F3.tuples",{"title":49,"path":50,"stem":51},"Dictionnaires","\u002Fnsi-1ere\u002Fpc-types-construits\u002Fdictionnaires","1.nsi-1ere\u002Fpc-types-construits\u002F4.dictionnaires",{"title":53,"path":54,"stem":55,"children":56},"Langages et programmation","\u002Fnsi-1ere\u002Fpg-langages-prog","1.nsi-1ere\u002Fpg-langages-prog\u002F0.index",[57,58,62,66,70,74,78],{"title":53,"path":54,"stem":55},{"title":59,"path":60,"stem":61},"Langages : diversité et unité","\u002Fnsi-1ere\u002Fpg-langages-prog\u002Fdiversite-langages","1.nsi-1ere\u002Fpg-langages-prog\u002F1.diversite-langages",{"title":63,"path":64,"stem":65},"Constructions élémentaires","\u002Fnsi-1ere\u002Fpg-langages-prog\u002Fconstructions-elementaires","1.nsi-1ere\u002Fpg-langages-prog\u002F2.constructions-elementaires",{"title":67,"path":68,"stem":69},"Fonctions","\u002Fnsi-1ere\u002Fpg-langages-prog\u002Ffonctions","1.nsi-1ere\u002Fpg-langages-prog\u002F3.fonctions",{"title":71,"path":72,"stem":73},"Spécification d'une fonction","\u002Fnsi-1ere\u002Fpg-langages-prog\u002Fspecification","1.nsi-1ere\u002Fpg-langages-prog\u002F4.specification",{"title":75,"path":76,"stem":77},"Mise au point des programmes","\u002Fnsi-1ere\u002Fpg-langages-prog\u002Fmise-au-point","1.nsi-1ere\u002Fpg-langages-prog\u002F5.mise-au-point",{"title":79,"path":80,"stem":81},"Utilisation de bibliothèques","\u002Fnsi-1ere\u002Fpg-langages-prog\u002Fbibliotheques","1.nsi-1ere\u002Fpg-langages-prog\u002F6.bibliotheques",{"title":83,"path":84,"stem":85,"children":86},"Algorithmique","\u002Fnsi-1ere\u002Fph-algorithmique","1.nsi-1ere\u002Fph-algorithmique\u002F0.index",[87,88,92,96,100,104,108],{"title":83,"path":84,"stem":85},{"title":89,"path":90,"stem":91},"Parcours séquentiel d'un tableau","\u002Fnsi-1ere\u002Fph-algorithmique\u002Fparcours-sequentiel","1.nsi-1ere\u002Fph-algorithmique\u002F1.parcours-sequentiel",{"title":93,"path":94,"stem":95},"Bases de la complexité","\u002Fnsi-1ere\u002Fph-algorithmique\u002Fcomplexite-bases","1.nsi-1ere\u002Fph-algorithmique\u002F2.complexite-bases",{"title":97,"path":98,"stem":99},"Tris par sélection et par insertion","\u002Fnsi-1ere\u002Fph-algorithmique\u002Ftris","1.nsi-1ere\u002Fph-algorithmique\u002F3.tris",{"title":101,"path":102,"stem":103},"Recherche dichotomique","\u002Fnsi-1ere\u002Fph-algorithmique\u002Fdichotomie","1.nsi-1ere\u002Fph-algorithmique\u002F4.dichotomie",{"title":105,"path":106,"stem":107},"Algorithmes gloutons","\u002Fnsi-1ere\u002Fph-algorithmique\u002Fgloutons","1.nsi-1ere\u002Fph-algorithmique\u002F5.gloutons",{"title":109,"path":110,"stem":111},"Les k plus proches voisins (k-NN)","\u002Fnsi-1ere\u002Fph-algorithmique\u002Fknn","1.nsi-1ere\u002Fph-algorithmique\u002F6.knn",{"title":113,"path":114,"stem":115,"children":116},"NSI · Terminale","\u002Fnsi-tale","2.nsi-tale\u002F0.index",[117,118],{"title":113,"path":114,"stem":115},{"title":119,"path":120,"stem":121,"children":122},"Structures de données","\u002Fnsi-tale\u002Fta-structures-donnees","2.nsi-tale\u002Fta-structures-donnees\u002F0.index",[123,124,128,132,136],{"title":119,"path":120,"stem":121},{"title":125,"path":126,"stem":127},"Objet, classe, interface","\u002Fnsi-tale\u002Fta-structures-donnees\u002Finterface-implementation","2.nsi-tale\u002Fta-structures-donnees\u002F1.interface-implementation",{"title":129,"path":130,"stem":131},"Implémenter une file FIFO","\u002Fnsi-tale\u002Fta-structures-donnees\u002Fimplementer-une-structure","2.nsi-tale\u002Fta-structures-donnees\u002F2.implementer-une-structure",{"title":133,"path":134,"stem":135},"Listes, piles, files, dictionnaires","\u002Fnsi-tale\u002Fta-structures-donnees\u002Flistes-piles-files-dict","2.nsi-tale\u002Fta-structures-donnees\u002F3.listes-piles-files-dict",{"title":137,"path":138,"stem":139},"Docstring, tests, assertions","\u002Fnsi-tale\u002Fta-structures-donnees\u002Fcontrat-tests-assertions","2.nsi-tale\u002Fta-structures-donnees\u002F4.contrat-tests-assertions",{"id":141,"title":142,"bo":143,"body":147,"description":2824,"eval":2825,"extension":2826,"icon":2825,"labo":2825,"meta":2827,"navigation":2828,"path":138,"publie":2829,"quizContext":2825,"quizzes":2830,"readingTime":418,"seo":2902,"stem":139,"tp":2825,"__hash__":2905},"cours\u002F2.nsi-tale\u002Fta-structures-donnees\u002F4.contrat-tests-assertions.md","Un contrat, trois écritures : docstring, tests, assertions",[144,145,146],"TA04","PG04","PG03",{"type":148,"value":149,"toc":2813},"minimark",[150,155,168,183,190,252,279,283,298,398,405,570,581,584,621,625,639,648,729,732,742,754,761,956,973,1008,1044,1048,1054,1074,1342,1349,1356,1379,1383,1389,1432,1927,1942,1961,2033,2047,2073,2077,2087,2170,2177,2204,2401,2405,2418,2494,2497,2519,2555,2585,2616,2620,2679,2683,2686,2800,2807,2809],[151,152,154],"h2",{"id":153},"introduction","Introduction",[156,157,158,159,163,164,167],"p",{},"Les cours précédents ont lu le contrat d'une structure du côté de qui\nl'",[160,161,162],"strong",{},"utilise"," : l'interface dit ce qu'une pile ou une file promet, et deux\nimplémentations différentes peuvent tenir la même promesse (",[165,166],"bo-ref",{"code":144},").",[156,169,170,171,174,175,178,179,182],{},"Ce cours lit le même contrat de l'autre côté, celui de qui ",[160,172,173],{},"écrit"," le code.\nVu de là, le contrat sert à deux choses. Il permet d'écrire le ",[160,176,177],{},"jeu de tests\navant la première ligne de code",", puisque les tests ne dépendent que de ce que\nla structure promet. Et il ",[160,180,181],{},"borne le périmètre"," du programme : il dit ce\nqu'il y a à écrire, donc à quoi on reconnaît que c'est fini.",[156,184,185,186,189],{},"Le fil conducteur tient en une phrase : un même contrat s'écrit ",[160,187,188],{},"trois fois",",\net les trois écritures disent la même chose.",[191,192,193,209],"table",{},[194,195,196],"thead",{},[197,198,199,203,206],"tr",{},[200,201,202],"th",{},"Écriture",[200,204,205],{},"Où elle vit",[200,207,208],{},"Ce qu'elle fait",[210,211,212,226,239],"tbody",{},[197,213,214,220,223],{},[215,216,217],"td",{},[160,218,219],{},"La docstring",[215,221,222],{},"dans le code, en français",[215,224,225],{},"dit ce que la méthode promet",[197,227,228,233,236],{},[215,229,230],{},[160,231,232],{},"Le jeu de tests",[215,234,235],{},"hors de la classe",[215,237,238],{},"éprouve l'implémentation sur des cas choisis",[197,240,241,246,249],{},[215,242,243],{},[160,244,245],{},"L'assertion",[215,247,248],{},"dans la méthode",[215,250,251],{},"refuse un appel que le contrat interdit",[253,254,255],"note",{},[156,256,257,258,262,263,266,267,269,270,266,272,274,275,278],{},"Aucune de ces trois notions n'est neuve : spécification, docstring et ",[259,260,261],"code",{},"assert","\nont été posés en Première (",[264,265,71],"a",{"href":72},",\n",[165,268],{"code":145},") et les jeux de tests aussi (",[264,271,75],{"href":76},[165,273],{"code":146},"). Ce qui est neuf, c'est l'",[160,276,277],{},"ordre"," : le test s'écrit en\npremier, et l'assertion change de rôle selon l'endroit où elle vit.",[151,280,282],{"id":281},"première-écriture-la-docstring","Première écriture : la docstring",[156,284,285,286,289,290,293,294,297],{},"Le contrat d'une pile tient dans un tableau : pour chaque opération, ce qu'elle\nreçoit, ce qu'elle renvoie, et si elle modifie la pile. C'est l'interface de la\n",[259,287,288],{},"Pile"," du cours précédent, avec ",[259,291,292],{},"len(p)"," en plus (la méthode spéciale\n",[259,295,296],{},"__len__",") pour pouvoir compter les éléments.",[191,299,300,316],{},[194,301,302],{},[197,303,304,307,310,313],{},[200,305,306],{},"Méthode",[200,308,309],{},"Reçoit",[200,311,312],{},"Renvoie",[200,314,315],{},"Modifie la pile ?",[210,317,318,340,355,371,385],{},[197,319,320,325,331,334],{},[215,321,322],{},[259,323,324],{},"empiler(x)",[215,326,327,328],{},"un élément ",[259,329,330],{},"x",[215,332,333],{},"rien",[215,335,336,337,339],{},"oui : ",[259,338,330],{}," passe au sommet",[197,341,342,347,349,352],{},[215,343,344],{},[259,345,346],{},"depiler()",[215,348,333],{},[215,350,351],{},"l'élément du sommet",[215,353,354],{},"oui : il est retiré",[197,356,357,362,364,366],{},[215,358,359],{},[259,360,361],{},"sommet()",[215,363,333],{},[215,365,351],{},[215,367,368],{},[160,369,370],{},"non",[197,372,373,378,380,383],{},[215,374,375],{},[259,376,377],{},"est_vide()",[215,379,333],{},[215,381,382],{},"un booléen",[215,384,370],{},[197,386,387,391,393,396],{},[215,388,389],{},[259,390,292],{},[215,392,333],{},[215,394,395],{},"le nombre d'éléments",[215,397,370],{},[156,399,400,401,404],{},"Ce tableau ",[160,402,403],{},"est"," la documentation de la classe : il suffit de recopier chaque\nligne dans la docstring de la méthode correspondante. Rien n'est ajouté, seule\nla place change.",[406,407,412],"pre",{"className":408,"code":409,"language":410,"meta":411,"style":411},"language-python shiki shiki-themes github-light github-light github-dark","class Pile:\n    \"\"\"Une pile : on n'accède qu'au dessus (LIFO).\"\"\"\n\n    def __init__(self):\n        \"\"\"Fabriquer une pile neuve, vide.\"\"\"\n\n    def empiler(self, x):\n        \"\"\"Poser l'élément x sur le dessus de la pile.\"\"\"\n\n    def depiler(self):\n        \"\"\"Retirer l'élément du sommet et le renvoyer.\"\"\"\n\n    def sommet(self):\n        \"\"\"Renvoyer l'élément du sommet sans le retirer.\"\"\"\n\n    def est_vide(self):\n        \"\"\"Renvoyer True si la pile ne contient aucun élément.\"\"\"\n\n    def __len__(self):\n        \"\"\"Renvoyer le nombre d'éléments de la pile.\"\"\"\n","python","",[259,413,414,431,438,445,458,464,469,480,486,491,501,507,512,522,528,533,543,549,554,564],{"__ignoreMap":411},[415,416,419,423,427],"span",{"class":417,"line":418},"line",1,[415,420,422],{"class":421},"s8jYJ","class",[415,424,426],{"class":425},"snPdu"," Pile",[415,428,430],{"class":429},"sxrX7",":\n",[415,432,434],{"class":417,"line":433},2,[415,435,437],{"class":436},"sIIMD","    \"\"\"Une pile : on n'accède qu'au dessus (LIFO).\"\"\"\n",[415,439,441],{"class":417,"line":440},3,[415,442,444],{"emptyLinePlaceholder":443},true,"\n",[415,446,448,451,455],{"class":417,"line":447},4,[415,449,450],{"class":421},"    def",[415,452,454],{"class":453},"sBjJW"," __init__",[415,456,457],{"class":429},"(self):\n",[415,459,461],{"class":417,"line":460},5,[415,462,463],{"class":436},"        \"\"\"Fabriquer une pile neuve, vide.\"\"\"\n",[415,465,467],{"class":417,"line":466},6,[415,468,444],{"emptyLinePlaceholder":443},[415,470,472,474,477],{"class":417,"line":471},7,[415,473,450],{"class":421},[415,475,476],{"class":425}," empiler",[415,478,479],{"class":429},"(self, x):\n",[415,481,483],{"class":417,"line":482},8,[415,484,485],{"class":436},"        \"\"\"Poser l'élément x sur le dessus de la pile.\"\"\"\n",[415,487,489],{"class":417,"line":488},9,[415,490,444],{"emptyLinePlaceholder":443},[415,492,494,496,499],{"class":417,"line":493},10,[415,495,450],{"class":421},[415,497,498],{"class":425}," depiler",[415,500,457],{"class":429},[415,502,504],{"class":417,"line":503},11,[415,505,506],{"class":436},"        \"\"\"Retirer l'élément du sommet et le renvoyer.\"\"\"\n",[415,508,510],{"class":417,"line":509},12,[415,511,444],{"emptyLinePlaceholder":443},[415,513,515,517,520],{"class":417,"line":514},13,[415,516,450],{"class":421},[415,518,519],{"class":425}," sommet",[415,521,457],{"class":429},[415,523,525],{"class":417,"line":524},14,[415,526,527],{"class":436},"        \"\"\"Renvoyer l'élément du sommet sans le retirer.\"\"\"\n",[415,529,531],{"class":417,"line":530},15,[415,532,444],{"emptyLinePlaceholder":443},[415,534,536,538,541],{"class":417,"line":535},16,[415,537,450],{"class":421},[415,539,540],{"class":425}," est_vide",[415,542,457],{"class":429},[415,544,546],{"class":417,"line":545},17,[415,547,548],{"class":436},"        \"\"\"Renvoyer True si la pile ne contient aucun élément.\"\"\"\n",[415,550,552],{"class":417,"line":551},18,[415,553,444],{"emptyLinePlaceholder":443},[415,555,557,559,562],{"class":417,"line":556},19,[415,558,450],{"class":421},[415,560,561],{"class":453}," __len__",[415,563,457],{"class":429},[415,565,567],{"class":417,"line":566},20,[415,568,569],{"class":436},"        \"\"\"Renvoyer le nombre d'éléments de la pile.\"\"\"\n",[156,571,572,573,576,577,580],{},"Cette classe n'a ",[160,574,575],{},"aucun corps de méthode",", et pourtant elle dit tout ce que\nle contrat dit. La documentation se lit sans ouvrir le code :\n",[259,578,579],{},"help(Pile.depiler)"," affiche la phrase, et elle suffit pour utiliser la\npile.",[156,582,583],{},"Quatre mots pour parler d'un contrat :",[585,586,587,594,605,615],"ul",{},[588,589,590,593],"li",{},[160,591,592],{},"prototype"," : le nom d'une méthode, ce qu'elle reçoit, ce qu'elle renvoie ;",[588,595,596,599,600,604],{},[160,597,598],{},"précondition"," : ce que l'appel doit garantir ",[601,602,603],"em",{},"avant"," (une pile non vide,\npar exemple) ;",[588,606,607,610,611,614],{},[160,608,609],{},"postcondition"," : ce que la méthode promet ",[601,612,613],{},"après",", si la précondition\nest tenue ;",[588,616,617,620],{},[160,618,619],{},"docstring"," : le contrat écrit dans le code, entre triples guillemets.",[151,622,624],{"id":623},"deuxième-écriture-le-jeu-de-tests","Deuxième écriture : le jeu de tests",[156,626,627,628,630,631,634,635,638],{},"Une instruction ",[259,629,261],{}," est une affirmation : vraie, rien ne se passe ; fausse,\nl'exécution s'arrête sur une ",[259,632,633],{},"AssertionError"," qui nomme ce qui a échoué. Un\n",[160,636,637],{},"jeu de tests"," est une suite d'affirmations tirées du contrat.",[156,640,641,642,647],{},"La traduction est mécanique : ",[160,643,644,645],{},"une promesse du contrat, un ",[259,646,261],{},".",[191,649,650,663],{},[194,651,652],{},[197,653,654,657],{},[200,655,656],{},"Ce que le contrat promet",[200,658,659,660,662],{},"L'",[259,661,261],{}," qui l'éprouve",[210,664,665,675,693,706,719],{},[197,666,667,670],{},[215,668,669],{},"une pile neuve est vide",[215,671,672],{},[259,673,674],{},"assert p.est_vide()",[197,676,677,688],{},[215,678,679,680,683,684,687],{},"après ",[259,681,682],{},"empiler(7)"," puis ",[259,685,686],{},"empiler(\"R\")",", le sommet est le dernier posé",[215,689,690],{},[259,691,692],{},"assert p.sommet() == \"R\"",[197,694,695,701],{},[215,696,697,700],{},[259,698,699],{},"sommet"," ne retire rien",[215,702,703],{},[259,704,705],{},"assert len(p) == 2",[197,707,708,714],{},[215,709,710,713],{},[259,711,712],{},"depiler"," rend le dernier élément empilé",[215,715,716],{},[259,717,718],{},"assert p.depiler() == \"R\"",[197,720,721,724],{},[215,722,723],{},"… puis celui qui était dessous",[215,725,726],{},[259,727,728],{},"assert p.depiler() == 7",[156,730,731],{},"Deux lignes du tableau méritent qu'on s'y arrête.",[156,733,734,737,738,741],{},[160,735,736],{},"Empiler deux éléments, pas un."," Avec un seul élément, le premier entré et le\ndernier entré sont le même : une ",[601,739,740],{},"file"," passerait le test. Pour éprouver\n« dernier entré, premier sorti », il faut au moins deux entrées ; sinon, la\npropriété qui définit la pile n'est tout simplement pas mise à l'épreuve.",[156,743,744,747,748,750,751,753],{},[160,745,746],{},"Tester une absence."," « ",[259,749,699],{}," ne retire rien » promet une absence d'effet,\net une absence ne se lit pas dans la valeur renvoyée : ",[259,752,361],{}," renvoie le\nbon élément, qu'il le retire ou non. Il faut regarder ailleurs : ici, la\nlongueur de la pile, qui doit rester à 2.",[156,755,756,757,760],{},"Rassemblées dans une fonction, ces affirmations forment le test. Il reçoit en\nparamètre ",[160,758,759],{},"la classe à éprouver",", ce qui permet de lui soumettre n'importe\nquelle implémentation :",[406,762,764],{"className":408,"code":763,"language":410,"meta":411,"style":411},"def tester_pile(fabriquer_une_pile):\n    \"\"\"Éprouver une classe de pile. Ne connaît que le CONTRAT :\n    aucune mention de liste, d'append ou de pop.\"\"\"\n    p = fabriquer_une_pile()\n    assert p.est_vide(), \"une pile neuve est vide\"\n\n    p.empiler(7)\n    p.empiler(\"R\")\n    assert len(p) == 2, \"deux empiler, deux éléments\"\n    assert not p.est_vide()\n\n    assert p.sommet() == \"R\", \"sommet renvoie le dessus\"\n    assert len(p) == 2, \"sommet ne retire rien\"\n\n    assert p.depiler() == \"R\", \"depiler renvoie le dessus\"\n    assert p.depiler() == 7, \"sous R, il y avait 7\"\n    assert p.est_vide(), \"tout est ressorti\"\n    return \"le contrat est honoré\"\n",[259,765,766,777,782,787,798,809,813,824,833,855,865,869,886,903,907,923,939,948],{"__ignoreMap":411},[415,767,768,771,774],{"class":417,"line":418},[415,769,770],{"class":421},"def",[415,772,773],{"class":425}," tester_pile",[415,775,776],{"class":429},"(fabriquer_une_pile):\n",[415,778,779],{"class":417,"line":433},[415,780,781],{"class":436},"    \"\"\"Éprouver une classe de pile. Ne connaît que le CONTRAT :\n",[415,783,784],{"class":417,"line":440},[415,785,786],{"class":436},"    aucune mention de liste, d'append ou de pop.\"\"\"\n",[415,788,789,792,795],{"class":417,"line":447},[415,790,791],{"class":429},"    p ",[415,793,794],{"class":421},"=",[415,796,797],{"class":429}," fabriquer_une_pile()\n",[415,799,800,803,806],{"class":417,"line":460},[415,801,802],{"class":421},"    assert",[415,804,805],{"class":429}," p.est_vide(), ",[415,807,808],{"class":436},"\"une pile neuve est vide\"\n",[415,810,811],{"class":417,"line":466},[415,812,444],{"emptyLinePlaceholder":443},[415,814,815,818,821],{"class":417,"line":471},[415,816,817],{"class":429},"    p.empiler(",[415,819,820],{"class":453},"7",[415,822,823],{"class":429},")\n",[415,825,826,828,831],{"class":417,"line":482},[415,827,817],{"class":429},[415,829,830],{"class":436},"\"R\"",[415,832,823],{"class":429},[415,834,835,837,840,843,846,849,852],{"class":417,"line":488},[415,836,802],{"class":421},[415,838,839],{"class":453}," len",[415,841,842],{"class":429},"(p) ",[415,844,845],{"class":421},"==",[415,847,848],{"class":453}," 2",[415,850,851],{"class":429},", ",[415,853,854],{"class":436},"\"deux empiler, deux éléments\"\n",[415,856,857,859,862],{"class":417,"line":493},[415,858,802],{"class":421},[415,860,861],{"class":421}," not",[415,863,864],{"class":429}," p.est_vide()\n",[415,866,867],{"class":417,"line":503},[415,868,444],{"emptyLinePlaceholder":443},[415,870,871,873,876,878,881,883],{"class":417,"line":509},[415,872,802],{"class":421},[415,874,875],{"class":429}," p.sommet() ",[415,877,845],{"class":421},[415,879,880],{"class":436}," \"R\"",[415,882,851],{"class":429},[415,884,885],{"class":436},"\"sommet renvoie le dessus\"\n",[415,887,888,890,892,894,896,898,900],{"class":417,"line":514},[415,889,802],{"class":421},[415,891,839],{"class":453},[415,893,842],{"class":429},[415,895,845],{"class":421},[415,897,848],{"class":453},[415,899,851],{"class":429},[415,901,902],{"class":436},"\"sommet ne retire rien\"\n",[415,904,905],{"class":417,"line":524},[415,906,444],{"emptyLinePlaceholder":443},[415,908,909,911,914,916,918,920],{"class":417,"line":530},[415,910,802],{"class":421},[415,912,913],{"class":429}," p.depiler() ",[415,915,845],{"class":421},[415,917,880],{"class":436},[415,919,851],{"class":429},[415,921,922],{"class":436},"\"depiler renvoie le dessus\"\n",[415,924,925,927,929,931,934,936],{"class":417,"line":535},[415,926,802],{"class":421},[415,928,913],{"class":429},[415,930,845],{"class":421},[415,932,933],{"class":453}," 7",[415,935,851],{"class":429},[415,937,938],{"class":436},"\"sous R, il y avait 7\"\n",[415,940,941,943,945],{"class":417,"line":545},[415,942,802],{"class":421},[415,944,805],{"class":429},[415,946,947],{"class":436},"\"tout est ressorti\"\n",[415,949,950,953],{"class":417,"line":551},[415,951,952],{"class":421},"    return",[415,954,955],{"class":436}," \"le contrat est honoré\"\n",[957,958,959],"tip",{},[156,960,961,962,965,966,969,970,972],{},"Le test ne mentionne ",[160,963,964],{},"aucune"," implémentation. S'il écrivait\n",[259,967,968],{},"assert p.elements == [7, \"R\"]",", il ne testerait plus le contrat mais une façon\nparticulière de le réaliser, et rejetterait à tort une ",[259,971,288],{}," correcte rangée\nautrement.",[974,975,979,992],"self-eval-qcm",{"correct":976,"explanation":977,"slug":978},"2","Avec un seul élément, premier entré et dernier entré se confondent : une file rendrait le même élément et passerait le test. Deux entrées suffisent à distinguer LIFO de FIFO.","contrat-tests-assertions-c1",[980,981,982],"template",{"v-slot:question":411},[156,983,984,985,988,989,991],{},"Pourquoi le test empile-t-il ",[160,986,987],{},"deux"," éléments avant d'appeler ",[259,990,346],{}," ?",[980,993,994],{"v-slot:choices":411},[585,995,996,999,1005],{},[588,997,998],{},"Pour vérifier que la pile accepte plusieurs types d'éléments",[588,1000,1001,1002],{},"Pour tester la performance de ",[259,1003,1004],{},"empiler",[588,1006,1007],{},"Parce qu'avec un seul élément, une file passerait aussi le test",[974,1009,1013,1024],{"correct":1010,"explanation":1011,"slug":1012},"1","sommet() renvoie le bon élément qu'il le retire ou non : la valeur renvoyée ne dit rien de l'effet. C'est la longueur, inchangée, qui prouve qu'il n'a rien retiré.","contrat-tests-assertions-c2",[980,1014,1015],{"v-slot:question":411},[156,1016,1017,1018,1020,1021,1023],{},"Quel ",[259,1019,261],{}," éprouve la promesse « ",[259,1022,361],{}," ne retire rien » ?",[980,1025,1026],{"v-slot:choices":411},[585,1027,1028,1032,1039],{},[588,1029,1030],{},[259,1031,692],{},[588,1033,1034,1036,1037],{},[259,1035,705],{}," juste après l'appel à ",[259,1038,361],{},[588,1040,1041],{},[259,1042,1043],{},"assert p.sommet() is not None",[151,1045,1047],{"id":1046},"le-test-avant-le-code","Le test avant le code",[156,1049,1050,1051,1053],{},"Le jeu de tests ne dépend que du contrat. Il peut donc s'écrire ",[160,1052,603],{}," la\nmoindre ligne d'implémentation, et c'est précisément l'ordre recommandé.",[156,1055,1056,1057,1059,1060,1063,1064,1066,1067,1070,1071,1073],{},"Lancé sur la ",[259,1058,288],{}," sans corps de la première partie, le test ",[160,1061,1062],{},"échoue"," dès sa\npremière ligne : ",[259,1065,377],{}," renvoie ",[259,1068,1069],{},"None",", qui compte comme faux, donc\n",[259,1072,674],{}," échoue.\nCe n'est pas un raté du test, c'est le résultat attendu.",[1075,1076,1077],"python-snippet",{},[406,1078,1080],{"className":408,"code":1079,"language":410,"meta":411,"style":411},"class Pile:\n    \"\"\"Le contrat seul : aucune méthode n'a de corps.\"\"\"\n    def __init__(self): pass\n    def empiler(self, x): pass\n    def depiler(self): pass\n    def sommet(self): pass\n    def est_vide(self): pass\n    def __len__(self): pass\n\ndef tester_pile(fabriquer_une_pile):\n    p = fabriquer_une_pile()\n    assert p.est_vide(), \"une pile neuve est vide\"\n    p.empiler(7)\n    p.empiler(\"R\")\n    assert len(p) == 2, \"deux empiler, deux éléments\"\n    assert p.sommet() == \"R\", \"sommet renvoie le dessus\"\n    assert len(p) == 2, \"sommet ne retire rien\"\n    assert p.depiler() == \"R\", \"depiler renvoie le dessus\"\n    assert p.depiler() == 7, \"sous R, il y avait 7\"\n    assert p.est_vide(), \"tout est ressorti\"\n    return \"le contrat est honoré\"\n\ntry:\n    print(tester_pile(Pile))\nexcept AssertionError as e:\n    print(\"échec :\", e)\n",[259,1081,1082,1090,1095,1107,1118,1128,1138,1148,1158,1162,1170,1178,1186,1194,1202,1218,1232,1248,1262,1276,1284,1291,1296,1304,1313,1328],{"__ignoreMap":411},[415,1083,1084,1086,1088],{"class":417,"line":418},[415,1085,422],{"class":421},[415,1087,426],{"class":425},[415,1089,430],{"class":429},[415,1091,1092],{"class":417,"line":433},[415,1093,1094],{"class":436},"    \"\"\"Le contrat seul : aucune méthode n'a de corps.\"\"\"\n",[415,1096,1097,1099,1101,1104],{"class":417,"line":440},[415,1098,450],{"class":421},[415,1100,454],{"class":453},[415,1102,1103],{"class":429},"(self): ",[415,1105,1106],{"class":421},"pass\n",[415,1108,1109,1111,1113,1116],{"class":417,"line":447},[415,1110,450],{"class":421},[415,1112,476],{"class":425},[415,1114,1115],{"class":429},"(self, x): ",[415,1117,1106],{"class":421},[415,1119,1120,1122,1124,1126],{"class":417,"line":460},[415,1121,450],{"class":421},[415,1123,498],{"class":425},[415,1125,1103],{"class":429},[415,1127,1106],{"class":421},[415,1129,1130,1132,1134,1136],{"class":417,"line":466},[415,1131,450],{"class":421},[415,1133,519],{"class":425},[415,1135,1103],{"class":429},[415,1137,1106],{"class":421},[415,1139,1140,1142,1144,1146],{"class":417,"line":471},[415,1141,450],{"class":421},[415,1143,540],{"class":425},[415,1145,1103],{"class":429},[415,1147,1106],{"class":421},[415,1149,1150,1152,1154,1156],{"class":417,"line":482},[415,1151,450],{"class":421},[415,1153,561],{"class":453},[415,1155,1103],{"class":429},[415,1157,1106],{"class":421},[415,1159,1160],{"class":417,"line":488},[415,1161,444],{"emptyLinePlaceholder":443},[415,1163,1164,1166,1168],{"class":417,"line":493},[415,1165,770],{"class":421},[415,1167,773],{"class":425},[415,1169,776],{"class":429},[415,1171,1172,1174,1176],{"class":417,"line":503},[415,1173,791],{"class":429},[415,1175,794],{"class":421},[415,1177,797],{"class":429},[415,1179,1180,1182,1184],{"class":417,"line":509},[415,1181,802],{"class":421},[415,1183,805],{"class":429},[415,1185,808],{"class":436},[415,1187,1188,1190,1192],{"class":417,"line":514},[415,1189,817],{"class":429},[415,1191,820],{"class":453},[415,1193,823],{"class":429},[415,1195,1196,1198,1200],{"class":417,"line":524},[415,1197,817],{"class":429},[415,1199,830],{"class":436},[415,1201,823],{"class":429},[415,1203,1204,1206,1208,1210,1212,1214,1216],{"class":417,"line":530},[415,1205,802],{"class":421},[415,1207,839],{"class":453},[415,1209,842],{"class":429},[415,1211,845],{"class":421},[415,1213,848],{"class":453},[415,1215,851],{"class":429},[415,1217,854],{"class":436},[415,1219,1220,1222,1224,1226,1228,1230],{"class":417,"line":535},[415,1221,802],{"class":421},[415,1223,875],{"class":429},[415,1225,845],{"class":421},[415,1227,880],{"class":436},[415,1229,851],{"class":429},[415,1231,885],{"class":436},[415,1233,1234,1236,1238,1240,1242,1244,1246],{"class":417,"line":545},[415,1235,802],{"class":421},[415,1237,839],{"class":453},[415,1239,842],{"class":429},[415,1241,845],{"class":421},[415,1243,848],{"class":453},[415,1245,851],{"class":429},[415,1247,902],{"class":436},[415,1249,1250,1252,1254,1256,1258,1260],{"class":417,"line":551},[415,1251,802],{"class":421},[415,1253,913],{"class":429},[415,1255,845],{"class":421},[415,1257,880],{"class":436},[415,1259,851],{"class":429},[415,1261,922],{"class":436},[415,1263,1264,1266,1268,1270,1272,1274],{"class":417,"line":556},[415,1265,802],{"class":421},[415,1267,913],{"class":429},[415,1269,845],{"class":421},[415,1271,933],{"class":453},[415,1273,851],{"class":429},[415,1275,938],{"class":436},[415,1277,1278,1280,1282],{"class":417,"line":566},[415,1279,802],{"class":421},[415,1281,805],{"class":429},[415,1283,947],{"class":436},[415,1285,1287,1289],{"class":417,"line":1286},21,[415,1288,952],{"class":421},[415,1290,955],{"class":436},[415,1292,1294],{"class":417,"line":1293},22,[415,1295,444],{"emptyLinePlaceholder":443},[415,1297,1299,1302],{"class":417,"line":1298},23,[415,1300,1301],{"class":421},"try",[415,1303,430],{"class":429},[415,1305,1307,1310],{"class":417,"line":1306},24,[415,1308,1309],{"class":453},"    print",[415,1311,1312],{"class":429},"(tester_pile(Pile))\n",[415,1314,1316,1319,1322,1325],{"class":417,"line":1315},25,[415,1317,1318],{"class":421},"except",[415,1320,1321],{"class":453}," AssertionError",[415,1323,1324],{"class":421}," as",[415,1326,1327],{"class":429}," e:\n",[415,1329,1331,1333,1336,1339],{"class":417,"line":1330},26,[415,1332,1309],{"class":453},[415,1334,1335],{"class":429},"(",[415,1337,1338],{"class":436},"\"échec :\"",[415,1340,1341],{"class":429},", e)\n",[156,1343,1344,1345,1348],{},"Le repère à retenir : ",[160,1346,1347],{},"un bon jeu de tests échoue tant que le code n'existe\npas, et passe une fois qu'il est juste."," Entre les deux, chaque échec désigne\nce qu'il reste à écrire. Le test devient alors la définition de « fini » : le\ntravail s'arrête quand il passe, ni avant ni beaucoup après.",[156,1350,1351,1352,1355],{},"Un test qui passerait ",[160,1353,1354],{},"déjà"," sur une classe vide serait suspect : il\nn'éprouverait rien.",[974,1357,1361,1366],{"correct":1358,"explanation":1359,"slug":1360},"0","Un test écrit depuis le contrat échoue tant que le code n'existe pas. Son échec n'accuse pas le test : il liste ce qu'il reste à écrire.","contrat-tests-assertions-c3",[980,1362,1363],{"v-slot:question":411},[156,1364,1365],{},"Le jeu de tests, lancé sur une classe dont les méthodes n'ont pas de corps, échoue. Qu'en conclure ?",[980,1367,1368],{"v-slot:choices":411},[585,1369,1370,1373,1376],{},[588,1371,1372],{},"Rien d'anormal : le test indique ce qu'il reste à écrire",[588,1374,1375],{},"Le test est mal écrit et doit être corrigé",[588,1377,1378],{},"Il faut écrire le code d'abord, et le test ensuite",[151,1380,1382],{"id":1381},"ce-quun-jeu-de-tests-ne-dit-pas","Ce qu'un jeu de tests ne dit pas",[156,1384,1385,1386,1388],{},"Trois implémentations de ",[259,1387,288],{},", chacune fausse à sa manière, passent devant le\nmême test, sans qu'il change d'une virgule :",[585,1390,1391,1406,1420],{},[588,1392,1393,1398,1399,1401,1402,1405],{},[160,1394,1395],{},[259,1396,1397],{},"PileA"," : ",[259,1400,712],{}," renvoie le plus ",[160,1403,1404],{},"ancien"," élément au lieu du plus\nrécent ;",[588,1407,1408,1398,1413,1415,1416,1419],{},[160,1409,1410],{},[259,1411,1412],{},"PileB",[259,1414,699],{}," ",[160,1417,1418],{},"retire"," l'élément qu'il renvoie ;",[588,1421,1422,1427,1428,1431],{},[160,1423,1424],{},[259,1425,1426],{},"PileC"," : au-delà de trois éléments, la pile ",[160,1429,1430],{},"oublie"," le plus ancien,\nsans rien signaler.",[1075,1433,1434],{},[406,1435,1437],{"className":408,"code":1436,"language":410,"meta":411,"style":411},"def tester_pile(fabriquer_une_pile):\n    p = fabriquer_une_pile()\n    assert p.est_vide(), \"une pile neuve est vide\"\n    p.empiler(7)\n    p.empiler(\"R\")\n    assert len(p) == 2, \"deux empiler, deux éléments\"\n    assert p.sommet() == \"R\", \"sommet renvoie le dessus\"\n    assert len(p) == 2, \"sommet ne retire rien\"\n    assert p.depiler() == \"R\", \"depiler renvoie le dessus\"\n    assert p.depiler() == 7, \"sous R, il y avait 7\"\n    assert p.est_vide(), \"tout est ressorti\"\n    return \"le contrat est honoré\"\n\nclass PileA:\n    def __init__(self): self.elements = []\n    def empiler(self, x): self.elements.append(x)\n    def depiler(self): return self.elements.pop(0)      # le plus ancien !\n    def sommet(self): return self.elements[-1]\n    def est_vide(self): return len(self.elements) == 0\n    def __len__(self): return len(self.elements)\n\nclass PileB(PileA):\n    def depiler(self): return self.elements.pop()\n    def sommet(self): return self.elements.pop()        # retire !\n\nclass PileC(PileA):\n    def empiler(self, x):\n        self.elements.append(x)\n        if len(self.elements) > 3:\n            self.elements.pop(0)                         # oublie le plus ancien\n    def depiler(self): return self.elements.pop()\n\nfor nom, classe in [(\"PileA\", PileA), (\"PileB\", PileB), (\"PileC\", PileC)]:\n    try:\n        print(nom, \":\", tester_pile(classe))\n    except AssertionError as e:\n        print(nom, \": REJETÉE,\", e)\n",[259,1438,1439,1447,1455,1463,1471,1479,1495,1509,1525,1539,1553,1561,1567,1571,1580,1599,1612,1638,1661,1685,1704,1708,1722,1737,1755,1759,1772,1781,1789,1811,1827,1842,1847,1880,1888,1903,1915],{"__ignoreMap":411},[415,1440,1441,1443,1445],{"class":417,"line":418},[415,1442,770],{"class":421},[415,1444,773],{"class":425},[415,1446,776],{"class":429},[415,1448,1449,1451,1453],{"class":417,"line":433},[415,1450,791],{"class":429},[415,1452,794],{"class":421},[415,1454,797],{"class":429},[415,1456,1457,1459,1461],{"class":417,"line":440},[415,1458,802],{"class":421},[415,1460,805],{"class":429},[415,1462,808],{"class":436},[415,1464,1465,1467,1469],{"class":417,"line":447},[415,1466,817],{"class":429},[415,1468,820],{"class":453},[415,1470,823],{"class":429},[415,1472,1473,1475,1477],{"class":417,"line":460},[415,1474,817],{"class":429},[415,1476,830],{"class":436},[415,1478,823],{"class":429},[415,1480,1481,1483,1485,1487,1489,1491,1493],{"class":417,"line":466},[415,1482,802],{"class":421},[415,1484,839],{"class":453},[415,1486,842],{"class":429},[415,1488,845],{"class":421},[415,1490,848],{"class":453},[415,1492,851],{"class":429},[415,1494,854],{"class":436},[415,1496,1497,1499,1501,1503,1505,1507],{"class":417,"line":471},[415,1498,802],{"class":421},[415,1500,875],{"class":429},[415,1502,845],{"class":421},[415,1504,880],{"class":436},[415,1506,851],{"class":429},[415,1508,885],{"class":436},[415,1510,1511,1513,1515,1517,1519,1521,1523],{"class":417,"line":482},[415,1512,802],{"class":421},[415,1514,839],{"class":453},[415,1516,842],{"class":429},[415,1518,845],{"class":421},[415,1520,848],{"class":453},[415,1522,851],{"class":429},[415,1524,902],{"class":436},[415,1526,1527,1529,1531,1533,1535,1537],{"class":417,"line":488},[415,1528,802],{"class":421},[415,1530,913],{"class":429},[415,1532,845],{"class":421},[415,1534,880],{"class":436},[415,1536,851],{"class":429},[415,1538,922],{"class":436},[415,1540,1541,1543,1545,1547,1549,1551],{"class":417,"line":493},[415,1542,802],{"class":421},[415,1544,913],{"class":429},[415,1546,845],{"class":421},[415,1548,933],{"class":453},[415,1550,851],{"class":429},[415,1552,938],{"class":436},[415,1554,1555,1557,1559],{"class":417,"line":503},[415,1556,802],{"class":421},[415,1558,805],{"class":429},[415,1560,947],{"class":436},[415,1562,1563,1565],{"class":417,"line":509},[415,1564,952],{"class":421},[415,1566,955],{"class":436},[415,1568,1569],{"class":417,"line":514},[415,1570,444],{"emptyLinePlaceholder":443},[415,1572,1573,1575,1578],{"class":417,"line":524},[415,1574,422],{"class":421},[415,1576,1577],{"class":425}," PileA",[415,1579,430],{"class":429},[415,1581,1582,1584,1586,1588,1591,1594,1596],{"class":417,"line":530},[415,1583,450],{"class":421},[415,1585,454],{"class":453},[415,1587,1103],{"class":429},[415,1589,1590],{"class":453},"self",[415,1592,1593],{"class":429},".elements ",[415,1595,794],{"class":421},[415,1597,1598],{"class":429}," []\n",[415,1600,1601,1603,1605,1607,1609],{"class":417,"line":535},[415,1602,450],{"class":421},[415,1604,476],{"class":425},[415,1606,1115],{"class":429},[415,1608,1590],{"class":453},[415,1610,1611],{"class":429},".elements.append(x)\n",[415,1613,1614,1616,1618,1620,1623,1626,1629,1631,1634],{"class":417,"line":545},[415,1615,450],{"class":421},[415,1617,498],{"class":425},[415,1619,1103],{"class":429},[415,1621,1622],{"class":421},"return",[415,1624,1625],{"class":453}," self",[415,1627,1628],{"class":429},".elements.pop(",[415,1630,1358],{"class":453},[415,1632,1633],{"class":429},")      ",[415,1635,1637],{"class":1636},"sCsY4","# le plus ancien !\n",[415,1639,1640,1642,1644,1646,1648,1650,1653,1656,1658],{"class":417,"line":551},[415,1641,450],{"class":421},[415,1643,519],{"class":425},[415,1645,1103],{"class":429},[415,1647,1622],{"class":421},[415,1649,1625],{"class":453},[415,1651,1652],{"class":429},".elements[",[415,1654,1655],{"class":421},"-",[415,1657,1010],{"class":453},[415,1659,1660],{"class":429},"]\n",[415,1662,1663,1665,1667,1669,1671,1673,1675,1677,1680,1682],{"class":417,"line":556},[415,1664,450],{"class":421},[415,1666,540],{"class":425},[415,1668,1103],{"class":429},[415,1670,1622],{"class":421},[415,1672,839],{"class":453},[415,1674,1335],{"class":429},[415,1676,1590],{"class":453},[415,1678,1679],{"class":429},".elements) ",[415,1681,845],{"class":421},[415,1683,1684],{"class":453}," 0\n",[415,1686,1687,1689,1691,1693,1695,1697,1699,1701],{"class":417,"line":566},[415,1688,450],{"class":421},[415,1690,561],{"class":453},[415,1692,1103],{"class":429},[415,1694,1622],{"class":421},[415,1696,839],{"class":453},[415,1698,1335],{"class":429},[415,1700,1590],{"class":453},[415,1702,1703],{"class":429},".elements)\n",[415,1705,1706],{"class":417,"line":1286},[415,1707,444],{"emptyLinePlaceholder":443},[415,1709,1710,1712,1715,1717,1719],{"class":417,"line":1293},[415,1711,422],{"class":421},[415,1713,1714],{"class":425}," PileB",[415,1716,1335],{"class":429},[415,1718,1397],{"class":425},[415,1720,1721],{"class":429},"):\n",[415,1723,1724,1726,1728,1730,1732,1734],{"class":417,"line":1298},[415,1725,450],{"class":421},[415,1727,498],{"class":425},[415,1729,1103],{"class":429},[415,1731,1622],{"class":421},[415,1733,1625],{"class":453},[415,1735,1736],{"class":429},".elements.pop()\n",[415,1738,1739,1741,1743,1745,1747,1749,1752],{"class":417,"line":1306},[415,1740,450],{"class":421},[415,1742,519],{"class":425},[415,1744,1103],{"class":429},[415,1746,1622],{"class":421},[415,1748,1625],{"class":453},[415,1750,1751],{"class":429},".elements.pop()        ",[415,1753,1754],{"class":1636},"# retire !\n",[415,1756,1757],{"class":417,"line":1315},[415,1758,444],{"emptyLinePlaceholder":443},[415,1760,1761,1763,1766,1768,1770],{"class":417,"line":1330},[415,1762,422],{"class":421},[415,1764,1765],{"class":425}," PileC",[415,1767,1335],{"class":429},[415,1769,1397],{"class":425},[415,1771,1721],{"class":429},[415,1773,1775,1777,1779],{"class":417,"line":1774},27,[415,1776,450],{"class":421},[415,1778,476],{"class":425},[415,1780,479],{"class":429},[415,1782,1784,1787],{"class":417,"line":1783},28,[415,1785,1786],{"class":453},"        self",[415,1788,1611],{"class":429},[415,1790,1792,1795,1797,1799,1801,1803,1806,1809],{"class":417,"line":1791},29,[415,1793,1794],{"class":421},"        if",[415,1796,839],{"class":453},[415,1798,1335],{"class":429},[415,1800,1590],{"class":453},[415,1802,1679],{"class":429},[415,1804,1805],{"class":421},">",[415,1807,1808],{"class":453}," 3",[415,1810,430],{"class":429},[415,1812,1814,1817,1819,1821,1824],{"class":417,"line":1813},30,[415,1815,1816],{"class":453},"            self",[415,1818,1628],{"class":429},[415,1820,1358],{"class":453},[415,1822,1823],{"class":429},")                         ",[415,1825,1826],{"class":1636},"# oublie le plus ancien\n",[415,1828,1830,1832,1834,1836,1838,1840],{"class":417,"line":1829},31,[415,1831,450],{"class":421},[415,1833,498],{"class":425},[415,1835,1103],{"class":429},[415,1837,1622],{"class":421},[415,1839,1625],{"class":453},[415,1841,1736],{"class":429},[415,1843,1845],{"class":417,"line":1844},32,[415,1846,444],{"emptyLinePlaceholder":443},[415,1848,1850,1853,1856,1859,1862,1865,1868,1871,1874,1877],{"class":417,"line":1849},33,[415,1851,1852],{"class":421},"for",[415,1854,1855],{"class":429}," nom, classe ",[415,1857,1858],{"class":421},"in",[415,1860,1861],{"class":429}," [(",[415,1863,1864],{"class":436},"\"PileA\"",[415,1866,1867],{"class":429},", PileA), (",[415,1869,1870],{"class":436},"\"PileB\"",[415,1872,1873],{"class":429},", PileB), (",[415,1875,1876],{"class":436},"\"PileC\"",[415,1878,1879],{"class":429},", PileC)]:\n",[415,1881,1883,1886],{"class":417,"line":1882},34,[415,1884,1885],{"class":421},"    try",[415,1887,430],{"class":429},[415,1889,1891,1894,1897,1900],{"class":417,"line":1890},35,[415,1892,1893],{"class":453},"        print",[415,1895,1896],{"class":429},"(nom, ",[415,1898,1899],{"class":436},"\":\"",[415,1901,1902],{"class":429},", tester_pile(classe))\n",[415,1904,1906,1909,1911,1913],{"class":417,"line":1905},36,[415,1907,1908],{"class":421},"    except",[415,1910,1321],{"class":453},[415,1912,1324],{"class":421},[415,1914,1327],{"class":429},[415,1916,1918,1920,1922,1925],{"class":417,"line":1917},37,[415,1919,1893],{"class":453},[415,1921,1896],{"class":429},[415,1923,1924],{"class":436},"\": REJETÉE,\"",[415,1926,1341],{"class":429},[156,1928,1929,1931,1932,1934,1935,1937,1938,1941],{},[259,1930,1397],{}," et ",[259,1933,1412],{}," sont rejetées : deux éléments suffisent à les démasquer.\n",[259,1936,1426],{},", elle, ",[160,1939,1940],{},"passe, et reste fausse",". Le jeu de tests n'empile jamais\nquatre éléments, donc il ne voit rien.",[156,1943,1944,1945,1948,1949,1952,1953,1956,1957,1960],{},"C'est la phrase du programme de Première, rencontrée en situation : ",[160,1946,1947],{},"le succès\nd'un jeu de tests ne garantit pas la correction d'un programme."," Un test qui\npasse prouve seulement que ",[601,1950,1951],{},"les cas écrits"," passent. D'où l'importance du\n",[160,1954,1955],{},"nombre"," et du ",[160,1958,1959],{},"choix"," des cas : ici, un cas « beaucoup d'éléments »\nmanquait.",[406,1962,1964],{"className":408,"code":1963,"language":410,"meta":411,"style":411},"p = PileC()\nfor n in [1, 2, 3, 4]:\n    p.empiler(n)\nassert len(p) == 4, \"empiler quatre éléments en laisse quatre\"   # PileC échoue\n",[259,1965,1966,1976,2007,2012],{"__ignoreMap":411},[415,1967,1968,1971,1973],{"class":417,"line":418},[415,1969,1970],{"class":429},"p ",[415,1972,794],{"class":421},[415,1974,1975],{"class":429}," PileC()\n",[415,1977,1978,1980,1983,1985,1988,1990,1992,1994,1996,1999,2001,2004],{"class":417,"line":433},[415,1979,1852],{"class":421},[415,1981,1982],{"class":429}," n ",[415,1984,1858],{"class":421},[415,1986,1987],{"class":429}," [",[415,1989,1010],{"class":453},[415,1991,851],{"class":429},[415,1993,976],{"class":453},[415,1995,851],{"class":429},[415,1997,1998],{"class":453},"3",[415,2000,851],{"class":429},[415,2002,2003],{"class":453},"4",[415,2005,2006],{"class":429},"]:\n",[415,2008,2009],{"class":417,"line":440},[415,2010,2011],{"class":429},"    p.empiler(n)\n",[415,2013,2014,2016,2018,2020,2022,2025,2027,2030],{"class":417,"line":447},[415,2015,261],{"class":421},[415,2017,839],{"class":453},[415,2019,842],{"class":429},[415,2021,845],{"class":421},[415,2023,2024],{"class":453}," 4",[415,2026,851],{"class":429},[415,2028,2029],{"class":436},"\"empiler quatre éléments en laisse quatre\"",[415,2031,2032],{"class":1636},"   # PileC échoue\n",[2034,2035,2038],"card",{"icon":2036,"title":2037},"i-lucide-target","Le périmètre, c'est ce que le contrat a dit",[156,2039,2040,2042,2043,2046],{},[259,2041,1426],{}," n'est pas fautive par étourderie : elle honore un ",[160,2044,2045],{},"autre"," contrat,\ncelui d'une pile de capacité bornée, que le contrat écrit n'interdisait nulle\npart. Le périmètre d'un programme n'est pas ce que son code fait : c'est ce que\nson contrat a dit. Un contrat précis (« la pile n'a pas de limite de taille »)\naurait appelé le test qui manquait.",[974,2048,2051,2058],{"correct":1010,"explanation":2049,"slug":2050},"Un jeu de tests ne vérifie que les cas qu'il contient. PileC passe parce qu'aucun cas n'empile plus de trois éléments : le succès d'un jeu de tests ne garantit pas la correction.","contrat-tests-assertions-c4",[980,2052,2053],{"v-slot:question":411},[156,2054,2055,2057],{},[259,2056,1426],{}," passe le jeu de tests. Qu'en conclure ?",[980,2059,2060],{"v-slot:choices":411},[585,2061,2062,2067,2070],{},[588,2063,2064,2066],{},[259,2065,1426],{}," est correcte",[588,2068,2069],{},"Le jeu de tests ne couvre pas le cas qui la met en défaut",[588,2071,2072],{},"Le jeu de tests est faux et doit être supprimé",[151,2074,2076],{"id":2075},"troisième-écriture-lassertion-dans-la-méthode","Troisième écriture : l'assertion dans la méthode",[156,2078,2079,2080,2086],{},"Le tableau du contrat ne dit pas ",[160,2081,2082,2083,2085],{},"ce que doit faire ",[259,2084,346],{}," sur une pile\nvide",". Deux réponses sont également correctes, à condition d'être écrites.",[585,2088,2089,2160],{},[588,2090,2091,2094,2095,2097,2098,2100,2101,2146,2149,2150,2152,2153,2156,2157,2159],{},[160,2092,2093],{},"L'interdire."," La pile non vide devient une ",[160,2096,598],{},", et ",[259,2099,712],{},"\ncommence par la vérifier :",[406,2102,2104],{"className":408,"code":2103,"language":410,"meta":411,"style":411},"def depiler(self):\n    \"\"\"Retirer l'élément du sommet et le renvoyer.\n    Précondition : la pile n'est pas vide.\"\"\"\n    assert not self.est_vide(), \"depiler exige une pile non vide\"\n    return self.elements.pop()\n",[259,2105,2106,2114,2119,2124,2138],{"__ignoreMap":411},[415,2107,2108,2110,2112],{"class":417,"line":418},[415,2109,770],{"class":421},[415,2111,498],{"class":425},[415,2113,457],{"class":429},[415,2115,2116],{"class":417,"line":433},[415,2117,2118],{"class":436},"    \"\"\"Retirer l'élément du sommet et le renvoyer.\n",[415,2120,2121],{"class":417,"line":440},[415,2122,2123],{"class":436},"    Précondition : la pile n'est pas vide.\"\"\"\n",[415,2125,2126,2128,2130,2132,2135],{"class":417,"line":447},[415,2127,802],{"class":421},[415,2129,861],{"class":421},[415,2131,1625],{"class":453},[415,2133,2134],{"class":429},".est_vide(), ",[415,2136,2137],{"class":436},"\"depiler exige une pile non vide\"\n",[415,2139,2140,2142,2144],{"class":417,"line":460},[415,2141,952],{"class":421},[415,2143,1625],{"class":453},[415,2145,1736],{"class":429},[2147,2148],"br",{},"La même précondition vaut pour ",[259,2151,361],{},". Lever une exception explicite,\ncomme le ",[259,2154,2155],{},"raise IndexError(\"pile vide\")"," de la ",[259,2158,288],{}," du cours précédent, est\nune autre façon de l'interdire : le message nomme lui aussi le contrat.",[588,2161,2162,1415,2165,1066,2167,2169],{},[160,2163,2164],{},"La définir.",[259,2166,712],{},[259,2168,1069],{}," sur une pile vide, et la\ndocumentation le dit.",[156,2171,2172,2173,2176],{},"Ce qui serait fautif, c'est de ",[160,2174,2175],{},"ne rien dire"," : le code déciderait alors à la\nplace du contrat, et personne ne saurait si le comportement obtenu était voulu.",[156,2178,2179,2180,2183,2184,2187,2188,2191,2192,2195,2196,2199,2200,2203],{},"La différence se voit dans le message d'erreur. Sans précondition écrite,\n",[259,2181,2182],{},"[].pop()"," lève ",[259,2185,2186],{},"IndexError: pop from empty list",", un message qui parle des\n",[160,2189,2190],{},"entrailles"," de la classe (une liste, un ",[259,2193,2194],{},"pop","). Avec l'assertion,\n",[259,2197,2198],{},"AssertionError: depiler exige une pile non vide"," parle de ",[160,2201,2202],{},"l'appel",", et\nnomme la promesse qui n'a pas été tenue.",[1075,2205,2206],{},[406,2207,2209],{"className":408,"code":2208,"language":410,"meta":411,"style":411},"class Pile:\n    def __init__(self): self.elements = []\n    def empiler(self, x): self.elements.append(x)\n    def est_vide(self): return len(self.elements) == 0\n    def depiler(self):\n        return self.elements.pop()\n\nclass PileGardee(Pile):\n    def depiler(self):\n        assert not self.est_vide(), \"depiler exige une pile non vide\"\n        return self.elements.pop()\n\nfor classe in [Pile, PileGardee]:\n    try:\n        classe().depiler()\n    except Exception as e:\n        print(classe.__name__, \"->\", type(e).__name__, \":\", e)\n",[259,2210,2211,2219,2235,2247,2269,2277,2286,2290,2303,2311,2324,2332,2336,2348,2354,2359,2370],{"__ignoreMap":411},[415,2212,2213,2215,2217],{"class":417,"line":418},[415,2214,422],{"class":421},[415,2216,426],{"class":425},[415,2218,430],{"class":429},[415,2220,2221,2223,2225,2227,2229,2231,2233],{"class":417,"line":433},[415,2222,450],{"class":421},[415,2224,454],{"class":453},[415,2226,1103],{"class":429},[415,2228,1590],{"class":453},[415,2230,1593],{"class":429},[415,2232,794],{"class":421},[415,2234,1598],{"class":429},[415,2236,2237,2239,2241,2243,2245],{"class":417,"line":440},[415,2238,450],{"class":421},[415,2240,476],{"class":425},[415,2242,1115],{"class":429},[415,2244,1590],{"class":453},[415,2246,1611],{"class":429},[415,2248,2249,2251,2253,2255,2257,2259,2261,2263,2265,2267],{"class":417,"line":447},[415,2250,450],{"class":421},[415,2252,540],{"class":425},[415,2254,1103],{"class":429},[415,2256,1622],{"class":421},[415,2258,839],{"class":453},[415,2260,1335],{"class":429},[415,2262,1590],{"class":453},[415,2264,1679],{"class":429},[415,2266,845],{"class":421},[415,2268,1684],{"class":453},[415,2270,2271,2273,2275],{"class":417,"line":460},[415,2272,450],{"class":421},[415,2274,498],{"class":425},[415,2276,457],{"class":429},[415,2278,2279,2282,2284],{"class":417,"line":466},[415,2280,2281],{"class":421},"        return",[415,2283,1625],{"class":453},[415,2285,1736],{"class":429},[415,2287,2288],{"class":417,"line":471},[415,2289,444],{"emptyLinePlaceholder":443},[415,2291,2292,2294,2297,2299,2301],{"class":417,"line":482},[415,2293,422],{"class":421},[415,2295,2296],{"class":425}," PileGardee",[415,2298,1335],{"class":429},[415,2300,288],{"class":425},[415,2302,1721],{"class":429},[415,2304,2305,2307,2309],{"class":417,"line":488},[415,2306,450],{"class":421},[415,2308,498],{"class":425},[415,2310,457],{"class":429},[415,2312,2313,2316,2318,2320,2322],{"class":417,"line":493},[415,2314,2315],{"class":421},"        assert",[415,2317,861],{"class":421},[415,2319,1625],{"class":453},[415,2321,2134],{"class":429},[415,2323,2137],{"class":436},[415,2325,2326,2328,2330],{"class":417,"line":503},[415,2327,2281],{"class":421},[415,2329,1625],{"class":453},[415,2331,1736],{"class":429},[415,2333,2334],{"class":417,"line":509},[415,2335,444],{"emptyLinePlaceholder":443},[415,2337,2338,2340,2343,2345],{"class":417,"line":514},[415,2339,1852],{"class":421},[415,2341,2342],{"class":429}," classe ",[415,2344,1858],{"class":421},[415,2346,2347],{"class":429}," [Pile, PileGardee]:\n",[415,2349,2350,2352],{"class":417,"line":524},[415,2351,1885],{"class":421},[415,2353,430],{"class":429},[415,2355,2356],{"class":417,"line":530},[415,2357,2358],{"class":429},"        classe().depiler()\n",[415,2360,2361,2363,2366,2368],{"class":417,"line":535},[415,2362,1908],{"class":421},[415,2364,2365],{"class":453}," Exception",[415,2367,1324],{"class":421},[415,2369,1327],{"class":429},[415,2371,2372,2374,2377,2380,2382,2385,2387,2390,2393,2395,2397,2399],{"class":417,"line":545},[415,2373,1893],{"class":453},[415,2375,2376],{"class":429},"(classe.",[415,2378,2379],{"class":453},"__name__",[415,2381,851],{"class":429},[415,2383,2384],{"class":436},"\"->\"",[415,2386,851],{"class":429},[415,2388,2389],{"class":453},"type",[415,2391,2392],{"class":429},"(e).",[415,2394,2379],{"class":453},[415,2396,851],{"class":429},[415,2398,1899],{"class":436},[415,2400,1341],{"class":429},[151,2402,2404],{"id":2403},"dedans-ou-dehors","Dedans ou dehors",[156,2406,2407,2408,2410,2411,2414,2415,647],{},"Le jeu de tests et la précondition s'écrivent tous deux avec ",[259,2409,261],{},". Ce qui\nles distingue n'est pas la syntaxe mais ",[160,2412,2413],{},"l'endroit où ils vivent",", et donc\n",[160,2416,2417],{},"qui ils mettent en cause",[191,2419,2420,2432],{},[194,2421,2422],{},[197,2423,2424,2426,2429],{},[200,2425],{},[200,2427,2428],{},"Le test",[200,2430,2431],{},"L'assertion (précondition)",[210,2433,2434,2445,2465,2478],{},[197,2435,2436,2441,2443],{},[215,2437,2438],{},[160,2439,2440],{},"Où il vit",[215,2442,235],{},[215,2444,248],{},[197,2446,2447,2452,2459],{},[215,2448,2449],{},[160,2450,2451],{},"Ce qu'il accuse",[215,2453,2454,2455,2458],{},"l'",[160,2456,2457],{},"implémentation"," : « ce code est faux »",[215,2460,2454,2461,2464],{},[160,2462,2463],{},"appelant"," : « cet appel n'avait pas le droit »",[197,2466,2467,2472,2475],{},[215,2468,2469],{},[160,2470,2471],{},"Quand il s'exécute",[215,2473,2474],{},"à la demande, pendant le développement, sur des cas choisis",[215,2476,2477],{},"à chaque appel, sur les vraies données",[197,2479,2480,2485,2487],{},[215,2481,2482],{},[160,2483,2484],{},"Part-il avec le programme ?",[215,2486,370],{},[215,2488,2489,2490,2493],{},"oui (sauf sous ",[259,2491,2492],{},"python -O",")",[156,2495,2496],{},"Le critère tient en une ligne :",[2498,2499,2500,2510],"blockquote",{},[156,2501,2502,2503,2506,2507,647],{},"Le test vit ",[160,2504,2505],{},"dehors"," et accuse ",[160,2508,2509],{},"l'implémentation",[156,2511,2512,2513,2506,2516,647],{},"L'assertion vit ",[160,2514,2515],{},"dedans",[160,2517,2518],{},"l'appelant",[974,2520,2523,2538],{"correct":976,"explanation":2521,"slug":2522},"Placée en première ligne de depiler, cette assertion vérifie une précondition : si elle saute, c'est l'appel qui est fautif (depiler sur une pile vide), pas le code de la pile.","contrat-tests-assertions-c5",[980,2524,2525],{"v-slot:question":411},[156,2526,2527,2528,2531,2532,2534,2535,2537],{},"Quand ",[259,2529,2530],{},"assert not self.est_vide()",", première ligne de ",[259,2533,712],{},", lève une ",[259,2536,633],{},", qui est mis en cause ?",[980,2539,2540],{"v-slot:choices":411},[585,2541,2542,2547,2549],{},[588,2543,2544,2545],{},"L'implémentation de ",[259,2546,712],{},[588,2548,232],{},[588,2550,2551,2552,2554],{},"Le code qui a appelé ",[259,2553,712],{}," sur une pile vide",[974,2556,2559,2572],{"correct":1358,"explanation":2557,"slug":2558},"Cette ligne vit hors de la classe et compare un résultat à ce que le contrat promet : c'est un test. S'il échoue, c'est l'implémentation de depiler qui est fausse.","contrat-tests-assertions-c6",[980,2560,2561],{"v-slot:question":411},[156,2562,2563,2564,2566,2567,683,2569,2571],{},"La ligne ",[259,2565,718],{},", écrite après avoir empilé ",[259,2568,820],{},[259,2570,830],{},", est…",[980,2573,2574],{"v-slot:choices":411},[585,2575,2576,2579,2582],{},[588,2577,2578],{},"un test : elle vit dehors et accuse l'implémentation",[588,2580,2581],{},"une précondition : elle vit dedans et accuse l'appelant",[588,2583,2584],{},"une postcondition écrite dans la docstring",[2586,2587,2589,2594],"self-eval-ordering",{"slug":2588},"contrat-tests-assertions-c7",[980,2590,2591],{"v-slot:question":411},[156,2592,2593],{},"Remettre dans l'ordre les étapes d'écriture d'une structure à partir de son contrat :",[980,2595,2596],{"v-slot:items":411},[585,2597,2598,2601,2607,2610,2613],{},[588,2599,2600],{},"Écrire la docstring de chaque méthode",[588,2602,2603,2604,2606],{},"Traduire chaque promesse en ",[259,2605,261],{}," dans un jeu de tests",[588,2608,2609],{},"Lancer le jeu de tests sur la classe vide et constater l'échec",[588,2611,2612],{},"Écrire le corps des méthodes",[588,2614,2615],{},"Relancer le jeu de tests jusqu'à ce qu'il passe",[151,2617,2619],{"id":2618},"pièges-courants","Pièges courants",[585,2621,2622,2631,2637,2645,2667],{},[588,2623,2624,1415,2627,2630],{},[160,2625,2626],{},"Tester l'implémentation au lieu du contrat.",[259,2628,2629],{},"assert p.elements == [7]","\nrejette une pile correcte rangée autrement. Le test ne passe que par les\nméthodes de l'interface.",[588,2632,2633,2636],{},[160,2634,2635],{},"Un seul élément pour tester l'ordre."," Pile et file rendent alors le même\nélément ; la propriété LIFO n'est pas éprouvée.",[588,2638,2639,2642,2643,167],{},[160,2640,2641],{},"Conclure d'un test qui passe que le code est juste."," Il prouve seulement\nque les cas écrits passent (",[259,2644,1426],{},[588,2646,2647,1415,2652,2655,2656,2659,2660,2663,2664,647],{},[160,2648,2649,2650,647],{},"Mettre des parenthèses autour d'un ",[259,2651,261],{},[259,2653,2654],{},"assert (x > 0, \"message\")","\nteste un ",[160,2657,2658],{},"tuple"," non vide, toujours vrai : l'assertion ne saute jamais.\nPython le signale d'ailleurs par un ",[259,2661,2662],{},"SyntaxWarning: assertion is always true",". Écrire ",[259,2665,2666],{},"assert x > 0, \"message\"",[588,2668,2669,2674,2675,2678],{},[160,2670,2671,2672,647],{},"Confier une vérification de sécurité à ",[259,2673,261],{}," Python lancé avec\nl'option ",[259,2676,2677],{},"-O"," ignore toutes les assertions. Elles documentent et gardent un\ncontrat entre parties d'un même programme ; elles ne filtrent pas une saisie\nmalveillante.",[151,2680,2682],{"id":2681},"pour-aller-plus-loin","Pour aller plus loin",[156,2684,2685],{},"Deux outils industrialisent le jeu de tests.",[585,2687,2688,2773],{},[588,2689,2690,2691,2694,2695,2698,2699,2702,2703,2706,2707],{},"Les ",[160,2692,2693],{},"doctests"," placent les exemples directement dans la docstring :\npremière et deuxième écritures réunies. ",[259,2696,2697],{},"python -m doctest fichier.py","\nexécute chaque ligne ",[259,2700,2701],{},">>>"," et compare son résultat à la ligne suivante. Il\nn'affiche rien quand tout passe ; l'option ",[259,2704,2705],{},"-v"," détaille chaque exemple.",[406,2708,2710],{"className":408,"code":2709,"language":410,"meta":411,"style":411},"def double(n):\n    \"\"\"Renvoyer le double de n.\n\n    >>> double(3)\n    6\n    >>> double(-2)\n    -4\n    \"\"\"\n    return 2 * n\n",[259,2711,2712,2722,2727,2731,2739,2744,2751,2756,2761],{"__ignoreMap":411},[415,2713,2714,2716,2719],{"class":417,"line":418},[415,2715,770],{"class":421},[415,2717,2718],{"class":425}," double",[415,2720,2721],{"class":429},"(n):\n",[415,2723,2724],{"class":417,"line":433},[415,2725,2726],{"class":436},"    \"\"\"Renvoyer le double de n.\n",[415,2728,2729],{"class":417,"line":440},[415,2730,444],{"emptyLinePlaceholder":443},[415,2732,2733,2736],{"class":417,"line":447},[415,2734,2735],{"class":421},"    >>> ",[415,2737,2738],{"class":436},"double(3)\n",[415,2740,2741],{"class":417,"line":460},[415,2742,2743],{"class":436},"    6\n",[415,2745,2746,2748],{"class":417,"line":466},[415,2747,2735],{"class":421},[415,2749,2750],{"class":436},"double(-2)\n",[415,2752,2753],{"class":417,"line":471},[415,2754,2755],{"class":436},"    -4\n",[415,2757,2758],{"class":417,"line":482},[415,2759,2760],{"class":436},"    \"\"\"\n",[415,2762,2763,2765,2767,2770],{"class":417,"line":488},[415,2764,952],{"class":421},[415,2766,848],{"class":453},[415,2768,2769],{"class":421}," *",[415,2771,2772],{"class":429}," n\n",[588,2774,2775,2780,2781,2784,2785,2788,2789,2791,2792,2795,2796,2799],{},[160,2776,2777],{},[259,2778,2779],{},"pytest"," découvre tous les fichiers ",[259,2782,2783],{},"test_*.py",", exécute toutes les\nfonctions ",[259,2786,2787],{},"test_*"," qu'ils contiennent, et rapporte chaque ",[259,2790,261],{}," qui a\néchoué. ",[259,2793,2794],{},"pytest.raises(AssertionError)"," vérifie qu'un appel interdit est bien\nrefusé : c'est un test ",[601,2797,2798],{},"de"," la précondition.",[156,2801,2802,2803,2806],{},"C'est aussi le format de l'",[160,2804,2805],{},"épreuve pratique"," du baccalauréat : une\nspécification donnée, des exemples, et du code à écrire jusqu'à ce qu'ils\npassent.",[165,2808],{"code":144},[2810,2811,2812],"style",{},"html pre.shiki code .s8jYJ, html code.shiki .s8jYJ{--shiki-light:#D73A49;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .snPdu, html code.shiki .snPdu{--shiki-light:#6F42C1;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sxrX7, html code.shiki .sxrX7{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sIIMD, html code.shiki .sIIMD{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sBjJW, html code.shiki .sBjJW{--shiki-light:#005CC5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":411,"searchDepth":433,"depth":433,"links":2814},[2815,2816,2817,2818,2819,2820,2821,2822,2823],{"id":153,"depth":433,"text":154},{"id":281,"depth":433,"text":282},{"id":623,"depth":433,"text":624},{"id":1046,"depth":433,"text":1047},{"id":1381,"depth":433,"text":1382},{"id":2075,"depth":433,"text":2076},{"id":2403,"depth":433,"text":2404},{"id":2618,"depth":433,"text":2619},{"id":2681,"depth":433,"text":2682},"Le contrat d'une structure lu du côté de qui écrit le code : la documentation qui le dit, le jeu de tests écrit avant la première ligne, l'assertion qui le garde du dedans.",null,"md",{},{"title":137},"2026-09-25",[2831,2844,2855,2860,2869,2883,2895],{"slug":978,"question":2832,"questionBody":2833,"explanation":977,"kind":2840,"choices":2841,"correct":976,"multi":2843},"Pourquoi le test empile-t-il deux éléments avant d'appeler depiler() ?",[2834],[156,2835,984,2836,988,2838,991],{},[160,2837,987],{},[259,2839,346],{},"qcm",[998,2842,1007],"Pour tester la performance de empiler",false,{"slug":1012,"question":2845,"questionBody":2846,"explanation":1011,"kind":2840,"choices":2853,"correct":1010,"multi":2843},"Quel assert éprouve la promesse « sommet() ne retire rien » ?",[2847],[156,2848,1017,2849,1020,2851,1023],{},[259,2850,261],{},[259,2852,361],{},[692,2854,1043],"assert len(p) == 2 juste après l'appel à sommet()",{"slug":1360,"question":1365,"questionBody":2856,"explanation":1359,"kind":2840,"choices":2859,"correct":1358,"multi":2843},[2857],[156,2858,1365],{},[1372,1375,1378],{"slug":2050,"question":2861,"questionBody":2862,"explanation":2049,"kind":2840,"choices":2867,"correct":1010,"multi":2843},"PileC passe le jeu de tests. Qu'en conclure ?",[2863],[156,2864,2865,2057],{},[259,2866,1426],{},[2868,2069,2072],"PileC est correcte",{"slug":2522,"question":2870,"questionBody":2871,"explanation":2521,"kind":2840,"choices":2880,"correct":976,"multi":2843},"Quand assert not self.est_vide(), première ligne de depiler, lève une AssertionError, qui est mis en cause ?",[2872],[156,2873,2527,2874,2531,2876,2534,2878,2537],{},[259,2875,2530],{},[259,2877,712],{},[259,2879,633],{},[2881,232,2882],"L'implémentation de depiler","Le code qui a appelé depiler sur une pile vide",{"slug":2558,"question":2884,"questionBody":2885,"explanation":2557,"kind":2840,"choices":2894,"correct":1358,"multi":2843},"La ligne assert p.depiler() == \"R\", écrite après avoir empilé 7 puis \"R\", est…",[2886],[156,2887,2563,2888,2566,2890,683,2892,2571],{},[259,2889,718],{},[259,2891,820],{},[259,2893,830],{},[2578,2581,2584],{"slug":2588,"question":2593,"questionBody":2896,"explanation":411,"kind":2899,"items":2900},[2897],[156,2898,2593],{},"ordering",[2600,2901,2609,2612,2615],"Traduire chaque promesse en assert dans un jeu de tests",{"title":2903,"description":2904},"Un contrat, trois écritures : docstring, tests, assertions","Le contrat d'une structure lu du côté de qui écrit le code : la documentation qui le dit, le jeu de tests écrit avant la première ligne, l'assertion qui le garde du dedans.","2ciFsEzpY1AUcbZ9Q6nVymbtaUS-inYLvjdgA6Uk-wc",{"id":2907,"title":2908,"bo":2909,"body":2910,"description":3301,"eval":2825,"extension":2826,"icon":2825,"labo":2825,"meta":3302,"navigation":2843,"path":3303,"publie":2829,"quizContext":2825,"quizzes":3304,"readingTime":418,"seo":3305,"stem":3307,"tp":2825,"__hash__":3308},"coursMemo\u002F2.nsi-tale\u002Fta-structures-donnees\u002F4.contrat-tests-assertions.memo.md","Un contrat, trois écritures",[144,145,146],{"type":148,"value":2911,"toc":3294},[2912,2916,2930,2934,2995,2999,3089,3091,3137,3141,3291],[151,2913,2915],{"id":2914},"en-une-phrase","En une phrase",[156,2917,2918],{},[160,2919,2920,2921,2923,2924,2926,2927,2929],{},"Un contrat s'écrit trois fois : en français dans la docstring, en ",[259,2922,261],{}," dans un jeu de tests écrit ",[601,2925,603],{}," le code, en ",[259,2928,261],{}," dans la méthode pour refuser un appel interdit.",[151,2931,2933],{"id":2932},"à-mémoriser","À mémoriser",[585,2935,2936,2945,2954,2962,2968,2978,2984],{},[588,2937,2938,2941,2942,2944],{},[160,2939,2940],{},"Docstring"," : le contrat écrit dans le code ; ",[259,2943,579],{}," l'affiche sans ouvrir le corps.",[588,2946,2947,2950,2951,2953],{},[160,2948,2949],{},"Précondition"," : ce que l'appel doit garantir avant ; ",[160,2952,609],{}," : ce que la méthode promet après.",[588,2955,2956,2961],{},[160,2957,2958,2959],{},"Une promesse du contrat, un ",[259,2960,261],{}," : c'est ainsi que s'écrit un jeu de tests.",[588,2963,2964,2965,2967],{},"Le jeu de tests ne dépend que du contrat, donc il s'écrit ",[160,2966,603],{}," le code.",[588,2969,2970,2971,2973,2974,2977],{},"Un bon jeu de tests ",[160,2972,1062],{}," tant que le code n'existe pas et ",[160,2975,2976],{},"passe"," une fois qu'il est juste : il définit « fini ».",[588,2979,2980,2983],{},[160,2981,2982],{},"Le succès d'un jeu de tests ne garantit pas la correction d'un programme",", seulement celle des cas écrits.",[588,2985,2502,2986,2506,2988,2990,2991,2506,2993,647],{},[160,2987,2505],{},[160,2989,2509],{}," ; l'assertion vit ",[160,2992,2515],{},[160,2994,2518],{},[151,2996,2998],{"id":2997},"à-savoir-reconnaître","À savoir reconnaître",[191,3000,3001,3011],{},[194,3002,3003],{},[197,3004,3005,3008],{},[200,3006,3007],{},"Situation",[200,3009,3010],{},"Ce que c'est",[210,3012,3013,3031,3046,3064,3072,3080],{},[197,3014,3015,3024],{},[215,3016,3017,3019,3020,851,3022],{},[259,3018,718],{}," après ",[259,3021,682],{},[259,3023,686],{},[215,3025,3026,3027,3030],{},"un ",[160,3028,3029],{},"test"," : dehors, accuse l'implémentation",[197,3032,3033,3040],{},[215,3034,3035,3037,3038],{},[259,3036,2530],{}," en première ligne de ",[259,3039,712],{},[215,3041,3042,3043,3045],{},"une ",[160,3044,598],{}," : dedans, accuse l'appelant",[197,3047,3048,3056],{},[215,3049,3050,3052,3053],{},[259,3051,705],{}," juste après ",[259,3054,3055],{},"p.sommet()",[215,3057,3058,3059,1398,3062,700],{},"test d'une ",[160,3060,3061],{},"absence d'effet",[259,3063,699],{},[197,3065,3066,3069],{},[215,3067,3068],{},"Le test échoue sur une classe sans corps",[215,3070,3071],{},"normal : il liste ce qu'il reste à écrire",[197,3073,3074,3077],{},[215,3075,3076],{},"Une implémentation fausse passe le test",[215,3078,3079],{},"un cas manque au jeu de tests",[197,3081,3082,3086],{},[215,3083,3084],{},[259,3085,2186],{},[215,3087,3088],{},"message qui parle des entrailles, pas du contrat : précondition non écrite",[151,3090,2619],{"id":2618},[585,3092,3093,3100,3107,3110,3116,3125,3134],{},[588,3094,3095,3096,3099],{},"Tester l'implémentation (",[259,3097,3098],{},"p.elements == [...]",") au lieu du contrat.",[588,3101,3102,3103,3106],{},"N'empiler qu'",[160,3104,3105],{},"un"," élément pour tester LIFO : une file passerait aussi.",[588,3108,3109],{},"Conclure qu'un code est juste parce que ses tests passent.",[588,3111,3112,3115],{},[259,3113,3114],{},"assert (condition, \"message\")"," : un tuple non vide est toujours vrai, l'assertion ne saute jamais.",[588,3117,3118,3119,3121,3122,3124],{},"Ne rien écrire sur ",[259,3120,346],{}," ou ",[259,3123,361],{}," d'une pile vide : le code décide alors à la place du contrat.",[588,3126,3127,3128,3130,3131,3133],{},"Compter sur ",[259,3129,261],{}," pour la sécurité : ",[259,3132,2492],{}," les désactive toutes.",[588,3135,3136],{},"Le jeu de tests se relance à chaque modification, pas une seule fois.",[151,3138,3140],{"id":3139},"syntaxe-python","Syntaxe Python",[406,3142,3144],{"className":408,"code":3143,"language":410,"meta":411,"style":411},"class Pile:\n    def depiler(self):\n        \"\"\"Retirer l'élément du sommet et le renvoyer.\n        Précondition : la pile n'est pas vide.\"\"\"\n        assert not self.est_vide(), \"depiler exige une pile non vide\"\n        return self.elements.pop()\n\n\ndef tester_pile(fabriquer_une_pile):\n    p = fabriquer_une_pile()\n    assert p.est_vide()\n    p.empiler(7)\n    p.empiler(\"R\")\n    assert p.sommet() == \"R\"\n    assert len(p) == 2            # sommet ne retire rien\n    assert p.depiler() == \"R\"\n    assert p.depiler() == 7\n    assert p.est_vide()\n",[259,3145,3146,3154,3162,3167,3172,3184,3192,3196,3200,3208,3216,3222,3230,3238,3249,3264,3274,3285],{"__ignoreMap":411},[415,3147,3148,3150,3152],{"class":417,"line":418},[415,3149,422],{"class":421},[415,3151,426],{"class":425},[415,3153,430],{"class":429},[415,3155,3156,3158,3160],{"class":417,"line":433},[415,3157,450],{"class":421},[415,3159,498],{"class":425},[415,3161,457],{"class":429},[415,3163,3164],{"class":417,"line":440},[415,3165,3166],{"class":436},"        \"\"\"Retirer l'élément du sommet et le renvoyer.\n",[415,3168,3169],{"class":417,"line":447},[415,3170,3171],{"class":436},"        Précondition : la pile n'est pas vide.\"\"\"\n",[415,3173,3174,3176,3178,3180,3182],{"class":417,"line":460},[415,3175,2315],{"class":421},[415,3177,861],{"class":421},[415,3179,1625],{"class":453},[415,3181,2134],{"class":429},[415,3183,2137],{"class":436},[415,3185,3186,3188,3190],{"class":417,"line":466},[415,3187,2281],{"class":421},[415,3189,1625],{"class":453},[415,3191,1736],{"class":429},[415,3193,3194],{"class":417,"line":471},[415,3195,444],{"emptyLinePlaceholder":443},[415,3197,3198],{"class":417,"line":482},[415,3199,444],{"emptyLinePlaceholder":443},[415,3201,3202,3204,3206],{"class":417,"line":488},[415,3203,770],{"class":421},[415,3205,773],{"class":425},[415,3207,776],{"class":429},[415,3209,3210,3212,3214],{"class":417,"line":493},[415,3211,791],{"class":429},[415,3213,794],{"class":421},[415,3215,797],{"class":429},[415,3217,3218,3220],{"class":417,"line":503},[415,3219,802],{"class":421},[415,3221,864],{"class":429},[415,3223,3224,3226,3228],{"class":417,"line":509},[415,3225,817],{"class":429},[415,3227,820],{"class":453},[415,3229,823],{"class":429},[415,3231,3232,3234,3236],{"class":417,"line":514},[415,3233,817],{"class":429},[415,3235,830],{"class":436},[415,3237,823],{"class":429},[415,3239,3240,3242,3244,3246],{"class":417,"line":524},[415,3241,802],{"class":421},[415,3243,875],{"class":429},[415,3245,845],{"class":421},[415,3247,3248],{"class":436}," \"R\"\n",[415,3250,3251,3253,3255,3257,3259,3261],{"class":417,"line":530},[415,3252,802],{"class":421},[415,3254,839],{"class":453},[415,3256,842],{"class":429},[415,3258,845],{"class":421},[415,3260,848],{"class":453},[415,3262,3263],{"class":1636},"            # sommet ne retire rien\n",[415,3265,3266,3268,3270,3272],{"class":417,"line":535},[415,3267,802],{"class":421},[415,3269,913],{"class":429},[415,3271,845],{"class":421},[415,3273,3248],{"class":436},[415,3275,3276,3278,3280,3282],{"class":417,"line":545},[415,3277,802],{"class":421},[415,3279,913],{"class":429},[415,3281,845],{"class":421},[415,3283,3284],{"class":453}," 7\n",[415,3286,3287,3289],{"class":417,"line":551},[415,3288,802],{"class":421},[415,3290,864],{"class":429},[2810,3292,3293],{},"html pre.shiki code .s8jYJ, html code.shiki .s8jYJ{--shiki-light:#D73A49;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .snPdu, html code.shiki .snPdu{--shiki-light:#6F42C1;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sxrX7, html code.shiki .sxrX7{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sIIMD, html code.shiki .sIIMD{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sBjJW, html code.shiki .sBjJW{--shiki-light:#005CC5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":411,"searchDepth":433,"depth":433,"links":3295},[3296,3297,3298,3299,3300],{"id":2914,"depth":433,"text":2915},{"id":2932,"depth":433,"text":2933},{"id":2997,"depth":433,"text":2998},{"id":2618,"depth":433,"text":2619},{"id":3139,"depth":433,"text":3140},"Mémo de révision : docstring, jeu de tests écrit avant le code, assertion de précondition.",{},"\u002Fnsi-tale\u002Fta-structures-donnees\u002Fcontrat-tests-assertions.memo",[],{"title":2908,"description":3306},"Mémo de révision : docstring, jeu de tests écrit avant le code, assertion de précondition.","2.nsi-tale\u002Fta-structures-donnees\u002F4.contrat-tests-assertions.memo","C7dbu12fm-hfaMJhtbKgU24lbTgFDaFElKPOHcAHDiM",{"id":2907,"title":2908,"bo":3310,"body":3311,"description":3301,"eval":2825,"extension":2826,"icon":2825,"labo":2825,"meta":3632,"navigation":2843,"path":3303,"publie":2829,"quizContext":2825,"quizzes":3633,"readingTime":418,"seo":3634,"stem":3307,"tp":2825,"__hash__":3308},[144,145,146],{"type":148,"value":3312,"toc":3625},[3313,3315,3325,3327,3371,3373,3445,3447,3477,3479,3623],[151,3314,2915],{"id":2914},[156,3316,3317],{},[160,3318,2920,3319,2923,3321,2926,3323,2929],{},[259,3320,261],{},[601,3322,603],{},[259,3324,261],{},[151,3326,2933],{"id":2932},[585,3328,3329,3335,3341,3347,3351,3357,3361],{},[588,3330,3331,2941,3333,2944],{},[160,3332,2940],{},[259,3334,579],{},[588,3336,3337,2950,3339,2953],{},[160,3338,2949],{},[160,3340,609],{},[588,3342,3343,2961],{},[160,3344,2958,3345],{},[259,3346,261],{},[588,3348,2964,3349,2967],{},[160,3350,603],{},[588,3352,2970,3353,2973,3355,2977],{},[160,3354,1062],{},[160,3356,2976],{},[588,3358,3359,2983],{},[160,3360,2982],{},[588,3362,2502,3363,2506,3365,2990,3367,2506,3369,647],{},[160,3364,2505],{},[160,3366,2509],{},[160,3368,2515],{},[160,3370,2518],{},[151,3372,2998],{"id":2997},[191,3374,3375,3383],{},[194,3376,3377],{},[197,3378,3379,3381],{},[200,3380,3007],{},[200,3382,3010],{},[210,3384,3385,3399,3411,3425,3431,3437],{},[197,3386,3387,3395],{},[215,3388,3389,3019,3391,851,3393],{},[259,3390,718],{},[259,3392,682],{},[259,3394,686],{},[215,3396,3026,3397,3030],{},[160,3398,3029],{},[197,3400,3401,3407],{},[215,3402,3403,3037,3405],{},[259,3404,2530],{},[259,3406,712],{},[215,3408,3042,3409,3045],{},[160,3410,598],{},[197,3412,3413,3419],{},[215,3414,3415,3052,3417],{},[259,3416,705],{},[259,3418,3055],{},[215,3420,3058,3421,1398,3423,700],{},[160,3422,3061],{},[259,3424,699],{},[197,3426,3427,3429],{},[215,3428,3068],{},[215,3430,3071],{},[197,3432,3433,3435],{},[215,3434,3076],{},[215,3436,3079],{},[197,3438,3439,3443],{},[215,3440,3441],{},[259,3442,2186],{},[215,3444,3088],{},[151,3446,2619],{"id":2618},[585,3448,3449,3453,3457,3459,3463,3469,3475],{},[588,3450,3095,3451,3099],{},[259,3452,3098],{},[588,3454,3102,3455,3106],{},[160,3456,3105],{},[588,3458,3109],{},[588,3460,3461,3115],{},[259,3462,3114],{},[588,3464,3118,3465,3121,3467,3124],{},[259,3466,346],{},[259,3468,361],{},[588,3470,3127,3471,3130,3473,3133],{},[259,3472,261],{},[259,3474,2492],{},[588,3476,3136],{},[151,3478,3140],{"id":3139},[406,3480,3481],{"className":408,"code":3143,"language":410,"meta":411,"style":411},[259,3482,3483,3491,3499,3503,3507,3519,3527,3531,3535,3543,3551,3557,3565,3573,3583,3597,3607,3617],{"__ignoreMap":411},[415,3484,3485,3487,3489],{"class":417,"line":418},[415,3486,422],{"class":421},[415,3488,426],{"class":425},[415,3490,430],{"class":429},[415,3492,3493,3495,3497],{"class":417,"line":433},[415,3494,450],{"class":421},[415,3496,498],{"class":425},[415,3498,457],{"class":429},[415,3500,3501],{"class":417,"line":440},[415,3502,3166],{"class":436},[415,3504,3505],{"class":417,"line":447},[415,3506,3171],{"class":436},[415,3508,3509,3511,3513,3515,3517],{"class":417,"line":460},[415,3510,2315],{"class":421},[415,3512,861],{"class":421},[415,3514,1625],{"class":453},[415,3516,2134],{"class":429},[415,3518,2137],{"class":436},[415,3520,3521,3523,3525],{"class":417,"line":466},[415,3522,2281],{"class":421},[415,3524,1625],{"class":453},[415,3526,1736],{"class":429},[415,3528,3529],{"class":417,"line":471},[415,3530,444],{"emptyLinePlaceholder":443},[415,3532,3533],{"class":417,"line":482},[415,3534,444],{"emptyLinePlaceholder":443},[415,3536,3537,3539,3541],{"class":417,"line":488},[415,3538,770],{"class":421},[415,3540,773],{"class":425},[415,3542,776],{"class":429},[415,3544,3545,3547,3549],{"class":417,"line":493},[415,3546,791],{"class":429},[415,3548,794],{"class":421},[415,3550,797],{"class":429},[415,3552,3553,3555],{"class":417,"line":503},[415,3554,802],{"class":421},[415,3556,864],{"class":429},[415,3558,3559,3561,3563],{"class":417,"line":509},[415,3560,817],{"class":429},[415,3562,820],{"class":453},[415,3564,823],{"class":429},[415,3566,3567,3569,3571],{"class":417,"line":514},[415,3568,817],{"class":429},[415,3570,830],{"class":436},[415,3572,823],{"class":429},[415,3574,3575,3577,3579,3581],{"class":417,"line":524},[415,3576,802],{"class":421},[415,3578,875],{"class":429},[415,3580,845],{"class":421},[415,3582,3248],{"class":436},[415,3584,3585,3587,3589,3591,3593,3595],{"class":417,"line":530},[415,3586,802],{"class":421},[415,3588,839],{"class":453},[415,3590,842],{"class":429},[415,3592,845],{"class":421},[415,3594,848],{"class":453},[415,3596,3263],{"class":1636},[415,3598,3599,3601,3603,3605],{"class":417,"line":535},[415,3600,802],{"class":421},[415,3602,913],{"class":429},[415,3604,845],{"class":421},[415,3606,3248],{"class":436},[415,3608,3609,3611,3613,3615],{"class":417,"line":545},[415,3610,802],{"class":421},[415,3612,913],{"class":429},[415,3614,845],{"class":421},[415,3616,3284],{"class":453},[415,3618,3619,3621],{"class":417,"line":551},[415,3620,802],{"class":421},[415,3622,864],{"class":429},[2810,3624,3293],{},{"title":411,"searchDepth":433,"depth":433,"links":3626},[3627,3628,3629,3630,3631],{"id":2914,"depth":433,"text":2915},{"id":2932,"depth":433,"text":2933},{"id":2997,"depth":433,"text":2998},{"id":2618,"depth":433,"text":2619},{"id":3139,"depth":433,"text":3140},{},[],{"title":2908,"description":3306},1791681197030]