Trying something new with testing.

Let's do this with ert-runner instead of python. Maybe it will work for once.
This commit is contained in:
John Miller 2018-02-27 14:38:13 -06:00
parent 7a52ebca35
commit 9d5309af59
32 changed files with 3548 additions and 1 deletions

3
.ert-runner Normal file
View file

@ -0,0 +1,3 @@
-l test/test-load.el
-L ./lisp
-L ./test

View file

@ -20,4 +20,4 @@ env:
- EVM_EMACS=emacs-git-snapshot-travis IPYCMD=jupyter JUPYTER=1.0.0 - EVM_EMACS=emacs-git-snapshot-travis IPYCMD=jupyter JUPYTER=1.0.0
script: script:
- emacs --version - emacs --version
- python tools/testein.py --emacs emacs --ipython $(which $IPYCMD) - cask exec ert-runner

View file

@ -119,6 +119,7 @@
,@(if kernelspec ,@(if kernelspec
`(("kernel" . `(("kernel" .
(("name" . ,(ein:$kernelspec-name kernelspec)))))))))) (("name" . ,(ein:$kernelspec-name kernelspec))))))))))
:sync ein:force-sync
:parser #'ein:json-read :parser #'ein:json-read
:success (apply-partially #'ein:kernel--kernel-started kernel) :success (apply-partially #'ein:kernel--kernel-started kernel)
:error (apply-partially #'ein:kernel--start-failed kernel notebook)))))) :error (apply-partially #'ein:kernel--start-failed kernel notebook))))))

76
test/ein-testing-cell.el Normal file
View file

@ -0,0 +1,76 @@
;;; ein-testing-cell.el --- Testing utilities for cell module
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-testing-cell.el is free software: you can redistribute it
;; and/or modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation, either version 3 of
;; the License, or (at your option) any later version.
;; ein-testing-cell.el is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with ein-testing-cell.el.
;; If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'json)
(defvar ein:testing-example-svg "\
<?xml version=\"1.0\" standalone=\"no\"?>
<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"
\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">
<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">
<circle cx=\"100\" cy=\"50\" r=\"40\" />
</svg>")
(defun ein:testing-codecell-pyout-data (text &optional prompt-number)
"Create a plist representing JSON data for code-cell output.
TEXT is a string and PROMPT-NUMBER is an integer."
(list :output_type "pyout"
:prompt_number (or prompt-number 0)
:text text))
(defun ein:testing-codecell-data (&optional input prompt-number outputs)
"Create a plist representing JSON data for code-type cell.
To make OUTPUTS data, use `ein:testing-codecell-pyout-data'."
(list :cell_type "code"
:source (or input "")
:language "python"
:outputs outputs
:metadata (list :collapsed json-false :autoscroll json-false)
:execution_count prompt-number))
(defun ein:testing-textcell-data (&optional source cell-type)
(list :cell_type cell-type
:source (or source "")))
(defun ein:testing-markdowncell-data (&optional source)
(ein:testing-textcell-data source "markdown"))
(defun ein:testing-rawcell-data (&optional source)
(ein:testing-textcell-data source "raw"))
(defun ein:testing-htmlcell-data (&optional source)
(ein:testing-textcell-data source "html"))
(defun ein:testing-headingcell-data (&optional source level)
(append (ein:testing-textcell-data source "heading")
(list :level (or level 1))))
(provide 'ein-testing-cell)
;;; ein-testing-cell.el ends here

View file

@ -0,0 +1,85 @@
;;; ein-testing-kernel.el --- Testing utilities for kernel module
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-testing-kernel.el is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; ein-testing-kernel.el is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with ein-testing-kernel.el. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-kernel)
;;; Test `ein:kernel-construct-help-string'
(defvar ein:testing-kernel-construct-help-string-pcallsig-list
'(nil :call_def :init_definition :definition))
(defvar ein:testing-kernel-construct-help-string-pdocstring-list
'(nil :call_docstring :init_docstring :docstring))
(defun ein:testing-kernel-construct-help-string-test-func (content result)
(should (equal (ein:kernel-construct-help-string content) result)))
(defun ein:testing-kernel-construct-help-string-loop
(&optional test pcallsig-list pdocstring-list)
"Run tests for `ein:kernel-construct-help-string-loop'.
TEST
A function takes two arguments, namely CONTENT and RESULT.
CONTENT is the argument to `ein:kernel-construct-help-string' and
RESULT must match to its returned value. Use `should' to test
equality.
PCALLSIG-LIST
`nil' or (subset of) `ein:testing-kernel-construct-help-string-pcallsig-list'.
PDOCSTRING-LIST
`nil' or (subset of) `ein:testing-kernel-construct-help-string-pdocstring-list'.
All combinations of PCALLSIG-LIST and PDOCSTRING-LIST are used to
construct CONTENT and RESULT."
(unless test
(setq test #'ein:testing-kernel-construct-help-string-test-func))
(unless pcallsig-list
(setq pcallsig-list
ein:testing-kernel-construct-help-string-pcallsig-list))
(unless pdocstring-list
(setq pdocstring-list
ein:testing-kernel-construct-help-string-pdocstring-list))
(loop with callsig = "function(a=1, b=2, c=d)"
with docstring = "This function does what."
for pcallsig in pcallsig-list
do (loop for pdoc in pdocstring-list
for content = (append
(when pcallsig (list pcallsig callsig))
(when pdoc (list pdoc docstring)))
for result = (ein:aif (append
(when pcallsig (list callsig))
(when pdoc (list docstring)))
(ein:join-str "\n" it))
do (funcall test content result))))
(provide 'ein-testing-kernel)
;;; ein-testing-kernel.el ends here

View file

@ -0,0 +1,122 @@
;;; ein-testing-notebook.el --- Testing utilities for notebook module
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-testing-notebook.el is free software: you can redistribute it
;; and/or modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation, either version 3 of
;; the License, or (at your option) any later version.
;; ein-testing-notebook.el is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with ein-testing-notebook.el.
;; If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(eval-when-compile (require 'cl))
(require 'ein-notebook)
(require 'ein-testing-cell)
(defun ein:testing-notebook-from-json (json-string &optional name path)
(let* ((data (ein:json-read-from-string json-string))
(name (plist-get data :name))
(path (plist-get data :path))
(kernelspec (make-ein:$kernelspec :name "python3"))
(content (make-ein:$content :url-or-port "DUMMY-URL"
:ipython-version 3
:path path)))
(unless name (setq name "NOTEBOOK-DUMMY"))
(unless path (setq path "NOTEBOOK-DUMMY"))
;; cl-flet does not work correctly here!
(cl-flet ((pop-to-buffer (buf)
buf)
(ein:query-ipython-version (&optional url-or-port force)
3)
(ein:notebook-start-kernel (notebook)
notebook))
(let ((notebook (ein:notebook-new "DUMMY-URL" path kernelspec)))
(setf (ein:$notebook-kernel notebook)
(ein:kernel-new 8888 "/kernels" (ein:$notebook-events notebook) (ein:query-ipython-version)))
(setf (ein:$kernel-events (ein:$notebook-kernel notebook))
(ein:events-new))
(ein:notebook-request-open-callback notebook (ein:new-content content nil :data data))
(ein:notebook-buffer notebook)))))
(defun ein:testing-notebook-make-data (cells &optional name path)
(setq cells
(ein:testing-notebook--preprocess-cells-data-for-json-encode cells))
(unless name (setq name "Dummy Name.ipynb"))
(unless path (setq path "Dummy Name.ipynb"))
`((path . ,path)
(name . ,name)
(type . "notebook")
(format . "json")
(mimetype . nil)
(writeable . t)
(content (metadata . ())
(nbformat . 4)
(nbformat_minor . 0)
(cells . ,(apply #'vector cells)))))
(defun ein:testing-notebook--preprocess-cells-data-for-json-encode (cells)
"Preprocess CELLS data to make it work nice with `json-encode'."
(mapcar (lambda (c)
(cond
((equal (plist-get c :cell_type) "code")
;; turn `:outputs' into an array.
(plist-put c :outputs (apply #'vector (plist-get c :outputs))))
(t c)))
cells))
(defun ein:testing-notebook-make-new (&optional name cells-data)
"Make new notebook. One empty cell will be inserted
automatically if CELLS-DATA is nil."
(ein:testing-notebook-from-json
(json-encode (ein:testing-notebook-make-data cells-data name))))
(defun ein:testing-notebook-make-empty (&optional name)
"Make empty notebook and return its buffer.
Automatically inserted cell for new notebook is deleted."
(let ((buffer (ein:testing-notebook-make-new name)))
(with-current-buffer buffer
(call-interactively #'ein:worksheet-delete-cell))
buffer))
(defmacro ein:testing-with-one-cell (cell-type &rest body)
"Insert new cell of CELL-TYPE in a clean notebook and execute BODY.
The new cell is bound to a variable `cell'."
(declare (indent 1))
`(with-current-buffer (ein:testing-notebook-make-empty)
(let ((cell (ein:worksheet-insert-cell-below ein:%worksheet%
,cell-type nil t)))
,@body)))
(defun ein:testing-make-notebook-with-outputs (list-outputs)
"Make a new notebook with cells with output.
LIST-OUTPUTS is a list of list of strings (pyout text). Number
of LIST-OUTPUTS equals to the number cells to be contained in the
notebook."
(ein:testing-notebook-make-new
nil
(mapcar (lambda (outputs)
(ein:testing-codecell-data
nil nil (mapcar #'ein:testing-codecell-pyout-data outputs)))
list-outputs)))
(provide 'ein-testing-notebook)
;;; ein-testing-notebook.el ends here

76
test/ein-testing.el Normal file
View file

@ -0,0 +1,76 @@
;;; ein-testing.el --- Tools for testing
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-testing.el is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; ein-testing.el is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with ein-testing.el. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'ein-log)
(defmacro ein:setq-if-not (sym val)
`(unless ,sym (setq ,sym ,val)))
(defvar ein:testing-dump-file-log nil
"File to save buffer specified by `ein:log-all-buffer-name'.")
(defvar ein:testing-dump-file-messages nil
"File to save the ``*Messages*`` buffer.")
(defvar ein:testing-dump-file-debug nil)
(defvar ein:testing-dump-server-log nil)
(defun ein:testing-save-buffer (buffer-or-name file-name)
(when (and buffer-or-name (get-buffer buffer-or-name) file-name)
(with-current-buffer buffer-or-name
(write-region (point-min) (point-max) file-name))))
(defun ein:testing-dump-logs ()
(ein:testing-save-buffer "*Messages*" ein:testing-dump-file-messages)
(ein:testing-save-buffer "*ein:jupyter-server*" ein:testing-dump-server-log)
(ein:testing-save-buffer ein:log-all-buffer-name ein:testing-dump-file-log))
(defvar ein:testing-dump-logs--saved nil)
(defun ein:testing-dump-logs-noerror ()
(if ein:testing-dump-logs--saved
(message "EIN:TESTING-DUMP-LOGS-NOERROR called but already saved.")
(condition-case err
(progn (ein:testing-dump-logs)
(setq ein:testing-dump-logs--saved t))
(error
(message "Error while executing EIN:TESTING-DUMP-LOGS. err = %S"
err)
(when ein:testing-dump-file-debug
(signal (car err) (cdr err)))))))
(defadvice ert-run-tests-batch (after ein:testing-dump-logs-hook activate)
"Hook `ein:testing-dump-logs-noerror' because `kill-emacs-hook'
is not run in batch mode before Emacs 24.1."
(ein:testing-dump-logs-noerror))
(add-hook 'kill-emacs-hook #'ein:testing-dump-logs-noerror)
(provide 'ein-testing)
;;; ein-testing.el ends here

290
test/func-test.el Normal file
View file

@ -0,0 +1,290 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-loaddefs)
(require 'ein-notebooklist)
(require 'ein-jupyter)
(require 'wid-edit)
(require 'ein-testing)
(require 'ein-testing-cell)
(let ((backend (getenv "EL_REQUEST_BACKEND")))
(when (and backend (not (equal backend "")))
(setq request-backend (intern backend))
(message "Using request-backend = %S" request-backend)))
(ein:setq-if-not ein:testing-dump-file-log "func-test-batch-log.log")
(ein:setq-if-not ein:testing-dump-file-messages "func-test-batch-messages.log")
(ein:setq-if-not ein:testing-dump-server-log "func-test_server_batch_emacs.log")
(setq message-log-max t)
(defun ein:testing-wait-until (message predicate &optional predargs max-count)
"Wait until PREDICATE function returns non-`nil'.
PREDARGS is argument list for the PREDICATE function.
Make MAX-COUNT larger \(default 50) to wait longer before timeout."
(ein:log 'debug "TESTING-WAIT-UNTIL start")
(ein:log 'debug "TESTING-WAIT-UNTIL waiting on: %s" message)
(unless max-count (setq max-count 50))
(unless (loop repeat max-count
when (apply predicate predargs)
return t
;; borrowed from `deferred:sync!':
do (sit-for 0.2)
do (sleep-for 0.2))
(error "Timeout"))
(ein:log 'debug "TESTING-WAIT-UNTIL end"))
(defun ein:testing-get-notebook-by-name (url-or-port notebook-name &optional path)
(ein:log 'debug "TESTING-GET-NOTEBOOK-BY-NAME start")
(when path
(setq notebook-name (format "%s/%s" path notebook-name)))
(ein:notebooklist-open url-or-port path t)
(ein:testing-wait-until "ein:notebooklist-open"
(lambda () (and (bufferp (get-buffer (format ein:notebooklist-buffer-name-template url-or-port)))
(ein:notebooklist-get-buffer url-or-port))))
(with-current-buffer (ein:notebooklist-get-buffer url-or-port)
(prog1
(ignore-errors
(ein:notebooklist-open-notebook-by-name notebook-name url-or-port))
(ein:log 'debug "TESTING-GET-NOTEBOOK-BY-NAME end"))))
(defun ein:testing-get-untitled0-or-create (url-or-port &optional path)
(ein:log 'debug "TESTING-GET-UNTITLED0-OR-CREATE start")
(let ((notebook (ein:testing-get-notebook-by-name url-or-port "Untitled.ipynb" path)))
(if notebook
(progn (ein:log 'debug
"TESTING-GET-UNTITLED0-OR-CREATE notebook already exists")
notebook)
(ein:log 'debug
"TESTING-GET-UNTITLED0-OR-CREATE creating notebook")
(let ((created nil)
(kernelspec (ein:get-kernelspec url-or-port "python3")))
(ein:notebooklist-new-notebook url-or-port kernelspec path
(lambda (&rest -ignore-)
(setq created t)))
(ein:testing-wait-until "ein:notebooklist-new-notebook"
(lambda () created)))
(prog1
(ein:testing-get-notebook-by-name url-or-port "Untitled.ipynb" path)
(ein:log 'debug "TESTING-GET-UNTITLED0-OR-CREATE end")))))
(defvar ein:notebooklist-after-open-hook nil)
(defadvice ein:notebooklist-url-retrieve-callback
(after ein:testing-notebooklist-url-retrieve-callback activate)
"Advice to add `ein:notebooklist-after-open-hook'."
(run-hooks 'ein:notebooklist-after-open-hook))
(defun ein:testing-delete-notebook (url-or-port notebook &optional path)
(ein:log 'debug "TESTING-DELETE-NOTEBOOK start")
(ein:notebooklist-open url-or-port (ein:$notebook-notebook-path notebook) t)
(ein:testing-wait-until "ein:notebooklist-open"
(lambda ()
(bufferp (get-buffer (format ein:notebooklist-buffer-name-template url-or-port))))
nil 50)
(with-current-buffer (ein:notebooklist-get-buffer url-or-port)
(ein:testing-wait-until "ein:notebooklist-get-buffer"
(lambda () (eql major-mode 'ein:notebooklist-mode))
nil
50)
(ein:log 'debug "TESTING-DELETE-NOTEBOOK deleting notebook")
(ein:notebooklist-delete-notebook (ein:$notebook-notebook-path notebook)))
(ein:log 'debug "TESTING-DELETE-NOTEBOOK end"))
;; (ert-deftest 00-jupyter-start-server ()
;; (ein:log 'verbose "ERT TESTING-JUPYTER-START-SERVER start")
;; (condition-case err
;; (ein:testing-start-server)
;; (error (ein:log 'verbose "ERT TESTING-JUPYTER-START-SERVER error when launching: %s" err)
;; (sit-for 10)
;; (ein:jupyter-server-login-and-open)))
;; (should (processp %ein:jupyter-server-session%))
;; (ein:log 'verbose "ERT TESTING-JUPYTER-START-SERVER end"))
(ert-deftest 01-open-notebooklist ()
(ein:log 'verbose "ERT OPEN-NOTEBOOKLIST start")
(ein:notebooklist-open *ein:testing-port* "/" t)
(ein:testing-wait-until
"ein:notebooklist-open"
(lambda ()
(ein:notebooklist-get-buffer *ein:testing-port*))
nil 5000)
(with-current-buffer (ein:notebooklist-get-buffer *ein:testing-port*)
(should (eql major-mode 'ein:notebooklist-mode))))
(ert-deftest 00-query-kernelspecs ()
(ein:log 'verbose "ERT QUERY-KERNELSPECS")
(ein:log 'verbose (format "ERT QUERY-KERNELSPECS: Pre-query kernelspec count %s." (hash-table-count ein:available-kernelspecs)))
(ein:query-kernelspecs *ein:testing-port*)
(should (>= (hash-table-count ein:available-kernelspecs) 1))
(ein:log 'verbose (format "ERT QUERY-KERNELSPECS: Post-query kernelspec count %s." (hash-table-count ein:available-kernelspecs)))
)
(ert-deftest 10-get-untitled0-or-create ()
(ein:log 'verbose "ERT TESTING-GET-UNTITLED0-OR-CREATE start")
(let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
(ein:testing-wait-until
"ein:testing-get-untitled0-or-create"
(lambda () (ein:aand (ein:$notebook-kernel notebook)
(ein:kernel-live-p it)))
nil 50000)
(with-current-buffer (ein:notebook-buffer notebook)
(should (equal (ein:$notebook-notebook-name ein:%notebook%)
"Untitled.ipynb"))))
(ein:log 'verbose "ERT TESTING-GET-UNTITLED0-OR-CREATE end"))
(ert-deftest 20-delete-untitled0 ()
(ein:log 'verbose "----------------------------------")
(ein:log 'verbose "ERT TESTING-DELETE-UNTITLED0 start")
(ein:log 'verbose "ERT TESTING-DELETE-UNTITLED0 creating notebook")
(let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
(ein:testing-wait-until
"ein:test-get-untitled0-or-create"
(lambda ()
(ein:aand notebook
(ein:$notebook-kernel it)
(ein:kernel-live-p it)))
nil 50)
(ein:log 'verbose "ERT TESTING-DELETE-UNTITLED0 deleting notebook")
(ein:testing-delete-notebook *ein:testing-port* notebook))
(ein:log 'verbose
"ERT TESTING-DELETE-UNTITLED0 check that the notebook is deleted")
(let ((num-notebook
(length (ein:testing-get-notebook-by-name *ein:testing-port*
"Untitled.ipynb"
""))))
(should (= num-notebook 0)))
(ein:log 'verbose "ERT TESTING-DELETE-UNTITLED0 end"))
(ert-deftest 11-notebook-execute-current-cell-simple ()
(let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
(ein:testing-wait-until
"ein:testing-get-untitled0-or-create"
(lambda () (ein:aand (ein:$notebook-kernel notebook)
(ein:kernel-live-p it)))
nil 50)
(with-current-buffer (ein:notebook-buffer notebook)
(call-interactively #'ein:worksheet-insert-cell-below)
(insert "a = 100\na")
(let ((cell (call-interactively #'ein:worksheet-execute-cell)))
(ein:testing-wait-until "ein:worksheet-execute-cell"
(lambda () (not (slot-value cell 'running)))
nil
50000))
;; (message "%s" (buffer-string))
(save-excursion
(should (search-forward-regexp "Out \\[[0-9]+\\]" nil t))
(should (search-forward "100" nil t))))))
(defun ein:testing-image-type (image)
"Return the type of IMAGE.
See the definition of `create-image' for how it works."
(assert (and (listp image) (eq (car image) 'image)) nil
"%S is not an image." image)
(plist-get (cdr image) :type))
(ert-deftest 12-notebook-execute-current-cell-pyout-image ()
(let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
(ein:testing-wait-until
"ein:testing-get-untitled0-or-create"
(lambda () (ein:aand (ein:$notebook-kernel notebook)
(ein:kernel-live-p it))))
(with-current-buffer (ein:notebook-buffer notebook)
(call-interactively #'ein:worksheet-insert-cell-below)
;; Use IPython.core.display rather than IPython.display to
;; test it with older (< 0.13) IPython.
(insert (concat "from IPython.core.display import SVG\n"
(format "SVG(data=\"\"\"%s\"\"\")"
ein:testing-example-svg)))
(let ((cell (call-interactively #'ein:worksheet-execute-cell)))
;; It seems in this case, watching `:running' does not work
;; well sometimes. Probably "output reply" (iopub) comes
;; before "execute reply" in this case.
(ein:testing-wait-until "ein:worksheet-execute-cell"
(lambda () (slot-value cell 'outputs))
nil
50)
;; This cell has only one input
(should (= (length (oref cell :outputs)) 1))
;; This output is a SVG image
(let ((out (nth 0 (oref cell :outputs))))
(should (equal (plist-get out :output_type) "execute_result"))
(should (plist-get out :svg))))
;; Check the actual output in the buffer:
(save-excursion
(should (search-forward-regexp "Out \\[[0-9]+\\]" nil t))
(should (= (forward-line) 0))
(if (image-type-available-p 'svg)
(let ((image (get-text-property (point) 'display)))
(should (eq (ein:testing-image-type image) 'svg)))
(ein:log 'info
"Skipping image check as SVG image type is not available."))))))
(ert-deftest 13-notebook-execute-current-cell-stream ()
(let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
(ein:testing-wait-until
"ein:testing-get-untitled0-or-create"
(lambda () (ein:aand (ein:$notebook-kernel notebook)
(ein:kernel-live-p it)))
nil 50)
(with-current-buffer (ein:notebook-buffer notebook)
(call-interactively #'ein:worksheet-insert-cell-below)
(insert "print('Hello')")
(let ((cell (call-interactively #'ein:worksheet-execute-cell)))
(ein:testing-wait-until "ein:worksheet-execute-cell"
(lambda () (not (oref cell :running)))
nil
50000))
(save-excursion
(should-not (search-forward-regexp "Out \\[[0-9]+\\]" nil t))
(should (search-forward-regexp "^Hello$" nil t))))))
(ert-deftest 14-notebook-execute-current-cell-question ()
(let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
(ein:testing-wait-until
"ein:testing-get-untitled0-or-create"
(lambda () (ein:aand (ein:$notebook-kernel notebook)
(ein:kernel-live-p it)))
nil 50)
(with-current-buffer (ein:notebook-buffer notebook)
(call-interactively #'ein:worksheet-insert-cell-below)
(insert "range?")
(let ((cell (call-interactively #'ein:worksheet-execute-cell)))
(ein:testing-wait-until
"ein:worksheet-execute-cell"
(lambda () (not (oref cell :running)))
nil 50))
(with-current-buffer (get-buffer (ein:$notebook-pager notebook))
(should (search-forward "Docstring:"))))))
(ert-deftest 15-notebook-request-help ()
(let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
(ein:testing-wait-until
"ein:testing-get-untitled0-or-create"
(lambda () (ein:aand (ein:$notebook-kernel notebook)
(ein:kernel-live-p it)))
nil 50000)
(with-current-buffer (ein:notebook-buffer notebook)
(call-interactively #'ein:worksheet-insert-cell-below)
(let ((pager-name (ein:$notebook-pager ein:%notebook%)))
(ein:aif (get-buffer pager-name)
(kill-buffer it))
(insert "file")
(call-interactively #'ein:pytools-request-help)
;; Pager buffer will be created when got the response
(ein:testing-wait-until
"ein:pythools-request-help"
(lambda () (get-buffer pager-name))
nil 50000)
(with-current-buffer (get-buffer pager-name)
(should (search-forward "Docstring:")))))))
(ert-deftest 30-testing-jupyter-stop-server ()
(ein:log 'verbose "ERT TESTING-JUPYTER-STOP-SERVER start")
(cl-letf (((symbol-function 'y-or-n-p) #'ignore))
(ein:jupyter-server-stop t))
(should-not (processp %ein:jupyter-server-session%))
(ein:log 'verbose "ERT TESTING-JUPYTER-STOP-SERVER end"))

View file

@ -0,0 +1,17 @@
from flask import Flask, redirect
app = Flask(__name__)
@app.route('/')
def jupyter_redirect():
return redirect("http://127.0.0.1:8888/", code=302)
@app.route('/api')
def api_check():
return redirect("http://127.0.0.1:8888/api", code=302)
if __name__=='__main__':
port = int(8000)
app.run(host='127.0.0.1', port=port)

17
test/test-ein-ac.el Normal file
View file

@ -0,0 +1,17 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-ac)
(require 'ein-testing-kernel)
(ert-deftest ein:ac-set-document ()
(let ((string "candidate string"))
(should-not (get-text-property 0 'document string))
(ein:testing-kernel-construct-help-string-loop
(lambda (content result)
(ein:ac-set-document string content '-not-used-)
(let ((props (text-properties-at 0 string)))
;; document property may be nil, but must be set.
(should (member 'document props))
(should (equal (plist-get props 'document) result)))))))

View file

@ -0,0 +1,249 @@
;; Tests for cell function that requires notebook buffer
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-notebook)
(require 'ein-testing-notebook)
;; ein:cell-location
(ert-deftest ein:cell-location-codecell-prompt-beg ()
(ein:testing-with-one-cell 'code
(should (equal (marker-position (ein:cell-location cell :prompt))
(save-excursion
(goto-char (point-max))
(search-backward "In [ ]:")
(point))))))
(ert-deftest ein:cell-location-codecell-prompt-end ()
(ein:testing-with-one-cell 'code
(should (equal (marker-position (ein:cell-location cell :prompt t))
(1- (point))))))
(ert-deftest ein:cell-location-codecell-input-beg ()
(ein:testing-with-one-cell 'code
(insert "some text")
(should (equal (marker-position (ein:cell-location cell :input))
(1- (point-at-bol))))))
(ert-deftest ein:cell-location-codecell-input-end ()
(ein:testing-with-one-cell 'code
(insert "some text")
(should (equal (marker-position (ein:cell-location cell :input t))
(1+ (point))))))
;; from-json
(ert-deftest eintest:cell-input-prompt-number ()
(ein:testing-with-one-cell
(ein:cell-from-json
(list :cell_type "code"
:source "some input"
:metadata (list :collapsed json-false :autoscroll json-false)
:execution_count 111)
:ewoc (oref ein:%worksheet% :ewoc))
(goto-char (ein:cell-location cell))
(should (looking-at "\
In \\[111\\]:
some input
"))))
(ert-deftest eintest:cell-input-prompt-star ()
(ein:testing-with-one-cell
(ein:cell-from-json
(list :cell_type "code"
:source "some input"
:metadata (list :collapsed json-false :autoscroll json-false)
:execution_count "*")
:ewoc (oref ein:%worksheet% :ewoc))
(goto-char (ein:cell-location cell))
(should (looking-at "\
In \\[\\*\\]:
some input
"))))
(ert-deftest eintest:cell-input-prompt-empty ()
(ein:testing-with-one-cell
(ein:cell-from-json
(list :cell_type "code"
:metadata (list :collapsed json-false :autoscroll json-false)
:source "some input")
:ewoc (oref ein:%worksheet% :ewoc))
(goto-char (ein:cell-location cell))
(should (looking-at "\
In \\[ \\]:
some input
"))))
;; Insert pyout/display_data
(defun eintest:cell-insert-output (outputs regexp)
(let ((ein:output-type-preference
'(emacs-lisp image/svg image/png jpeg text/plain text/html text/latex text/javascript)))
(message "%S" (list :cell_type "code"
:outputs outputs
:source "Some input"
:metadata (list :collapsed json-false :autoscroll json-false)
:execution_count 111))
(ein:testing-with-one-cell
(ein:cell-from-json
(list :cell_type "code"
:outputs outputs
:source "some input"
:metadata (list :collapsed json-false :autoscroll json-false)
:execution_count 111)
:ewoc (oref ein:%worksheet% :ewoc))
(goto-char (ein:cell-location cell))
(should (looking-at (format "\
In \\[111\\]:
some input
%s" regexp))))))
(defmacro eintest:gene-test-cell-insert-output-pyout-and-display-data
(name regexps outputs)
(declare (indent defun))
(let ((test-pyout
(intern (format "ein:cell-insert-output-pyout-%s" name)))
(test-display-data
(intern (format "ein:cell-insert-output-display-data-%s" name)))
(outputs-pyout
(loop for i from 1
for x in outputs
collect
(append x (list :output_type "execute_result" :execution_count i :metadata nil))))
(outputs-display-data
(mapcar (lambda (x) (append '(:output_type "display_data" :metadata nil) x))
outputs))
(regexp-pyout
(ein:join-str
""
(loop for i from 1
for x in regexps
collect (format "Out \\[%s\\]:\n%s\n" i x))))
(regexp-display-data
(concat (ein:join-str "\n" regexps) "\n")))
`(progn
(ert-deftest ,test-pyout ()
(eintest:cell-insert-output ',outputs-pyout
,regexp-pyout))
(ert-deftest ,test-display-data ()
(eintest:cell-insert-output ',outputs-display-data
,regexp-display-data)))))
(eintest:gene-test-cell-insert-output-pyout-and-display-data
text ("some output") ((:data (:text/plain "some output"))))
(eintest:gene-test-cell-insert-output-pyout-and-display-data
latex
("some output \\\\LaTeX")
((:data (:text/latex "some output \\LaTeX"))))
(when (image-type-available-p 'svg)
(eintest:gene-test-cell-insert-output-pyout-and-display-data
svg
(" ")
((:data (:text/plain "some output text" :svg ein:testing-example-svg)))))
(eintest:gene-test-cell-insert-output-pyout-and-display-data
html
("some output text")
((:data (:text/plain ("some output text") :text/html ("<b>not shown</b>")))))
(eintest:gene-test-cell-insert-output-pyout-and-display-data
javascript
("some output text")
((:data (:text/plain "some output text" :text/javascript "$.do.something()"))))
(eintest:gene-test-cell-insert-output-pyout-and-display-data
text-two
("first output text" "second output text")
((:data (:text/plain "first output text")) (:text/plain "second output text")))
(eintest:gene-test-cell-insert-output-pyout-and-display-data
text-javascript
("first output text" "second output text")
((:data (:text/plain "first output text"))
(:data (:text/plain "second output text" :text/javascript "$.do.something()"))))
(when (image-type-available-p 'svg)
(eintest:gene-test-cell-insert-output-pyout-and-display-data
text-latex-svg
("first output text" "second output \\\\LaTeX" " ")
((:data (:text/plain "first output text"))
(:data (:text/latex "second output \\LaTeX"))
(:data (:text/plain "some output text" :image/svg ein:testing-example-svg)))))
;; Insert pyerr
(ert-deftest ein:cell-insert-output-pyerr-simple ()
(eintest:cell-insert-output
(list (list :output_type "pyerr"
:traceback '("some traceback 1"
"some traceback 2")))
"\
some traceback 1
some traceback 2
"))
;; Insert stream
(ert-deftest ein:cell-insert-output-stream-simple-stdout ()
(eintest:cell-insert-output
(list (list :output_type "stream"
:name "stdout"
:text "some stdout 1"))
"\
some stdout 1
"))
(ert-deftest ein:cell-insert-output-stream-stdout-stderr ()
(eintest:cell-insert-output
(list (list :output_type "stream"
:name "stdout"
:text "some stdout 1")
(list :output_type "stream"
:name "stderr"
:text "some stderr 1"))
"\
some stdout 1
some stderr 1
"))
(ert-deftest ein:cell-insert-output-stream-flushed-stdout ()
(eintest:cell-insert-output
(list (list :output_type "stream"
:name "stdout"
:text "some stdout 1")
(list :output_type "stream"
:name "stdout"
:text "some stdout 2"))
"\
some stdout 1some stdout 2
"))
(ert-deftest ein:cell-insert-output-stream-flushed-stdout-and-stderr ()
(eintest:cell-insert-output
(list (list :output_type "stream"
:name "stdout"
:text "some stdout 1")
(list :output_type "stream"
:name "stderr"
:text "some stderr 1")
(list :output_type "stream"
:name "stdout"
:text "some stdout 2")
(list :output_type "stream"
:name "stderr"
:text "some stderr 2"))
"\
some stdout 1
some stderr 1
some stdout 2
some stderr 2
"))

270
test/test-ein-cell.el Normal file
View file

@ -0,0 +1,270 @@
(eval-when-compile (require 'cl))
(require 'ert)
(when load-file-name
(add-to-list 'load-path
(concat (file-name-directory load-file-name) "mocker")))
(require 'mocker)
(require 'ein-cell)
(require 'ein-testing-cell)
;;; ein:cell-from-json
(defun eintest:cell-from-json (data &rest args)
(let ((cell (apply #'ein:cell-from-json data args)))
(should-not (ein:cell-active-p cell))
cell))
(ert-deftest ein:cell-from-json-code ()
(let* ((input-prompt-number 111)
(output-prompt-number 222)
(input (ein:join-str "\n" '("first input" "second input")))
(output-0 (list :output_type "execute_result"
:prompt_number output-prompt-number
:text (list "first output"
"second output")))
(data (ein:testing-codecell-data
input input-prompt-number (list output-0)))
(cell (eintest:cell-from-json data)))
(should (ein:codecell-p cell))
(should (equal (oref cell :input-prompt-number) input-prompt-number))
(should (equal (oref cell :input) input))
(should (equal (car (oref cell :outputs)) output-0))
(should (equal (oref cell :collapsed) nil))))
(ert-deftest ein:cell-from-json-text ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "text" :source input))
(cell (eintest:cell-from-json data)))
(should (ein:textcell-p cell))
(should (equal (oref cell :input) input))))
(ert-deftest ein:cell-from-json-html ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "html" :source input))
(cell (eintest:cell-from-json data)))
(should (ein:htmlcell-p cell))
(should (equal (oref cell :input) input))))
(ert-deftest ein:cell-from-json-markdown ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "markdown" :source input))
(cell (eintest:cell-from-json data)))
(should (ein:markdowncell-p cell))
(should (equal (oref cell :input) input))))
(ert-deftest ein:cell-from-json-raw ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "raw" :source input))
(cell (eintest:cell-from-json data)))
(should (ein:rawcell-p cell))
(should (equal (oref cell :input) input))))
(ert-deftest ein:cell-from-json-heading ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "heading" :source input))
(cell (eintest:cell-from-json data)))
(should (ein:headingcell-p cell))
(should (equal (oref cell :input) input))))
;; ein:cell-to-json
(defun eintest:cell-to-json (cell input &optional discard-output)
(mocker-let ((ein:cell-get-text
(cell)
((:input (list cell) :output input))))
(ein:cell-to-json cell discard-output)))
(ert-deftest ein:cell-to-json-code ()
(let* ((input-prompt-number 111)
(output-prompt-number 222)
(input (ein:join-str "\n" '("first input" "second input")))
(output-0 (list :output_type "execute_result"
:prompt_number output-prompt-number
:text (list "first output"
"second output")))
(data (ein:testing-codecell-data
input input-prompt-number (list output-0)))
(cell (eintest:cell-from-json data))
(alist (eintest:cell-to-json cell input)))
(should (equal (cdr (assq 'input alist)) "first input\nsecond input"))
(should (equal (cdr (assq 'cell_type alist)) "code"))
(should (equal (cdr (assq 'outputs alist)) `[,output-0]))
(should (equal (cdr (assq 'language alist)) "python"))
(should (equal (cdr (assq 'collapsed alist)) json-false))))
(ert-deftest ein:cell-to-json-code-discard-output ()
(let* ((input-prompt-number 111)
(output-prompt-number 222)
(input (ein:join-str "\n" '("first input" "second input")))
(output-0 (list :output_type "execute_result"
:prompt_number output-prompt-number
:text (list "first output"
"second output")))
(data (ein:testing-codecell-data
input input-prompt-number (list output-0)))
(cell (eintest:cell-from-json data))
(alist (eintest:cell-to-json cell input t)))
(should (equal (cdr (assq 'input alist)) "first input\nsecond input"))
(should (equal (cdr (assq 'cell_type alist)) "code"))
(should (equal (cdr (assq 'outputs alist)) []))
(should (equal (cdr (assq 'language alist)) "python"))
(should (equal (cdr (assq 'collapsed alist)) json-false))))
(ert-deftest ein:cell-to-json-text ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "text" :source input))
(cell (eintest:cell-from-json data))
(alist (eintest:cell-to-json cell input)))
(should (equal (cdr (assq 'cell_type alist)) "text"))
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))))
(ert-deftest ein:cell-to-json-html ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "html" :source input))
(cell (eintest:cell-from-json data))
(alist (eintest:cell-to-json cell input)))
(should (equal (cdr (assq 'cell_type alist)) "html"))
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))))
(ert-deftest ein:cell-to-json-markdown ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "markdown" :source input))
(cell (eintest:cell-from-json data))
(alist (eintest:cell-to-json cell input)))
(should (equal (cdr (assq 'cell_type alist)) "markdown"))
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))))
(ert-deftest ein:cell-to-json-raw ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "raw" :source input))
(cell (eintest:cell-from-json data))
(alist (eintest:cell-to-json cell input)))
(should (equal (cdr (assq 'cell_type alist)) "raw"))
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))))
(ert-deftest ein:cell-to-json-heading ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type "heading" :source input))
(cell (eintest:cell-from-json data))
(alist (eintest:cell-to-json cell input)))
(should (equal (cdr (assq 'cell_type alist)) "heading"))
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))
(should (equal (cdr (assq 'level alist)) 1))))
;;; ein:cell-convert/copy
(ert-deftest ein:cell-convert-code-to-markdown ()
(let* ((input-prompt-number 111)
(output-prompt-number 222)
(input (ein:join-str "\n" '("first input" "second input")))
(output-0 (list :output_type "execute_result"
:prompt_number output-prompt-number
:text (list "first output"
"second output")))
(data (ein:testing-codecell-data
input input-prompt-number (list output-0)))
(dummy-ewoc (ewoc-create 'dummy))
(old (eintest:cell-from-json data :ewoc dummy-ewoc))
(new (ein:cell-convert old "markdown")))
(should (ein:codecell-p old))
(should (ein:markdowncell-p new))
(should (equal (oref new :input) input))))
(ert-deftest ein:cell-convert-markdown-to-code ()
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(dummy-ewoc (ewoc-create 'dummy))
(data (list :cell_type "markdown" :source input))
(old (eintest:cell-from-json data :ewoc dummy-ewoc))
(new (ein:cell-convert old "code")))
(should (ein:markdowncell-p old))
(should (ein:codecell-p new))
(should (equal (oref new :input) input))))
(ert-deftest ein:cell-copy-code ()
(let* ((input-prompt-number 111)
(output-prompt-number 222)
(input (ein:join-str "\n" '("first input" "second input")))
(output-0 (list :output_type "execute_result"
:prompt_number output-prompt-number
:text (list "first output"
"second output")))
(data (ein:testing-codecell-data
input input-prompt-number (list output-0)))
(dummy-ewoc (ewoc-create 'dummy))
(old (eintest:cell-from-json data :ewoc dummy-ewoc))
(new (ein:cell-copy old)))
(should (ein:codecell-p old))
(should (ein:codecell-p new))
(should-not (equal (oref old :cell-id)
(oref new :cell-id)))
(should (equal (oref old :input) input))
(should (equal (oref new :input) input))))
(ert-deftest ein:cell-copy-text-types ()
(loop for cell-type in '("text" "html" "markdown" "raw" "heading")
for cell-p = (intern (format "ein:%scell-p" cell-type))
do
(let* ((input (ein:join-str "\n" '("first input" "second input")))
(data (list :cell_type cell-type :source input :metadata nil))
(dummy-ewoc (ewoc-create 'dummy))
(old (eintest:cell-from-json data :ewoc dummy-ewoc))
(new (ein:cell-copy old)))
(should (funcall cell-p old))
(should (funcall cell-p new))
(should-not (equal (oref old :cell-id)
(oref new :cell-id)))
(should (equal (oref old :input) input))
(should (equal (oref new :input) input)))))
;;; ein:cell-element-get
(ert-deftest ein:cell-element-get-basecell ()
(let ((cell (ein:basecell "Cell")))
;; it's not supported
(should-error (ein:cell-element-get :prompt))))
(ert-deftest ein:cell-element-get-codecell ()
(let* ((element (list :prompt 1
:input 2
:output '(3 4)
:footer 5))
(cell (ein:cell-from-type "code" :element element)))
(mapc (lambda (kv)
(should (equal (ein:cell-element-get cell (car kv)) (cdr kv))))
(ein:plist-iter element))
(should (equal (ein:cell-element-get cell :output 0) 3))
(should (equal (ein:cell-element-get cell :output 1) 4))
(should (equal (ein:cell-element-get cell :output 2) nil))
(should (equal (ein:cell-element-get cell :after-input) 3))
(should (equal (ein:cell-element-get cell :after-output) 5))
(should (equal (ein:cell-element-get cell :before-input) 1))
(should (equal (ein:cell-element-get cell :before-output) 2))
(should (equal (ein:cell-element-get cell :last-output) 4))))
(ert-deftest ein:cell-element-get-codecell-no-ouput ()
(let* ((element (list :prompt 1
:input 2
:footer 5))
(cell (ein:cell-from-type "code" :element element)))
(mapc (lambda (kv)
(should (equal (ein:cell-element-get cell (car kv)) (cdr kv))))
(ein:plist-iter element))
(should (equal (ein:cell-element-get cell :after-input) 5))
(should (equal (ein:cell-element-get cell :last-output) 2))))
(ert-deftest ein:cell-element-get-textcell ()
(let* ((element (list :prompt 1
:input 2
:footer 5))
(cell (ein:cell-from-type "text" :element element)))
(mapc (lambda (kv)
(should (equal (ein:cell-element-get cell (car kv)) (cdr kv))))
(ein:plist-iter element))
(should (equal (ein:cell-element-get cell :after-input) 5))
(should (equal (ein:cell-element-get cell :before-input) 1))))

View file

@ -0,0 +1,23 @@
(eval-when-compile (require 'cl))
(require 'ert)
(when load-file-name
(add-to-list 'load-path
(concat (file-name-directory load-file-name) "mocker")))
(require 'mocker)
(require 'ein-completer)
(ert-deftest ein:completer-finish-completing ()
(let* ((matched-text 'dummy-matched-text-value) ; value can be anything
(matches 'dummy-matches-value)
(content (list :matched_text matched-text
:matches matches))
(args '(:extend t)))
(mocker-let
((ein:completer-choose () ((:output 'completer)))
(completer
(matched-text matches &rest args)
((:input (list matched-text matches args)))))
(ein:completer-finish-completing args content '-not-used-))))

47
test/test-ein-connect.el Normal file
View file

@ -0,0 +1,47 @@
(require 'ein-connect)
(require 'ein-testing-notebook)
(defmacro eintest:with-connected-buffer (&rest body)
(declare (indent 0))
`(let* ((notebook-buffer (ein:testing-notebook-make-empty))
(notebook (buffer-local-value 'ein:notebook notebook-buffer)))
(with-temp-buffer
(erase-buffer)
(ein:connect-buffer-to-notebook notebook)
,@body)))
(ert-deftest ein:get-url-or-port--connect ()
(eintest:with-connected-buffer
(should (equal (ein:get-url-or-port)
(ein:$notebook-url-or-port notebook)))))
(ert-deftest ein:get-notebook--connect ()
(eintest:with-connected-buffer
(should (eq (ein:get-notebook) notebook))))
(ert-deftest ein:get-kernel--connect ()
(eintest:with-connected-buffer
(should (eq (ein:get-kernel)
(ein:$notebook-kernel notebook)))))
(ert-deftest ein:get-cell-at-point--connect ()
"`ein:get-cell-at-point' is in empty context in connected buffer."
(eintest:with-connected-buffer
(should-not (ein:get-cell-at-point))))
(ert-deftest ein:get-traceback-data--connect ()
(eintest:with-connected-buffer
;; FIXME: write test with non-empty TB
(should-not (ein:get-traceback-data))))
(ert-deftest ein:connect-mode-revert-buffer-resistance ()
(let ((temp-file (make-temp-file "ein")))
(unwind-protect
(with-temp-buffer
(setq buffer-file-name temp-file)
(ein:connect-mode 1)
(setq ein:%connect% 'very-important-value)
(revert-buffer t t nil)
(should ein:connect-mode)
(should (eq ein:%connect% 'very-important-value)))
(delete-file temp-file))))

25
test/test-ein-console.el Normal file
View file

@ -0,0 +1,25 @@
(require 'ein-console)
(ert-deftest ein:console-security-dir-string ()
(let ((ein:console-security-dir "/some/dir/"))
(should (equal (ein:console-security-dir-get "DUMMY-URL-OR-PORT")
ein:console-security-dir))))
(ert-deftest ein:console-security-dir-list ()
(let ((ein:console-security-dir
'((8888 . "/dir/8888/")
("htttp://dummy.org" . "/dir/http/")
(7777 . my-secret-directory)
(default . "/dir/default/")))
(my-secret-directory "/dir/secret/"))
(should (equal (ein:console-security-dir-get 8888) "/dir/8888/"))
(should (equal (ein:console-security-dir-get "htttp://dummy.org")
"/dir/http/"))
(should (equal (ein:console-security-dir-get 7777) "/dir/secret/"))
(should (equal (ein:console-security-dir-get 9999) "/dir/default/"))))
(ert-deftest ein:console-security-dir-func ()
(let ((ein:console-security-dir
'(lambda (x) (should (equal x "DUMMY-URL-OR-PORT")) "/dir/")))
(should (equal (ein:console-security-dir-get "DUMMY-URL-OR-PORT")
"/dir/"))))

38
test/test-ein-content.el Normal file
View file

@ -0,0 +1,38 @@
;;; test-ein-content.el --- Testing content interface
;; Copyright (C) 2015 John Miller
;; Authors: Takafumi Arakaki <aka.tkf at gmail.com>
;; John M. Miller <millejoh at mac.com>
;; This file is NOT part of GNU Emacs.
;; test-ein-content.el is free software: you can redistribute it
;; and/or modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation, either version 3 of
;; the License, or (at your option) any later version.
;; test-ein-content.el is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with ein-testing-notebook.el.
;; If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(eval-when-compile (require 'cl))
(require 'ein-contents-api)
(defvar *list-content-result* nil)
(defun ein-test-list-contents-1 ()
(ein:content-list-contents "" )
)

92
test/test-ein-core.el Normal file
View file

@ -0,0 +1,92 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-core)
;;; `ein:version'
(ert-deftest ein:version ()
"Check if `ein:version' can be parsed by `version-to-list'."
(version-to-list ein:version))
(ert-deftest ein:version-func-prefix-is-the-variable ()
(should (string-prefix-p ein:version (ein:version)))
(let ((default-directory "/tmp/"))
(should (string-prefix-p ein:version (ein:version)))))
(ert-deftest ein:version-func-outside-of-git-repo ()
(flet ((ein:git-root-p (dir) nil))
(should (equal (ein:version) ein:version)))
(flet ((ein:git-revision-dirty () nil))
(should (equal (ein:version) ein:version))))
;; Generic getter
(defmacro eintest:generic-getter-should-return-nil (func)
"In an \"empty\" context, generic getter should return nil."
`(ert-deftest ,(intern (format "%s--nil name" func)) ()
(with-temp-buffer
(should (not (,func))))))
(eintest:generic-getter-should-return-nil ein:get-url-or-port)
(eintest:generic-getter-should-return-nil ein:get-notebook)
(eintest:generic-getter-should-return-nil ein:get-kernel)
(eintest:generic-getter-should-return-nil ein:get-cell-at-point)
(eintest:generic-getter-should-return-nil ein:get-traceback-data)
;;; File name translation
;; Requiring `tramp' during (inside of) tests yields error from
;; MuMaMo. Although I don't understand the reason, requiring it
;; before running tests workarounds this problem.
(require 'tramp)
(ert-deftest ein:filename-translations-from-to-tramp ()
(loop with ein:filename-translations =
`((8888 . ,(ein:tramp-create-filename-translator "HOST" "USER")))
with filename = "/file/name"
for port in '(7777 8888) ; check for the one w/o translation
for emacs-filename = (ein:filename-from-python port filename)
do (message "emacs-filename = %s" emacs-filename)
do (should
(equal (ein:filename-to-python port emacs-filename)
filename))))
(ert-deftest ein:filename-translations-to-from-tramp ()
(loop with ein:filename-translations =
`((8888 . ,(ein:tramp-create-filename-translator "HOST" "USER")))
with filename = "/USER@HOST:/filename"
for port in '(8888)
do (should
(equal (ein:filename-from-python
port (ein:filename-to-python port filename))
filename))))
(ert-deftest ein:filename-to-python-tramp ()
(let* ((port 8888)
(ein:filename-translations
`((,port . ,(ein:tramp-create-filename-translator "DUMMY")))))
(loop with python-filename = "/file/name"
for emacs-filename in '("/scpc:HOST:/file/name"
"/USER@HOST:/file/name")
do (should
(equal (ein:filename-to-python port emacs-filename)
python-filename)))
;; Error: Not a Tramp file name: /file/name
(should-error (ein:filename-to-python port "/file/name"))))
(ert-deftest ein:filename-from-python-tramp ()
(loop with ein:filename-translations =
`((8888 . ,(ein:tramp-create-filename-translator "HOST" "USER")))
with python-filename = "/file/name"
for emacs-filename in '("/USER@HOST:/file/name" "/file/name")
for port in '(8888 7777)
do (should
(equal (ein:filename-from-python port python-filename)
emacs-filename))))

43
test/test-ein-iexec.el Normal file
View file

@ -0,0 +1,43 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-iexec)
(require 'ein-testing-notebook)
;;; `ein:iexec-should-execute-p'
(defun* eintest:iexec-should-execute-p (cell &key (this-command t) beg end)
"Simple wrapper for `ein:iexec-should-execute-p' which
returns `t' by default, if the CELL is code cell."
(unless beg (setq beg (ein:cell-input-pos-min cell)))
(unless end (setq end (ein:cell-input-pos-max cell)))
(ein:iexec-should-execute-p cell beg end))
;; cell types
(ert-deftest ein:iexec-should-execute-p-codecell ()
(ein:testing-with-one-cell 'code
(should (eintest:iexec-should-execute-p cell))))
(ert-deftest ein:iexec-should-execute-p-markdowncell ()
(ein:testing-with-one-cell 'markdown
(should-not (eintest:iexec-should-execute-p cell))))
(ert-deftest ein:iexec-should-execute-p-dead-cell ()
(ein:testing-with-one-cell 'code
(should-not (eintest:iexec-should-execute-p (ein:cell-copy cell)))))
;; other
(ert-deftest ein:iexec-should-execute-p-non-interactive ()
(ein:testing-with-one-cell 'code
(should-not (eintest:iexec-should-execute-p cell :this-command nil))))
(ert-deftest ein:iexec-should-execute-p-beg-too-small ()
(ein:testing-with-one-cell 'code
(should-not (eintest:iexec-should-execute-p cell :beg (point-min)))))
(ert-deftest ein:iexec-should-execute-p-end-too-big ()
(ein:testing-with-one-cell 'code
(should-not (eintest:iexec-should-execute-p cell :end (point-max)))))

80
test/test-ein-kernel.el Normal file
View file

@ -0,0 +1,80 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-kernel)
(require 'ein-testing-kernel)
(defun eintest:kernel-new (port)
(ein:kernel-new port "/api/kernels"
(get-buffer-create "*eintest: dummy for kernel test*")))
(ert-deftest ein:kernel-start-check-url ()
(let* ((kernel (eintest:kernel-new 8888))
(notebook-id "NOTEBOOK-ID")
(desired-url "http://127.0.0.1:8888/api/sessions")
(dummy-response (make-request-response))
got-url)
(flet ((request (url &rest ignore) (setq got-url url) dummy-response)
(set-process-query-on-exit-flag (process flag)))
(ein:kernel-start kernel notebook-id)
(should (equal got-url desired-url)))))
(ert-deftest ein:kernel-restart-check-url ()
(let* ((kernel (eintest:kernel-new 8888))
(kernel-id "KERNEL-ID")
(session-id "SESSION-ID")
(desired-url "http://127.0.0.1:8888/api/kernels/KERNEL-ID/restart")
(dummy-response (make-request-response))
got-url)
(flet ((request (url &rest ignore) (setq got-url url) dummy-response)
(set-process-query-on-exit-flag (process flag))
(ein:kernel-stop-channels (&rest ignore))
(ein:websocket (&rest ignore) (make-ein:$websocket))
(ein:events-trigger (&rest ignore)))
(ein:kernel--kernel-started
kernel :data (list :ws_url "ws://127.0.0.1:8888" :id kernel-id))
(ein:kernel-restart kernel)
(should (equal got-url desired-url)))))
(ert-deftest ein:kernel-interrupt-check-url ()
(let* ((kernel (eintest:kernel-new 8888))
(kernel-id "KERNEL-ID")
(desired-url "http://127.0.0.1:8888/api/kernels/KERNEL-ID/interrupt")
(dummy-response (make-request-response))
got-url)
(flet ((request (url &rest ignore) (setq got-url url) dummy-response)
(set-process-query-on-exit-flag (process flag))
(ein:kernel-stop-channels (&rest ignore))
(ein:websocket (&rest ignore) (make-ein:$websocket)))
(ein:kernel--kernel-started
kernel :data (list :ws_url "ws://127.0.0.1:8888" :id kernel-id))
(ein:kernel-interrupt kernel)
(should (equal got-url desired-url)))))
(ert-deftest ein:kernel-kill-check-url ()
(let* ((kernel (eintest:kernel-new 8888))
(kernel-id "KERNEL-ID")
(desired-url "http://127.0.0.1:8888/api/kernels/KERNEL-ID")
(dummy-response (make-request-response))
got-url)
(flet ((request (url &rest ignore) (setq got-url url) dummy-response)
(set-process-query-on-exit-flag (process flag))
(ein:kernel-stop-channels (&rest ignore))
(ein:websocket (&rest ignore) (make-ein:$websocket)))
(ein:kernel--kernel-started
kernel :data (list :ws_url "ws://127.0.0.1:8888" :id kernel-id))
(ein:kernel-kill kernel)
(should (equal got-url desired-url)))))
;;; Test `ein:kernel-construct-help-string'
(ert-deftest ein:kernel-construct-help-string-when-found ()
(ein:testing-kernel-construct-help-string-loop))
(ert-deftest ein:kernel-construct-help-string-when-not-found ()
(should (equal (ein:kernel-construct-help-string nil) nil)))
;; Included in `ein:kernel-construct-help-string-when-found', but test
;; it explicitly to be sure.

View file

@ -0,0 +1,41 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-kill-ring)
(ert-deftest ein:kill-ring-simple ()
(let (ein:kill-ring
ein:kill-ring-yank-pointer)
(ein:kill-new 1)
(should (equal (ein:current-kill 0) 1))))
(defun eintest:kill-ring-simple-repeat-setup ()
(loop for i from 0 below 5
do (ein:kill-new i)
do (should (equal (ein:current-kill 0) i))))
(ert-deftest ein:kill-ring-simple-repeat ()
(let (ein:kill-ring
ein:kill-ring-yank-pointer)
(eintest:kill-ring-simple-repeat-setup)
(should (equal ein:kill-ring ein:kill-ring-yank-pointer))
(should (equal ein:kill-ring '(4 3 2 1 0)))))
(ert-deftest ein:kill-ring-repeat-n-1 ()
(let (ein:kill-ring
ein:kill-ring-yank-pointer)
(eintest:kill-ring-simple-repeat-setup)
(loop for i in '(3 2 1 0 4 3 2)
do (should (equal (ein:current-kill 1) i)))
(should-not (equal ein:kill-ring ein:kill-ring-yank-pointer))
(should (equal ein:kill-ring '(4 3 2 1 0)))
(should (equal ein:kill-ring-yank-pointer '(2 1 0)))))
(ert-deftest ein:kill-ring-exceeds-max ()
(let (ein:kill-ring
ein:kill-ring-yank-pointer
(ein:kill-ring-max 3))
(eintest:kill-ring-simple-repeat-setup)
(should (equal ein:kill-ring ein:kill-ring-yank-pointer))
(should (equal (length ein:kill-ring) ein:kill-ring-max))
(should (equal ein:kill-ring '(4 3 2)))))

82
test/test-ein-node.el Normal file
View file

@ -0,0 +1,82 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-node)
(defun ein:testing-node-dummy-ewco-node (data)
`[nil nil ,data])
(defun ein:testing-node-ewoc-data (ewoc-node)
(ein:$node-data (ewoc-data ewoc-node)))
(ert-deftest ein:testing-node-dummy-ewco-node ()
(let* ((obj "some-object")
(ewoc-node (ein:testing-node-dummy-ewco-node obj)))
(should (eq (ewoc-data ewoc-node) obj))))
(ert-deftest ein:node-filter-is ()
(let ((en-list (mapcar
#'ein:testing-node-dummy-ewco-node
(list (ein:node-new nil "s" '(spam sag))
(ein:node-new nil "p" '(spam))
(ein:node-new nil "e" '(egg))
(ein:node-new nil "a" '(spam sag))
(ein:node-new nil "g" '(egg sag))
(ein:node-new nil "m" '(spam))
(ein:node-new nil "g" '(egg))))))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :is 'spam))
'("s" "p" "a" "m")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :is 'egg))
'("e" "g" "g")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :is 'sag))
'("s" "a" "g")))))
(ert-deftest ein:node-filter-not ()
(let ((en-list (mapcar
#'ein:testing-node-dummy-ewco-node
(list (ein:node-new nil "s" '(spam sag))
(ein:node-new nil "p" '(spam))
(ein:node-new nil "e" '(egg))
(ein:node-new nil "a" '(spam sag))
(ein:node-new nil "g" '(egg sag))
(ein:node-new nil "m" '(spam))
(ein:node-new nil "g" '(egg))))))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :not 'spam))
'("e" "g" "g")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :not 'egg))
'("s" "p" "a" "m")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :not 'sag))
'("p" "e" "m" "g")))))
(ert-deftest ein:node-filter-is-and-not ()
(let ((en-list (mapcar
#'ein:testing-node-dummy-ewco-node
(list (ein:node-new nil "s" '(spam sag))
(ein:node-new nil "p" '(spam))
(ein:node-new nil "e" '(egg))
(ein:node-new nil "a" '(spam sag))
(ein:node-new nil "g" '(egg sag))
(ein:node-new nil "m" '(spam))
(ein:node-new nil "g" '(egg))))))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :not 'spam :is 'sag))
'("g")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :is 'sag :not 'spam))
'("g")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :is 'spam :is 'sag))
'("s" "a")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :is 'sag :not 'spam
:not 'not-existing))
'("g")))
(should (equal (mapcar #'ein:testing-node-ewoc-data
(ein:node-filter en-list :is 'sag :is 'spam))
'("s" "a")))))

1347
test/test-ein-notebook.el Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
(require 'ein-notebooklist)
(defun eintest:notebooklist-make-empty (&optional url-or-port)
"Make empty notebook list buffer."
(ein:notebooklist-url-retrieve-callback (or url-or-port "DUMMY-URL")
(ein:query-ipython-version)
""))
(defmacro eintest:notebooklist-is-empty-context-of (func)
`(ert-deftest ,(intern (format "%s--notebooklist" func)) ()
(with-current-buffer (eintest:notebooklist-make-empty)
(should-not (,func)))))
;; Generic getter
(ert-deftest ein:get-url-or-port--notebooklist ()
(with-current-buffer (eintest:notebooklist-make-empty "DUMMY-URL")
(should (equal (ein:get-url-or-port) "DUMMY-URL"))))
(eintest:notebooklist-is-empty-context-of ein:get-notebook)
(eintest:notebooklist-is-empty-context-of ein:get-kernel)
(eintest:notebooklist-is-empty-context-of ein:get-cell-at-point)
(eintest:notebooklist-is-empty-context-of ein:get-traceback-data)

View file

@ -0,0 +1,79 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-notification)
(defun ein:testing-notification-tab-mock ()
(make-instance 'ein:notification-tab
:get-list (lambda () '(a b c))
:get-current (lambda () 'a)
:get-name #'ignore))
(ert-deftest ein:header-line-normal ()
(let* ((ein:%notification% (ein:notification "NotificationTest"))
(kernel (oref ein:%notification% :kernel)))
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
(should (equal (ein:header-line)
"IP[y]: /1\\ /2\\ /3\\ [+]"))))
(ert-deftest ein:header-line-kernel-status-busy ()
(let* ((ein:%notification% (ein:notification "NotificationTest"))
(kernel (oref ein:%notification% :kernel)))
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
(ein:notification-status-set kernel
'status_busy.Kernel)
(should (equal (ein:header-line)
"IP[y]: Kernel is busy... | /1\\ /2\\ /3\\ [+]"))))
(ert-deftest ein:header-line-notebook-status-busy ()
(let* ((ein:%notification% (ein:notification "NotificationTest"))
(notebook (oref ein:%notification% :notebook)))
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
(ein:notification-status-set notebook
'notebook_saved.Notebook)
(should (equal (ein:header-line)
"IP[y]: Notebook is saved | /1\\ /2\\ /3\\ [+]"))))
(ert-deftest ein:header-line-notebook-complex ()
(let* ((ein:%notification% (ein:notification "NotificationTest"))
(kernel (oref ein:%notification% :kernel))
(notebook (oref ein:%notification% :notebook)))
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
(ein:notification-status-set kernel
'status_dead.Kernel)
(ein:notification-status-set notebook
'notebook_saving.Notebook)
(should (equal
(ein:header-line)
(concat "IP[y]: Saving Notebook... | "
"Kernel is dead. Need restart. | "
"/1\\ /2\\ /3\\ [+]")))))
(ert-deftest ein:notification-and-events ()
(let* ((notification (ein:notification "NotificationTest"))
(kernel (oref notification :kernel))
(notebook (oref notification :notebook))
(events (ein:events-new))
(event-symbols
'(notebook_saved.Notebook
notebook_saving.Notebook
notebook_save_failed.Notebook
execution_count.Kernel
status_restarting.Kernel
status_idle.Kernel
status_busy.Kernel
status_dead.Kernel
))
(callbacks (oref events :callbacks)))
(ein:notification-bind-events notification events)
(mapc (lambda (s) (should (gethash s callbacks))) event-symbols)
(should (= (hash-table-count callbacks) (length event-symbols)))
(should (equal (oref kernel :status) nil))
(loop for et in (mapcar #'car (oref kernel :s2m))
do (ein:events-trigger events et)
do (should (equal (oref kernel :status) et))
do (should (equal (oref notebook :status) nil)))
(loop for et in (mapcar #'car (oref notebook :s2m))
do (ein:events-trigger events et)
do (should (equal (oref kernel :status) 'status_dead.Kernel))
do (should (equal (oref notebook :status) et)))))

View file

@ -0,0 +1,44 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-output-area)
(defun ein:testing-insert-html--fix-urls-do-test (source desired)
(setq source (ein:xml-parse-html-string source))
(setq desired (ein:xml-parse-html-string desired))
(ein:insert-html--fix-urls source 8888)
(should (equal source desired)))
(defmacro ein:testing-insert-html--fix-urls-deftests (args-list)
`(progn
,@(loop for i from 0
for args in args-list
for test = (intern (format "ein:insert-html--fix-urls/%s" i))
collect
`(ert-deftest ,test ()
(ein:testing-insert-html--fix-urls-do-test ,@args)))))
(when (require 'shr nil t)
(ein:testing-insert-html--fix-urls-deftests
(;; Simple replaces
("<a href=files/spam>text</a>"
"<a href=http://127.0.0.1:8888/files/spam>text</a>")
("<a href=/files/spam>text</a>"
"<a href=http://127.0.0.1:8888/files/spam>text</a>")
("<img src=files/sample.png />"
"<img src=http://127.0.0.1:8888/files/sample.png />")
("<img src=/files/sample.png />"
"<img src=http://127.0.0.1:8888/files/sample.png />")
;; Do not modify dom in these cases:
("<a>text</a>"
"<a>text</a>")
("<a href=http://example>text</a>"
"<a href=http://example>text</a>")
("<img src=http://example />"
"<img src=http://example />")
;; Bit more complicated cases:
("<p><a href=files/spam>link</a> normal</p>"
"<p><a href=http://127.0.0.1:8888/files/spam>link</a> normal</p>")
("<img><img src=files/sample.png /> normal</p>"
"<img><img src=http://127.0.0.1:8888/files/sample.png /> normal</p>")
)))

27
test/test-ein-pytools.el Normal file
View file

@ -0,0 +1,27 @@
(require 'ert)
(when load-file-name
(add-to-list 'load-path
(concat (file-name-directory load-file-name) "mocker")))
(require 'mocker)
(require 'ein-pytools)
(require 'ein-testing-kernel)
(ert-deftest ein:pytools-finish-tooltip ()
(ein:testing-kernel-construct-help-string-loop
(lambda (content result)
(if result
(mocker-let
((featurep
(feature)
((:input '(pos-tip) :output t)))
(pos-tip-show
(string &optional tip-color pos window timeout)
((:input (list result 'ein:pos-tip-face nil nil 0)))))
(let ((window-system t))
(ein:pytools-finish-tooltip '-not-used- content '-not-used-)))
(mocker-let
((featurep (feature) ()))
(ein:pytools-finish-tooltip '-not-used- content '-not-used-))))))

View file

@ -0,0 +1,28 @@
(require 'ein-shared-output)
(defmacro eintest:shared-output-with-buffer (&rest body)
(declare (indent 0))
`(with-current-buffer (ein:shared-output-create-buffer)
(ein:shared-output-get-or-create)
,@body))
(defmacro eintest:shared-output-is-empty-context-of (func)
`(ert-deftest ,(intern (format "%s--shared-output" func)) ()
(eintest:shared-output-with-buffer
(should-not (,func)))))
;; Generic getter
(ert-deftest ein:get-cell-at-point--shared-output ()
(eintest:shared-output-with-buffer
(should (eq (ein:get-cell-at-point)
(ein:shared-output-get-cell))))
(with-temp-buffer
(should-not (ein:get-cell-at-point--shared-output))))
;; FIXME: Add tests with non-empty shared output buffer.
(eintest:shared-output-is-empty-context-of ein:get-url-or-port)
(eintest:shared-output-is-empty-context-of ein:get-notebook)
(eintest:shared-output-is-empty-context-of ein:get-kernel)
(eintest:shared-output-is-empty-context-of ein:get-traceback-data)

View file

@ -0,0 +1,8 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-smartrep)
(ert-deftest ein:smartrep-notebook-mode-alist-fboundp ()
(loop for (k . f) in ein:smartrep-notebook-mode-alist
do (should (fboundp f))))

182
test/test-ein-utils.el Normal file
View file

@ -0,0 +1,182 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein) ; for `ein:version'
(require 'ein-utils)
(ert-deftest ein-url-simple ()
(should (equal (ein:url 8888) "http://127.0.0.1:8888"))
(should (equal (ein:url "http://localhost") "http://localhost")))
(ert-deftest ein-url-slashes ()
(loop for a in '("a" "a/" "/a")
do (loop for b in '("b" "/b")
do (should (equal (ein:url 8888 a b)
"http://127.0.0.1:8888/a/b")))
do (should (equal (ein:url 8888 a "b/")
"http://127.0.0.1:8888/a/b/"))))
(ert-deftest ein-trim-simple ()
(should (equal (ein:trim "a") "a"))
(should (equal (ein:trim " a ") "a"))
(should (equal (ein:trim "\na\n") "a")))
(ert-deftest ein-trim-middle-spaces ()
(should (equal (ein:trim "a b") "a b"))
(should (equal (ein:trim " a b ") "a b"))
(should (equal (ein:trim "\na b\n") "a b")))
(ert-deftest ein-trim-left-simple ()
(should (equal (ein:trim-left "a") "a"))
(should (equal (ein:trim-left " a ") "a "))
(should (equal (ein:trim-left "\na\n") "a\n")))
(ert-deftest ein-trim-right-simple ()
(should (equal (ein:trim-right "a") "a"))
(should (equal (ein:trim-right " a ") " a"))
(should (equal (ein:trim-right "\na\n") "\na")))
(ert-deftest ein:trim-indent-empty ()
(should (equal (ein:trim-indent "") "")))
(ert-deftest ein:trim-indent-one-line ()
(should (equal (ein:trim-indent "one line") "one line")))
(ert-deftest ein:trim-indent-one-newline ()
(should (equal (ein:trim-indent "one line\n") "one line\n")))
(ert-deftest ein:trim-indent-multi-lines-no-trim ()
(let ((original "\
def func():
pass
")
(trimmed "\
def func():
pass
"))
(should (equal (ein:trim-indent original) trimmed))))
(ert-deftest ein:trim-indent-multi-lines-one-trim ()
(let ((original "\
def func():
pass
")
(trimmed "\
def func():
pass
"))
(should (equal (ein:trim-indent original) trimmed))))
(ert-deftest ein:trim-indent-multi-lines-with-empty-lines ()
(let ((original "\
def func():
pass
")
(trimmed "\
def func():
pass
"))
(should (equal (ein:trim-indent original) trimmed))))
;;; Text manipulation on buffer
(ert-deftest ein:find-leftmot-column-simple-cases ()
(loop for (indent text) in
'(;; No indent
(0 "\
def f():
pass")
;; Indented python code
(4 "\
def f():
pass")
;; Deeper indent can come first
(4 "\
# indent = 8
# indent 4")
;; With empty lines
(4 "\
# indent = 8
# indent 4
")
)
do (with-temp-buffer
(insert text)
(should (= (ein:find-leftmot-column (point-min) (point-max))
indent)))))
;;; Misc
(ert-deftest ein:list-insert-after ()
(should (equal (ein:list-insert-after '(a) 'a 'X) '(a X)))
(should (equal (ein:list-insert-after '(a b c) 'a 'X) '(a X b c)))
(should (equal (ein:list-insert-after '(a b c) 'b 'X) '(a b X c)))
(should (equal (ein:list-insert-after '(a b c) 'c 'X) '(a b c X)))
(should-error (ein:list-insert-after '(a b c) 'd 'X)))
(ert-deftest ein:list-insert-before ()
(should (equal (ein:list-insert-before '(a) 'a 'X) '(X a)))
(should (equal (ein:list-insert-before '(a b c) 'a 'X) '(X a b c)))
(should (equal (ein:list-insert-before '(a b c) 'b 'X) '(a X b c)))
(should (equal (ein:list-insert-before '(a b c) 'c 'X) '(a b X c)))
(should-error (ein:list-insert-before '(a b c) 'd 'X)))
(ert-deftest ein:list-move-left ()
(should (equal (ein:list-move-left '(a) 'a) '(a)))
(should (equal (ein:list-move-left '(a b) 'a) '(b a)))
(should (equal (ein:list-move-left '(a b) 'b) '(b a)))
(should (equal (ein:list-move-left '(a b c d) 'a) '(b c d a)))
(should (equal (ein:list-move-left '(a b c d) 'b) '(b a c d)))
(should (equal (ein:list-move-left '(a b c d) 'c) '(a c b d)))
(should (equal (ein:list-move-left '(a b c d) 'd) '(a b d c)))
(should-error (ein:list-move-left '(a b c d) 'X)))
(ert-deftest ein:list-move-right ()
(should (equal (ein:list-move-right '(a) 'a) '(a)))
(should (equal (ein:list-move-right '(a b) 'a) '(b a)))
(should (equal (ein:list-move-right '(a b) 'b) '(b a)))
(should (equal (ein:list-move-right '(a b c d) 'a) '(b a c d)))
(should (equal (ein:list-move-right '(a b c d) 'b) '(a c b d)))
(should (equal (ein:list-move-right '(a b c d) 'c) '(a b d c)))
(should (equal (ein:list-move-right '(a b c d) 'd) '(d a b c)))
(should-error (ein:list-move-right '(a b c d) 'X)))
(defun ein:testing-choose-setting-should-equal
(setting value desired &optional single-p)
(let ((setting setting))
(should (equal (ein:choose-setting 'setting value single-p) desired))))
(ert-deftest ein:choose-setting-single-string ()
(let ((test 'ein:testing-choose-setting-should-equal))
(funcall test "a" nil "a")
(funcall test "a" 'whatever "a")))
(ert-deftest ein:choose-setting-single-int ()
(let ((test #'ein:testing-choose-setting-should-equal))
(funcall test 1 nil 1 #'integerp)
(funcall test 1 'whatever 1 #'integerp)))
(ert-deftest ein:choose-setting-alist ()
(let* ((test (lambda (&rest args)
(apply #'ein:testing-choose-setting-should-equal
'(("a" . 1) ("b" . 2) ("c" . 3))
args))))
(funcall test "a" 1)
(funcall test "b" 2)))
(ert-deftest ein:choose-setting-func ()
(let* ((test (lambda (&rest args)
(apply #'ein:testing-choose-setting-should-equal
(lambda (x) 1)
args))))
(funcall test nil 1)
(funcall test 'whatever 1)))

View file

@ -0,0 +1,47 @@
(eval-when-compile (require 'cl))
(require 'ert)
(require 'ein-notebook)
(require 'ein-testing-notebook)
;;; Event handler
(defun ein:testing-worksheet-set-dirty
(pre-dirty value post-dirty fired-in)
(with-current-buffer (ein:testing-make-notebook-with-outputs '(nil))
(when pre-dirty
(ein:cell-goto (ein:worksheet-get-current-cell))
(insert "something"))
(should (equal (ein:worksheet-modified-p ein:%worksheet%) pre-dirty))
(with-current-buffer (funcall fired-in)
(let ((events (oref ein:%worksheet% :events))
(cell (ein:worksheet-get-current-cell)))
(ein:events-trigger events 'set_dirty.Worksheet
(list :cell cell :value value))))
(should (equal (ein:worksheet-modified-p ein:%worksheet%) post-dirty))))
(defun ein:testing-scratchsheet-buffer ()
(ein:worksheet-buffer (ein:notebook-scratchsheet-open ein:%notebook%)))
(defmacro ein:testing-worksheet-set-dirty-deftest
(pre-dirty value post-dirty &optional fired-in)
(let ((name (intern (format "ein:worksheet-set-dirty/%s-to-%s-fired-in-%s"
pre-dirty value
(or fired-in "current-buffer"))))
(fired-in-defun
(case fired-in
(scratchsheet 'ein:testing-scratchsheet-buffer)
(t 'current-buffer))))
`(ert-deftest ,name ()
(ein:testing-worksheet-set-dirty ,pre-dirty ,value ,post-dirty
#',fired-in-defun))))
(ein:testing-worksheet-set-dirty-deftest t nil nil)
(ein:testing-worksheet-set-dirty-deftest t t t )
(ein:testing-worksheet-set-dirty-deftest nil nil nil)
(ein:testing-worksheet-set-dirty-deftest nil t t )
(ein:testing-worksheet-set-dirty-deftest t nil t scratchsheet)
(ein:testing-worksheet-set-dirty-deftest t t t scratchsheet)
(ein:testing-worksheet-set-dirty-deftest nil nil nil scratchsheet)
(ein:testing-worksheet-set-dirty-deftest nil t nil scratchsheet)

View file

@ -0,0 +1,40 @@
(require 'ert)
(require 'ein-worksheet)
(require 'ein-testing-cell)
(defvar ein:testing-worksheet-example-data
(list (ein:testing-codecell-data "code example input")
(ein:testing-markdowncell-data "markdown example input")
(ein:testing-rawcell-data "raw example input")
(ein:testing-htmlcell-data "html example input")
(ein:testing-headingcell-data "heading example input")))
(defun ein:testing-worksheet-new ()
(make-instance 'ein:worksheet
:discard-output-p (cons #'ignore nil)))
(defun ein:testing-worksheet-to-json (cells &optional metadata)
(let* ((ws-0 (ein:worksheet-from-json (ein:testing-worksheet-new)
(list :cells cells
:metadata metadata)))
(ws-1 (ein:testing-worksheet-new))
(json-0 (ein:worksheet-to-json ws-0))
(json-1 (ein:worksheet-to-json
(ein:worksheet-from-json ws-1
(ein:json-read-from-string
(json-encode json-0))))))
(let* ((found (assoc 'metadata json-0)))
(when found
(should (cdr found))))
(should (equal json-0 json-1))))
(ert-deftest ein:worksheet-to-json/empty ()
(ein:testing-worksheet-to-json nil))
(ert-deftest ein:worksheet-to-json/example-data ()
(ein:testing-worksheet-to-json ein:testing-worksheet-example-data))
(ert-deftest ein:worksheet-to-json/example-data-with-metadata ()
(ein:testing-worksheet-to-json ein:testing-worksheet-example-data
'(:name "Worksheet name")))

44
test/test-load.el Normal file
View file

@ -0,0 +1,44 @@
;; Load all test-ein-*.el files for interactive/batch use.
;; Usage:
;; emacs -Q -batch -L ... -l tests/test-load.el -f ert-run-tests-batch
;; You will need to set load paths using `-L' switch.
(prefer-coding-system 'utf-8)
(require 'ein-dev)
(require 'ein-testing)
(require 'ein-jupyter)
(require 'deferred)
(ein:log 'info "Starting jupyter notebook server.")
(defvar *ein:testing-jupyter-server-command* (or (getenv "JUPYTER_TESTING_COMMAND")
(executable-find "jupyter"))
"Path to command that starts the jupyter notebook server.")
(defvar *ein:testing-jupyter-server-directory* (or (getenv "JUPYTER_TESTING_DIR") (concat default-directory "test"))
"Location where to start the jupyter notebook server.")
(defvar *ein:testing-port* nil)
(defvar *ein:testing-token* nil)
(ein:setq-if-not ein:testing-dump-file-log "test-batch-log.log")
(ein:setq-if-not ein:testing-dump-file-messages "test-batch-messages.log")
(setq message-log-max t)
(setq ein:force-sync t)
(ein:log 'info "Staring local jupyter notebook server.")
(setq ein:jupyter-server-args '("--no-browser" "--debug"))
(deferred:sync! (ein:jupyter-server-start *ein:testing-jupyter-server-command* *ein:testing-jupyter-server-directory*))
(multiple-value-bind (url token) (ein:jupyter-server-conn-info)
(ein:log 'info (format "testing-start-server url: %s, token: %s" url token))
(setq *ein:testing-port* url)
(setq *ein:testing-token* token)
(ein:log 'info "testing-start-server succesfully logged in."))
(ein:load-files "^test-ein-.*\\.el$"
"./" ;(file-name-directory load-file-name)
t) ; ignore-compiled