+django-tests.el 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. ;;; +django-tests.el -*- lexical-binding: t; -*-
  2. (require 'projectile)
  3. (require 'python)
  4. (require 'subr-x)
  5. (defun django--project-root ()
  6. (or (projectile-project-root)
  7. (user-error "Not in a Projectile project")))
  8. (defun django--module-from-file (file root)
  9. (let* ((rel (file-relative-name file root))
  10. (no-ext (file-name-sans-extension rel)))
  11. (replace-regexp-in-string "/" "." no-ext)))
  12. (defun django--def-name-at-point ()
  13. (save-excursion
  14. (when (ignore-errors (python-nav-beginning-of-defun) t)
  15. (when (looking-at (rx bol (* space) "def" (+ space)
  16. (group (+ (or word ?_))) (* space) "("))
  17. (match-string-no-properties 1)))))
  18. (defun django--enclosing-class-name ()
  19. (save-excursion
  20. (let ((found nil)
  21. (limit (point-min)))
  22. (while (and (not found) (> (point) limit))
  23. (python-nav-beginning-of-statement)
  24. (when (looking-at (rx bol (* space) "class" (+ space)
  25. (group (+ (or word ?_)))))
  26. (setq found (match-string-no-properties 1)))
  27. (condition-case _err
  28. (python-nav-backward-block)
  29. (error (goto-char limit))))
  30. found)))
  31. (defun django--selector-at-point ()
  32. (let ((fn (django--def-name-at-point))
  33. (cls (django--enclosing-class-name)))
  34. (cond
  35. ((and fn (string-prefix-p "test_" fn))
  36. (if cls (format "%s.%s" cls fn) fn))
  37. (cls cls)
  38. (t nil))))
  39. (defun django-run-tests (&optional module selector)
  40. (interactive)
  41. (let* ((module-part (or module ""))
  42. (selector-part (if selector (concat "." selector) ""))
  43. (param (string-trim (concat module-part selector-part)))
  44. (command (format "python manage.py test %s" param)))
  45. (message "Running command: %s" command)
  46. (projectile-run-async-shell-command-in-root command "*Django tests*")))
  47. (defun django-run-test-at-point ()
  48. (interactive)
  49. (let* ((root (django--project-root))
  50. (file (or (buffer-file-name) (user-error "Buffer is not visiting a file")))
  51. (module (django--module-from-file file root))
  52. (sel (django--selector-at-point)))
  53. (django-run-tests module sel)))
  54. (defun django-run-tests-for-current-file ()
  55. (interactive)
  56. (let* ((root (django--project-root))
  57. (file (or (buffer-file-name) (user-error "Buffer is not visiting a file")))
  58. (module (django--module-from-file file root)))
  59. (django-run-tests module nil)))
  60. (provide '+django-tests)