Reputation: 2701
I'm new to CL and am using AllegroCL. I'm trying to figure out how to organize my source code to meet the following requirements:
I've been trying to creatively use ASDF to meet these requirements, and I can't get it right. How do other people approach this problem? Are these 2 requirements just not "Lispy"?
Upvotes: 8
Views: 1972
Reputation: 3642
The advice above is good, but you will be frustrated trying to test un-exported things. A simple work-around is not to define two packages. Just put your tests in the same package with your other sources. What's the harm?
If you think there will be harm, then you'll have to do it like this:
(defpackage #:sources
(:use #:cl))
(defpackage #:tests
(:use #:cl #:lisp-unit)
(:import-from #:sources))
The important part is to :import-from
your source package instead of :use
ing it.
Then you will have to qualify the symbols in your source package when you use them in your test package. For example, say you have this function:
(defun return-true () t)
Your test might look like:
(define-test test-return-true
"Make sure it works"
(assert-equal t (sources::return-true)))
The important part is your're saying (sources::return-true)
instead of merely (return-true)
. The same goes for symbols like 'sym
; refer to it as 'sources::sym
.
Upvotes: 1
Reputation: 1045
If Quicklisp is installed you can use the built-in feature Quickproject.
(ql:quickload "quickproject")
(quickproject:make-project "~/src/lisp/swatchblade/"
:depends-on '(vecto hunchentoot))
This creates 4 files:
package.lisp defines package namespaces:
(defpackage #:swatchblade
(:use #:cl)
(:shadowing-import-from #:vecto
#:with-canvas
#:rounded-rectangle
#:set-rgb-fill
#:save-png-stream))
swatchblade.asd defines the system/project, source code files, dependencies, etc.
(asdf:defsystem #:swatchblade
:serial t
:depends-on (#:vecto
#:hunchentoot
#:cl-colors)
:components ((:file "package")
(:file "swatchblade")))
swatchblade.lisp is where the source code goes.
You can load the the project via Quicklisp's quickload:
* (ql:quickload "swatchblade")
loading output
* (swatchblade:start-web-server :port 8080)
Server started on port 8080.
If you then create another project that depends on the swatchblade system:
quickproject:make-project "~/src/lisp/whimsytron/"
:depends-on '(swatchblade))
Regarding tests, you can add another namespace in package.lisp for your tests:
(defpackage #:swatchblade-tests
(:use #:cl #:swatchblade))
Create a test file, write the code, and add the file to the system definition:
(asdf:defsystem #:swatchblade
:serial t
:depends-on (#:vecto
#:hunchentoot
#:cl-colors)
:components ((:file "package")
(:file "swatchblade")
(:file "swatchglade-tests")))
Load the swatchblade-tests namespace to run the tests.
Sample project with tests here
If you want to avoid Quicklisp installing all dependencies into the system, you'll have to install the dependencies and load the system manually as far as I know.
The author of Quicklisp, Zach Beane, has a more detailed post on using quickproject.
Upvotes: 5
Reputation: 1014
Per Rainer's suggestion, I propose that you use the ASDF system definition facility to define two systems, your main system, foo, and the ancillary system foo-tests.
In the definition of the foo system, add a specification that in-order-to
do the test-op
on the foo, you need to do the test-op
on foo-tests. This ensures that if you do (asdf:test-system "foo")
, the corresponding test system, with its dependencies, will be loaded, and then ASDF will execute the test-op.
I find that FiveAM is an adequate library for building tests.
The above will get everything loaded, but now you need to make sure that doing the test-op
on foo-tests actually runs the tests! To do that, you need to add a method on PERFORM
for TEST-OP
and (eql (find-system "foo-tests"))
. That PERFORM
method should invoke all the FiveAM tests you have defined, and either succeed, or raise an error if the tests fail.
I have made a FiveAM-tester add-on for ASDF. I will try to see about making it publicly available.
Upvotes: 4
Reputation: 4184
I am using quicklisp which makes a "quicklisp"-folder in your home-folder in which a "local-project" folder can be found. This one contains a txt file in which you can insert the URIs to the .asd files.
How to use that utility:
project.asd (manages the includes for the pure project code)
(asdf:defsystem :project-name
:description "description here"
:version "version here"
:author "your name here"
:depends-on (:a
:list
:of
:dependencie
:libraries)
:components ((:file "sourcefileone")
(:file "sourcefiletwo")))
project-test.asd (manages the includes for the test code)
(asdf:defsystem :project-name-test
:description "testing"
...
:depends-on (:project-name)
:components ((:file "sourcefileone-test")
(:file "sourcefiletwo-test")))
now insert the URIs for those files into the above named local-projects.txt
program parallel the project source in < filename>.lisp files and the test-calls in < filename>-test.lisp files (the *-test.lisp files have to contain a test-execute call)
start your sbcl or whatever you use and then use (ql:quickload "project-name")
or (ql:quickload "project-name-test")
depending if you just want to load a project or test it.
The only thing you have to do porting this anywhere else, is to write the local-projects.txt on the computer the project is copied on. After that your colleges may depend on it using asdf-files and quickload in any other project they want. For copying the project folder you can either use ctr+c/v or maybe something more sophisticated as git.
For testing I programmed my own small test-suite, but I bet there are good ones out there. More information about quicklisp can be found here and about asdf here. Maybe this question can help you if you get stuck configuring quicklisp.
Upvotes: 5
Reputation: 139251
Use ASDF or use the Allegro CL defsystem tool.
Upvotes: 5