#+TITLE: Testing pearl #+OPTIONS: toc:2 * Overview pearl uses [[https://github.com/jorgenschaefer/emacs-lisp-mode][ERT]] for tests, [[https://emacs-eask.github.io/][Eask]] to manage the test sandbox and dependencies, and [[https://github.com/undercover-el/undercover.el][undercover]] for coverage reports. A root =Makefile= drives everything and delegates test targets to =tests/Makefile=. * Prerequisites - Emacs 27.1+ - [[https://emacs-eask.github.io/Getting-Started/Install-Eask/][Eask]] on =PATH= (=npm install -g @emacs-eask/cli=, or the standalone installer) * First-time setup #+begin_src shell make setup #+end_src Installs runtime deps (=request=, =dash=, =s=) and development deps (=elisp-lint=, =package-lint=, =undercover=) into a project-local =.eask/= sandbox. ** Note on Eask's global package store Eask keeps a global package store at =~/.eask//elpa/=. When a dependency already sits there at the version the project wants, =eask install-deps= skips installing it into the project sandbox — but =eask emacs= (which runs the tests) only activates the project sandbox, so the dependency ends up "installed" yet unloadable. =make setup= guards against this: after =eask install-deps= it verifies each runtime dep is present in the sandbox and installs any that were skipped. The guard is a no-op where the global store is empty (fresh clones, CI). * Running tests #+begin_src shell make test # all tests, excluding :slow make test-all # all tests, including :slow make test-unit # unit tests only make test-integration # integration tests only make test-file FILE=mapping # one file (fuzzy match on name) make test-one TEST=priority # one test (fuzzy match on name) make test-name TEST='pattern' # tests matching an ERT name pattern #+end_src * Coverage #+begin_src shell make coverage #+end_src Cleans =.elc= files (so undercover can instrument the source), runs every test file in its own Emacs process with =pearl.el= instrumented, and merges per-file results into =.coverage/simplecov.json=. Under CI (=CI=true=) it emits =.coverage/coveralls.json= instead for upload. * Other targets #+begin_src shell make validate # parens-balance check (no deps needed) make compile # byte-compile pearl.el (warnings are errors) make lint # elisp-lint over pearl.el make count # count tests per file make list # list all test names make clean # remove .elc, logs, and .coverage make help # full target list #+end_src =make compile= (warnings as errors), =make lint=, and =eask lint checkdoc= are all clean; keep them that way as part of normal maintenance. * Writing tests - One test file per source function/area: =tests/test-pearl-.el=. - Start each file with =(require 'test-bootstrap (expand-file-name "test-bootstrap.el"))= — it loads the deps and the package source. - Name tests =test-pearl---=. - Cover Normal, Boundary, and Error cases. - Tag slow tests with =:tags '(:slow)= so the default =make test= skips them. - Integration files are named =tests/test-integration-*.el=.