diff --git a/asdf-rt.asd b/asdf-rt.asd
new file mode 100644
index 0000000..98569ee
--- /dev/null
+++ b/asdf-rt.asd
@@ -0,0 +1,10 @@
+;;; -*- mode: lisp -*-
+;;;
+;;; Free Software available under an MIT-style license.
+;;;
+;;; Copyright (c) 2010 Juan Jose Garcia-Ripoll
+;;;
+
+(defsystem :asdf-rt
+    :depends-on (#+sbcl :sb-rt #+ecl :rt)
+    :components ((:file "asdf-rt")))
diff --git a/asdf-rt.lisp b/asdf-rt.lisp
new file mode 100644
index 0000000..1f23371
--- /dev/null
+++ b/asdf-rt.lisp
@@ -0,0 +1,120 @@
+;;; -*- mode: lisp -*-
+;;;
+;;; Free Software available under an MIT-style license.
+;;;
+;;; Copyright (c) 2010 Juan Jose Garcia-Ripoll
+;;;
+
+(defpackage "ASDF-RT"
+  (:use "ASDF" "CL")
+  (:export #:rt-test-system))
+
+(in-package "ASDF-RT")
+
+;;----------------------------------------------------------------------
+;; action class (components that do things)
+
+(defclass action-component (component)
+  ((forcedp :initform nil :initarg :forced :accessor action-component-forcedp)
+   (form :initform nil :initarg :form :accessor action-component-form)
+   (closure :initform nil :accessor action-component-closure)))
+
+(defmethod shared-initialize :after ((c action-component) slot-names
+                                     &key forms
+                                     &allow-other-keys)
+  (setf (action-component-closure c)
+        (coerce `(lambda () ,forms) 'function)))
+
+(defmethod perform ((o load-op) (c action-component))
+  (funcall (action-component-closure c)))
+
+(defmethod perform ((o test-op) (c action-component))
+  (funcall (action-component-closure c)))
+
+(defmethod operation-done-p ((o operation) (c action-component))
+  (if (action-component-forcedp c)
+      nil
+      (call-next-method)))
+
+;;----------------------------------------------------------------------
+;; rt-test-system class for driving RT
+
+(defclass rt-test-system (system)
+  ((pre-action :initform nil :accessor rt-test-system-pre-action)
+   (post-action :initform nil :accessor rt-test-system-post-action)
+   (variables :initform nil :accessor rt-test-system-variables)))
+
+(defparameter +rt-package-name+ #+sbcl "SB-RT" #+ecl "RT")
+
+(defparameter +rt-to-be-saved-variables+
+  (copy-tree '(("*TEST*" . NIL)
+	       ("*DO-TESTS-WHEN-DEFINED*" . NIL)
+	       ("*ENTRIES*" . (list NIL))
+	       ("*IN-TEST*" . NIL)
+	       ("*DEBUG*" . NIL)
+	       ("*CATCH-ERRORS*" . T)
+	       ("*PRINT-CIRCLE-ON-FAILURE*" . NIL)
+	       ("*COMPILE-TESTS*" . NIL)
+	       ("*OPTIMIZATION-SETTINGS*" . NIL)
+	       ("*EXPECTED-FAILURES*" . NIL))))
+
+(defun save-variables (package-designator names)
+  (let ((package (find-package package-designator)))
+    (if package
+        (loop for (name . default-value) in names
+           for symbol = (find-symbol name package)
+           collect (symbol-value symbol))
+        (mapcar #'cdr +rt-to-be-saved-variables+))))
+
+(defun restore-variables (package-designator names values &optional (failure-p t))
+  (let ((package (find-package package-designator)))
+    (cond (package
+	   (loop for (name . default-value) in names
+              for value in values
+              for symbol = (find-symbol name package)
+              do (setf (symbol-value symbol) value)))
+	  (failure-p
+	   (error "Unable to find package ~A" package-designator)))))
+
+(defun save-rt-variables (module)
+  (setf (rt-test-system-variables module)
+        (save-variables +rt-package-name+
+                        +rt-to-be-saved-variables+)))
+
+(defun restore-rt-variables (module)
+  (restore-variables +rt-package-name+
+                     +rt-to-be-saved-variables+
+                     (rt-test-system-variables module)))
+
+(defun ensure-rt-test-actions (m)
+  (unless (rt-test-system-pre-action m)
+    (let* ((pre-action (make-instance 'action-component
+                                      :name "rt-test-pre"
+                                      :form `(save-rt-variables ,m)))
+           (ordinary-components (slot-value m 'asdf::components))
+           (dependencies (list* pre-action ordinary-components))
+           (post-action (make-instance 'action-component
+                                       :name "rt-test-post"
+                                       :load-dependencies dependencies
+                                       :form `(restore-rt-variables ,m))))
+      (setf (rt-test-system-pre-action m) pre-action
+            (rt-test-system-post-action m) post-action
+            (module-components m) (append dependencies (list post-action)))
+      (asdf::compute-module-components-by-name m))))
+
+(defmethod asdf::module-components :before ((m rt-test-system))
+  (ensure-rt-test-actions m))
+
+(defmethod asdf::module-components-by-name :before ((m rt-test-system))
+  (ensure-rt-test-actions m))
+
+(defmethod asdf::system-tests :around ((m rt-test-system))
+  (append (call-next-method)
+          (list #'(lambda ()
+                    (unwind-protect
+                         (progn
+                           (restore-rt-variables m)
+                           (funcall (intern "DO-TESTS"
+                                            (find-package +rt-package-name+))))
+                      (save-rt-variables m))))))
+
diff --git a/asdf.lisp b/asdf.lisp
index e1c5621..ada76aa 100644
--- a/asdf.lisp
+++ b/asdf.lisp
@@ -228,6 +228,7 @@
            #:system-source-file
            #:system-source-directory
            #:system-relative-pathname
+           #:system-tests
            #:map-systems
 
            #:operation-on-warnings
@@ -928,6 +929,7 @@ actually-existing directory."
    (maintainer :accessor system-maintainer :initarg :maintainer)
    (licence :accessor system-licence :initarg :licence
             :accessor system-license :initarg :license)
+   (tests :accessor system-tests :initarg :tests :initform nil)
    (source-file :reader system-source-file :initarg :source-file
                 :writer %set-system-source-file)))
 
@@ -1745,10 +1747,42 @@ recursive calls to traverse.")
 (defmethod perform ((operation test-op) (c component))
   nil)
 
+(defun parse-symbol-name (s-designator)
+  (if (symbolp s-designator)
+      s-designator
+      (handler-case
+          (with-standard-io-syntax
+            (read-from-string (string s-designator)))
+        (error (c) (sysdef-error "~@<invalid symbol designator ~A~@:>"
+                                 s-designator)))))
+
+(defun test-system-designator (c)
+  (and (consp c)
+       (string-equal (first c) "system")
+       (= (length c) 2)
+       (second c)))
+
+(defmethod perform ((o test-op) (c system))
+  (loop for item in (system-tests c)
+     do (cond ((typep item 'string)
+               (funcall (parse-symbol-name item)))
+              ((typep item '(or symbol function))
+               (funcall item))
+              ((test-system-designator item))
+              (t (sysdef-error "~@<invalid argument to a system :tests ~A~@:>"
+                               item)))))
+
 (defmethod operation-done-p ((operation test-op) (c system))
   "Testing a system is _never_ done."
   nil)
 
+(defmethod component-depends-on ((o test-op) (c system))
+  (let ((tests (system-tests c)))
+    (loop for item in tests
+       when (and (consp item)
+                 (string-equal (first item) "system"))
+       collect `(test-op ,(second item)))))
+
 (defmethod component-depends-on :around ((o test-op) (c system))
   (cons `(load-op ,(component-name c)) (call-next-method)))
 
@@ -1869,9 +1903,14 @@ details."
 
 (defmacro defsystem (name &body options)
   (destructuring-bind (&key (pathname nil pathname-arg-p) (class 'system)
-                            &allow-other-keys)
+                            asdf-dependencies &allow-other-keys)
       options
-    (let ((component-options (remove-keyword :class options)))
+    (let ((component-options (remove-keys '(:asdf-dependencies :class) options)))
+      ;; First load the possible dependencies
+      (mapc #'load-system asdf-dependencies)
+      ;; Now look for the class name, which might be a string including
+      ;; a package prefix.
+      (setf class (parse-symbol-name class))
       `(progn
          ;; system must be registered before we parse the body, otherwise
          ;; we recur when trying to find an existing system of the same name
