Code Kata avec SRFI-64

Guile Logo

J'ai pris l'habitude de faire environ 30 minutes de Code Kata chaque matin. Je pratique ces Kata suivant la méthode du développement dirigé par les tests (TDD).

Guile est distribué le module SRFI-64 : un framework de test unitaire. Dans cet article, je t'explique comment l'utiliser et comment le configurer.

Utilisation de base

Le module SRFI-64 dispose d'une configuration par défaut. Je te montre à quoi ça ressemble ici.

Ci-dessous, un programme Guile qui créé une suite de tests ne comprenant qu'un seul test (voué à l'échec) :

(use-modules (srfi srfi-64))
(test-begin "demo")
(test-equal "Hookup" #f #t)
(test-end "demo")

Explication du programme :

C'est relativement simple, il y a peu de fioritures. Voilà le résultat de l'exécution de cette suite si tu l'enregistres dans un fichier /tmp/tests.scm  et que tu exécutes le script :

$ guile --no-auto-compile test.scm 
%%%% Starting test demo  (Writing full log to "demo.log")
/tmp/test.scm:3: FAIL Hookup
# of unexpected failures  1

La console n'affiche ici qu'un résumé du résultat : la ligne 3 remonte un échec inattendu depuis le test “Hookup”. C'est très sommaire mais ça permet d'avoir une idée rapide de l'état du programme.

Le détail complet se trouve dans le fichier /tmp/demo.log :

$ cat demo.log
%%%% Starting test demo
Group begin: demo
Test begin:
  test-name: "Hookup"
  source-file: "/tmp/test.scm"
  source-line: 3
  source-form: (test-equal "Hookup" #f #t)
Test end:
  result-kind: fail
  actual-value: #t
  expected-value: #f
Group end: demo
# of unexpected failures  1

Ce rapport me donne deux informations que j'utilise beaucoup : actual-value et expected-value.

Cette configuration par défaut, bien que prête à l'emploi, présente l'inconvénient de fournir de l'information à deux endroits : dans la console (liste des tests et leurs états) et dans un fichier (résultats des tests). Pas très pratique…

Heureusement, le framework de test est facilement configurable. Dans la suite de l'article, je te présente ma configuration dédiée aux kata de programmation.

Configuration pour Code Kata

L'idée ici est de configurer le module SRFI-64 pour qu'il m'affiche toutes les informations dont j'ai besoin directement dans la console (et je n'ai pas besoin rapport dans un fichier). Je veux voir d'un coup d’œil :

D'après la référence du SRFI-64, les objets qui entretiennent les statistiques sur la suite de tests (le nombre total de tests, le nombre de tests réussis, échoués, passé, ...) sont les test-runners.

Grâce à la section Writing a new test-runner et à quelques exemples glanés sur le web, tu devrais pouvoir créer le test-runner qui te convient !

Voici celui que je me suis confectionné (à partir du travail de Mathieu Lirzin et Alex Sassmannshausen) :

;;;; kata-driver.scm - Guile test driver for code kata practice

(define script-version "2020-10-04") ;UTC

;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org>
;;; Copyright © 2019 Alex Sassmannshausen <alex@pompo.co>
;;; Copyright © 2019 Jérémy Korwin-Zmijowski <jeremy@korwin-zmijowski.fr>
;;;
;;; This program is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;;; Commentary:
;;;
;;; This script provides a Guile test driver using the SRFI-64 Scheme API for
;;; test suites.  SRFI-64 is distributed with Guile since version 2.0.9.
;;;
;;; This script is a very cleaned up version of the Alex Sassmannshausen 's 
;;; version. The changes make it suitable for use in a code kata practice.
;;;
;;;; Code:

(define-module (runner-kata)
  #:export (test-runner-kata))

(use-modules (srfi srfi-64)
             (ice-9 pretty-print)
             (srfi srfi-26))

(define* (test-display field value  #:optional (port (current-output-port))
                       #:key pretty?)
  "Display 'FIELD: VALUE\n' on PORT."
  (if pretty?
      (begin
        (format port "~A:~%" field)
        (pretty-print value port #:per-line-prefix "+ "))
      (format port "~A: ~S~%" field value)))

(define* (result->string symbol)
  "Return SYMBOL as an upper case string.  Use colors when COLORIZE is #t."
  (let ((result (string-upcase (symbol->string symbol))))
    (string-append (case symbol
                     ((pass)       "")  ;green
                     ((xfail)      "")  ;light green
                     ((skip)       "")  ;blue
                     ((fail xpass) "")  ;red
                     ((error)      "")) ;magenta
                   result
                   "")))

(define* (test-runner-kata)

  (define (test-on-test-end-kata runner)
    (let* ((results (test-result-alist runner))
           (result? (cut assq <> results))
           (result  (cut assq-ref results <>)))
      (if (equal? 'fail (result 'result-kind))
	  (begin
	    (newline)
	    (format #t "~a ~A~%"
		    (result->string (result 'result-kind))
		    (result 'test-name))
	    (when (result? 'expected-value)
              (test-display "expected-value" (result 'expected-value)))
	    (when (result? 'expected-error)
              (test-display "expected-error" (result 'expected-error) #:pretty? #t))
	    (when (result? 'actual-value)
              (test-display "actual-value" (result 'actual-value)))
	    (newline))
	  (begin
	    (format #t "~a ~A~%"
		    (result->string (result 'result-kind))
		    (result 'test-name))))))

  (let ((runner (test-runner-null)))
    (test-runner-on-test-end! runner test-on-test-end-kata)
    runner))

J'ai créé un dépôt git qui contient un template de projet pour un kata de programmation. Lorsque tu exécutes le script run.sh, voici le résultat que tu obtiens :

$ ./run.sh 

FAIL Hookup
expected-value: #f
actual-value: #t

Plus besoin de regarder le contenu du rapport (qui n'est d'ailleurs plus généré) pour savoir ce qui pose problème.

À toi de jouer !

Choisis un exercice de kata de code, travail dessus pendant environ 30 minutes, partages le lien vers ton code et tes tests en commentaire !

Ensuite, je te donne des billes pour ta prochaine session !

Merci beaucoup d'avoir lu cet article !

N'hésites pas à me donner ton avis, proposer une idée d'amélioration, ou poser une question ! Pour ce faire, laisses un commentaire plus bas ou contactes-moi

Abonnes-toi pour ne pas manquer les prochains :articles via Mastodon @jeko@write.as et RSSscreencasts via Peertube jeko@video.tedomum.net et RSS

Et encore plus important, partages ce blog et dis à tes amis que c'est le meilleur blog de l'histoire du logiciel libre ! Sans dec'

#français #guile #tool #tdd #kata #gnu