]> git.eshelyaron.com Git - sweep.git/commitdiff
ADDED: PlUnit tests block skeleton and command for inserting it
authorEshel Yaron <me@eshelyaron.com>
Wed, 23 Nov 2022 19:25:39 +0000 (21:25 +0200)
committerEshel Yaron <me@eshelyaron.com>
Wed, 23 Nov 2022 19:25:39 +0000 (21:25 +0200)
* sweeprolog.el (sweeprolog-format-string-as-atom): new function.
(sweeprolog-module-header-skeleton): use define-skeleton, making it a
command instead of a defconst.
(sweeprolog-plunit-testset-skeleton): new skeleton and command.
* sweeprolog-tests: test it.
* README.org ("Writing Tests"): new section.
("Using templates for creating new modules"): rename to "Creating New
Modules".

README.org
sweep.pl
sweeprolog-tests.el
sweeprolog.el

index bc344bbb9a8ca7256d9cdac358359d327762341a..9fdfe56a3327398663effb3e1fc40b36c7ded8e7 100644 (file)
@@ -821,9 +821,9 @@ C-l=).
 More relevant information about loading code in SWI-Prolog can be
 found in [[https://www.swi-prolog.org/pldoc/man?section=consulting][Loading Prolog source files]] in the SWI-Prolog manual.
 
-** Using templates for creating new modules
+** Creating New Modules
 :PROPERTIES:
-:CUSTOM_ID: auto-insert
+:CUSTOM_ID: creating-new-modules
 :DESCRIPTION: Commands for populating new Prolog modules with predefined contents
 :END:
 
@@ -1105,6 +1105,41 @@ Emacs manual]]).
 
 [fn:1] see [[info:elisp#Text Properties][Text Properties in the Elisp manual]]
 
+** Writing Tests
+:PROPERTIES:
+:CUSTOM_ID: writing-tests
+:DESCRIPTION: Commands that facilitate writing Prolog unit tests
+:END:
+
+#+FINDEX: sweeprolog-plunit-testset-skeleton~
+#+CINDEX: plunit
+#+CINDEX: testing
+
+SWI-Prolog includes the =PlUnit= unit testing framework[fn:3], in which
+unit tests are written in special blocks of Prolog code enclosed
+within the directives ~begin_tests/1~ and ~end_tests/1~.  To insert a new
+block of unit tests (also known as a /test-set/) in a Prolog buffer, use
+the command ~M-x sweeprolog-plunit-testset-skeleton~.  This command
+prompts for a name to give the new test-set and inserts a template
+such as the following:
+
+#+begin_src prolog
+:- begin_tests(foo_regression_tests).
+
+test() :- TestBody.
+
+:- end_tests(foo_regression_tests).
+#+end_src
+
+The cursor is left between the parentheses in ~test()~ head term and the
+~TestBody~ variable is marked as a hole (see [[#filling-holes][Filling Holes]]).  To insert
+another unit test, place point after a complete test case and type
+~C-M-m~ or ~M-RET~ to invoke ~sweeprolog-insert-term-dwim~ (see
+[[#insert-term-at-point][Context-Based Term Insertion]]).
+
+[fn:3] See [[https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/plunit.html%27)][Prolog Unit Tests in the SWI-Prolog manual]].
+
+
 * Prolog Help
 :PROPERTIES:
 :CUSTOM_ID: prolog-help
index 3314f570a63f6ded1c1eeda3a0261d0f7ede8aa7..dba4772329d1bd25d15bb00621f49a77ef74da44 100644 (file)
--- a/sweep.pl
+++ b/sweep.pl
@@ -67,7 +67,8 @@
             sweep_context_callable/2,
             sweep_predicate_completion_candidates/2,
             sweep_exportable_predicates/2,
-            sweep_interrupt/0
+            sweep_interrupt/0,
+            sweep_string_to_atom/2
           ]).
 
 :- use_module(library(pldoc)).
@@ -841,3 +842,9 @@ sweep_interrupt :- prolog_interrupt.
 :- else.
 sweep_interrupt :- trace.
 :- endif.
+
+sweep_string_to_atom(String, AtomString) :-
+    atom_string(Atom, String),
+    format(string(AtomString),
+           "~W",
+           [Atom, [quoted(true), character_escapes(true)]]).
index 9953d09a61943991cd6495aa5b047428f533ba0a..db03e459804c14ed49ee5d70b38337ace889e2e9 100644 (file)
@@ -177,6 +177,24 @@ foo(Foo) :- bar.
                    '(sweeprolog-undefined-default-face
                      sweeprolog-body-default-face)))))
 
+(ert-deftest plunit-testset-skeleton ()
+  "Tests inserting PlUnit test-set blocks."
+  (let ((temp (make-temp-file "sweeprolog-test"
+                              nil
+                              "pl"
+                              "")))
+    (find-file-literally temp)
+    (sweeprolog-mode)
+    (sweeprolog-plunit-testset-skeleton "foo")
+    (should (string= (buffer-string)
+                     ":- begin_tests(foo).
+
+test() :- TestBody.
+
+:- end_tests(foo).
+"
+                     ))))
+
 (ert-deftest auto-insert-module-header ()
   "Tests inserting Prolog module header with `auto-insert'."
   (find-file-literally (expand-file-name "sweeprolog_test_auto_insert.pl"
index 490012d6311b2c58ff0a047771e73c4ef2b35bb7..7faf331c57ce48978b6a4a62393439649465d83b 100644 (file)
@@ -427,7 +427,11 @@ non-terminals)."
     [ "Find Prolog predicate"  sweeprolog-find-predicate  t ]
     [ "Export predicate"
       sweeprolog-export-predicate
-      sweeprolog--exportable-predicates ]
+      (and (eq major-mode 'sweeprolog-mode)
+           (sweeprolog-definition-at-point)) ]
+    [ "Insert test-set template"
+      sweeprolog-plunit-testset-skeleton
+      (eq major-mode 'sweeprolog-mode) ]
     [ "Insert module template"
       auto-insert
       (eq major-mode 'sweeprolog-mode) ]
@@ -3494,31 +3498,46 @@ certain contexts to maintain conventional Prolog layout."
     (cursor-sensor-mode 1)))
 
 
-;;;; Auto-insert Prolog module header
-
-(defconst sweeprolog-module-header-skeleton
-  '((or (and (buffer-file-name)
-             (file-name-sans-extension
-              (file-name-base (buffer-file-name))))
-        (read-string "Module name: "))
-    "/*"
-    "\n    Author:        "
-    (progn user-full-name)
-    "\n    Email:         "
-    (progn user-mail-address)
-    (progn sweeprolog-module-header-comment-skeleton)
-    "\n*/"
-    "\n\n:- module("
-    str
-    ", [])."
-    "\n\n/** <module> "
-    -
-    "\n\n*/\n\n")
-  "Prolog module header skeleton inserted by \\[auto-insert].")
+;;;; Skeletons and auto-insert
+
+(defun sweeprolog-format-string-as-atom (string)
+  "Return STRING formatted as a Prolog atom.
+
+Notably, the returned string is quoted if required to make it a
+valid Prolog atom."
+  (sweeprolog--query-once "sweep" "sweep_string_to_atom" string))
+
+(define-skeleton sweeprolog-plunit-testset-skeleton
+  "Insert PlUnit test-set skeleton."
+  (let* ((fn (buffer-file-name))
+         (def (when fn (file-name-base fn))))
+    (sweeprolog-format-string-as-atom
+     (read-string (concat "Test set name"
+                          (when def (concat " (default " def ")"))
+                          ": ")
+                  nil nil def)))
+  ":- begin_tests(" str ").\n\n"
+  "test(" _ ") :- " (sweeprolog--hole "TestBody") ".\n\n"
+  ":- end_tests(" str ").\n")
+
+(define-skeleton sweeprolog-module-header-skeleton
+  "Insert SWI-Prolog module header skeleton."
+  (sweeprolog-format-string-as-atom
+   (or (and (buffer-file-name)
+            (file-name-sans-extension
+             (file-name-base (buffer-file-name))))
+       (read-string "Module name: ")))
+  "/*"
+  "\n    Author:        " (progn user-full-name)
+  "\n    Email:         " (progn user-mail-address)
+  (progn sweeprolog-module-header-comment-skeleton)
+  "\n*/\n\n:- module(" str ", []).\n\n/** <module> "
+  -
+  "\n\n*/\n\n")
 
 (define-auto-insert
   '(sweeprolog-mode . "SWI-Prolog module header")
-  sweeprolog-module-header-skeleton)
+  #'sweeprolog-module-header-skeleton)
 
 
 ;;;; Indentation