|
|
@@ -0,0 +1,70 @@
|
|
|
+;;; +django-tests.el -*- lexical-binding: t; -*-
|
|
|
+
|
|
|
+(require 'projectile)
|
|
|
+(require 'python)
|
|
|
+(require 'subr-x)
|
|
|
+
|
|
|
+(defun django--project-root ()
|
|
|
+ (or (projectile-project-root)
|
|
|
+ (user-error "Not in a Projectile project")))
|
|
|
+
|
|
|
+(defun django--module-from-file (file root)
|
|
|
+ (let* ((rel (file-relative-name file root))
|
|
|
+ (no-ext (file-name-sans-extension rel)))
|
|
|
+ (replace-regexp-in-string "/" "." no-ext)))
|
|
|
+
|
|
|
+(defun django--def-name-at-point ()
|
|
|
+ (save-excursion
|
|
|
+ (when (ignore-errors (python-nav-beginning-of-defun) t)
|
|
|
+ (when (looking-at (rx bol (* space) "def" (+ space)
|
|
|
+ (group (+ (or word ?_))) (* space) "("))
|
|
|
+ (match-string-no-properties 1)))))
|
|
|
+
|
|
|
+(defun django--enclosing-class-name ()
|
|
|
+ (save-excursion
|
|
|
+ (let ((found nil)
|
|
|
+ (limit (point-min)))
|
|
|
+ (while (and (not found) (> (point) limit))
|
|
|
+ (python-nav-beginning-of-statement)
|
|
|
+ (when (looking-at (rx bol (* space) "class" (+ space)
|
|
|
+ (group (+ (or word ?_)))))
|
|
|
+ (setq found (match-string-no-properties 1)))
|
|
|
+ (condition-case _err
|
|
|
+ (python-nav-backward-block)
|
|
|
+ (error (goto-char limit))))
|
|
|
+ found)))
|
|
|
+
|
|
|
+(defun django--selector-at-point ()
|
|
|
+ (let ((fn (django--def-name-at-point))
|
|
|
+ (cls (django--enclosing-class-name)))
|
|
|
+ (cond
|
|
|
+ ((and fn (string-prefix-p "test_" fn))
|
|
|
+ (if cls (format "%s.%s" cls fn) fn))
|
|
|
+ (cls cls)
|
|
|
+ (t nil))))
|
|
|
+
|
|
|
+(defun django-run-tests (&optional module selector)
|
|
|
+ (interactive)
|
|
|
+ (let* ((module-part (or module ""))
|
|
|
+ (selector-part (if selector (concat "." selector) ""))
|
|
|
+ (param (string-trim (concat module-part selector-part)))
|
|
|
+ (command (format "python manage.py test %s" param)))
|
|
|
+ (message "Running command: %s" command)
|
|
|
+ (projectile-run-async-shell-command-in-root command "*Django tests*")))
|
|
|
+
|
|
|
+(defun django-run-test-at-point ()
|
|
|
+ (interactive)
|
|
|
+ (let* ((root (django--project-root))
|
|
|
+ (file (or (buffer-file-name) (user-error "Buffer is not visiting a file")))
|
|
|
+ (module (django--module-from-file file root))
|
|
|
+ (sel (django--selector-at-point)))
|
|
|
+ (django-run-tests module sel)))
|
|
|
+
|
|
|
+(defun django-run-tests-for-current-file ()
|
|
|
+ (interactive)
|
|
|
+ (let* ((root (django--project-root))
|
|
|
+ (file (or (buffer-file-name) (user-error "Buffer is not visiting a file")))
|
|
|
+ (module (django--module-from-file file root)))
|
|
|
+ (django-run-tests module nil)))
|
|
|
+
|
|
|
+(provide '+django-tests)
|