Code Kata with SRFI-64
I got into the habit of doing about 30 minutes of Code Kata every morning. I practice these Kata following the test-driven development (TDD) approach.
Guile distribution includes the SRFI-64 module: a unit testing framework. In this article, I explain how to use it and how to configure it in order to practice code kata.
Basic usage
The SRFI-64 module has a default configuration. Let me show you what it looks like here.
Below is a Guile program that creates a test suite with only one test (doomed to fail) :
(use-modules (srfi srfi-64))
(test-begin "demo")
(test "Hookup" #f #t)
(test-end "demo")
Explanation of the program :
- line 1 : load the module named
(srfi srfi-64)
. - line 2 : indicate the beginning of the test group
demo
. - line 3: define a test, named “Hookup”, with the procedure
test-equal
whose first parameter is the result expected by the test (here,#t
) and the second parameter is the tested expression (here,#t
). - line 4: indicate the end of the `demo' test group.
It is relatively simple, there are few frills.
This is the result of the execution of this suite if you save it in a /tmp/tests.scm
file and execute the :
$ 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
The console displays only a summary of the result: line 3 shows an unexpected failure from the “Hookup” test. It's very brief but it gives a quick idea of the state of the program.
The complete detail is in the /tmp/demo.log
file:
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
This report gives me two pieces of information that I use a lot : actual-value
and expected-value
.
This default configuration, although ready to use, has the disadvantage of providing informations in two places : in the console (list of tests and their states) and in a file (test results). Not very practical...
Fortunately, the test framework is easily configurable. In the following article, I present you my configuration dedicated to code kata.
Configuration for Code Kata
The idea here is to configure the SRFI-64 module to display all the information I need directly in the console (and I don't need to report in a file). I want to see at a glance :
- the list of executed tests ;
- the status of each of these tests;
- for failed tests, display the expected value and the value obtained.
According to the SRFI-64 reference, the objects that maintain the statistics on the test suite (total number of tests, number of successful, failed, passed, ...) are the test-runners.
Thanks to the section Writing a new test-runner and some examples gleaned from the web, you should be able to create the test-runner that suits you!
Here is the one I made for myself (based on the work of Mathieu Lirzin and 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))
I created a git repository which contains a project template for a code kata. Just follow the README instructions and code !
Here is an example of feedback from your terminal while the watch.sh
script is running :
FAIL Hookup
expected-value: #f
actual-value: #t
No more need to look at the content of the report (which is no longer generated) to find out what the problem is. So I can execute this script in a dedicated emacs buffer, every time I save, and act according to the test results.
Now it's up to you!
Choose a code kata exercise, work on it for about 30 minutes, share the link to your code and your tests in comments below!
Then, I give you my 2 cents for your next session!
Thank you so much for reading this article!
Don't hesitate to give me your opinion or ask a question !
To do so, please leave a comment below or contact me.
Also, please subscribe so you don't miss the next ones :
– blog via Mastodon @jeko@write.as et RSS
– screencast via Peertube @jeko@video.tedomum.net et RSS
And most importantly, share the blog and tell your friends it's the best blog in the history of Free Software! No shit!