Skip to content

Instantly share code, notes, and snippets.

@dbushenko
Created November 17, 2013 20:46
Show Gist options
  • Save dbushenko/7518070 to your computer and use it in GitHub Desktop.
Save dbushenko/7518070 to your computer and use it in GitHub Desktop.
(defun string/starts-with (s arg)
(cond ((>= (length s) (length arg))
(string-equal (substring s 0 (length arg)) arg))
(t nil)))
(defun chomp (str)
(while (string-match "\\`\n+\\|^\\s-+\\|\\s-+$\\|\n+\\'"
str)
(setq str (replace-match "" t t str)))
str)
;; Scan comments from the current point to the top while it finds
;; lines beginning with ';;#'.
;; Each line with ';;#' -- testcase. Remove the ';;#', split it and
;; save as a list with two values.
;; Results are accumulated in the variable 'tc'.
(defun get-test-cases (tc)
;; 1) Mark whole current line from the beginning to the end.
(beginning-of-line)
(set-mark (point))
(end-of-line)
;; 2) Copy current line text (without text properties).
(let ((line (buffer-substring-no-properties (mark) (point))))
;; 3) If the line starts with ';;#' -- it is a testcase, process it.
(if (string/starts-with line ";;#")
;; 3a) Get the input and output data from the testcase.
(let* ((splitted (split-string line "->"))
(fst (car splitted))
(snd (cadr splitted))
(data (list (chomp (substring fst 3 (length fst)))
(chomp snd))))
;; 3b) Set cursor to the line above.
(previous-line)
;; 3c) Continue searching for testcases.
(get-test-cases (cons data tc)))
;; 4) When no more testcases found -- return the accumulated results.
tc)))
(defun tst-begin (func-name)
(concat ";;vvv " func-name))
(defun tst-end (func-name)
(concat ";;^^^ " func-name))
;; The function finds autogenerated testcase and deletes it.
(defun delete-tests-from-buffer (func-name file-name)
;; 1) Open tests file.
(with-current-buffer (find-file tst-file)
;; 2) Find test for the specified function.
(if (search-forward (tst-begin func-name) (point-max) 't)
;; 3) If the test was found -- find its end and delete the test.
(progn
(previous-line)
(beginning-of-line)
(set-mark (point))
(search-forward (tst-end func-name))
(next-line)
(kill-region (mark) (point))))))
;; The function generates test for the specified function
(defun add-tests-to-buffer (func-name filename testcases)
;; 1) Open tests file.
(with-current-buffer (find-file tst-file)
;; 2) Writ test beginning to the end of the file.
(end-of-buffer)
(newline)
(insert (tst-begin func-name))
(newline)
(insert (concat "(deftest " func-name "-test\n(testing \"Autotest of " func-name "\""))
;; 3) For each testcase add some code to the test function.
(dolist (tst testcases)
(newline)
(insert "(is (= ("func-name " " (car tst) ") " (cadr tst) "))" ))
;; 4) Insert ending of the test function.
(insert "))\n")
(insert (tst-end func-name))
(indent-region 1 (point-max))))
;; Command which generates tests.
(defun generate-test-case ()
(interactive)
(let* ((func-name (read-string "Function: " (thing-at-point 'symbol))) ;; ask function name
(testcases nil)
(file-name (buffer-file-name)) ;; current file name
(root-dir (ede-lein2-project-root)) ;; project directory root
(src-file (substring file-name (+ 4 (length root-dir)) ;; exclude "src/"
(- (length file-name) 4))) ;; exclude ".clj"
(tst-file (concat root-dir "test/" src-file "_test.clj")))
(save-excursion
;; 1) Go to the first comment line.
(previous-line)
;; 2) Search for testcases.
(setq testcases (get-test-cases nil))
;; 3) Delete the test for the current function.
(delete-tests-from-buffer func-name file-name)
;; 4) Generate new test for the current function.
(add-tests-to-buffer func-name file-name testcases))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment