Commit b8882830 authored by Sean Whitton's avatar Sean Whitton

Merge tag 'v1.14'

parents 24cc827a a394fea9
[bumpversion]
current_version = 1.13
current_version = 1.14
parse = (?P<major>\d+)\.(?P<minor>.*)
serialize = {major}.{minor}
files = buttercup.el buttercup-pkg.el
......
......@@ -91,5 +91,24 @@ If INCLUDE-DIRECTORIES, also include directories that have matching names."
(and (> (length name) 0)
(char-equal (aref name (1- (length name))) ?/))))
(when (not (fboundp 'seconds-to-string))
(defvar seconds-to-string
(list (list 1 "ms" 0.001)
(list 100 "s" 1)
(list (* 60 100) "m" 60.0)
(list (* 3600 30) "h" 3600.0)
(list (* 3600 24 400) "d" (* 3600.0 24.0))
(list nil "y" (* 365.25 24 3600)))
"Formatting used by the function `seconds-to-string'.")
(defun seconds-to-string (delay)
"Convert the time interval in seconds to a short string."
(cond ((> 0 delay) (concat "-" (seconds-to-string (- delay))))
((= 0 delay) "0s")
(t (let ((sts seconds-to-string) here)
(while (and (car (setq here (pop sts)))
(<= (car here) delay)))
(concat (format "%.2f" (/ delay (car (cddr here)))) (cadr here)))))))
(provide 'buttercup-compat)
;;; buttercup-compat.el ends here
(define-package "buttercup" "1.13"
(define-package "buttercup" "1.14"
"Behavior-Driven Emacs Lisp Testing")
......@@ -2,7 +2,7 @@
;; Copyright (C) 2015-2017 Jorgen Schaefer <contact@jorgenschaefer.de>
;; Version: 1.13
;; Version: 1.14
;; Author: Jorgen Schaefer <contact@jorgenschaefer.de>
;; Package-Requires: ((emacs "24.3"))
;; URL: https://github.com/jorgenschaefer/emacs-buttercup
......@@ -670,7 +670,8 @@ See also `buttercup-define-matcher'."
(status 'passed)
failure-description
failure-stack
)
time-started
time-ended)
(cl-defstruct (buttercup-suite (:include buttercup-suite-or-spec))
;; Any children of this suite, both suites and specs
......@@ -771,6 +772,21 @@ See also `buttercup-define-matcher'."
(push name duplicates)
(push name seen)))))
(defun buttercup--set-start-time (suite-or-spec)
"Set time-started of SUITE-OR-SPEC to `current-time'."
(setf (buttercup-suite-or-spec-time-started suite-or-spec) (current-time)))
(defun buttercup--set-end-time (suite-or-spec)
"Set time-ended of SUITE-OR-SPEC to `current-time'."
(setf (buttercup-suite-or-spec-time-ended suite-or-spec) (current-time)))
(defun buttercup-elapsed-time (suite-or-spec)
"Get elapsed time of SUITE-OR-SPEC."
;; time-subtract does not handle nil arguments until Emacs 25.1
(time-subtract
(or (buttercup-suite-or-spec-time-ended suite-or-spec) (current-time))
(or (buttercup-suite-or-spec-time-started suite-or-spec) (current-time))))
;;;;;;;;;;;;;;;;;;;;
;;; Suites: describe
......@@ -919,7 +935,7 @@ FUNCTION is a function containing the body instructions passed to
"Process FORMS to make any suites or specs pending."
(when (eq (car forms) :var)
(setq forms (cddr forms)))
(let (retained inner)
(let (retained)
(dolist (form forms (nreverse retained))
(pcase form
;; Make it pending by just keeping the description
......@@ -1349,6 +1365,7 @@ Do not change the global value.")
(defun buttercup--run-suite (suite)
"Run SUITE. A suite is a sequence of suites and specs."
(buttercup--set-start-time suite)
(let* ((buttercup--before-each (append buttercup--before-each
(buttercup-suite-before-each suite)))
(buttercup--after-each (append (buttercup-suite-after-each suite)
......@@ -1364,9 +1381,11 @@ Do not change the global value.")
(buttercup--run-spec sub))))
(dolist (f (buttercup-suite-after-all suite))
(buttercup--update-with-funcall suite f))
(buttercup--set-end-time suite)
(funcall buttercup-reporter 'suite-done suite)))
(defun buttercup--run-spec (spec)
(buttercup--set-start-time spec)
(unwind-protect
(progn
;; Kill any previous warning buffer, just in case
......@@ -1391,9 +1410,13 @@ Do not change the global value.")
(buffer-string)
'yellow)))))
(when (get-buffer buttercup-warning-buffer-name)
(kill-buffer buttercup-warning-buffer-name))))
(kill-buffer buttercup-warning-buffer-name))
(buttercup--set-end-time spec)))
(defun buttercup--update-with-funcall (suite-or-spec function &rest args)
"Update SUITE-OR-SPEC with the result of calling FUNCTION with ARGS.
Sets the `status', `failure-description', and `failure-stack' for
failed and pending specs."
(let* ((result (apply 'buttercup--funcall function args))
(status (elt result 0))
(description (elt result 1))
......@@ -1405,8 +1428,8 @@ Do not change the global value.")
(`(error (buttercup-pending . ,pending-description))
(setq status 'pending
description pending-description))))
(when (eq (buttercup-suite-or-spec-status suite-or-spec)
'passed)
(when (memq (buttercup-suite-or-spec-status suite-or-spec)
'(passed pending))
(setf (buttercup-suite-or-spec-status suite-or-spec) status
(buttercup-suite-or-spec-failure-description suite-or-spec) description
(buttercup-suite-or-spec-failure-stack suite-or-spec) stack))))
......@@ -1465,17 +1488,19 @@ EVENT and ARG are described in `buttercup-reporter'."
(`spec-done
(cond
((eq (buttercup-spec-status arg) 'passed)
(buttercup--print "\n"))
((eq (buttercup-spec-status arg) 'passed)) ; do nothing
((eq (buttercup-spec-status arg) 'failed)
(buttercup--print " FAILED\n")
(buttercup--print " FAILED")
(setq buttercup-reporter-batch--failures
(append buttercup-reporter-batch--failures
(list arg))))
((eq (buttercup-spec-status arg) 'pending)
(buttercup--print " %s\n" (buttercup-spec-failure-description arg)))
(buttercup--print " %s" (buttercup-spec-failure-description arg)))
(t
(error "Unknown spec status %s" (buttercup-spec-status arg)))))
(error "Unknown spec status %s" (buttercup-spec-status arg))))
(buttercup--print " (%s)\n"
(seconds-to-string
(float-time (buttercup-elapsed-time arg)))))
(`suite-done
(when (= 0 (length (buttercup-suite-or-spec-parents arg)))
......@@ -1536,11 +1561,11 @@ EVENT and ARG are described in `buttercup-reporter'."
(let ((level (length (buttercup-suite-or-spec-parents arg))))
(cond
((eq (buttercup-spec-status arg) 'passed)
(buttercup--print (buttercup-colorize "\r%s%s\n" 'green)
(buttercup--print (buttercup-colorize "\r%s%s" 'green)
(make-string (* 2 level) ?\s)
(buttercup-spec-description arg)))
((eq (buttercup-spec-status arg) 'failed)
(buttercup--print (buttercup-colorize "\r%s%s FAILED\n" 'red)
(buttercup--print (buttercup-colorize "\r%s%s FAILED" 'red)
(make-string (* 2 level) ?\s)
(buttercup-spec-description arg))
(setq buttercup-reporter-batch--failures
......@@ -1548,13 +1573,16 @@ EVENT and ARG are described in `buttercup-reporter'."
(list arg))))
((eq (buttercup-spec-status arg) 'pending)
(if (equal (buttercup-spec-failure-description arg) "SKIPPED")
(buttercup--print " %s\n" (buttercup-spec-failure-description arg))
(buttercup--print (buttercup-colorize "\r%s%s %s\n" 'yellow)
(buttercup--print " %s" (buttercup-spec-failure-description arg))
(buttercup--print (buttercup-colorize "\r%s%s %s" 'yellow)
(make-string (* 2 level) ?\s)
(buttercup-spec-description arg)
(buttercup-spec-failure-description arg))))
(t
(error "Unknown spec status %s" (buttercup-spec-status arg))))))
(error "Unknown spec status %s" (buttercup-spec-status arg))))
(buttercup--print " (%s)\n"
(seconds-to-string
(float-time (buttercup-elapsed-time arg))))))
(`buttercup-done
(dolist (failed buttercup-reporter-batch--failures)
......
......@@ -302,6 +302,70 @@
:to-equal
"su1 su2 sp2"))))
(describe "The `buttercup-elapsed-time' function"
(let ((spytime (current-time)))
(before-each
(spy-on 'current-time
:and-call-fake
(lambda ()
(setq spytime (time-add spytime (seconds-to-time 1.5))))))
(it "should report elapsed time for suites"
(let ((suite (make-buttercup-suite)))
(buttercup--set-start-time suite)
(buttercup--set-end-time suite)
(expect (buttercup-elapsed-time suite)
:to-equal (seconds-to-time 1.5))))
(it "should report elapsed time for specs"
(let ((spec (make-buttercup-spec)))
(buttercup--set-start-time spec)
(buttercup--set-end-time spec)
(expect (buttercup-elapsed-time spec)
:to-equal (seconds-to-time 1.5))))))
(defmacro with-local-buttercup (&rest body)
"Execute BODY with local buttercup state variables."
(declare (debug t) (indent defun))
`(let (buttercup--after-all
buttercup--after-each
buttercup--before-all
buttercup--before-each
buttercup--cleanup-functions
buttercup--current-suite
(buttercup-reporter #'ignore)
buttercup-suites
(buttercup-warning-buffer-name " *ignored buttercup warnings*"))
,@body))
(describe "The `buttercup--run-suite' function"
(before-each
(spy-on 'buttercup--set-start-time :and-call-through)
(spy-on 'buttercup--set-end-time :and-call-through))
(it "should set start and end time of the suite"
(with-local-buttercup
(let ((suite (make-buttercup-suite)))
(buttercup--run-suite suite)
(expect 'buttercup--set-start-time :to-have-been-called-times 1)
(expect (buttercup-suite-or-spec-time-started suite)
:not :to-be nil)
(expect 'buttercup--set-end-time :to-have-been-called-times 1)
(expect (buttercup-suite-or-spec-time-ended suite)
:not :to-be nil)))))
(describe "The `buttercup--run-spec' function"
(before-each
(spy-on 'buttercup--set-start-time :and-call-through)
(spy-on 'buttercup--set-end-time :and-call-through))
(it "should set start and end time of the spec"
(with-local-buttercup
(let ((spec (make-buttercup-spec)))
(buttercup--run-spec spec)
(expect 'buttercup--set-start-time :to-have-been-called-times 1)
(expect (buttercup-suite-or-spec-time-started spec)
:not :to-be nil)
(expect 'buttercup--set-end-time :to-have-been-called-times 1)
(expect (buttercup-suite-or-spec-time-ended spec)
:not :to-be nil)))))
;;;;;;;;;;;;;;;;;;;;
;;; Suites: describe
......@@ -530,7 +594,15 @@
(expect (buttercup-spec-status
(car (last (buttercup-suite-children
buttercup--current-suite))))
:to-be 'pending))))
:to-be 'pending)))
(it "should set the failure description to PENDING"
(let ((buttercup--current-suite (make-buttercup-suite))
spec)
(buttercup-xit "bla bla")
(setq spec (car (buttercup-suite-children buttercup--current-suite)))
(buttercup--update-with-funcall spec (buttercup-spec-function spec))
(expect (buttercup-suite-or-spec-failure-description spec) :to-equal "PENDING"))))
;;;;;;;;;
;;; Spies
......@@ -840,10 +912,16 @@
"spec")))
(describe "on the spec-done event"
(it "should simply emit a newline for a passed spec"
(it "should print no status tag for a passed spec"
(buttercup--set-start-time spec)
(setf (buttercup-spec-failure-description spec) "DONTSHOW")
(buttercup--set-end-time spec)
(buttercup-reporter-batch 'spec-done spec)
(expect 'buttercup--print :to-have-been-called-with "\n"))
(expect (mapconcat (apply-partially #'apply #'format)
(spy-calls-all-args 'buttercup--print)
"")
:to-match "^\\s-*([0-9]+\\.[0-9]+\\(h\\|m\\|m?s\\))\n$"))
(it "should say FAILED for a failed spec"
(setf (buttercup-spec-status spec) 'failed)
......@@ -851,13 +929,38 @@
(let ((buttercup-reporter-batch--failures nil))
(buttercup-reporter-batch 'spec-done spec))
(expect 'buttercup--print :to-have-been-called-with " FAILED\n"))
(expect (mapconcat (apply-partially #'apply #'format)
(spy-calls-all-args 'buttercup--print)
"")
:to-match "FAILED\\(\\s-+.*\\)?\n$"))
(it "should output the failure-description for a pending spec"
(setf (buttercup-spec-status spec) 'pending
(buttercup-spec-failure-description spec) "DESCRIPTION")
(let ((buttercup-reporter-batch--failures nil))
(buttercup-reporter-batch 'spec-done spec))
(expect (mapconcat (apply-partially #'apply #'format)
(spy-calls-all-args 'buttercup--print) "")
:to-match "DESCRIPTION\\(\\s-+.*\\)?\n$"))
(it "should throw an error for an unknown spec status"
(setf (buttercup-spec-status spec) 'unknown)
(expect (buttercup-reporter-batch 'spec-done spec)
:to-throw)))
:to-throw))
(it "should print the elapsed time for all specs"
(dolist (state '(pending failed passed))
(setq spec (make-buttercup-spec :description "spec" :status state :parent child-suite))
(buttercup--set-start-time spec)
(buttercup--set-end-time spec)
(let ((buttercup-reporter-batch--failures nil))
(buttercup-reporter-batch 'spec-done spec))
(expect (mapconcat (apply-partially #'apply #'format)
(spy-calls-all-args 'buttercup--print)
"")
:to-match "([0-9]+\\.[0-9]+\\(h\\|m\\|m?s\\))"))))
(describe "on the suite-done event"
(it "should emit a newline at the end of the top-level suite"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment