{"action":"created","comment":{"url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/comments/96284721","pull_request_review_id":16861345,"id":96284721,"diff_hunk":"@@ -0,0 +1,300 @@\n+---\n+date: \"2017-01-07\"  \n+title: \"Se lancer dans le TDD\"  \n+tags:\n+  - tdd\n+  - bdd\n+  - ci  \n+authors:\n+  - Freezystem\n+---\n+\n+## Introduction\n+\n+Tout commence en octobre 1999 lorsque [Kent Beck](https://fr.wikipedia.org/wiki/Kent_Beck) \n+présente une nouvelle méthode de programmation basée sur AGILE: l'eXtreme Programmming abrégé _XP_.  \n+l'_XP_ définit des pratiques de développement optimisées améliorant la production et \n+la robustesse du code.  \n+Parmi les principes les plus connus de sa méthode on pourra citer **l'intégration continue**\n+aussi appelée _CI_ pour _Continuous Integration_ et **la programmation en binôme** \n+ou _pair programming_ en anglais.\n+\n+L'aspect qui nous intéresse ici est un autre pilier de la méthode qui consiste à piloter \n+le développement par les tests alias _TDD_.\n+\n+Le TDD est une pratique controversée car coûteuse à mettre en place. \n+Popularisée par les développeurs elle peine à émerger.\n+\n+Avec la multiplications des environnements d'execution, la complexité des applications web\n+et l'essort des projets Open-Source, les développeurs se heurtent à des problèmes de\n+compatibilités croisées et d'inconsistances.  \n+Aujourd’hui les standards sont de plus en plus permissifs et favorisent \n+ainsi les comportements à risque. La plupart du temps, les systèmes sont capables de \n+corriger vos erreurs, des fois sans même vous en avertir. \n+Dans ce contexte : \n+- Comment écrire un code multi-plateforme fonctionnel ? \n+- Comment être sûr que les ajouts ne cassent pas le code plus ancien ? \n+- Comment être sûr que le code se comporte comme voulu ?\n+\n+Commencer par vous imposer des pratiques de développement rigoureuses est impératif \n+mais les tests seront un complément indispensable à la qualité de votre code.\n+\n+Heureusement, le TDD apporte alors une réponse élégante à l'ensemble de ces problématiques.\n+\n+## TDD, vous avez dit TDD ?\n+\n+Le Test Driven Development _(Développement Dirigé par les Tests)_, \n+est une technique de développement qui impose l’écriture de tests \n+avant même l’écriture de la première ligne de code.\n+\n+Dans la théorie, la méthode requiert l’intervention d’au moins \n+deux intervenants différents, une personne écrit les tests, l’autre \n+le code testé. Cela permet d’éviter les problèmes liés à la subjectivité. \n+\n+Dans la pratique les choses sont plus compliquées, \n+parfois on développe seul ou on écrit soit même les tests qui \n+garantissent l’intégrité d'une nouvelle feature dans un projet collaboratif. \n+\n+> Quoi qu’il arrive, un test peu efficace vaudra toujours mieux que pas de test du tout. \n+> Le but étant de prendre l’habitude d’en écrire et d’être objectif dans leur rédaction. \n+\n+Le TDD tend à se démocratiser et elle requiert l’effort de chacun pour devenir un standard. \n+Tout développeur soucieux de son environnement et de son héritage doit se poser sérieusement \n+la question.  \n+Les frameworks de tests, les guides et les documentations sur le sujet fleurissent,\n+vous pouvez donc vous lancer sans crainte.\n+\n+On peut découper le TDD en 5 étapes distinctes :\n+\n+1. Ecrire un test.\n+2. Vérifier qu’il échoue.\n+3. Ecrire le code **suffisant** pour que le test passe.\n+4. Vérifier que le test passe.\n+5. Optimiser le code et vérifier qu’il n’y ai pas de régression.\n+\n+Pour simplifier cette logique on peut regrouper ces cinq étapes en trois grandes idées :\n+\n+- **Tester d’abord**, qui correspond aux 2 premières étapes.\n+- **Rendre fonctionnel**, qui englobe les points 3 et 4.\n+- **Rendre meilleur**, qui n’est autre que l’étape 5.\n+\n+Bill Wake définit ainsi la méthode [3A](http://xp123.com/articles/3a-arrange-act-assert/), \n+pour Arrange, Act, Assert _(Arranger, Agir, Affirmer)_.  \n+Il insiste sur le fait que la méthode ne définit pas un ordre immuable, \n+l’_affirmation_ peut ainsi venir avant l’_action_, etc...\n+\n+- **Arranger** : Phase de préparation de l’environnement de test dans laquelle \n+on déclare les variables et les fonctions.\n+- **Agir** : Phase qui met à l’épreuve notre environnement en lui faisant subir des mutations.\n+- **Affirmer** : On formule des attentes à propos de l'environement \n+(variables, fonctions, paramètres).\n+\n+## TDD : concepts de base\n+\n+Pour la série de tests suivante on utilisera EcmaScript 6 et la methode\n+[`.assert()`](https://developer.mozilla.org/fr/docs/Web/API/Console/assert) \n+de la console navigateur: Vous pourrez ainsi reproduire ces tests vous-même.\n+\n+Objectif : Ecrire une fonction `countWords()` qui compte les mots d'une phrase.\n+\n+**ITERATION 1** : écriture et échec du test initial\n+\n+On écrit tout d'abord une affirmation de base.\n+```js\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+```\n+> `Uncaught ReferenceError: countWords is not defined`\n+\n+Après execution la console rejète le test. \n+On doit d'abord définir `countWords()`.\n+\n+```js\n+const countWords = () => {};\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+```\n+> `Assertion failed: test 0: le texte ne contient aucun mot`\n+\n+`countWords()` est définie et le test échoue mais l'erreur a changé.  \n+Il faut à présent définir la logique du coeur de notre fonction.\n+\n+```js\n+const countWords = text => text || 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+```\n+> `undefined`\n+\n+La console ne renvoie rien, le test est donc passé.  \n+\n+> `countWords()` étant très simple nous omettrons les phases d'optimisation.\n+> On peut aussi considérer que les itérations suivantes comme des optimisations.\n+\n+**ITERATION 2** : test pour les phrases d'un seul mot\n+\n+Très bien. Essayons à présent une phrase d'un seul mot.\n+\n+```js\n+const countWords = text => text || 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+console.assert(countWords('nope') === 1, 'test 1: le texte contient 1 mot');\n+```\n+> `Assertion failed: test 1: le texte contient 1 mot`\n+\n+`countWords()` ne compte pas correctement, ajoutons le code suffisant pour passer le test.\n+\n+```js\n+const countWords = text => text ? text.split(' ').length : 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+console.assert(countWords('nope') === 1, 'test 1: le texte contient 1 mot');\n+```\n+> `undefined`\n+\n+Le test est passé, ajoutons un autre cas standard.\n+\n+**ITERATION 3** : test pour les phrases de plusieurs mots\n+\n+```js\n+const countWords = text => text ? text.split(' ').length : 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+console.assert(countWords('nope') === 1, 'test 1: le texte contient 1 mot');\n+console.assert(countWords('tdd is fun bro') === 4, 'test 2: le texte contient 4 mots');\n+```\n+> `undefined`\n+\n+Le nouveau test passe sans modification, on peut continuer.\n+\n+**ITERATION 4** : test pour les phrases contenant des espaces au début et à la fin\n+\n+Vérifions à présent la robustesse de la fonction.\n+\n+```js\n+const countWords = text => text ? text.split(' ').length : 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+console.assert(countWords('nope') === 1, 'test 1: le texte contient 1 mot');\n+console.assert(countWords('tdd is fun bro') === 4, 'test 2: le texte contient 4 mots');\n+console.assert(countWords(' so is skateboarding ') === 3, 'test 3: le texte contient 3 mots');\n+```\n+> `Assertion failed: test 3: le texte contient 3 mots`\n+\n+Aie.. notre fonction n'est pas assez solide. Corrigeons la pour capter ce nouveau cas en supprimant les \n+espaces inutiles avant et après le texte.\n+\n+```js\n+const countWords = text => text ? text.trim().split(' ').length : 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+console.assert(countWords('nope') === 1, 'test 1: le texte contient 1 mot');\n+console.assert(countWords('tdd is fun bro') === 4, 'test 2: le texte contient 4 mots');\n+console.assert(countWords(' so is skateboarding ') === 3, 'test 3: le texte contient 3 mots');\n+```\n+> `undefined`\n+\n+Parfait, La fonction est améliorée! Ajoutons quand même un dernier test pour être sur.\n+\n+**ITERATION 5** : test pour les phrases contenant un nombre inégal d'espaces entre les mots\n+\n+```js\n+const countWords = text => text ? text.trim().split(' ').length : 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+console.assert(countWords('nope') === 1, 'test 1: le texte contient 1 mot');\n+console.assert(countWords('tdd is fun bro') === 4, 'test 2: le texte contient 4 mots');\n+console.assert(countWords(' so is skateboarding ') === 3, 'test 3: le texte contient 3 mots');\n+console.assert(countWords(`  I'm 28, I love $#@! and    multi-spaces  `) === 7, 'test 4: le texte contient 7 mots');\n+```\n+> `Assertion failed: test 4: le texte contient 7 mots`\n+\n+Et mince.. Encore un cas particulier, modifions l'algorithme en conséquence.\n+On doit ici retirer les espaces inutiles entre les mots.\n+\n+```js\n+const countWords = text => text ? text.trim().replace(/\\s+/g, ' ').split(' ').length : 0;\n+console.assert(countWords('') === 0, 'test 0: le texte ne contient aucun mot');\n+console.assert(countWords('nope') === 1, 'test 1: le texte contient 1 mot');\n+console.assert(countWords('tdd is fun bro') === 4, 'test 2: le texte contient 4 mots');\n+console.assert(countWords(' so is skateboarding ') === 3, 'test 3: le texte contient 3 mots');\n+console.assert(countWords(`  I'm 28, I love $#@! and    multi-spaces  `) === 7, 'test 4: le texte contient 7 mots');\n+```\n+> `undefined`\n+\n+Le test final est passé sans que les précédents n'échouent.\n+\n+On notera que l'écriture de tests est un processus itératif.  \n+La phase d'optimisation implique l'écriture d'un nouveau test qui échoue \n+et relance donc une nouvelle itération.\n+\n+Evidemment `countWords()` est très largement sous-optimisée et ne couvre pas tous les cas spéciaux.\n+On aurait pu ajouter une vérification sur le paramètre `text` et compter avec une expression régulière comme ceci :\n+\n+```js\n+const countWords = text => typeof text === 'string' && text.trim() ? text.match(/\\S+\\s{0,1}/g).length : 0;\n+```\n+L'idée ici est que coder est un processus incrémental et que chaque nouveau cycle doit être initié\n+par un besoin spécifique définit par un test dédié.  \n+\n+L'écriture des tests est simple: on décompose notre script en une suite d'affirmations \n+correspondant chacune à une fonctionnalité précise de notre algorithme.\n+\n+Grâce à ce processus on évite :\n+- **les régressions**: la suite valide de tests est la garantie que le code reste \n+fonctionnel malgré les évolutions de l'algorithm.\n+- **le code mort**: chaque morceau de code écrit est testé et a son utilité.\n+- **le code non documenté**: chaque comportement est décrit de manière fonctionnelle.\n+\n+## BDD : Des tests pour tous\n+\n+Une variante plus agnostique de la logique du développeur existe et permet à des \n+intervenants externes de faire partie intégrante du processus créatif. \n+\n+le BDD, Behaviour Driven Development (Développement Dirigé par le Comportement), \n+permet de définir de manière compréhensible pour tous les intervenants les \n+spécifications d’une fonctionnalité. Cela permet aussi aux développeurs de comprendre \n+le comportement général sans évoquer les détails techniques. \n+La discussion est donc facilitée entre les différents acteurs.  \n+\n+Pour illustrer cette variante adaptons l'exemple précédent :\n+\n+> Note : Pour exécuter ce type de code vous aurez besoin d'un _test-runner_ comme \n+> [Karma](https://karma-runner.github.io), [Mocha](https://mochajs.org) ou [Jest](https://facebook.github.io/jest/). \n+\n+```js\n+const countWords = text => text ? text.trim().replace(/\\s+/g, ' ').split(' ').length : 0;\n+\n+describe('countWords()', () => {\n+  it('doit traiter un texte vide', () => {\n+    expect(countWords('')).toBe(0);\n+  });\n+  \n+  it('doit traiter un texte d\\'un seul mot', () => {\n+    expect(countWords('nope')).toBe(1);\n+  });\n+  \n+  it('doit traiter un texte de n mots', () => {\n+    expect(countWords('tdd is fun bro')).toBe(4);\n+  });\n+  \n+  it('doit traiter un texte avec des espaces aux extrémités', () => {\n+    expect(countWords(' so is skateboarding ')).toBe(3);\n+  });\n+  \n+  it('doit traiter un texte avec des espaces inégaux entre les mots', () => {\n+    expect(countWords(`  I'm 28, I love $#@! and    multi-spaces  `)).toBe(7);\n+  });\n+});\n+```\n+\n+Voici le résultat du run :\n+\n+![résultat du run de tests](./testrunner.png)\n+\n+La relecture est simplifiée pour tous les participants non technique.\n+\n+## Conclusion\n+\n+Le TDD est destiné à être incorporé à un processus d'[Intégration Continue](http://putaindecode.io/fr/articles/ci/)\n+pour s'assurer du bon fonctionnement de l'application sur tous les environnements\n+de production après chaque nouveau `commit`.  ","path":"content/fr/articles/tdd/index.md","position":293,"original_position":293,"commit_id":"d3fcb3636cebaa43d10d3f547b4719472a46d2e0","original_commit_id":"d3fcb3636cebaa43d10d3f547b4719472a46d2e0","user":{"login":"ffesseler","id":653899,"avatar_url":"https://avatars.githubusercontent.com/u/653899?v=3","gravatar_id":"","url":"https://api.github.com/users/ffesseler","html_url":"https://github.com/ffesseler","followers_url":"https://api.github.com/users/ffesseler/followers","following_url":"https://api.github.com/users/ffesseler/following{/other_user}","gists_url":"https://api.github.com/users/ffesseler/gists{/gist_id}","starred_url":"https://api.github.com/users/ffesseler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ffesseler/subscriptions","organizations_url":"https://api.github.com/users/ffesseler/orgs","repos_url":"https://api.github.com/users/ffesseler/repos","events_url":"https://api.github.com/users/ffesseler/events{/privacy}","received_events_url":"https://api.github.com/users/ffesseler/received_events","type":"User","site_admin":false},"body":"Même remarque qu'en haut, il s'agit d'une remarque qui est général aux tests, pas au TDD.\r\n\r\nLe fait que tu fasses du TDD te permet d'avoir une suite de tests mais tu pourrais très bien développer ton appli sans TDD et toutefois avoir une bonne base de tests qui te permettent de détecter les régressions à chaque commit.","created_at":"2017-01-16T18:32:13Z","updated_at":"2017-01-16T18:33:27Z","html_url":"https://github.com/putaindecode/putaindecode.io/pull/703#discussion_r96284721","pull_request_url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703","_links":{"self":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/comments/96284721"},"html":{"href":"https://github.com/putaindecode/putaindecode.io/pull/703#discussion_r96284721"},"pull_request":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703"}}},"pull_request":{"url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703","id":100548915,"html_url":"https://github.com/putaindecode/putaindecode.io/pull/703","diff_url":"https://github.com/putaindecode/putaindecode.io/pull/703.diff","patch_url":"https://github.com/putaindecode/putaindecode.io/pull/703.patch","issue_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/703","number":703,"state":"open","locked":false,"title":"Recreate TDD post (FR, EN)","user":{"login":"Freezystem","id":1469878,"avatar_url":"https://avatars.githubusercontent.com/u/1469878?v=3","gravatar_id":"","url":"https://api.github.com/users/Freezystem","html_url":"https://github.com/Freezystem","followers_url":"https://api.github.com/users/Freezystem/followers","following_url":"https://api.github.com/users/Freezystem/following{/other_user}","gists_url":"https://api.github.com/users/Freezystem/gists{/gist_id}","starred_url":"https://api.github.com/users/Freezystem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Freezystem/subscriptions","organizations_url":"https://api.github.com/users/Freezystem/orgs","repos_url":"https://api.github.com/users/Freezystem/repos","events_url":"https://api.github.com/users/Freezystem/events{/privacy}","received_events_url":"https://api.github.com/users/Freezystem/received_events","type":"User","site_admin":false},"body":"Salut à tous! Voila, ça faisait un petit temps que je devais le refaire, le voici. \r\n\r\nUn post unique et simplifié pour parler du TDD. Il y a plus de recherches et d'objectivité par rapport à l'ancien. Les phrases sont plus simples et moins axées sur mon opinion personnelle. \r\n\r\nIl y a pas mal de code en deuxième partie mais ça reste lite pour un temps de lecture global d'une dizaine de minutes.\r\n\r\nP.S: Cette PR est directement liée à l'issue #608 ","created_at":"2017-01-07T00:30:03Z","updated_at":"2017-01-16T18:33:27Z","closed_at":null,"merged_at":null,"merge_commit_sha":"190edad5f75732eadfc477f166286746ae275e85","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703/commits","review_comments_url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703/comments","review_comment_url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/comments{/number}","comments_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/703/comments","statuses_url":"https://api.github.com/repos/putaindecode/putaindecode.io/statuses/d3fcb3636cebaa43d10d3f547b4719472a46d2e0","head":{"label":"putaindecode:post.tdd","ref":"post.tdd","sha":"d3fcb3636cebaa43d10d3f547b4719472a46d2e0","user":{"login":"putaindecode","id":4541781,"avatar_url":"https://avatars.githubusercontent.com/u/4541781?v=3","gravatar_id":"","url":"https://api.github.com/users/putaindecode","html_url":"https://github.com/putaindecode","followers_url":"https://api.github.com/users/putaindecode/followers","following_url":"https://api.github.com/users/putaindecode/following{/other_user}","gists_url":"https://api.github.com/users/putaindecode/gists{/gist_id}","starred_url":"https://api.github.com/users/putaindecode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/putaindecode/subscriptions","organizations_url":"https://api.github.com/users/putaindecode/orgs","repos_url":"https://api.github.com/users/putaindecode/repos","events_url":"https://api.github.com/users/putaindecode/events{/privacy}","received_events_url":"https://api.github.com/users/putaindecode/received_events","type":"Organization","site_admin":false},"repo":{"id":10319056,"name":"putaindecode.io","full_name":"putaindecode/putaindecode.io","owner":{"login":"putaindecode","id":4541781,"avatar_url":"https://avatars.githubusercontent.com/u/4541781?v=3","gravatar_id":"","url":"https://api.github.com/users/putaindecode","html_url":"https://github.com/putaindecode","followers_url":"https://api.github.com/users/putaindecode/followers","following_url":"https://api.github.com/users/putaindecode/following{/other_user}","gists_url":"https://api.github.com/users/putaindecode/gists{/gist_id}","starred_url":"https://api.github.com/users/putaindecode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/putaindecode/subscriptions","organizations_url":"https://api.github.com/users/putaindecode/orgs","repos_url":"https://api.github.com/users/putaindecode/repos","events_url":"https://api.github.com/users/putaindecode/events{/privacy}","received_events_url":"https://api.github.com/users/putaindecode/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/putaindecode/putaindecode.io","description":" :ok_hand: Putain de code ! is a place where you can read (and write) about best coding practices.  High quality content, reviewed by the community.","fork":false,"url":"https://api.github.com/repos/putaindecode/putaindecode.io","forks_url":"https://api.github.com/repos/putaindecode/putaindecode.io/forks","keys_url":"https://api.github.com/repos/putaindecode/putaindecode.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/putaindecode/putaindecode.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/putaindecode/putaindecode.io/teams","hooks_url":"https://api.github.com/repos/putaindecode/putaindecode.io/hooks","issue_events_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/events{/number}","events_url":"https://api.github.com/repos/putaindecode/putaindecode.io/events","assignees_url":"https://api.github.com/repos/putaindecode/putaindecode.io/assignees{/user}","branches_url":"https://api.github.com/repos/putaindecode/putaindecode.io/branches{/branch}","tags_url":"https://api.github.com/repos/putaindecode/putaindecode.io/tags","blobs_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/putaindecode/putaindecode.io/statuses/{sha}","languages_url":"https://api.github.com/repos/putaindecode/putaindecode.io/languages","stargazers_url":"https://api.github.com/repos/putaindecode/putaindecode.io/stargazers","contributors_url":"https://api.github.com/repos/putaindecode/putaindecode.io/contributors","subscribers_url":"https://api.github.com/repos/putaindecode/putaindecode.io/subscribers","subscription_url":"https://api.github.com/repos/putaindecode/putaindecode.io/subscription","commits_url":"https://api.github.com/repos/putaindecode/putaindecode.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/putaindecode/putaindecode.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/putaindecode/putaindecode.io/contents/{+path}","compare_url":"https://api.github.com/repos/putaindecode/putaindecode.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/putaindecode/putaindecode.io/merges","archive_url":"https://api.github.com/repos/putaindecode/putaindecode.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/putaindecode/putaindecode.io/downloads","issues_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues{/number}","pulls_url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls{/number}","milestones_url":"https://api.github.com/repos/putaindecode/putaindecode.io/milestones{/number}","notifications_url":"https://api.github.com/repos/putaindecode/putaindecode.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/putaindecode/putaindecode.io/labels{/name}","releases_url":"https://api.github.com/repos/putaindecode/putaindecode.io/releases{/id}","deployments_url":"https://api.github.com/repos/putaindecode/putaindecode.io/deployments","created_at":"2013-05-27T17:08:41Z","updated_at":"2017-01-11T11:54:08Z","pushed_at":"2017-01-13T12:34:10Z","git_url":"git://github.com/putaindecode/putaindecode.io.git","ssh_url":"git@github.com:putaindecode/putaindecode.io.git","clone_url":"https://github.com/putaindecode/putaindecode.io.git","svn_url":"https://github.com/putaindecode/putaindecode.io","homepage":"http://putaindecode.io/","size":22949,"stargazers_count":153,"watchers_count":153,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":89,"mirror_url":null,"open_issues_count":56,"forks":89,"open_issues":56,"watchers":153,"default_branch":"master"}},"base":{"label":"putaindecode:master","ref":"master","sha":"e735c40a627a419be5ac7f885f41fd82db4d553f","user":{"login":"putaindecode","id":4541781,"avatar_url":"https://avatars.githubusercontent.com/u/4541781?v=3","gravatar_id":"","url":"https://api.github.com/users/putaindecode","html_url":"https://github.com/putaindecode","followers_url":"https://api.github.com/users/putaindecode/followers","following_url":"https://api.github.com/users/putaindecode/following{/other_user}","gists_url":"https://api.github.com/users/putaindecode/gists{/gist_id}","starred_url":"https://api.github.com/users/putaindecode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/putaindecode/subscriptions","organizations_url":"https://api.github.com/users/putaindecode/orgs","repos_url":"https://api.github.com/users/putaindecode/repos","events_url":"https://api.github.com/users/putaindecode/events{/privacy}","received_events_url":"https://api.github.com/users/putaindecode/received_events","type":"Organization","site_admin":false},"repo":{"id":10319056,"name":"putaindecode.io","full_name":"putaindecode/putaindecode.io","owner":{"login":"putaindecode","id":4541781,"avatar_url":"https://avatars.githubusercontent.com/u/4541781?v=3","gravatar_id":"","url":"https://api.github.com/users/putaindecode","html_url":"https://github.com/putaindecode","followers_url":"https://api.github.com/users/putaindecode/followers","following_url":"https://api.github.com/users/putaindecode/following{/other_user}","gists_url":"https://api.github.com/users/putaindecode/gists{/gist_id}","starred_url":"https://api.github.com/users/putaindecode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/putaindecode/subscriptions","organizations_url":"https://api.github.com/users/putaindecode/orgs","repos_url":"https://api.github.com/users/putaindecode/repos","events_url":"https://api.github.com/users/putaindecode/events{/privacy}","received_events_url":"https://api.github.com/users/putaindecode/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/putaindecode/putaindecode.io","description":" :ok_hand: Putain de code ! is a place where you can read (and write) about best coding practices.  High quality content, reviewed by the community.","fork":false,"url":"https://api.github.com/repos/putaindecode/putaindecode.io","forks_url":"https://api.github.com/repos/putaindecode/putaindecode.io/forks","keys_url":"https://api.github.com/repos/putaindecode/putaindecode.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/putaindecode/putaindecode.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/putaindecode/putaindecode.io/teams","hooks_url":"https://api.github.com/repos/putaindecode/putaindecode.io/hooks","issue_events_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/events{/number}","events_url":"https://api.github.com/repos/putaindecode/putaindecode.io/events","assignees_url":"https://api.github.com/repos/putaindecode/putaindecode.io/assignees{/user}","branches_url":"https://api.github.com/repos/putaindecode/putaindecode.io/branches{/branch}","tags_url":"https://api.github.com/repos/putaindecode/putaindecode.io/tags","blobs_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/putaindecode/putaindecode.io/statuses/{sha}","languages_url":"https://api.github.com/repos/putaindecode/putaindecode.io/languages","stargazers_url":"https://api.github.com/repos/putaindecode/putaindecode.io/stargazers","contributors_url":"https://api.github.com/repos/putaindecode/putaindecode.io/contributors","subscribers_url":"https://api.github.com/repos/putaindecode/putaindecode.io/subscribers","subscription_url":"https://api.github.com/repos/putaindecode/putaindecode.io/subscription","commits_url":"https://api.github.com/repos/putaindecode/putaindecode.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/putaindecode/putaindecode.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/putaindecode/putaindecode.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/putaindecode/putaindecode.io/contents/{+path}","compare_url":"https://api.github.com/repos/putaindecode/putaindecode.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/putaindecode/putaindecode.io/merges","archive_url":"https://api.github.com/repos/putaindecode/putaindecode.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/putaindecode/putaindecode.io/downloads","issues_url":"https://api.github.com/repos/putaindecode/putaindecode.io/issues{/number}","pulls_url":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls{/number}","milestones_url":"https://api.github.com/repos/putaindecode/putaindecode.io/milestones{/number}","notifications_url":"https://api.github.com/repos/putaindecode/putaindecode.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/putaindecode/putaindecode.io/labels{/name}","releases_url":"https://api.github.com/repos/putaindecode/putaindecode.io/releases{/id}","deployments_url":"https://api.github.com/repos/putaindecode/putaindecode.io/deployments","created_at":"2013-05-27T17:08:41Z","updated_at":"2017-01-11T11:54:08Z","pushed_at":"2017-01-13T12:34:10Z","git_url":"git://github.com/putaindecode/putaindecode.io.git","ssh_url":"git@github.com:putaindecode/putaindecode.io.git","clone_url":"https://github.com/putaindecode/putaindecode.io.git","svn_url":"https://github.com/putaindecode/putaindecode.io","homepage":"http://putaindecode.io/","size":22949,"stargazers_count":153,"watchers_count":153,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":89,"mirror_url":null,"open_issues_count":56,"forks":89,"open_issues":56,"watchers":153,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703"},"html":{"href":"https://github.com/putaindecode/putaindecode.io/pull/703"},"issue":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/703"},"comments":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/issues/703/comments"},"review_comments":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703/comments"},"review_comment":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/pulls/703/commits"},"statuses":{"href":"https://api.github.com/repos/putaindecode/putaindecode.io/statuses/d3fcb3636cebaa43d10d3f547b4719472a46d2e0"}}}}
{"actor":{"display_login":"ffesseler"}}