2

I'm using

and following this guide:

One thing I use frequently in python development is elpy's C-c C-t to run a single test at point.

How can I configure this to use lsp-mode instead?

1 Answer 1

2

For my Emacs Python environment, I recently switched from Elpy to lsp-mode too. Mainly to benefit from the dap-mode debugger and a better "Find definition" functionality (able to find a definition in the virtual environement libraries). And also because the great Elpy package is not maintained anymore.

But what I was still missing from Elpy, was the ability to quickly run the tests as @Mittenchops pointed it out.

As I couldn't find any package to easily fix that, I wrote my own Elisp functions : django-run-all-tests, django-run-buffer-tests, and django-run-test-at-point (the last one inspired by the Elpy one).

These work well assuming :

  • it is a Django project (else the test runner command needs to be adapted)
  • tests are in a single directory that have to be configured with django-tests-dir-name variable relatively to the project root ((setq django-tests-dir-name "tests") for example)
  • projectile package is installed (needed to retrieve project root)
;; Copy of elpy-test--current-test-name function from Elpy project
;; https://github.com/jorgenschaefer/elpy
(defun django-get-test-name-at-point ()
  "Return the name of the test at point."
  (let ((name (python-info-current-defun)))
    (if (and name (string-match "\\`\\([^.]+\\.[^.]+\\)\\." name)) (match-string 1 name) name)))

(defun django-get-module ()
  (file-name-sans-extension (buffer-name)))

(defun django-run-tests (&optional module test)
  (let* ((dir-part django-tests-dir-name)
         (module-part (if module (concat "." module) ""))
         (test-part (if test (concat "." test) ""))
         (param (concat dir-part module-part test-part))
         (command (format "./manage.py test %s --keepdb" param)))
    (message command)          
    (projectile-run-async-shell-command-in-root command "*Django tests*")))

(defun django-run-all-tests ()
  "Run all Django api tests."
  (interactive)
  (django-run-tests))

(defun django-run-buffer-tests ()
  "Run Django api tests for current buffer."
  (interactive)
  (let ((module (django-get-module)))
    (django-run-tests module)))

(defun django-run-test-at-point ()
  "Run Django api test at point."
  (interactive)
  (let ((module (django-get-module))
        (test (django-get-test-name-at-point)))
    (django-run-tests module test)))

Put this code in your init.el file. An example using use-package package and adding some key bindings to the Python mode :

(use-package python
  :bind (:map python-mode-map (("C-c t a" . django-run-all-tests)
                               ("C-c t f" . django-run-buffer-tests)
                               ("C-c t p" . django-run-test-at-point)))
  :config
;; Past the functions here
)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.