C'était la première fois que j'assistais aux HumanTalks. Je pense que j'y retournerai régulièrement, ça ouvre des reflexions sur pleins de choses annexes à la vie d'un developpeur sans trop rentrer dans le technique. Très rafraichissant.
Ca se passait à La Cordée, un espace de coworking vers la gare de Lyon. 4 Talks de 10mn chacun + questions. Avec un ROTI à la fin (mais pas à la manière OCTO du mélangeage de doigts, mais de marquer une croix dans une des trois colonnes Bon, Moyen, Mauvais de chacun des talks).
Ecrire sur Internet, c'est mieux avec Markdown
Présentation de markdown. Vu que je prends déjà mes notes en markdown, prendre les notes de ce talk avait un petit coté inception.
Markdown est un moyen d'écrire facilement sur internet. C'est un système de mise en forme de texte simple, sans avoir besoin de logiciel particulier, qui permet de rendre un texte à la fois facile à lire et facile à écrire, tout en gardant une hiérarchie, et quelques bonus (emphase, liste, liens, etc).
Bien sur, il y a un script perl qui convertit le markdown en html. Markdown est utilisé (dans des versions légérement modifiées) par github et stackoverflow.
Les MOOCs
Par Yannick Grenzinger, de Xebia.
Ce sont les Massive Open Online Course. C'est à dire les systèmes de cours en ligne à la coursera. Les cours drainent en général entre 50.000 et 200.000 inscrits (beaucoup moins de réels personnes qui suivent les cours jusqu'à la fin, mais des volumétries quand même honorables).
Globalement les cours sont gratuits et fait par des pointures (Google, ou le créateur de Scala qui donne un cours de Scala). Les cours sont de haute qualité en général.
Cela dit, les cours ne sont pas complétement ouverts. Il est souvent interdit/impossible de télécharger les vidéos ou les supports des cours. De plus en plus de cours deviennent payant au bout d'un moment (les premiers sont gratuits pour créer une envie, puis deviennent payants).
Certains cours sont à heures fixes, d'autres sont accessibles 24/24. Paradoxalement, les cours à heure fixe ont plus d'étudiants que les autres, car on a tendance à se dire “je le ferai plus tard” pour ne jamais le faire au final.
Le speaker avertissait qu'il était un peu boulimique des cours, qu'il en faisait beaucoup, voire trop. Ses conseils étaient de télécharger les vidéos pour les regarder dans le métro et de garder le temps réel devant son pc pour les cotés pratiques. Et surtout, de ne pas fréquenter les forums des cours, rapport temps investi/choses apprises est faible par rapport aux vidéos.
Les cours de business sont les plus faciles. Les cours d'UX ne sont pas durs mais nécessitent beaucoup de travail. Les cours de code sont les plus longs et les plus durs.
Certains cours comme ceux de code peuvent être validés automatiquement (check de l'input et de l'output). Les cours d'UX doivent être validés manuellement, donc un système de peer review est mis en place. Chacun doit évaluer 5 cours de 5 autres étudiants random pour que le sien soit aussi reviewé. Selon lui cette étape est beaucoup plus facile dans les cours américains que dans les cours français où les reviewers sont généralement moins laxistes.
Il conseille particulièrement coursera pour la qualité des cours. Il indiquait aussi qu'être prof d'un cours comme ça était une très bonne pub qui permettait aux auteurs de se mettre en avant, et de vendre leurs livres avec beaucoup plus de légitimité.
Il a fini avec une liste de recommandations :
Startup Engineering.
Intro aux Malwares.
Reactive Programming.
Comment créer son entreprise
Human computer interaction
Gamification.
Social Psychology
LES LANGAGES ESOTERIQUES
Conférence amusant et wtf sur les langages ésotériques, comme le brainfuck, dont le but n'est pas d'être lisible, ni même d'être pratique. A partir du moment où le langage est capable d'effectuer une liste d'instructions élémentaires, il est dit Turing-complet (ceux qui sont plus calés que moi en algo, reprenez-moi quand je me trompe), et tout langage turing-complet est capable d'exprimer n'importe quel autre langage turing-complet.
Le brainfuck, dont les seuls caracteres autorisés sont <, >, +, -, [ et ] en est un. Tout comme Piet qui s'écrit avec des images composées de pixels tirés d'une palette de 17 couleurs et la transition d'une couleur à une autre se traduit en une instruction, avec un pointeur qui se déplace de pixel en pixel pour executer le code.
(A ce moment il a été demandé pourquoi on n'utilise pas Piet en place des QRcode. A part les problématique évidentes de sécurité, l'idée est interessante.)
Puis vint la présentation de langages tous plus wtf les uns que les autres :
Le Malbolge, qui est fait pour être impossible à programmer.
L'Unlambda, qui n'est constitué que de fonctions.
Le whitespace où les seuls caracteres possibles sont space, tab et new line.
Sans doute la conf' la plus captivante de la soirée, en partie pour les discussions qu'elle a entrainée autour d'une bière ensuite.
En gros, le speaker comparait les entreprises à des personnes atteintes de maladies mentales, et faisait des parallelles très intéressants. Il avait isolé trois pathologies principales.
Les anorexiques/boulimiques sont des sociétés qui vont acheter des filiales… puis effectuer un plan social. Ou créer un nouveau service, avant d'externaliser. Ca pose evidemment des problèmes de digestion la masse salariale devient comme une friandise dont on ne parvient pas à gérer excès. Difficile ensuite pour la société de garder sa ligne et de s'aligner avec les critères de beauté du marché.
Les hypochondriaques, qui sont persuadés que quelque chose ne va pas chez eux. Alors ils demandent des audit, des coachs, et ont une surconsommation de consultants exterieurs. Ils font des séminaires, de réunions, des réorganisations. Leur pole RH devient hypertrophié et touche à tout.
Au final, cela leur cache leurs vrais problèmes. Ils fantasment sur des problèmes qui flattent leur image sans voir la vraie cause. Ils deviennent très liés à leurs consultants, et finissent par racheter les sociétés de conseil, pour avoir leur médecin directement chez eux. Au bout d'un moment cela crée des jalousies en interne et tout le monde veut alors sa part des soins.
Les derniers sont les bipolaires, qui alternent des phases de croissance fulgurante avec de longues périodes de doute. Particulièrement les startups, qui ont des changement de business plan très souvent. Qui “pivotent” à tout va, font des revirement à 180° et perdent complétement leurs employés.
Ils sont dans la surenchère, ils font beaucoup d'effets d'annonce flamboyant, alors que leurs résultats sont fragiles. Ils font tout pour garder la tête haute et avoir l'air bien portant devant le monde exterieur alors qu'en interne tout n'est pas si facile. Ils supportent mal la critique.
Cette fois-ci c'était dans les sous-sols de la mairie de Paris.
PARIS IS API
Présentation de "Paris Numérique”, le département de la direction de la communication de la ville de Paris. Ce sont les responsables du site paris.fr et de tous les sites annexes sur les actualités de la ville (~300 sites, dont paris plage, velib, etc).
Ils ont particulièrement deux sites dont ils sont fiers :
equipements.paris.fr qui référence toutes les piscines, parcs, écoles, etc de la ville, avec placement google maps. Pour chacun ils ont des infos contextuelles en temps réel comme les heures d'ouverture, si la piscine est actuellement bondée ou non, etc.
quefaire.paris.fr qui est un agenda des sorties culturelles et des loisirs de paris.
Toutes les données utilisées dans ces deux sites sont accessibles publiquement par des API et documentées. Les données sont des données en temps réel, on tape réellement sur les bases de prod (nécessaire par exemple pour des events qui sont annulés au dernier moment). Leur documentation est générée automatiquement à partir du code. L'accès est gratuit, il faut juste demander une clée d'API pour qu'ils monitorent l'usage.
Techniquement c'est construit sur une stack MEAN (Mongo/MySQL, Express, Angular, Node).
Très intéressant, ça donne envie de jouer avec les données.
Grunt
Présentation rapide de Grunt, mais sincérement regardez les screencasts de CSSTricks ou egghead.io et vous en saurez autant, voire plus.
node-libspotify
Présentation de Florent Jaby et de son module nodejs qui wrappe la librairie C/C++ de spotify pour la rendre accessible depuis node. Florent étant un collègue, je n'ai pas pris vraiment de notes, sachant qu'il pouvait m'expliquer tout ça directement si besoin.
Très bonne présentation cela dit, Florent a réussi à rendre compréhensible et amusant un sujet qui est à la base pas super simple.
Growing your prototype
Finalement un REX sur quand et comment passer d'un prototype à quelque chose de mieux construit. Ce que j'en ai retenu c'est qu'il préconise de ne pas se lancer dans les tests ou le TDD trop tôt dans la vie du projet. Au début on experimente, on essaie, et si on commence à mettre des tests, ça nous bloque dans une vision, et on a du mal à jeter tous les tests qu'on a fait.
Dans la même veine, pour tester la faisabilité d'un proto, ils n'utilisaient même pas de DB, tout était dans des fichiers plats JSON. Plus facile à éditer, versionnable, pas de problématique de scaling. Ce n'est qu'une fois qu'ils ont vraiment été sur du set de fonctionnalités qu'ils voulaient qu'ils ont commencé à choisir une vraie techno pour leur db, et qu'ils ont alors commencé à la tester.
D'un point de vue technique, il donnait quelques astuces pour faire du quick and dirty en node. Comme par exemple définir un app.all() qui filtre toutes les requetes, check que les parametres indispensables soient bien là, fait quelques manips de data élémentaires et modifie la requete en conséquence avant de la laisser passer aux app.get et app.post plus précis ensuite.
Il conseillait aussi la library paperwork qui permet de valider un schéma de JSON simplement, à intégrer dans une API REST. Elle retourne un 4xx avec le détail de l'erreur de validation si le JSON envoyé ne corresponds pas à ce qu'on attends.
Il montrait finalement une micro-library maison nommée transquire qui remplace require et qui lui permet de mocker des modules, comme par exemple des drivers mysql qui retournent des données simplement en RAM plutot que de taper dans leur DB. Pour ça, il modifie l'objet require.cache pour toujours retourner son mock plutot que le véritable module. Il ne l'a pas publiée car la librairie fait à peine quelques lignes.
Paris.Rb dans les locaux d'Epita, grand amphi, comme d'habitude. Début de la session officiellement à 19h30, mais premier véritable talk à 21h. Avant ça, présentation de Paris.Rb, pizza et bières.
Tizen
Romuald Rozan, d'Intel, nous a présenté Tizen, un OS Open Source basé sur le noyau Linux. Destiné à être multi-support (tablette, mobile, desktop, voiture, tv, appareil photo), il est poussé globalement par Intel et Samsung mais avec des partenariats avec d'autres fabricants et opérateurs. Résultat du merge de deux projets internes à Samsung et Intel.
Pas vraiment convaincu de la conférence, c'était plus un message à enrobage commercial qu'autre chose. La question lui a été posé des différences entre Tizen et FirefoxOS. Il a répondu qu'il n'avait pas pour habitude de dire du mal des concurrents, qu'il suffisait d'aller voir ce que faisait FirefoxOS pour voir en quoi Tizen était différent… Il a aussi laissé sous-entendre que Tizen était poussé par des gros du hardware et destiné à tourner sur du matériel de plus haut de gamme que FirefoxOS.
Phusion Passenger
Présentation de Hongli Lai, qui était de passage à Paris pour dotJS et qui nous a présenté Phusion Passenger, et surtout les améliorations apportées ces dernières années. Passenger est un serveur qui fait la liaison entre un webserver (Apache, Nginx) et une appli Rails qui tourne derrière. Il a rapidement comparé Passenger à ses concurrents : Mongrel, Thin, Unicorn et Puma.
Il a mis l'accent sur le fait que Passenger execute beaucoup d'automagic dans sa config et possède des adapter pour Apache et Nginx qui font presque tout tout seul (il a comparé à une config typique de Unicorn qui semble beaucoup plus complexe –mais qui propose peut-être justement plus de fine-tuning ?–).
Niveau perf, il a aussi benchmarké contre Puma, qui est plus rapide sur les benchmarks, mais où les différences de perfs ne sont plus perceptibles in real life, sur une appli déployée. Il a de toute façon précisé que si on cherche à avoir une appli avec de bonnes performances, il ne faut pas faire du Rails, ou alors le blinder derrière du cache et du load balancing.
A part ça, Passenger permet de restarter automatiquement l'appli en cas de crash, de laisser nginx servir les fichiers statiques, d'utiliser des sockets unix pour communiquer si disponible, se scale automatiquement en cas de traffic en spawnant de nouvelles instances du serveur sur chaque CPU de la machine, et il permet aussi l'utilisation de web sockets. Et tout ceci est monitorable depuis la command line avec passenger-status. Il permet aussi d'envoyer un mail ou un log avec la stacktrace complete lors d'un crash.
Ils ont aussi grandement facilité l'installation avec des dépots officiels Debian, Ubuntu et Homebrew. Marche sous heroku et peut même servir de serveur devant du nodejs ou du python (même si j'ai pas trop compris le use-case).
Le seul drawback, si on veut l'utiliser avec nginx est qu'il faut une version spécialement compilée de nginx, mais qui est fournie avec passenger.
Il existe aussi une version pro de passenger, qui intègre des features supplémentaires, mais tous les bugs sont d'abord fixés sur la version open.
Zeus
Lightning talk à propose de Zeus, qui permet de preloader en mémoire son appli rails et donc de pouvoir ensuite executer toutes les taches rails console, rails tests, etc de manière quasi-instanée. En utilisant parallel_test en complément de Zeus, on peut même executer ses tests en parallele sur chaque CPU de la machine, de manière à réduire drastiquement le temps d'execution des tests (exemple présenté sur : 14mn de tests de base, ~6mn avec Zeus+ParallelTest).
Code Reviews
La dernière conf était celle qui m'interessait le plus sur le programme. Christophe Philemotte, de 8th Color nous a parlé des code reviews, des outils, et de la manière dont ils le font dans sa boite.
Il a commencé par rappeller l'utilité d'avoir des tests : pour vérifier d'abord que tout fonctionne, mais aussi pour éviter la non-regression, servir de documentation, ne pas oublier les edge-cases, et au final accélérer les cycles de dev.
Ensuite, il a évoqué l'autre facteur de création de qualité selon lui : les code reviews. Toute nouvelle feature, tout bug fix, est relu par un autre membre de l'équipe. Cela créé une discussion et permet de partager la connaissance du projet au sein de l'équipe, d'éduquer l'équipe, de détecter des bugs qui auraient pu passer devant une seule paire d'yeux. Mais ça améliore aussi selon lui la lisibilité et la consistency du code ainsi que le co-ownership de celui-ci. Et au final, une fois encore ça accèlere les cycles de dev.
Pour faire ça, ils utilisent plusieurs outils qui, en plus des tests, leur permettent de régler automatiquement certains des soucis de leur code avant de le soumettre au code review des autres. L'idée est que si un outil automatique peut nous faire gagner du temps, c'est autant de temps gagner à discuter constructivement avec un autre être humain sur du code, et donc profiter de son experience et de sa pédagogie, ce qu'une machine ne peut pas fournir.
Ils passent donc leur code au travers d'une série de moulinettes, entre autres :
un linter, pour checker les syntax error très rapidement
Flog, qui évalue la complexité du code (nombre de loop, branching, etc) et se mettent d'accord sur une valeur de complexité maximum autorisée
Flay, qui teste la duplication du code au sein d'une codebase
Rails best practices, qui comme son nom l'indique output les manquements aux bonnes pratiques (à fine-tuner quand même car il est un peu extremiste avec les options par défaut).
BrakeManScanner, qui vérifie le code pour y trouver des vulnérabilités de sécurité
Rubocop qui checke le code en suivant le Ruby Style Guide et qui peut même corriger certains soucis de lui-même.
Si on ne veut pas s'occuper d'installer tout ces outils, il existe des solutions en SaaS comme CodeClimate et PullReview (le dernier étant fait par le speaker).
Son conseil est de commencer par un des outils présentés, n'importe lequel, et l'incorporer dans son workflow. Puis une fois maitrisé, en rajouter un autre, et ainsi de suite, et une fois que tout ce qui peut être automatisé l'est, passer aux code review manuelle.
Il mettait en garde contre les défenses naturellement humaines que les codeurs ont contre les pull review, la sensation d'être testé, surveillé, quand on commit, et que cela peut créer un climat complétement contraire au but recherché.
Un site de cours en ligne pour apprendre WebGL. Fait par un formateur de WebGL qui s'est rendu compte qu'il est difficile d'apprendre les rudiments de 3D à ses élèves et qui a construit le site pour l'aider dans ses formations. Le code de chaque chapitre est éditable et tourne en live dans le browser, découpé en étapes qu'on peut avancer ou reculer.
De ses retours d'experience, la partie la plus dure pour s'y mettre est l'un des premiers exercices qui consiste à afficher un cube coloré qui tourne sur lui même. Après ça, la courbe d'apprentissage (shaders, etc) est beaucoup plus facile.
Babylon.js
La seconde présentation était de David Rousset (@davrous), qui avec son collègue David Catuhe (@deltakosh) ont développé Babylon.js, un framework de jeux 3D avec HTML5 et WebGL. Les deux david bossent pour Microsoft, mais leur framework est fait sur leur temps libre et aucunement affilié à Microsoft. Le code est dispo ici : https://github.com/BabylonJS/Babylon.js
Le framework est une couche d'abstraction au dessus de WebGL pour le rendre beaucoup plus facile d'accès aux néophytes, et orienté développement de jeu. Plein de choses sont déjà incluses dans le framework comme une camera libre, un moteur de collision, la gravité, le déplacement au clavier/souris/touch/accelerometre, des joysticks virtuels en surimpression pour se déplacer sur interface tactile. Le framework va intéragir directement avec le GPU. Ils ont même développé un plugin pour Blender pour exporter directement des modèles en JSON pour les importer dans Babylon.
La majorité des shaders de base sont déjà intégrés, mais il est possible d'en développer des customs. Un système de cache est inclu pour permettre d'optimiser l'affichage d'un même élement de multiple fois, ainsi que le “frustrum” (le fait de ne gérer que ce qui se trouve dans l'angle de vision du joueur et de discard ce qu'il ne peut pas voir, pour économiser des perfs). Ajouté à ça un loading incrémental des assets en fonction de leur distance avec la camera (mais pas de gestion de LOD encore), il est techniquement possible de créer des mondes ouverts à la GTA ou Skyrim.
Marche sur tous les navigateurs, et possibilité d'exporter son code pour le transformer en appli pour le Windows Store et tournera directement en natif sous windows 8. Fonctionne aussi avec une manette Xbox.
Ils ont même une version Occulus Rift dans les cartons, ainsi que des améliorations telles que la création d'un format binaire d'export, le drag'n'drop direct depuis Blender dans Visual Studio, l'intégration d'un moteur physique et pas mal d'autres choses trop techniques WebGL que je n'ai pas retenues.
Bref, c'était un beau projet, très impressionnant, vous pouvez checker les démos sur http://www.babylonjs.com/
ASM.js
Bon, alors là je suis désolé mais mon cerveau est passé en mode shutdown et j'ai pas tout suivi. Je vous invite donc à aller sur la FAQ du site officiel : http://asmjs.org/faq.html
En gros, ASM.js est un subset de javascript qui ne contient que les méthodes les plus bas niveau pour faire du JS hyper rapide, aussi rapide que du C. Il est possible d'écrire en ASM.js dans n'importe quel navigateur aujourd'hui, et pour peu qu'on se plie à la nouvelle syntaxe, notre JS sera de toutes façons executé plus rapidement. Mais si le browser inclue lui-même ASM.js, alors le code serait extremement plus rapide. Actuellement, seul Firefox incluerait ASM.
ASM est donc particulièrement adapté pour écrire du bas niveau qui va parler directement avec le GPU, lui aussi pour faire du WebGL. Les démos étaient impressionnantes, mais le niveau technique en 3D (et en C) était bien trop complexe pour moi.
Cozy Cloud
https://www.cozycloud.cc/
Présentation rapide de Cozy Cloud, un cloud personnel à déployer sur ses propres machines (laptop, mobile, tablette, boxes, etc). L'idée principale est de garder ses données personnelles chez soi, sur son propre cloud, mais de pouvoir néanmoins y accèder sur tous ses devices (potentiellement même en mode offline). Leur idée principale est que nos datas personnelles restent sur nos machines personnelles.
Tout ça tourne sur du linux, avec une couche de node.js en interne. Chacun peut développer ses propres apps sur le système, la principale utilité étant que toutes les apps peuvent avoir accès aux mêmes données (mails, todo list, contacts, films, etc). Actuellement seul node est dispo comme langage de dev, mais python et ruby vont bientot arriver.
Il faut quand même un bon matos pour faire tourner Cozy (ie. un raspberryPi est trop petit, un cubieboard est ok), et ils sont actuellement en discussion avec GDF pour s'intégrer dans leur future box domotique.
Conclusion
Paris.js c'est bon, mangez-en. En plus, il y avait des donuts.
Lors de mes premiers jours à Octo, j'ai eu la chance de me voir offrir une formation HumanCoders. JVE avait en effet gagné cette formation en retweetant une annonce des HumanCoders et ne pouvant pas y aller, il m'avait filé sa place.
Débutant en Rails et n'ayant jamais fait de tests, c'est exactement ce qu'il me fallait et ce que je voulais apprendre. La formation a donc eu lieu sur deux jours, dans un sympathique petit appart loué sur AirBnB à coté de République.
Nous étions trois élèves en tout pour un formateur (Jean-Michel Garnier) et Matthieu Segret qui restait dans un coin pour suivre aussi la formation.
Jean-Michel fait normalement cette formation sur une journée, du coup en l'étendant sur deux on avait un peu plus le temps de poser quelques questions et de tester plus profondément certaines parties. La formation était dédiée à des gens qui connaissent bien Rails mais qui n'ont jamais posés de tests, j'étais un peu plus largué que les deux autres, mais ayant déjà un background de cakePHP, je n'étais pas trop perdu dans les concepts.
Types de tests
On a déjà vu les différents types de tests et les noms qui leur sont donnés, pour s'y repérer un peu.
Tests unitaires, ou TU, où on va tester unitairement une classe, en l'isolant complètement de ses dépendances.
Tests d'intégration, où on va tester une classe et ses dépendances
Tests d'Acceptance, où on va tester un scénario utilisateur complet, avec toute la stack depuis le browser jusque la base de donnée.
Petit rappel sur les qualités d'un bon test: lisible, petit, indépendant, sans copié-collé et rapide. Tout ça permet de substituer les tests à la documentations, pouvoir les lancer dans le désordre pour le même résultat, avoir un feedback rapide et pouvoir en ajouter facilement.
On nous présente aussi rapidement le principe du TDD et des baby steps. Red, Green, Refactor. Mais on nous prévient que c'est un peu le Graal des tests et qu'avant d'en arriver là il faut déjà bien comprendre comment s'écrivent des tests. Mais qu'une fois qu'on y arrive, c'est bonheur.
Rspec
Rspec est le framework de TU de Rails. Il peut être utilisé à part aussi sur d'autres projets, mais il s'avère que c'est celui utilisé par Rails. Il y a plein de super magie made in Ruby dans sa syntaxe qui permettent d'écrire des tests qui soient très lisible. Son API a pas mal changée par le passé et évolue encore, mais à l'heure où j'écris ses lignes (2015, soit 2 ans après avoir fait la formation), l'API de la v3 devrait être stable.
Un test Rspec, ça ressemble à ça
describe"Class"doit"has feature"doendend
describe et it permettent de découper les tests en blocks. describe est utiliser comme wrapper pour grouper plusieurs tests ensemble. On groupe généralement par classe, et/ou par méthode selon la complexité des tests. Les describe peuvent s'imbriquer sans problème.
Les it représentent nos tests. À noter qu'on peut utiliser fdescribe et fit pour focus sur un seul describe ou un seul it et donc n'exécuter que celui-ci dans la suite de tests.
Il existe une convention partagée dans le nommage des variables dans les tests. On nomme en général expected la valeur qu'on attends et actual la valeur qu'on génère. Et on vérifie bien souvent que actual est égal à expected.
À noter que eq, eql et equal ont des comportements différents. Il n'y a rien là de spécifique à Rspec, c'est simplement du Ruby, mais un cas un peu particulier.
a.should eq(b) est identique à a.should == b. On teste si la valeur est identique, mais a et b peuvent avoir des types différents.
a.should eql(b) teste que la valeur et le type soient identiques
a.should equal(b) quand à lui vérifie que a et b référencent carrément le même objet.
Rspec expose une syntaxe très proche de l'anglais, à base de should et should_not, ce qui rends les tests très facile à lire et donc très facile à comprendre. En pratique c'est plus facile à lire qu'à écrire car on ne sait jamais trop où placer les _ au début (should_not raise_error et pas should_not_raise error). Il faut un peu de compréhension des rouages internes pour deviner la séparation.
Tips Rspec
Jean-Michel nous a donné quelques tips appris à force de travailler avec Rspec.
Il est possible de définir un subject de nos tests, qui deviendra le sujet par défaut des comparaisons.
Il nous conseille aussi d'utiliser le matcher match_array plutôt que include car son output donne plus d'informations sur les différences en cas d'échec (quelles clés sont communes, lesquelles sont différentes).
let permet de définir une variable dont l'initialisation ne sera exécutée que la première fois que la variable sera utilisée, et qui retournera toujours la même valeur pour un même block. On l'a rapidement abordé théoriquement dans la formation, mais on ne l'a pas utilisé ensuite en pratique dans la formation.
Les callbacks before(:each), before(:all), after(:each) et after(:all) permettent de simplifier les tests en ajoutant un peu de boilerplate avant et après chaque test.
En passant --order à rspec on le force à exécuter les tests de manière aléatoire, nous assurant donc qu'ils soient indépendants. De même, ajouter --backtrace permet d'avoir plus de contexte sur là où les tests fails, ce qui est bien utile pour le debug.
Des gems comme timecop ou delorean permettent de joueur finement avec la notion de temps et de mocker des dates.
WTF Rspec ‽
On a eu un petit moment WTF dans la formation quand la syntaxe un peu magique s'est retournée contre nous.
Le code suivant marchait parfaitement, failant quand l'erreur n'était pas du bon type.
Le problème semble venir de l'absence de parenthèses autour du raise_error qui gène RSpec dans la compréhension du contexte. Pour info, voici le code corrigé qui passe comme prévu :
Du coup, ça nous a bien montré l'intérêt de toujours commencer par un test qui foire, pour être sur que nos tests testent bien les bonnes choses et pas du vide. Avoir des tests qui passent toujours est bien pire que de ne pas avoir de tests du tout.
Outils
Les tests RSpec d'une appli Rails sont quand même assez lents car ils doivent instancier la totalité de l'appli à chaque fois. Et la force des tests c'est quand même d'avoir un feedback rapide. Et si on doit attendre 20s avant d'avoir le résultat, c'est beaucoup trop long.
Pour contrer ça il existe des outils comme Spork, Spring ou Zeus. Après avoir utilisé longuement les trois, Jean-Michel nous a conseillé Zeus. Il suffit de lancer Zeus dans un terminal, puis dans un autre zeus rspec /path/to/file.rb pour lancer des tests qui utilisent la même version de l'appli gardée en mémoire par zeus.
Sur ma machine, mes tests qui s'exécutaient en 7s sont passés à 0.2s. Impressionnant. Attention toutefois, zeus n'est pas bulletproof et nécessite parfois d'être killé et relancé car il ne parvient pas régénérer toutes les modifications de code (notamment l'update du Gemfile, les fichiers d'i18n, etc). Idem, il faut un workaround non expliqué ici pour réussir à le faire fonctionner avec le mode random de rspec.
La question a été posée de la redondance de code entre les règles de validation du modèle qu'on pose en Rails et les tests de validation qui vont avec. Est-ce utilise d'avoir cette info deux fois, et si non, alors lequel garder ?
Jean-Michel nous a suggéré d'utiliser la gem schema_validation qui va générer automatiquement les règles de validation en fonction du schema de la base de donnée. Du coup, c'est la DB qui est la source du schéma.
Par défaut, RSpec efface la DB de test après les tests, ce qui est assez embêtant pour débugguer et traquer les bugs. Pour contrer cela, il est possible de définir use_transactional_fixture et d'ajouter un clean de la DB avant tous les tests, puis entre chaque test, mais pas après tous, pour pouvoir étudier la DB à loisir. Il est aussi possible de définir quelles tables vider et lesquelles garder (inutile de supprimer toute l'immense table d'i18n à chaque test).
Il est aussi possible d'utiliser la gem rspec-set qui permet de définir certains objets en DB qui reviendront toujours au même état entre chaque tests, même après des update et des delete.
On a aussi été mis en garde de ne pas faire des tests sur la DB avec des volumes très différents de ceux de production. Des problèmes peuvent survenir si les données sont tellement importantes que la DB devient un bottleneck. Pour ça, il est intéressant de posséder un dump d'une DB de prod (anonymisé bien sur) pour faire des tests sur des données réelles.
Tester une API
RSpec permet aussi de tester une API, mais ne fait pas réellement appel à la couche réseau. À la place, il se pluggue sur les routes qui ont été définies dans Rails. L'avantage c'est que c'est très rapide, l'inconvénient c'est qu'on ne teste pas réellement en conditions réelles.
Au passage, si son API est bien définie, il est possible de générer automatiquement sa documentation avec la gem rspecapidocumentation qui créé alors automatiquement les tests avec les endpoints, les arguments attendus et quelques exemples de réponse. Ces tests peuvent très facilement servir de documentation.
Tests Full Stack
Les tests d'Acceptance, ou full stack, vont tester l'ensemble de l'application, depuis le point de vue de l'utilisateur. C'est à dire qu'on va tester le navigateur, la couche réseau, les appels au back-end et les mises à jour en base de données.
Ces tests sont très lent à jouer, et très long à écrire. Ils sont aussi sujets à beaucoup d'erreurs et sont très fragiles (la moindre modification à n'importe quel étage de la chaine peut faire foirer le test).
Pour les faire, on utilise Selenium, qui est un driver pour piloter un navigateur. On peut aussi utiliser un service en SaaS comme Saucelabs pour le faire à notre place.
Si on veut le faire nous-mêmes, c'est Capybara qu'on utilise. Celui-ci dispose de méthodes simples pour simuler un comportement utilisateur comme visit, fill_in ou click_on. On peut alors tester des scénarios entiers de remplissage de formulaire et tester qu'une phrase spécifique est alors bien affichée à l'écran. On peut aller plus loin et tester que le record est bien arrivé dans la base de données, mais on teste plutôt généralement que la page qui affiche les records comprends bien celui que l'on vient de rentrer.
Le debug de tests Capybara se fait encore pas mal manuellement à l'aide de la méthode save_and_open_page qui ouvre alors la page en cours dans un navigateur pour que l'on puisse inspecter ce qu'il se passe.
Au final, ce sont des tests très fragiles car très dépendants du markup et du wording. Il n'est pas certain que le temps investi sur ces tests soit rentabilisé, il vaut mieux donc le garder pour les chemins critiques.
Doubles, Stubs, Mocks, etc
On a gardé le meilleur pour la fin. On a eu le droit à une explication sur la différence entre un stub et un mock.
En gros un double est un terme général pour parler des stubs et des mocks. Un double est comme une doublure au cinéma. On dirait que c'est le vrai objet, mais en fait c'est un faux. Il ne fait rien d'intéressant, à part répondre aux méthodes qu'on appelle sur lui.
On peut en créer facilement avec Rspec comme ceci double('name', method1: response1, method2: response2).
On peut aussi créer un stub depuis un objet existant en court-circuitant une des ses méthodes et en hard codant ce qu'il doit retourner. Cela permet par exemple d'éviter des appels couteux en temps vers une API.
Attention toutefois, il est tellement facile de créer des stubs qu'il peut être tentant de stubber un module complet et ses dépendances. Trop de stubs dans un test est un gros code smell. Cela signifie que le code est trop couplé. Il vaut mieux le séparer en plusieurs entités qui sont testables individuellement.
Les mocks de leur coté sont des stubs améliorés. On court-circuite toujours l'appel initial à la méthode pour retourner une réponse sur mesure, mais en plus on peut tester le nombre de fois qu'une méthode a été appelée et avec quels arguments.
On a aussi abordé rapidement les fake objects et les spy objects, mais bien trop rapidement pour que je puisse me souvenir de leur utilité.
Conclusion
J'ai appris beaucoup en deux jours de formation, ça m'a permis d'avoir une vision générale de ce que sont les tests exactement. Il y a beaucoup de nouvelle terminologie et beaucoup d'outils à utiliser.
Je ne me suis pas mis à ajouter des tests tout de suite après la formation, surtout que je n'ai pas fait de rails, mais les concepts m'ont permis de monter rapidement la même chose sur une stack JavaScript. Et aujourd'hui, 2 ans après, j'écris mon premier plugin testé avec RSpec et je me rends compte que cette formation m'a vraiment aidé à y voir clair.
S'il y a un bouquin que je peux vous conseiller aussi c'est Practical Object-Oriented Design in Ruby par Sandy Metz. Du très beau clean code, des patterns clairs, des exemples de séparation of concern très imagés. Chaque phrase de chaque page est bien pensée, il faut le lire à tête reposée mais il expose vraiment les choses clairement.
Et sinon aussi, en vrac, plein de liens que j'avais noté pendant la formation.