/ emacs.d / rails / rails-test.el
rails-test.el
  1  ;;; rails-test.el --- tests integration with the compile library
  2  
  3  ;; Copyright (C) 2006 Dmitry Galinsky <dima dot exe at gmail dot com>
  4  
  5  ;; Authors: Dmitry Galinsky <dima dot exe at gmail dot com>,
  6  
  7  ;; Keywords: ruby rails languages oop
  8  ;; $URL: svn+ssh://rubyforge/var/svn/emacs-rails/trunk/rails-ws.el $
  9  ;; $Id: rails-ws.el 140 2007-03-27 23:33:36Z dimaexe $
 10  
 11  ;;; License
 12  
 13  ;; This program is free software; you can redistribute it and/or
 14  ;; modify it under the terms of the GNU General Public License
 15  ;; as published by the Free Software Foundation; either version 2
 16  ;; of the License, or (at your option) any later version.
 17  
 18  ;; This program is distributed in the hope that it will be useful,
 19  ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 20  ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21  ;; GNU General Public License for more details.
 22  
 23  ;; You should have received a copy of the GNU General Public License
 24  ;; along with this program; if not, write to the Free Software
 25  ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 26  
 27  ;;; Code:
 28  
 29  (defvar rails-test:history nil)
 30  
 31  (defconst rails-test:result-regexp
 32    "\\([0-9]+ tests, [0-9]+ assertions, \\([0-9]+\\) failures, \\([0-9]+\\) errors\\)")
 33  
 34  (defconst rails-test:progress-regexp
 35    "^[\\.EF]+$")
 36  
 37  (defun rails-test:file-ext-regexp ()
 38    (let ((rails-templates-list (append rails-templates-list (list "rb"))))
 39      (substring (rails-core:regex-for-match-view) 0 -1)))
 40  
 41  (defun rails-test:line-regexp (&optional append prepend)
 42    (concat
 43     append
 44     (format
 45      "\\(#{RAILS_ROOT}\/\\)?\\(\\(\\.\\|[A-Za-z]:\\)?\\([a-z/_.]+%s\\)\\):\\([0-9]+\\)"
 46      (rails-test:file-ext-regexp))
 47     prepend))
 48  
 49  (defun rails-test:error-regexp-alist ()
 50    (list
 51     (list 'rails-test-trace
 52           (rails-test:line-regexp) 2 6 nil 0)
 53     (list 'rails-test-failure
 54           (rails-test:line-regexp "\\[" "\\]") 2 6 nil 2)
 55     (list 'rails-test-error
 56           (rails-test:line-regexp nil ".*\n$") 2 6 nil 2)))
 57  
 58  (defun rails-test:print-result ()
 59    (with-current-buffer (get-buffer rails-script:buffer-name)
 60      (let ((msg (list))
 61            (failures 0)
 62            (errors 0))
 63        (save-excursion
 64          (goto-char (point-min))
 65          (while (re-search-forward rails-test:result-regexp (point-max) t)
 66            (setq failures (+ failures (string-to-number (match-string-no-properties 2))))
 67            (setq errors (+ errors (string-to-number (match-string-no-properties 3))))
 68            (add-to-list 'msg (match-string-no-properties 1))))
 69        (unless (zerop (length msg))
 70          (message (strings-join " || " (reverse msg))))
 71        (when (and (or (not (zerop rails-script:output-mode-ret-value))
 72                       (not (zerop errors))
 73                       (not (zerop failures)))
 74                   (not (buffer-visible-p (current-buffer))))
 75          (rails-script:popup-buffer)))))
 76  
 77  (defun rails-test:print-progress (start end len)
 78    (let (content)
 79      (save-excursion
 80        (goto-char (point-min))
 81        (while (re-search-forward "^Started" end t)
 82          (line-move 1)
 83          (save-match-data
 84            (let ((progress (string=~ rails-test:progress-regexp
 85                                      (current-line-string) $m)))
 86              (when progress
 87                (setq content (concat content progress)))))))
 88      (when content
 89        (message "Progress of %s: %s" rails-script:running-script-name content))))
 90  
 91  (define-derived-mode rails-test:compilation-mode compilation-mode "RTest"
 92    "Major mode for RoR tests."
 93    (rails-script:setup-output-buffer)
 94    (set (make-local-variable 'compilation-error-regexp-alist-alist)
 95         (rails-test:error-regexp-alist))
 96    (set (make-local-variable 'compilation-error-regexp-alist)
 97         '(rails-test-error
 98           rails-test-failure
 99           rails-test-trace))
100    (add-hook 'after-change-functions 'rails-test:print-progress nil t)
101    (add-hook 'rails-script:run-after-stop-hook 'rails-test:print-result nil t)
102    (add-hook 'rails-script:show-buffer-hook
103              #'(lambda()
104                  (let ((win (get-buffer-window (current-buffer))))
105                    (when (window-live-p win)
106                      (set-window-point win 0)
107                      (unless (buffer-visible-p (current-buffer))
108                        (compilation-set-window-height win)))))
109              t t))
110  
111  (defun rails-test:list-of-tasks ()
112    "Return a list contains test tasks."
113    (append (list "all")
114            (delete* nil
115                     (mapcar
116                      #'(lambda (task) (string=~ "^test\\:\\([^ ]+\\)" task $1))
117                      (rails-rake:list-of-tasks))
118                     :if 'null)))
119  
120  (defun rails-test:run (task)
121    "Run rake tests in RAILS_ROOT."
122    (interactive (rails-completing-read "What test run"
123                                        (rails-test:list-of-tasks)
124                                        'rails-test:history t))
125    (unless task
126      (setq task "all")
127      (add-to-list rails-test:history task))
128    (let ((task-name
129           (if (string= "all" task)
130               "test"
131             (concat "test:" task))))
132      (rails-rake:task task-name 'rails-test:compilation-mode)))
133  
134  (defun rails-test:run-single-file (file &optional param)
135    "Run test for single file FILE."
136    (let ((param (if param (append (list file) (list param))
137                   (list file))))
138      (rails-script:run "ruby" param 'rails-test:compilation-mode)))
139  
140  (defun rails-test:run-current ()
141    "Run a test for the current controller/model/mailer."
142    (interactive)
143    (let* ((model (rails-core:current-model))
144           (controller (rails-core:current-controller))
145           (func-test (rails-core:functional-test-file controller))
146           (unit-test (rails-core:unit-test-file model))
147           (mailer-test (rails-core:unit-test-file controller)))
148      (rails-test:run-single-file
149       (cond
150        ;; model
151        ((and model unit-test) unit-test)
152        ;; controller
153        ((and controller (not (rails-core:mailer-p controller)) func-test)
154         func-test)
155       ;; mailer
156       ((and controller (rails-core:mailer-p controller) unit-test)
157        unit-test)))))
158  
159  (defun rails-test:run-current-method ()
160    "Run a test for the current method."
161    (interactive)
162    (let ((file (substring (buffer-file-name) (length (rails-project:root))))
163          (method (rails-core:current-method-name)))
164      (when method
165        (rails-test:run-single-file file (format "--name=%s" method)))))
166  
167  (provide 'rails-test)