I can't figure out how to test a function with fiveam. I setup a project using cl-project. My project name is my-projects/proj1:
~/quicklisp% tree local-projects
local-projects
├── dtrace
│ ├── dtrace.asd
│ └── dtrace.lisp
├── my-projects
│ └── proj1
│ ├── #proj1.asd#
│ ├── README.markdown
│ ├── README.org
│ ├── proj1.asd
│ ├── proj1.asd~
│ ├── src
│ │ ├── main.fasl
│ │ ├── main.lisp
│ │ └── main.lisp~
│ └── tests
│ ├── main.fasl
│ ├── main.lisp
│ └── main.lisp~
└── system-index.txt
And:
~/quicklisp/local-projects% cat system-index.txt
dtrace/dtrace.asd
my-projects/proj1/proj1.asd
Here is proj1/proj1.asd:
(defsystem "proj1"
:version "0.0.1"
:author "7stud"
:license "any"
:depends-on ()
:components ((:module "src"
:components
((:file "main"))))
:description ""
:in-order-to ((test-op (test-op "proj1/tests"))))
(defsystem "proj1/tests"
:author "7stud"
:license "any"
:depends-on ("proj1"
"fiveam")
:components ((:module "tests"
:components
((:file "main"))))
:description "Test system for proj1"
:perform (test-op (op c) (symbol-call :fiveam '#:run! :proj1)))
proj1/src/main.lisp:
(defpackage proj1
(:use :cl))
(in-package :proj1)
;; blah blah blah.
(defun anyoddp (number-list)
(cond ((null number-list) nil)
((oddp (first number-list)) t)
(t (anyoddp (rest number-list)))))
proj1/tests/main.lisp:
(defpackage proj1/tests/main
(:use :cl
:proj1
:fiveam))
(in-package :proj1/tests/main)
;; Note: To run this test file, execute `(asdf:test-system :proj1)' in your Lisp.
;; (deftest test-target-1
;; (testing "should (= 1 1) to be true"
;; (ok (= 1 1))))
(def-suite master-suite
:description "Test my system.")
(def-suite anyoddp-tests
:description "Test anyoddp"
:in master-suite)
(in-suite anyoddp-tests)
(test simple-maths
(is (= 3 (+ 1 1))))
(test anyoddp-with-odds
(let ((result (anyoddp '(1 3 4))))
(is (equal result t))
"True expected but got ~a" result))
I've tried every permutation of commands that I've read about in an attempt to test my proj1 "system", and I either get an error or Didn't run anything...huh?. Here's my latest attempt:
CL-USER> (ql:quickload "fiveam")
To load "fiveam":
Load 1 ASDF system:
fiveam
; Loading "fiveam"
("fiveam")
CL-USER> (asdf:load-system "proj1")
T
CL-USER> (asdf:test-system :proj1)
; compiling file "/Users/7stud/quicklisp/local-projects/my-projects/proj1/tests/main.lisp" (written 20 MAR 2024 10:04:40 AM):
; wrote /Users/7stud/.cache/common-lisp/sbcl-2.4.0-macosx-arm64/Users/7stud/quicklisp/local-projects/my-projects/proj1/tests/main-tmpUSHT8RIL.fasl
; compilation finished in 0:00:00.004
Didn't run anything...huh?; in: ALEXANDRIA:NAMED-LAMBDA PROJ1/TESTS/MAIN::%TEST-ANYODDP-WITH-ODDS
; (PROJ1/TESTS/MAIN::ANYODDP '(1 3 4))
;
; caught STYLE-WARNING:
; undefined function: PROJ1/TESTS/MAIN::ANYODDP
;
; compilation unit finished
; Undefined function:
; PROJ1/TESTS/MAIN::ANYODDP
; caught 1 STYLE-WARNING condition
T
CL-USER>
Why am I getting
undefined function: PROJ1/TESTS/MAIN::ANYODDP
??? At the top of proj1/tests/main.lisp it says:
(defpackage proj1/tests/main
(:use :cl
:proj1
:fiveam))
Isn't use :proj1 supposed to let me call the functions defined in proj1 without the package name? Okay, here is proj1/tests/main.lisp with the package name added to the function name anyoddp:
(defpackage proj1/tests/main
(:use :cl
:proj1
:fiveam))
(in-package :proj1/tests/main)
(def-suite master-suite
:description "Test my system.")
(def-suite anyoddp-tests
:description "Test anyoddp"
:in master-suite)
(in-suite anyoddp-tests)
(test simple-maths
(is (= 3 (+ 1 1))))
(test anyoddp-with-odds
(let ((result (proj1::anyoddp '(1 3 4)))) ;; **CHANGE HERE**
(is (equal result t))
"True expected but got ~a" result))
Then:
CL-USER> (ql:quickload "fiveam")
To load "fiveam":
Load 1 ASDF system:
fiveam
; Loading "fiveam"
("fiveam")
CL-USER> (asdf:load-system "proj1")
T
CL-USER> (asdf:test-system :proj1)
; compiling file "/Users/7stud/quicklisp/local-projects/my-projects/proj1/tests/main.lisp" (written 20 MAR 2024 10:33:11 AM):
; wrote /Users/7stud/.cache/common-lisp/sbcl-2.4.0-macosx-arm64/Users/7stud/quicklisp/local-projects/my-projects/proj1/tests/main-tmp7YCPD44Y.fasl
; compilation finished in 0:00:00.004
Didn't run anything...huh?
T
CL-USER>
I'm also wondering if there is a way to use fiveam to test a function in a file that is not in a project. Suppose I have this file:
;; a.lisp
(defun anyoddp (number-list)
(cond ((null number-list) nil)
((oddp (first number-list)) t)
(t (anyoddp (rest number-list)))))
How can I add some tests to a.lisp, then run those tests?
I made some progress running tests in a project. I was able to execute my tests with the following code:
proj1/src/main.lisp:proj1/tests/main.lisp:Then in slime:
I have no idea why I got this error:
I, or rather
cl-project, defined the "system"proj1/testsin the file~/quicklisp/local-projects/my-projects/proj1/proj1.asd:In any case, the command:
causes quickslip to look through the directories under
~/quicklisp/local-projectsand write the paths to all the .asd files it finds into~/quicklisp/local-projects/system-index.txt. After I evaluated that command, then(ql:quickload 'proj1/tests)was successful.Essentially, I loaded a system, then I used a package name that was defined somewhere in the system to call a function defined in that package:
And, here are the changes I made to
proj1.asdto integrate withasdf:Then:
And:
Whenever I made changes to the files in
~/quicklisp/local-projects/my-projects/proj1/, I usually tried to execute:or
in the slime repl. I found that the slime repl would often get out of sync with the current files in
proj1, which would cause errors.As far as I can figure out, this line:
has to use some trickery because it is read before the packages/functions in
proj1are created.symbol-callis in the uiop package, and it is used to specify a function call that is read before the package containing the function definition exists. You specify the package name, the function name, and the args. Insymbol-callabove, the package name is:fiveam, the function name is'#:run!and the arg for the function is whatever is returned by:find-symbol*is a function in theuioppackage which comes withasdfwhich comes withsbcl, which is the lisp implementation I'm using.find-symbol*takes a symbol and a package name as arguments and is used when the package isn't present.The result is, I am specifying a function call something like:
But, instead of dealing with all that crazy syntax, I found I can do this:
test-proj1is this function:which is defined in the package
proj1/tests/main, which is defined in the file.../proj1/test/main.lisp. Then I only needed to export the functiontest-proj1:...proj1/tests/main.lisp:I found nothing about what
test-op (o s)does.Resources:
ASDF manual: test-op
Tutorial: Working with FiveAM