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.
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
- line 2 : indicate the beginning of the test group
- line 3: define a test, named “Hookup”, with the procedure
test-equalwhose first parameter is the result expected by the test (here,
#t) and the second parameter is the tested expression (here,
- 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
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 :
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 <firstname.lastname@example.org> ;;; Copyright © 2019 Alex Sassmannshausen <email@example.com> ;;; Copyright © 2019 Jérémy Korwin-Zmijowski <firstname.lastname@example.org> ;;; ;;; 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.
And most importantly, share the blog and tell your friends it's the best blog in the history of Free Software! No shit!