Emerger des parenthèses

Cybo Test n°19

by Jeko — ven. 02 août 2019

Test n°19 : un fichier todo.txt ne contenant qu'une ligne vide

Le fichier todo.txt est le fichier contenant la liste des tâches à donner en entrée au logiciel Cybo que je développe.

Red : écrire un test qui échoue

Hier, je me demandais se que retournerai l'appel de la fonction next-action si le fichier todo.txt ne contenait qu'une ligne vide. Personnellement, j'aimerais que ça retourne null puisqu'il n'y a pas de tâche à proprement parler... J'ai donc écrit un test pour répondre à ma question :

(append-tasks-to-file TODO.TXT '(""))
(test-assert "Next-action-with-one-blank-task-Should-return-null"
  (null? (next-action TODO.TXT)))
(clear-test-files)

Et voila le résultat :

;;; note: source file ./cybo.scm
;;;       newer than compiled /home/jeko/.cache/guile/ccache/2.2-LE-8-3.A/home/jeko/Workspace/guile-cybo/cybo.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling ./cybo.scm
;;; compiled /home/jeko/.cache/guile/ccache/2.2-LE-8-3.A/home/jeko/Workspace/guile-cybo/cybo.scm.go
%%%% Starting test cybo-harness  (Writing full log to "cybo-harness.log")
cybo-test.scm:68: FAIL Next-action-with-one-blank-task-Should-return-null
# of expected passes      17
# of unexpected failures  1

Bah ça ne fonctionne pas comme prévu visiblement. Le test est au rouge donc il y a un problème ! Mais j'ai pu mettre le doigt dessus avec un test, je peux donc modifier le code pour faire passer le test. C'est parti !

Green : écrire le code nécessaire pour faire passer le test qui échoue

Quel est le problème en fait ? Voyons ce que le REPL nous raconte :

$ guile -L .
GNU Guile 2.2.3
Copyright (C) 1995-2017 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> ,m (cybo)
scheme@(cybo)> (next-action "todo.txt")
ERROR: In procedure substring:
Value out of range 0 to 0: 2

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.

Il semble qu'il y ait un souci à l'exécution avec un des appels de la fonction substring, mais lequel (elle est appelée à plusieurs endroits) ? Pour le savoir, j'affiche la backtrace :

scheme@(cybo) [1]> ,backtrace
In cybo.scm:
    46:18  3 (next-action _)
In unknown file:
           2 (filter #<procedure remaining? (task)> (""))
In cybo.scm:
    73:31  1 (remaining? "")
In unknown file:
           0 (substring "" 0 2)

Effectivement, dans la fonction remaining? j'appelle la fonction substring qui permet de tester la présence du marqueur de complétion d'une tâche. Ce marqueur est "x ". Donc ici on cherche un motif "x " plus long que la chaîne de caractère dans laquelle le chercher "". On se retrouve alors avec un dépassement.

Voila comment je pense contourner le problème :

(define (todo.txt->scm filename)
  (call-with-input-file filename
    (lambda (file-port)
      (let loop ((line (read-line file-port)) (task-list '()))
        (if (eof-object? line)
            (reverse task-list)
            (loop (read-line file-port) (if (string-null? line)
    				                        task-list
    				                        (cons line task-list))))))
    #:encoding UTF-8_ENCODING))

À chaque appelle de la fonction next-action Cybo va lire dans le fichier contenant la liste des tâches pour extraire chaque ligne et construire une liste de chaînes de caractères (une ligne de fichier devient un élément de la liste). La modification que j'ai apporter pour faire passer le test empêche de d'ajouter un élément à la liste lorsque la ligne est vide.

Voyons ce que ça donne :

;;; note: source file ./cybo.scm
;;;       newer than compiled /home/jeko/.cache/guile/ccache/2.2-LE-8-3.A/home/jeko/Workspace/guile-cybo/cybo.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling ./cybo.scm
;;; compiled /home/jeko/.cache/guile/ccache/2.2-LE-8-3.A/home/jeko/Workspace/guile-cybo/cybo.scm.go
%%%% Starting test cybo-harness  (Writing full log to "cybo-harness.log")
# of expected passes      18

Le test passe! Je peux donc sereinement réusiner le code pour le rendre meilleur. Notemmement en suivant les préceptes dispensés par Uncle Bob dans son livre Clean Code

Refactor : éliminer les duplications, rendre expressif, réduire les fonctions

test 19 refactoring

La petite passe est faite. Mes compétences en réusinage (refactoring) en Guile évolueront (du moins je l'espère) avec mes développements sur Cybo !