ISO ert inline test idiom (appending TEST_OUTPUT from multiple ert calls) - emacs

---+ BRIEF
Q: if I have multiple, separate, independent calls to ert, can I arrange to concatenate the output of these tests in the same buffer? With the calls to ert being made at different times?
(Without a centralized thingamajig that knows about these independent tests.)
E.g. if I have two (or more) tests, e.g. in a .emacs file
(ert-deftest test1 ()(should t))
(ert 'test1)
... many miles away, quite likely in a separate file ...
(ert-deftest test2 ()(should t))
(ert 'test2)
Both will run - I can tell this by looking at *Messages*
...
Running 1 tests (2017-07-07 12:10:39-0700)
passed 1/1 test_ag_non-null_and_true
...
Running 1 tests (2017-07-07 12:10:39-0700)
passed 1/1 test-ag-code-disabling
...
But the *ert* buffer will only contain output for the last test run.
---+ DETAIL
---++ MOTIVATION
Q: Why do I want to do this?
A: "inline testing". In particular, inline testing of stuff in my .emacs file (and in files it loads and/or requires).
Tests that are run every time .emacs or similar file is loaded. (There may be other tests that I run in batch mode - but here I am talking about tests that I want to run right away, every time .emacs is loaded (and convenient for edit/debug while modifying .emacs).
I.e. I am looking for an idiom for inline tests.
I have been putting code in my .emacs and ~/lib/gnu-emacs/**.el files that looks like this:
;; some blob of code
(defun foo (arg) ... )
(ert-deftest test-foo () ... )
(ert 'test-foo)
i.e. I define the function, the test, and run the test, right next to each other.
... I might as well admit that I often wrap a `progn' around,
(progn
;; some blob of code
(defun foo (arg) ... )
(ert-deftest test-foo () ... )
(ert 'test-foo)
)
because this makes it easy to make an edit to function foo or the test, and then jump to the end of the progn and do eval-last-sexp (which I have bound to C-j). And I often also wrap an if or and and around, to make it easy to disable a feature that is in development. Sometimes with let* in then mix, if the feature has variables.
(I have used other ert- family runners, like ert-run-tests-batch and ert-run-tests-interactively. But plain old ert seems enough.)
(Putting defun and deftest inside a progn or other breaks some tools that expect defun to always be at top level. And it makes multiline docstrings even uglier. But it is darn convenient, and IMHO tools that operate on programming language files should parse the programming language.)
So, later, I will do the same thing for another module. Far away. Possibly in a separate file, possibly a library file.
(progn
;; some blob of code
(defun bar (arg) ... )
(ert-deftest test-bar () ... )
(ert 'test-bar)
)
Neither module should know about the other.
Nor should there be a centralized module that has a list of all such tests, that get run at the end.
If only because there may be a failure partway through loading the file. And it is convenient to know what tests up to that point passed or failed.
(Whereas collecting and running all tests at the end loses that incremental test running ability.)
---++ Should be a macro
I hate repetition. E.g. in the stuff below, I hate having to type BAR three times.
(progn
;; some blob of code
(defun BAR (arg) ... )
(ert-deftest test-BAR () ... )
(ert 'test-BAR)
)
Therefore, of course I will create a macro that reduces this repetition. Although then folks looking for the ert-deftest will get confused...
---++ MEDIUM LENGTH SIMPLE EXAMPLE
If I have
(ert-deftest test1 ()(should t))
(ert 'test1)
I will get a nice *ert* buffer
Selector: test1
Passed: 1
Failed: 0
Skipped: 0
Total: 1/1
Started at: 2017-07-07 14:16:06-0700
Finished.
Finished at: 2017-07-07 14:16:07-0700
.
and if later I have
(ert-deftest test2 () (should t))
(ert 'test2)
It will erase the output of test1 in the *ert* buffer, and replace it with
Selector: test2
Passed: 1
Failed: 0
Skipped: 0
Total: 1/1
Started at: 2017-07-07 14:15:47-0700
Finished.
Finished at: 2017-07-07 14:15:47-0700
.
What I would like is to have the output of both tests concatenated:
Selector: test1
Passed: 1
Failed: 0
Skipped: 0
Total: 1/1
Started at: 2017-07-07 14:16:06-0700
Finished.
Finished at: 2017-07-07 14:16:07-0700
.
Selector: test2
Passed: 1
Failed: 0
Skipped: 0
Total: 1/1
Started at: 2017-07-07 14:15:47-0700
Finished.
Finished at: 2017-07-07 14:15:47-0700
.

As so often happens, the act of posting the question suggests the answer.
Although it is somewhat ugly, and certainly non-standard. So if anyone posts a concise standard-ish way, I will accept such an answer.
The IMHO ugly way:
When I do
(progn
;; some blob of code
(defun foo (arg) ... )
(ert-deftest test-foo () ... )
(ert 'test-foo)
)
I can add more code to manipulate the ert output buffer:
(progn
;; some blob of code
(defun foo (arg) ... )
(ert-deftest test-foo () ... )
(ert 'test-foo)
...append `*ert*' contents to `*ert-multiple-independent-tests*'
)
(Less to type if macro-fied)
This is obvious. I was hoping that the "automated self-test" arguments of `ert' might accomplish something similar.
ert is an alias for ‘ert-run-tests-interactively’ in ‘ert.el’.
(ert SELECTOR &optional OUTPUT-BUFFER-NAME MESSAGE-FN)
Run the tests specified by SELECTOR and display the results in a buffer.
SELECTOR works as described in ‘ert-select-tests’.
OUTPUT-BUFFER-NAME and MESSAGE-FN should normally be nil; they
are used for automated self-tests and specify which buffer to use
and how to display message.
Perfunctory investigation has so far yielded little.
I would love a better way, if only because it might have worked out the details of whether to do this in batch mode, etc.
Or if somebody has managed not just to concatenate the ert buffers from independent tests, but has managed to create a fused buffer that reports all concisely.

Related

sleep-for within while loop is ignored

I'm trying to write an emacs function that executes a shell command every 5 seconds. However, I can't get the pause to work. Here's what I have:
(while '(test)
(insert (format "echo hello"))
(comint-send-input))
(sleep-for 0 5000)
I suspect that the sleep is ignored for reasons related to functional evaluation of Lisp. Any advice on how to get the pause to occur after each command evaluation?
As mentioned in the comment, the issue is with a paren.
Also, I've just tried sit-for in *scratch* and it performs smoother compared to sleep-for.
(while 1
(insert "hello")
(sit-for 1))
But both lock up Emacs, since it's single threaded, so you should be careful with this sort of activity.
Consider using async package or something similar instead.

Files with macros compilation without loading a file in sbcl (common lisp)

I have a file with some lisp code and I want to compile it to fasl. I'm defining some functions and macros that use some of that functions and more functions that use these macros.
So when I tried to compile the file with
$ sblc --eval "(compile-file \"file.lisp\")" --eval "(quit)"
I got compilation errors about that the macro couldn't expand because the function is not defined. But everything has been compiling in the normal order:
; compiling (DEFUN MY-FUNCTION ...)
; compiling (DEFMACRO MY-MACRO-THAT-USES-MY-FUNCTION ...)
; compiling (DEFUN OTHER-FUNCTION-THAT-USES-MACRO ...)
; file: /path/to/file/file.lisp
; in: DEFUN OTHER-MY-FUNCTION-THAT-USES-MACRO
; (MY-MACRO-THAT-USES-MY-FUNCTION 1)
;
; caught ERROR:
; during macroexpansion of (MY-MACRO-THAT-USES-MY-FUNCTION 1). Use *BREAK-ON-SIGNALS* to
; intercept.
; The function COMMON-LISP-USER::MY-FUNCTION is undefined.
So then I tried to load the file first and then to compile it:
sbcl --eval "(load \"file.lisp\")" --eval "(compile-file \"file.lisp\")" --eval "(quit)"
And this worked without warning or errors.
But this solution looks ugly because of:
1) I need to specify the file twice (even if I write the bash script, this doesn't look so good)
2) It looks like the file is compiled twice: first time when I load it and second time when I actually compile it.
3) If I'll do it from repl, the file will be loaded to it and sometimes this can be bad. What if I just want to compile the file, but not load it?
So I see 3 variant here:
1) I'm doing something completely wrong.
2) I need to regroup macros and functions several files and load only necessary function with load but not the whole file. (this doesn't help with any of the problems but make them less significant)
3) There is a command that does does what I want to do and I just couldn't find it.
So how should I compile such type of files?
Thanks for help in advance.
That's a frequent question. Probably already answered on Stackoverflow.
during compilation, the code of functions is generated, but not loaded into the compiler.
macros OTOH are also made available in the compile-time environment
Two solutions:
separate files: one which defines macros and the needed functions, another one where the macros are being used. Load the macro and its support code, before compiling dependent files.
use EVAL-WHEN with :load-toplevel, :compile-toplevel and :execute around the functions which are needed at compile-time. :compile-toplevel makes sure than any enclosed top-level code gets executed during compilation - for a defun this would define the function at compile-time, too.
See: http://www.lispworks.com/documentation/HyperSpec/Body/s_eval_w.htm#eval-when
Note, that you don't need two evals in your example. You can also write --eval "(progn (load ...) (compile-file ...)) or even --eval "(let ((file ...)) (load file) (compile-file file)).

Emacs process list seems not to work

I am experimenting processes in emacs/ielm for a sort of parallel computing, i.e. to start many processes for different computations and then to wait for all the processes have terminated to compose the result. In order to do this I set up the following simple function:
(defun testp ()
(while (> (length (process-list)) 1)))
I call testp after all the child-processes have been started and, when I get again the control, I compose the result:
If there are no child-processes testp exits immediately: ok;
If there is at least one child-process testp loops: ok;
When all child-processes have finished testp continues looping, and this is
not good.
May I ask you to help me understand where I am wrong.
After a process finishes, it is not necessarily deleted immediately. So (process-list) may still list it. The user variable delete-exited-processes controls this, so check that you have set it to t. The function list-processes will also explicitly delete finished processes, so that may be helpful.
Check out the chapter on processes in the manual for further details.
Emacs is single-threaded and doesn't handle external input (e.g. about the change in a process's status) until it reaches a "safe point". So the above loop (as #juanleon suggests) is "too tight". You want to add a sleep into it.
But better is to use set-process-sentinel so that Emacs gets told when the processes end rather than having to busy-wait for it.
E.g.:
...start a new process stored in proc...
(push proc my-list-of-running-processes)
(set-process-sentinel proc #'my-run-when-its-over)
...
(defun my-run-when-its-over (proc msg)
(setq my-list-of-running-processes (delq proc my-list-of-running-processes))
(unless my-list-of-running-processes
(message "Haha! all my processes are done!")))
Note also that you probably don't want to use process-list since that can contain unrelated processes (e.g. if you use M-x shell or various other things), which is why I used my-list-of-running-processes above.
Maybe the tight loop is not letting emacs do a proper process cleanup. My recommendation would be to apply a filter to the result of (process-list) (since if you have a runnning compilations, server, shell, etc. the process list won't be empty), to filter out processes different of those you are interested in, and also to add a small delay to the while ((sleep 0 500), for instance).

Can you program without REPL on Lisp?

So I just got Land of Lisp and started to do the first program.
I have a couple questions.
Is there a way to just write some code and run it through a compiler, or interpreter, and not use the REPL thing? I don't like it much. I can't seem to go back if I messed up. It just kinda says "Ha you screwed up, retype that whole function."
I would also like to know what the point of REPL is.
Non-REPL work flow
Edit your file
Compile the file using compile-file; fix errors and warnings; repeat.
Load the file using load; evaluate the form you want; repeat
Example
$ cat > f.lisp <<EOF
(defun f (x) (if (zerop x) 1 (* (f (1- x)) x)))
EOF
$ clisp -q -norc -c f.lisp
;; Compiling file /home/sds/f.lisp ...
;; Wrote file /home/sds/f.fas
0 errors, 0 warnings
$ clisp -q -norc -i f.fas -x '(f 10)'
;; Loading file f.fas ...
;; Loaded file f.fas
3628800
$
The Right Way
Use an IDE, e.g., Emacs with SLIME.
This way, you edit the code in an editor which supports auto-indent and shows you help for each standard symbol.
You compile and test the functions as soon as you write them, giving you a very short development cycle. Under the hood this is accomplished by the IDE interacting with the REPL (this answers your last question).
What is REPL?
Read-Eval-Print loop is a faster, more versatile version of the Edit-Compile-Run loop.
Instead of operating in terms of whole programs (which can be slow to compile and whose execution can be tedious to navigate to the specific location being tested), you operate in terms of a specific function you work on.
E.g., in gdb, you can execute a function with print my_func(123), but if you change my_func, you have to recompile the file and relink the whole executable, and then reload it into gdb, and then restart the process.
With Lisp-style REPL, all you need to do is re-eval the (defun my-func ...) and you can do (my-func 123) at the prompt.

Can I save source files in Clisp?

I'm a beginner programmer and am going through the book "Land of Lisp".
I have been typing in the examples from the book with the REPL. Is it possible to save my current program as a .lisp file so I can load it and continue working on it later? I know I can just create the .lisp files in a text editor and load them in, but I am enjoying using the REPL in full screen mode to do the examples.
Short answer
No. Once you enter a function into the REPL, the source form is gone and you just have the interpreted or compiled form. You can do some clever things, but I suspect you don't want to deal with them right now.
Long answer
Use Emacs and SLIME
First, I know you are enjoying the REPL, but I would encourage you to look at some of the editors with Lisp support, such as Emacs with SLIME (http://common-lisp.net/project/slime/) that gives you the best of both worlds. You type into the editor, it types into the REPL, and you really don't know the difference from how you are doing things now. Then you can copy and paste the functions you like into a "proper" .lisp file. The other advantage of using Emacs is that it's based on a variant of Lisp called Elisp, so you can program your editor in Lisp. You can pretty print your code, reformat and refactor it into multiple functions, and do all kinds of excellent things.
Enough preaching!
If you still just want to type clisp and play at the REPL, then you still have options.
If you want to log the output of your REPL session, check out DRIBBLE. It will log your session to a file, and you can edit that later to extract what you want.
For example, this is a simple session:
ataylor:~ $ clisp
blah blah
[1]> (dribble "/Users/ataylor/jerome.lisp")
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"/Users/ataylor/jerome.lisp">
[2]> (defun add-two (a b) (+ a b))
ADD-TWO
[3]> (add-two 1 2)
3
[4]> (dribble)
#<CLOSED OUTPUT BUFFERED FILE-STREAM CHARACTER #P"/Users/ataylor/jerome.lisp">
[5]>
Bye.
Viewing the contents of the file is easy, but it can get big quickly.
ataylor:~ $ cat jerome.lisp
;; Dribble of #<IO TERMINAL-STREAM> started on 2011-09-14 18:16:57.
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"/Users/ataylor/jerome.lisp">
[2]> (defun add-two (a b) (+ a b))
ADD-TWO
[3]> (add-two 1 2)
3
[4]> (dribble)
;; Dribble of #<IO TERMINAL-STREAM> finished on 2011-09-14 18:17:16.
You could copy (defun add-two (a b) (+ a b)) and paste it into a file for later.
Loading that file (I added it to jerome1.lisp) is very simple.
ataylor:~ $ cat jerome1.lisp
(defun add-two (a b) (+ a b))
ataylor:~ $ clisp
blah blah
[1]> (load "/Users/ataylor/jerome1.lisp")
;; Loading file /Users/ataylor/jerome1.lisp ...
;; Loaded file /Users/ataylor/jerome1.lisp
T
[2]> (add-two 1 2)
3
[3]>
Bye.
Saving a session
The easiest thing you can do is saving your Lisp session to an image. It will save all of the functions you've created or compiled, along with most state. When you load it at your next session, it will be almost as if you hadn't exited clisp. The way to do this is implementation dependent, and differs between clisp, sbcl, etc. I'll show you what you would do for clisp.
The problem with this is that you can't open a file and edit it, post it on github, or whatever. I'll give a brief example.
ataylor:~ $ clisp
blah blah
[1]> (defun add-two (a b) (+ a b))
ADD-TWO
[2]> (add-two 1 2)
3
[3]> (EXT:SAVEINITMEM)
;; Wrote the memory image into lispinit.mem (3,422,616 bytes)
Bytes permanently allocated: 171,840
Bytes currently in use: 3,243,400
Bytes available until next GC: 808,130
3243400 ;
808130 ;
171840 ;
1 ;
65640 ;
7834
[4]>
Bye.
Note that message about where clisp wrote the memory image. You'll give that back to clisp with the -M flag when starting it the next time.
ataylor:~ $ clisp -M lispinit.mem
blah blah
[1]> (add-two 1 2)
3
I wanted a better answer to this same question for the following reasons:
(1) When learning a language, oftentimes you more want to experiment than to actually write a full application.
(2) When experimenting, it can be really nice to look through your history and see what you entered and what results you got.
(3) I come from the world of bash, where you can literally dump your command history into a text file and call it a "script" (though this is only a tiny fraction of the power you can get with actual bash scripting, it still serves the purpose of after-the-fact-automation, with a little cleanup.)
So, from the world of bash, I just went with the simple route—I automated a cleanup of the stdout dump. If you're using a terminal with scrollback history (anything but a virtual terminal—and if you code lisp in a VT you're just strange) to play with clisp interactively, just copy the entire terminal scrollback history to a file, then run:
sed -n -e 's/^\[[0-9]\+\]> //;tstuff' -e 'b;:stuff' -e 'p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/{s/.*//;h;d;};h;n;p;x;G;brep' myfile.lisphist > myfile.lisp
Magic! You have a working lisp program. (Obviously you should clean it up; the purpose is to have your history, not really to use it as a program. But it will only contain the lisp commands you entered, not the output/result, so it could be used directly as the program file.)
Then you can run clisp -repl myfile.lisp and voila! You're back where you got to in the last session. Of course, to load it interactively, you should take out the final (quit) line. :)
As for that sed command, what it does is look for the clisp prompt [number]>, then print that line (removing the prompt) and then try to balance the parentheses. If it succeeds, it scans for the next prompt; if the parentheses don't balance, it prints lines until they do.
Actually, it can be simplified slightly to:
sed -n -e '/^\[[0-9]\+\]> /{s///;p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/d;h;n;p;x;G;brep' -e '}' myfile.lisphist > myfile.lisp
(Note: I don't use emacs; I've been using just clisp called directly at the command line. I don't know if there is a scrollback history within SLIME.