Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Une révolution dans le monde des tests

410e3353165c33043ab69be7fc366428?s=47 Boris Feld
October 06, 2018

Une révolution dans le monde des tests

Depuis plusieurs années, les outils de qualité ont évolués, les outils de CI sont de plus en plus scalables, les librairies d'écriture de tests sont plus nombreuses et ont bien mûries et de nouveaux outils sont apparus pour améliorer encore plus la qualité du code que l'on produit.

Néanmoins, la plupart des outils de CI se contentent de lancer un script et de vérifier le code de retour, la plupart des librairies de tests nous imposent de choisir entre lancer l'ensemble de nos suites de tests ou s'arrêter pour voir le détail du test en échec et enfin la plupart des innovations des outils de CI, l'exécution en parallèle et l'exécution à distance, n'ont pas encore trouvé le chemin jusqu'au développeurs.

Comment améliorer la situation ? Je vous présenterai l'un de mes projets, LITF (https://github.com/Lothiraldan/litf) un nouveau format d'entrée et de sortie pour les librairies de test et BALTO (https://github.com/lothiraldan/balto), un orchestrateur de tests utilisant ce nouveau format. BALTO est écrit en Python 3.6 / Asyncio et supporte bien entendu Pytest comme première librairie compatible.

Grâce à ce nouveau format, BALTO peut exécuter plusieurs suites de tests dans des langages différents, à distance sur un clusteur Kubernetes et le tout en parallèle. En tout cas, c'est le but pour la version stable.

410e3353165c33043ab69be7fc366428?s=128

Boris Feld

October 06, 2018
Tweet

Transcript

  1. UNE RÉVOLUTION DANS LE MONDE DES TESTS UNE RÉVOLUTION DANS

    LE MONDE DES TESTS Boris Feld - PyConfr 2018 octobus.net
  2. PRESENTATION PRESENTATION

  3. BORIS FELD BORIS FELD Expert Mercurial, Python et DevOps. Enthousiaste

    sur la qualité. https://octobus.net/ @lothiraldan
  4. QUI FAIT DES TESTS? QUI FAIT DES TESTS?

  5. SONDAGE: COMBIEN DE PERSONNES SONDAGE: COMBIEN DE PERSONNES ÉCRIVENT DES

    TESTS ? ÉCRIVENT DES TESTS ?
  6. SONDAGE: COMBIEN DE PERSONNES SONDAGE: COMBIEN DE PERSONNES EXECUTENT DES

    TESTS ? EXECUTENT DES TESTS ?
  7. VOUS N’ÊTES PAS LES SEULS VOUS N’ÊTES PAS LES SEULS

    2017 2018 0.00% 10.00% 20.00% 30.00% 40.00% 50.00% 60.00% 70.00% 80.00% Launching tests Writing tests => 70% lancent des tests
  8. ÉTAT DE L’ART EN PYTHON ÉTAT DE L’ART EN PYTHON

  9. OUTILS OUTILS Unittest Nosetests Pytest Autre ?

  10. UNITTEST UNITTEST Inclut dans Python Permet d’écrire des tests sous

    la forme de classes Fournit des assertions sous la forme de méthodes d’assertions.
  11. UNITTEST EXEMPLE UNITTEST EXEMPLE import unittest class TestStringMethods(unittest.TestCase): def test_upper(self):

    self.assertEqual('foo'.upper(), 'FOO') def test_isupper(self): self.assertTrue('FOO'.isupper()) self.assertTrue('Foo'.isupper()) if __name__ == '__main__': unittest.main()
  12. EXECUTION AVEC UNITTEST EXECUTION AVEC UNITTEST F. ================================================================= ===== FAIL:

    test_isupper (__main__.TestStringMethods) ----------------------------------------------------------------- ----- Traceback (most recent call last): File "test.py", line 10, in test_isupper self.assertTrue('Foo'.isupper()) AssertionError: False is not true ----------------------------------------------------------------- ----- Ran 2 tests in 0.000s FAILED (failures=1)
  13. NOSETESTS NOSETESTS Un unittest meilleur Un ecosystem de plugin Une

    vraie avancée Mais deux paquets Pypi, nose et nose2 Un écosystème parcemé
  14. EXECUTION AVEC NOSETESTS EXECUTION AVEC NOSETESTS F. ================================================================= ===== FAIL:

    test_isupper (test.TestStringMethods) ----------------------------------------------------------------- ----- Traceback (most recent call last): File "/home/lothiraldan/Labo/presentations/balto_revolution_fr/src/tes t.py", line 10, in test_isupper self.assertTrue('Foo'.isupper()) AssertionError: False is not true ----------------------------------------------------------------- ----- Ran 2 tests in 0.000s FAILED (failures=1)
  15. REDNOSE (PLUGIN NOSE1) REDNOSE (PLUGIN NOSE1) F. ================================================================= ===== 1)

    FAIL: test_isupper (test.TestStringMethods) ----------------------------------------------------------------- ----- Traceback (most recent call last): test.py line 10 in test_isupper self.assertTrue('Foo'.isupper()) AssertionError: False is not true ----------------------------------------------------------------- ------------ 2 tests run in 0.001 seconds. 1 FAILED (1 test passed)
  16. PYTEST PYTEST La vraie étoile montante du marché Un meilleur

    unittest Tests sous forme de fonctions Fixtures De nombreux utilitaires De nombreux plugins
  17. EXECUTION AVEC PYTEST EXECUTION AVEC PYTEST ============================= test session starts

    ============================== platform linux2 -- Python 2.7.15, pytest-3.1.2, py-1.5.3, pluggy- 0.4.0 rootdir: /home/lothiraldan/Labo/presentations/balto_revolution_fr/src, inifile: collected 2 items test.py F. =================================== FAILURES =================================== ________________________ TestStringMethods.test_isupper ________________________ self = <test.TestStringMethods testMethod=test_isupper> def test_isupper(self): self.assertTrue('FOO'.isupper()) > self.assertTrue('Foo'.isupper())
  18. PYTEST-SUGAR PYTEST-SUGAR

  19. QU’EST-CE QU’ON VEUT DANS UNE QU’EST-CE QU’ON VEUT DANS UNE

    INTERFACE ? INTERFACE ?
  20. MA LISTE AU PÈRE NOËL MA LISTE AU PÈRE NOËL

    Couleur Barre de progression Lancer uniquement les tests échoués Lancer un test donné Interface web
  21. BALTO BALTO

  22. BALTO KESAKO? BALTO KESAKO? Ce n’est pas YAPTL (Yet Another

    Python Testing Library).
  23. COULEUR COULEUR

  24. BARRE DE PROGRESSION BARRE DE PROGRESSION

  25. SÉLECTIONNER SEULEMENT LES TESTS QUI SÉLECTIONNER SEULEMENT LES TESTS QUI

    ONT ECHOUES ONT ECHOUES
  26. SÉLECTIONNER SEULEMENT UN TEST SÉLECTIONNER SEULEMENT UN TEST

  27. BALTO DEMO BALTO DEMO [Demo live]

  28. ARCHITECTURE ARCHITECTURE

  29. QUESTION POUR UN CHAMPION QUESTION POUR UN CHAMPION C’est quoi

    Balto ? Un plugin pytest Une interface web Un serveur websocket Un lanceur de processus
  30. LA BONNE RÉPONSE LA BONNE RÉPONSE

  31. TOUTES CES RÉPONSES TOUTES CES RÉPONSES Pytest Pytest-plugin Balto-Server Balto-UI

  32. COMMUNICATION COMMUNICATION Pytest Pytest-plugin Process Balto-Server ? Balto-UI WS

  33. LE SECRET DE BALTO LE SECRET DE BALTO

  34. LE SECRET LE SECRET Le Secret de Balto c’est qu’il

    lit la sortie standard du processus lancé
  35. L’AUTRE PARTIE DU SECRET L’AUTRE PARTIE DU SECRET Mais il

    faut que le plugin, balto-server et balto-ui puissent se comprendre
  36. POUR SE COMPRENDRE POUR SE COMPRENDRE Il faut une langue

    commun
  37. SORTIE STANDARD DE PYTEST SORTIE STANDARD DE PYTEST ============================= test

    session starts ============================== platform linux2 -- Python 2.7.15, pytest-3.1.2, py-1.5.3, pluggy- 0.4.0 rootdir: /home/lothiraldan/Labo/presentations/balto_revolution_fr/src, inifile: collected 2 items test.py F. =================================== FAILURES =================================== ________________________ TestStringMethods.test_isupper ________________________ self = <test.TestStringMethods testMethod=test_isupper> def test_isupper(self): self.assertTrue('FOO'.isupper()) > self.assertTrue('Foo'.isupper()) E AssertionError: False is not true
  38. LES FORMATS DE SORTIE DE TEST LES FORMATS DE SORTIE

    DE TEST Junit.xml Tap Mozlog
  39. JUNIT.XML JUNIT.XML Basé sur XML Un gros chier à la

    n du build Format lié à Junit => Non streamable
  40. TAP TAP Très connu dans la communauté Perl Très simpliste,

    peu extensible Format lié à TAP Perl => Nécessite un parseur en Python et en JS
  41. MOZLOG MOZLOG Format utilisé dans les tests Mozilla 1 au

    début et à la n de chaque test => Avoir une atomicite, 1 test == 1 ligne est plus simple
  42. LISTE AU PÈRE NOËL LISTE AU PÈRE NOËL Simple à

    écrire et lire Streaming pour pas attendre la n du run Format indépendant d’une implémentation
  43. UN NOUVEAU FORMAT UN NOUVEAU FORMAT

  44. DE QUOI ON AS BESOIN? DE QUOI ON AS BESOIN?

    Nom du test Le résultat du test (failed, passed, skipped…) Error en cas d’erreur
  45. EXEMPLE EXEMPLE { "test_name": "test_success", "outcome": "passed" } { "test_name":

    "test_failed", "outcome": "failed", "error": { "humanrepr": "def test_fails():\n> assert False\nE assert False\n\ntest_func.py:9: AssertionError" } }
  46. PIÈCE MANQUANTE PIÈCE MANQUANTE { "test_number": 6, "_type": "session_start" }

    { "failed": 3, "total_duration": 0.03, "_type": "session_end", "skipped": 0, "error": 0, "passed": 3 }
  47. PLUS DE DONNÉES PLUS DE DONNÉES Temps Messages de log

    Sortie standard et sortie standard d’erreur Diff de text ou d’images Fichier, ligne, etc…
  48. LANCER UN TEST SPECIFIQUE? LANCER UN TEST SPECIFIQUE?

  49. SORTIE VS ENTRÉE SORTIE VS ENTRÉE On as aussi besoin

    d’un format d’entrée: { "collect_only": true } { "files": ["file1.py", "file2.py"], "nodes": ["file1.py::test_func"] }
  50. COMMENT RÉCUPÉRER UN IDENTIFIANT? COMMENT RÉCUPÉRER UN IDENTIFIANT? Ajoutons un

    nouveau champ de sortie: { "test_name": "test_success", "outcome": "passed", "_id": "test_func.py::test_success" }
  51. LA POST-RÉVOLUTION LA POST-RÉVOLUTION

  52. EXEMPLE DE SORTIE EXEMPLE DE SORTIE { "test_name": "test_failed", "_id":

    "test_func.py::test_success", "outcome": "failed", "error": { "humanrepr": "def test_fails():\n> assert False\nE assert False\n\ntest_func.py:9: AssertionError" } }
  53. ET SI ON ALLAIT PLUS LOIN ? ET SI ON

    ALLAIT PLUS LOIN ? Et si on faisait un plugin nosetests pour ce format?
  54. ET SI ON ALLAIT ENCORE PLUS LOIN ? ET SI

    ON ALLAIT ENCORE PLUS LOIN ? Et si on faisait un plugin pour un test runner dans un autre langage?
  55. JUSQU’AU PEUT-ON ALLER ? JUSQU’AU PEUT-ON ALLER ? Et si

    on lisait la sortie standard d’autre chose qu’un process ? Comme une commande ssh ou un container Docker ?
  56. VERS L’INFINIE ET AU-DELÀ VERS L’INFINIE ET AU-DELÀ Balto etant

    base sur Asyncio, et si on lancait plusieurs suites pytest en parallelle ? Ou plusieurs suites dans des langages differents sur une machine distante avec Docker?
  57. RÉVOLUTION DEMO RÉVOLUTION DEMO

  58. LA VRAIE RÉVOLUTION LA VRAIE RÉVOLUTION

  59. UN NOUVEAU PROTOCOLE UN NOUVEAU PROTOCOLE Similaire à HTTP ou

    LSP, c’est une fondation au dessus duquel construire les nouveaux outils de demain.
  60. EXEMPLE EXEMPLE Vous voulez un dashboard curses pour lancer vos

    tests? Vous pouvez ! Vous voulez un rapport sur les temps de chacun de vos tests? Vous pouvez !
  61. LITF LITF Language Independent Test Format

  62. BALTO BALTO BAlto is a Language Independent Test Orchestrator

  63. INSTALLER BALTO INSTALLER BALTO Télécharger la dernière release sur Github:

    https://github.com/Lothiraldan/balto/releases Le mettre dans le path Installer le plugin litf de votre test runner Pro ter
  64. QUE POUVEZ-VOUS FAIRE ? QUE POUVEZ-VOUS FAIRE ? Utiliser Balto

    Parler de Balto autour de vous Parler de LITF au mainteneur de votre test runner préféré
  65. CONTRIBUER CONTRIBUER Balto et LITF sont open-source : https://github.com/lothiraldan/litf https://github.com/lothiraldan/balto

  66. CONCLUSION CONCLUSION

  67. QUESTIONS? QUESTIONS?