← スキル一覧に戻る

emacs-testing
by jingtaozf
Native Emacs SDK for Claude Code with org-mode as the interactive UI
⭐ 0🍴 0📅 2026年1月24日
SKILL.md
name: emacs-testing description: Test Emacs Lisp code using ERT (Emacs Lisp Regression Testing) - provides patterns for unit tests, integration tests, and test-driven development allowed-tools: [mcp__emacs__evalElisp]
Emacs Lisp Testing Skill
This skill teaches testing patterns for Emacs Lisp using ERT and related tools.
When to Use This Skill
Use when:
- Writing unit tests for elisp functions
- Setting up test suites for packages
- Running tests programmatically
- Mocking/stubbing dependencies
- Testing interactive commands
ERT Basics
Define a Test
(require 'ert)
(ert-deftest my-function-test ()
"Test that my-function works correctly."
(should (equal (my-function 1 2) 3))
(should-not (my-function nil nil))
(should-error (my-function "bad" "args")))
Assertion Macros
;; Basic assertions
(should FORM) ; FORM should be non-nil
(should-not FORM) ; FORM should be nil
(should-error FORM) ; FORM should signal an error
;; Error type checking
(should-error FORM :type 'wrong-type-argument)
;; Custom failure message (via test name/docstring)
(ert-deftest descriptive-test-name ()
"Clear description of what this tests."
(should ...))
Run Tests
;; Run all tests
(ert-run-tests-batch-and-exit)
;; Run specific test
(ert-run-tests-interactively "my-function-test")
;; Run tests matching pattern
(ert-run-tests-batch "^my-package-")
;; Run and get results programmatically
(let ((results (ert-run-tests-batch "^test-")))
(list :passed (ert-stats-completed-expected results)
:failed (ert-stats-completed-unexpected results)
:total (ert-stats-total results)))
Test Organization
Test File Structure
;;; test-my-package.el --- Tests for my-package -*- lexical-binding: t -*-
(require 'ert)
(require 'my-package)
;;; Helper functions
(defun test-helper-setup ()
"Set up test environment."
...)
;;; Unit tests
(ert-deftest test-my-package-basic ()
"Test basic functionality."
...)
(ert-deftest test-my-package-edge-cases ()
"Test edge cases."
...)
;;; Integration tests
(ert-deftest test-my-package-integration ()
"Test component integration."
...)
(provide 'test-my-package)
;;; test-my-package.el ends here
Test Fixtures (Setup/Teardown)
(ert-deftest test-with-temp-buffer ()
"Test using temporary buffer."
(with-temp-buffer
(insert "test content")
(should (equal (buffer-string) "test content"))))
(ert-deftest test-with-temp-file ()
"Test using temporary file."
(let ((temp-file (make-temp-file "test-")))
(unwind-protect
(progn
(with-temp-file temp-file
(insert "test data"))
(should (file-exists-p temp-file)))
(delete-file temp-file))))
Shared Fixtures
(defvar test-fixture nil)
(defun test-setup ()
"Run before each test."
(setq test-fixture (create-test-data)))
(defun test-teardown ()
"Run after each test."
(cleanup-test-data test-fixture)
(setq test-fixture nil))
(ert-deftest test-with-fixture ()
"Test using shared fixture."
(test-setup)
(unwind-protect
(should (valid-fixture-p test-fixture))
(test-teardown)))
Mocking and Stubbing
Using cl-letf for Mocking
(require 'cl-lib)
(ert-deftest test-with-mock ()
"Test with mocked function."
(cl-letf (((symbol-function 'external-api-call)
(lambda (arg) (format "mocked: %s" arg))))
(should (equal (my-function-using-api "test")
"mocked: test"))))
Mock Return Values
(ert-deftest test-mock-return-sequence ()
"Test with sequential return values."
(let ((call-count 0))
(cl-letf (((symbol-function 'get-next-item)
(lambda ()
(cl-incf call-count)
(nth (1- call-count) '("first" "second" "third")))))
(should (equal (get-next-item) "first"))
(should (equal (get-next-item) "second"))
(should (equal (get-next-item) "third")))))
Verify Function Calls
(ert-deftest test-verify-calls ()
"Verify function was called with expected args."
(let ((call-log nil))
(cl-letf (((symbol-function 'tracked-function)
(lambda (&rest args) (push args call-log))))
(my-function-that-calls-tracked)
(should (equal (length call-log) 1))
(should (equal (car call-log) '("expected" "args"))))))
Testing Async Code
Test Timers
(ert-deftest test-timer-callback ()
"Test that timer callback is set up correctly."
(let ((timer (my-function-with-timer)))
(unwind-protect
(progn
(should (timerp timer))
(should (equal (timer--function timer) #'expected-callback)))
(cancel-timer timer))))
Test Process Output
(ert-deftest test-process-filter ()
"Test process filter handles output."
(let ((output-received nil))
(cl-letf (((symbol-function 'handle-output)
(lambda (out) (setq output-received out))))
(my-process-filter nil "test output")
(should (equal output-received "test output")))))
Testing Interactive Commands
Simulate User Input
(ert-deftest test-interactive-command ()
"Test interactive command."
(let ((read-string-result "user input"))
(cl-letf (((symbol-function 'read-string)
(lambda (&rest _) read-string-result)))
(should (equal (call-interactively 'my-command)
"processed: user input")))))
Test Buffer Changes
(ert-deftest test-command-modifies-buffer ()
"Test that command modifies buffer correctly."
(with-temp-buffer
(insert "original")
(goto-char (point-min))
(my-transform-command)
(should (equal (buffer-string) "transformed"))))
Running Tests from MCP
Run All Package Tests
;; Load test file and run
(load-file "/path/to/test-my-package.el")
(let ((ert-quiet t)) ; Suppress interactive output
(ert-run-tests-batch "^test-my-package-"))
Get Test Results as Data
(defun run-tests-get-results (selector)
"Run tests matching SELECTOR and return results."
(let* ((stats (ert-run-tests-batch selector))
(passed (ert-stats-completed-expected stats))
(failed (ert-stats-completed-unexpected stats)))
(list :selector selector
:passed passed
:failed failed
:total (+ passed failed)
:success (= failed 0))))
(run-tests-get-results "^test-claude-")
Run Single Test
(defun run-single-test (test-name)
"Run single test and return result."
(let ((result (ert-run-test (ert-get-test test-name))))
(list :name test-name
:status (ert-test-result-type-p result :passed)
:duration (ert-test-result-duration result))))
Test-Driven Development Pattern
;; 1. Write failing test first
(ert-deftest test-new-feature ()
"Test the new feature."
(should (equal (new-feature "input") "expected")))
;; 2. Run test - should fail
;; (ert-run-tests-interactively "test-new-feature")
;; 3. Implement minimal code to pass
(defun new-feature (input)
"Implement new feature."
"expected")
;; 4. Run test - should pass
;; 5. Refactor if needed, keeping tests passing
Quick Reference
| Task | Code |
|---|---|
| Define test | (ert-deftest name () (should ...)) |
| Run all | (ert-run-tests-batch-and-exit) |
| Run pattern | (ert-run-tests-batch "^prefix-") |
| Assert true | (should FORM) |
| Assert nil | (should-not FORM) |
| Assert error | (should-error FORM) |
| Mock function | (cl-letf (((symbol-function 'f) #'mock)) ...) |
| Temp buffer | (with-temp-buffer ...) |
| Temp file | (make-temp-file "prefix") |
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です