I’ve been working with Common Lisp for about eight months now, and I’ve become curious about how to test my code in this language, similar to how it's done in other languages like Pytest for python or Rspec for Ruby. The good news is that there are several testing frameworks in Common Lisp, and the one I chose to delve is FiveAM.
FiveAM is a mature testing framework designed for Common-lisp; and it provides a way to test our code systematically; simplifies or scale the program; and be able to prevent bugs. Just as tasting a dish that helps us assess its flavor and quality, using FiveAM also helps us to evaluate and ensure the correctness of our code.
Obviously, we have to set up first our project and load FiveAM via Quicklisp on our Lisp implementations.
(ql:quickload :cl-project)") (ql:quickload :fiveam
This should be the tree directory layout or skeleton produced by cl-project. See this link regarding skeleton project generation.
├── cl-sample.asd
├── README.markdown
├── README.org
├── src
│ └── main.lisp
└── tests
└── main.lisp
Here what our integration should look like:
"cl-sample"
(defsystem :version "0.0.0"
"nycto"
:author ""
:mailto ""
:license
:depends-on ()"src"
:components ((:module
:components"main"))))
((:file ""
:description "cl-sample/tests"))))
:in-order-to ((test-op (test-op
"cl-sample/tests/main"
(defsystem "nycto"
:author ""
:license "cl-sample"
:depends-on ("fiveam")
"tests"
:components ((:module
:components"main"))))
((:file "Test system for cl-sample"
:description
:perform (test-op (op c) (symbol-call :fiveam :run!
(find-symbol* :cl-sample :cl-sample/tests/main))))
Once everything are already set-up. Make sure the project is on the
source registry so we can be able to check the integration via ASDF or quicklisp
(ql:quickload :cl-sample) (ql:quickload :cl-sample/tests)
In the, Tree Section under /src
, a
main.lisp
file. We can write there our own
experimentation for testing. For example, we could write a function to
compute the factorial of N
. This will
allow us to test the function using FiveAM.
;;; main.lisp --> our main file
defpackage cl-sample
(:use :cl)
(
(:export #:fact))
in-package :cl-sample)
(
;; bleh bleh bleh.
defun fact (n)
("Computes the factorial of N."
do ((count 1 (1+ count))
(1 (* res count)))
(res > count n) res)))
((
In this file, We are going to test our function definition that we
exported from the package name— cl-sample
.
For this experimentation, we can obviously see below the basic check.
check
is the one that checks its argument
if it is truthy. The most used check is is
.
;;; main.lisp --> our main test file
defpackage cl-sample/tests/main
(:use :cl
(
:cl-sample
:fiveam))
in-package :cl-sample/tests/main)
(
;; NOTE: To run this test file, execute—(asdf:test-system :cl-sample) in your SBCL.
;; Root suite
(def-suite cl-sample"Test my cl-sample")
:description
(def-suite test-fact"one returns one"
:description
:in cl-sample)
(def-suite test-fact1"one returns -one"
:description
:in cl-sample)
(test test-fact= 1 (fact 1))))
(is (
(test test-fact1= -1 (fact 1))))
(is (
This is how we can execute the test on the SBCL:
> (run! 'cl-sample) ;; Run it through the Root Suite, if we want to; or
> (run! 'test-fact) ;; Run it through the test.
If you want to run all the test in your test file we can execute it this way:
> (5am:run-all-tests)
NOTE: run! accepts a name of suite or a test, then prints testing report in pretty output.