A simple example that takes the RT package, which is a rather fragile testing framework, and wraps it inside an ASDF system using the previous ideas I just coded.
This allows declaring the dependency on the given plug-in, using the new class and relying on the fact that the tests will be automagically recorded in the system.
How this works?
- The new test class, specialized for RT, wraps new components which are "actions" before and at the end of any LOAD process. - These actions save and restore the values of the variables in the RT package which are responsible for the tests being run. - When the test system is loaded, RT stores the tests in the variables and the last action saves them all in the ASDF system. - When the test system is first used, the class prepares a new component in the SYSTEM-TESTS fields which is a closure.
The plug-in in asdf-rt.lisp reveals various deficiencies:
- If we want a purely declarative syntax, without side effects, we have to specify symbols in other packages using strings (see the asdf-rt:rt-test-system) clas below. - The parsing of DEFSYSTEM currently can not be customized by the class. - Adding components to a module is not done using SHARED-INITIALIZE and this is bad because, once more, additional classes can not extend or process the list of components.
CL-USER> (asdf:test-system :my-package) [...] ; loading system definition from ; /Users/jjgarcia/devel/asdf/my-package-test.asd into #<PACKAGE "ASDF0"> ; registering #<RT-TEST-SYSTEM :MY-PACKAGE-TEST {1281F7A1}> as ; MY-PACKAGE-TEST Doing 2 pending tests of 2 tests total. Test MY-PACKAGE-TEST::TEST-001 failed Form: (MY-FUNCTION 0) Expected value: 1.0 Actual value: #<UNDEFINED-FUNCTION MY-FUNCTION {120504E9}>. Test MY-PACKAGE-TEST::TEST-002 failed Form: (HANDLER-CASE (AND (MY-FUNCTION 'MY-PACKAGE-TEST::A) NIL) (ERROR (MY-PACKAGE-TEST::C) T)) Expected value: NIL Actual value: T. 2 out of 2 total tests failed: MY-PACKAGE-TEST::TEST-001,
my-package.asd: (defsystem :my-package :components ((:file "my-package")) :tests ((:system :my-package-test)))
my-package.lisp: (in-package :cl-user)
(defun my-function (a) (cos a))
my-package-test.asd: (defsystem :my-package-test :asdf-dependencies (:asdf-rt) :class "ASDF-RT:RT-TEST-SYSTEM" :serial t :components ((:file "my-package-test")))
my-package-test.lisp: (defpackage :my-package-test (:use #+sbcl :sb-rt #+ecl :rt :cl))
(in-package :my-package-test) (deftest test-001 (cl-user::my-function 0) 1.0)
(deftest test-002 (handler-case (and (cl-user::my-function 'a) nil) (error (c) t)) nil)