emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/buttercup 0e40587 231/340: Tweak the spy-contexts to be mo


From: ELPA Syncer
Subject: [nongnu] elpa/buttercup 0e40587 231/340: Tweak the spy-contexts to be more backward compatible
Date: Thu, 16 Dec 2021 14:59:40 -0500 (EST)

branch: elpa/buttercup
commit 0e4058708e09c762f0003b8244197ccd91a017fe
Author: Ola Nilsson <ola.nilsson@gmail.com>
Commit: Ola Nilsson <ola.nilsson@gmail.com>

    Tweak the spy-contexts to be more backward compatible
    
    Replace the spy-context constructor with a function to construct both
    spy-context-return and spy-context-thrown objects while keeping the
    semantics of the pre-struct-split make-spy-context function.
    
    Make the accessor functions of spy-context-return and
    spy-context-thrown internal and define new accessors that signal
    errors with better user messages.
    
    Rewrite some spy-context documentation in writing-tests.md
    
    Fixes #139.
---
 buttercup.el          | 58 ++++++++++++++++++++++++++++++++++++++++-----------
 docs/writing-tests.md | 50 +++++++++++++++++++++++++-------------------
 2 files changed, 75 insertions(+), 33 deletions(-)

diff --git a/buttercup.el b/buttercup.el
index 2bed332..c3465ab 100644
--- a/buttercup.el
+++ b/buttercup.el
@@ -1022,16 +1022,50 @@ DESCRIPTION has the same meaning as in `xit'. FUNCTION 
is ignored."
                                                  :weakness 'key)
   "A mapping of currently-defined spies to their contexts.")
 
-(cl-defstruct spy-context
+;; The base struct has no constructor so a factory function
+;; `make-spy-context' masquerading as a constructor can be defined
+;; later.
+(cl-defstruct (spy-context (:constructor nil))
   args current-buffer)
-;; The struct and slot names are kind of a cheat so that the accessor
-;; function names remain unchanged: `spy-context-return-value' and
-;; `spy-context-thrown-signal'.
-(cl-defstruct (spy-context-return (:include spy-context))
+(cl-defstruct (spy-context-return (:include spy-context)
+                                  (:conc-name spy-context--return-))
   value)
-(cl-defstruct (spy-context-thrown (:include spy-context))
+(cl-defstruct (spy-context-thrown (:include spy-context)
+                                  (:conc-name spy-context--thrown-))
   signal)
 
+(cl-defun make-spy-context (&key args current-buffer
+                                 (return-value nil has-return-value)
+                                 (thrown-signal nil has-thrown-signal))
+  "Constructor for objects of type spy-context.
+ARGS is the argument list of the called function.
+CURRENT-BUFFER is the buffer that was current when the spy was called.
+RETURN-VALUE is the returned value, if any.
+THROWN-SIGNAL is the signal raised by the function, if any.
+Only one of RETURN-VALUE and THROWN-SIGNAL may be given. Giving
+none of them is equivalent to `:return-value nil'."
+  (cond
+   ((and has-return-value has-thrown-signal)
+    (error "Only one of :return-value and :thrown-signal may be given"))
+   (has-thrown-signal (make-spy-context-thrown :args args
+                                               :current-buffer current-buffer
+                                               :signal thrown-signal))
+   (t (make-spy-context-return :args args
+                               :current-buffer current-buffer
+                               :value return-value))))
+
+(defun spy-context-return-value (context)
+  "Access slot \"return-value\" of `spy-context' struct CONTEXT."
+  (unless (spy-context-return-p context)
+    (error "Not a returning context"))
+  (spy-context--return-value context))
+
+(defun spy-context-thrown-signal (context)
+  "Access slot \"thrown-signal\" of `spy-context' struct CONTEXT."
+  (unless (spy-context-thrown-p context)
+    (error "Not a signal-raising context"))
+  (spy-context--thrown-signal context))
+
 (defun spy-on (symbol &optional keyword arg)
   "Create a spy (mock) for the function SYMBOL.
 
@@ -1122,9 +1156,9 @@ responsibility to ensure ARG is a command."
                      returned t)
                (buttercup--spy-calls-add
                 this-spy-function
-                (make-spy-context-return :args args
-                                         :value return-value
-                                         :current-buffer (current-buffer)))
+                (make-spy-context :args args
+                                  :return-value return-value
+                                  :current-buffer (current-buffer)))
                return-value)
            (error
             ;; If returned is non-nil, then the error we caught
@@ -1132,9 +1166,9 @@ responsibility to ensure ARG is a command."
             (unless returned
               (buttercup--spy-calls-add
                this-spy-function
-               (make-spy-context-thrown :args args
-                                        :signal err
-                                        :current-buffer (current-buffer))))
+               (make-spy-context :args args
+                                 :thrown-signal err
+                                 :current-buffer (current-buffer))))
             ;; Regardless, we only caught this error in order to
             ;; record it, so we need to re-throw it.
             (signal (car err) (cdr err)))))))
diff --git a/docs/writing-tests.md b/docs/writing-tests.md
index 94d9129..9d6cc54 100644
--- a/docs/writing-tests.md
+++ b/docs/writing-tests.md
@@ -532,17 +532,17 @@ and then `t` once at least one call happens. 
`spy-calls-count` returns
 the number of times the spy was called. `spy-calls-args-for` returns
 the arguments passed to a given call (by index). `spy-calls-all-args`
 returns the arguments to all calls. `spy-calls-all` returns the
-current buffer and arguments passed to all calls.
-`spy-calls-most-recent` returns the current buffer and arguments for
-the most recent call. `spy-calls-first` returns the current buffer and
-arguments for the first call.
-
-Each spy context is a struct with 3 slots. A successful function call
-is represented by a `spy-context-return` struct with slots `args`,
-`current-buffer`, and `value`. A function call the signalled an error
-is represented by a `spy-context-thrown` struct with slots `args`,
-`current-buffer`, and `signal`. See the examples below for accessing
-these slots.
+context (current buffer, arguments passed and return status) of all
+calls.  `spy-calls-most-recent` returns the context of the most recent
+call. `spy-calls-first` returns the context for the first call.
+
+Contexts are represented by instances of the `spy-context` struct with
+the slots `args`, `current-buffer`, `return-value` and
+`thrown-signal`. The `return-value` and `thrown-signal` slots
+represent the return status. Calling `spy-context-return-value` for a
+context representing a raised signal (or vice versa) will raise an
+error. Test the context type with `spy-context-return-p` and
+`spy-context-thrown-p`.
 
 Finally, `spy-calls-reset` clears all tracking for a spy.
 
@@ -603,9 +603,8 @@ Finally, `spy-calls-reset` clears all tracking for a spy.
 
     (expect (spy-calls-all 'set-foo)
             :to-equal
-            `(,(make-spy-context-return :current-buffer (current-buffer)
-                                        :args '(123)
-                                        :value nil))))
+            `(,(make-spy-context :current-buffer (current-buffer)
+                                 :args '(123)))))
 
   (it "has a shortcut to the most recent call"
     (set-foo 123)
@@ -613,9 +612,8 @@ Finally, `spy-calls-reset` clears all tracking for a spy.
 
     (expect (spy-calls-most-recent 'set-foo)
             :to-equal
-            (make-spy-context-return :current-buffer (current-buffer)
-                                     :args '(456 "baz")
-                                     :value nil)))
+            (make-spy-context :current-buffer (current-buffer)
+                              :args '(456 "baz"))))
 
   (it "has a shortcut to the first call"
     (set-foo 123)
@@ -623,9 +621,8 @@ Finally, `spy-calls-reset` clears all tracking for a spy.
 
     (expect (spy-calls-first 'set-foo)
             :to-equal
-            (make-spy-context-return :current-buffer (current-buffer)
-                                     :args '(123)
-                                     :value nil)))
+            (make-spy-context :current-buffer (current-buffer)
+                              :args '(123))))
 
   (it "tracks the return values and error signals of each call"
     ;; Set up `set-foo' so that it can either return a value or throw
@@ -658,7 +655,18 @@ Finally, `spy-calls-reset` clears all tracking for a spy.
     (expect
      (spy-context-return-value
       (spy-calls-most-recent 'set-foo))
-     :to-throw))
+     :to-throw)
+    ;; Use :return-value and :thrown-signal to create matching spy-contexts
+    (expect
+     (spy-calls-all 'set-foo)
+      :to-equal
+      (list
+       (make-spy-context :args '(1)
+                         :current-buffer (current-buffer)
+                         :return-value 1)
+       (make-spy-context :args '(-1)
+                         :current-buffer (current-buffer)
+                         :thrown-signal '(error "Value must not be 
negative")))))
 
   (it "counts the number of successful and failed calls"
     ;; Set up `set-foo' so that it can either return a value or throw



reply via email to

[Prev in Thread] Current Thread [Next in Thread]