@@ -144,7 +144,8 @@ When non-nil only ‘test_foo()’ will match, and nothing else."
144144 [" Run tests for specific files"
145145 (" f" " Test file (dwim)" python-pytest-file-dwim)
146146 (" F" " Test this file" python-pytest-file)
147- (" m" " Test multiple files" python-pytest-files)]
147+ (" m" " Test multiple files" python-pytest-files)
148+ (" m" " Test multiple directories" python-pytest-directories)]
148149 [" Run tests for current function/class"
149150 (" d" " Test def/class (dwim)" python-pytest-function-dwim)
150151 (" D" " Test this def/class" python-pytest-function)]])
@@ -201,13 +202,30 @@ Additional ARGS are passed along to pytest.
201202With a prefix argument, allow editing."
202203 (interactive
203204 (list
204- (python-pytest--select-test-files)
205+ (python-pytest--select-test-files :type 'file )
205206 (python-pytest-arguments)))
206207 (setq args (-concat args (-map 'python-pytest--shell-quote files )))
207208 (python-pytest--run
208209 :args args
209210 :edit current-prefix-arg))
210211
212+ ;;;### autoload
213+ (defun python-pytest-directories (directories &optional args )
214+ " Run pytest on DIRECTORIES, using ARGS.
215+
216+ When run interactively, this allows for interactive directory selection.
217+
218+ Additional ARGS are passed along to pytest.
219+ With a prefix argument, allow editing."
220+ (interactive
221+ (list
222+ (python-pytest--select-test-files :type 'directory )
223+ (python-pytest-arguments)))
224+ (setq args (-concat args (-map 'python-pytest--shell-quote directories)))
225+ (python-pytest--run
226+ :args args
227+ :edit current-prefix-arg))
228+
211229;;;### autoload
212230(defun python-pytest-function (file func args )
213231 " Run pytest on FILE with FUNC (or class).
@@ -516,30 +534,36 @@ Example: ‘MyABCThingy.__repr__’ becomes ‘test_my_abc_thingy_repr’."
516534 (python-pytest--relative-file-name file)
517535 (python-pytest--find-test-file file)))
518536
519- (cl-defun python-pytest--select-test-files ()
537+ (cl-defun python-pytest--select-test-files (& key type )
520538 " Interactively choose test files."
521539 (cl-block nil
522- (let ((test-files
523- (->> (projectile-project-files (python-pytest--project-root))
524- (-sort 'string< )
525- (projectile-sort-by-recentf-first)
526- (projectile-test-files)))
527- (done-message (propertize " [finish test file selection]" 'face 'success ))
528- (choices)
529- (choice)
530- (selection-active t ))
531- (unless test-files
540+ (let* ((test-files
541+ (->> (projectile-project-files (python-pytest--project-root))
542+ (-sort 'string< )
543+ (projectile-sort-by-recentf-first)
544+ (projectile-test-files)))
545+ (test-directories
546+ (->> test-files
547+ (-map 'file-name-directory )
548+ (-uniq)
549+ (-sort 'string< )))
550+ (candidates (if (eq type 'file ) test-files test-directories))
551+ (done-message (propertize " [finish test file selection]" 'face 'success ))
552+ (choices)
553+ (choice)
554+ (selection-active t ))
555+ (unless candidates
532556 (user-error " No test files found" ))
533- (while (and selection-active test-files )
557+ (while (and selection-active candidates )
534558 (setq choice (completing-read
535559 " Choose test files: "
536- (if choices (cons done-message test-files) test-files )
560+ (if choices (cons done-message candidates) candidates )
537561 nil t ))
538562 (if (s-equals-p choice done-message)
539563 (setq selection-active nil )
540564 (setq
541565 choices (cons choice choices)
542- test-files (-remove-item choice test-files ))))
566+ candidates (-remove-item choice candidates ))))
543567 (cl-return (reverse choices)))))
544568
545569(defun python-pytest--maybe-save-buffers ()
0 commit comments