artemchernyak
2021-1-23 14:06:24

Thanks! That makes it much nicer to work with raco test .


artemchernyak
2021-1-23 14:09:30

Do you have any suggestions for then running those in the repl?


laurent.orseau
2021-1-23 14:11:43

Personally (possibly a bad habit?) I don’t use test suites, just test cases. Either in a test submodule, or in plain module files in a tests subdirectory. The info.rkt at the base directory can control which files raco test should run (via test-include-paths and test-omit-paths ).


artemchernyak
2021-1-23 14:12:47

So do you not run those tests through the repl then? It doesn’t seem like test cases get evaluated when I evaluate the buffer.


laurent.orseau
2021-1-23 14:12:59

DrRacket can be configured to run the test submodule. In a repl, you can require the test submodule directly with require + submod


laurent.orseau
2021-1-23 14:13:42

To check the tests of a single file, I usually run it in DrRacket. To check all tests I use raco test


artemchernyak
2021-1-23 14:15:00

Interesting maybe it’s something with emacs… I evaluate the test submodule I believe since the repl changes to main.rkt/test> but the test cases don’t run. They do run if I execute raco test


laurent.orseau
2021-1-23 14:16:02

I don’t use emacs much, and I haven’t tried with tests. You can force entering the test submodule with this: (require (only-in racket/enter dynamic-enter!) (only-in syntax/location quote-module-path)) (dynamic-enter! (quote-module-path test))


laurent.orseau
2021-1-23 14:16:17

Not ideal though, but at least you can try it and see if something happens


greg
2021-1-23 14:17:40

If you simply evaluate a rackunit form like check-equal?, and it succeeds, it prints nothing. It only prints failures.


greg
2021-1-23 14:18:10

So when you put tests in a test submodule, and run that submodule in Racket Mode, it runs the submodule like any other. There’s nothing special.


greg
2021-1-23 14:19:02

There is some “test runner” stuff to collect info on the number of tests that pass, and print that at the end. But Racket Mode doesn’t do that when simply running the test submodule.


artemchernyak
2021-1-23 14:19:45

:face_palm: that was the problem


greg
2021-1-23 14:19:49

If you just want reassurance the tests ran, at all, you could put a (displayln "tests ran!") at the end of the test submodule


greg
2021-1-23 14:20:14

If you want the stats about how many, etc., I’m not sure but rackunit may have a thing you could call to print that? I’m not sure.


artemchernyak
2021-1-23 14:20:21

Oh I like the displayln idea just for safety.


greg
2021-1-23 14:21:20

(Personally, I usually just want to know if tests fail. Don’t want noise about them passing. So this has never bothered me much. But I appreciate not everyone feels the same way.)


artemchernyak
2021-1-23 14:22:26

Yeah I can get the stats if I use test-suite with run-tests from rackunit/text-ui, but then I have to manually collect all the tests.

Maybe I should work on creating something similar to what Clojure has with test-all. You would call it plain and it would automatically collect all the test suites and excute them.


greg
2021-1-23 14:23:04

So, I do run raco test a lot, automatically, and get those stats.


greg
2021-1-23 14:23:17

But when I’m drilled down on one source file, I usually don’t care.


greg
2021-1-23 14:23:41

Usually, tests silently passing is the exact opposite of my problem — usually plenty of tests are failing. :slightly_smiling_face:


greg
2021-1-23 14:23:57

And I’m in that test submodule in the REPL, exploring and figuring out why.


greg
2021-1-23 14:24:22

So, again, that’s why it’s been OK for me, but, again, I understand it’s not everyone’s M.O.


greg
2021-1-23 14:25:04

Also I totally get that it sucks that there’s no affirmative indication that the tests ran, at all, and that can be unsettling if someone is new to rackunit and the workflow. That totally makes sense.


artemchernyak
2021-1-23 14:26:01

Makes complete sense. I like that. It’s very linux style (succeed silently).


greg
2021-1-23 14:26:30

btw for packages, e.g. if you have an info.rkt, then raco test -p <pkg-name> is the Clojure test-all AFAIK


greg
2021-1-23 14:26:57

And I usually have that in a makefile, and also it runs on CI.


artemchernyak
2021-1-23 14:28:18

Ah good to know. My next task was going to be configuring the test paths info.rkt so I could just run raco test . Since right now I have to explicitly provide the package name.


greg
2021-1-23 14:28:44

From emacs I sometimes do M-x compile and enter make setup test and it builds my Racket project and run the tests.


greg
2021-1-23 14:29:24

If all your .rkt files are in one dir, you could just do something like raco test . IIRC


laurent.orseau
2021-1-23 14:30:04

I haven’t tried but I don’t think you need a package to use an info.rkt file in the base directory.


laurent.orseau
2021-1-23 14:30:28

If you run raco test . in the directory where the info.rkt is, I think it will look it up (to be confirmed though)


laurent.orseau
2021-1-23 14:30:53

This will also look in subdirectories I think


greg
2021-1-23 14:31:10

Oh cool.


greg
2021-1-23 14:33:53

Yeah I think my experience with Clojure is more things work only if you’ve Set Up a Formal Project Infrastructure. Whereas with Racket more things can work with a formal project but also work in “more causual” or ad hoc ways.


artemchernyak
2021-1-23 14:34:19

Thanks for all the help everyone. I definitely feel like I have a solid test workflow now!


greg
2021-1-23 14:34:52

(as a rough rule of thumb, and probably not 100% true. Like I believe Clojure has gotten better recently about running files from the command line, ad hoc)


anything
2021-1-23 15:09:48

I’d like to split a string into a list of strings-of-length–2, that is, “deadbeef” —> (list “de” “ad” “be” “ef”). That’s because what I really want is the bytes from a hex string. What is the idiomatic way to do this?


sorawee
2021-1-23 15:11:02

See in-slice


anything
2021-1-23 15:12:28

That’s so nice! Thanks!


laurent.orseau
2021-1-23 15:12:29

one more pretty useful thing I didn’t know existed!


soegaard2
2021-1-23 15:13:39

Neither did I. But it seems it splits the string in lists of characters.


anything
2021-1-23 15:14:42

Yes, I’ll treat that myself now. I mean, that’s what I think sorawee’s pointer is.


laurent.orseau
2021-1-23 15:16:32

Otherwise you have the obvious: (let ([s "abcde"]) (define len (string-length s)) (for/list ([i (in-range 0 len 2)]) (substring s i (min (+ i 2) len)))) ; '("ab" "cd" "e")


soegaard2
2021-1-23 15:16:33

For strings of even length, you can use: (let* ([s "deadbeef"] [n (string-length s)]) (for/list ([from (in-range 0 (+ n 1) 2)] [to (in-range 2 (+ n 1) 2)]) (substring s from to)))


laurent.orseau
2021-1-23 15:16:47

:smile:


soegaard2
2021-1-23 15:17:06

Laurent’s version is better!


anything
2021-1-23 15:17:12

Lol. That’s what I call parallelism!


anything
2021-1-23 15:20:40

Here’s my contribution: (it does work with non-even-length strings [because in-slice does]) (define (hex->bytes hex-str) (define ls-of-hex (for/list ([ls (in-slice 2 hex-str)]) (list->string ls))) (list->bytes (map (λ (b) (string->number b 16)) ls-of-hex)))


sorawee
2021-1-23 15:23:04

You can avoid map, since that’s what for/list does


sorawee
2021-1-23 15:23:07

(define (hex->bytes hex-str) (list->bytes (for/list ([ls (in-slice 2 hex-str)]) (string->number (list->string ls) 16))))


sorawee
2021-1-23 15:24:13

(map f (map g xs)) = (map (compose1 f g) xs)


sorawee
2021-1-23 15:24:21

With less allocation


sorawee
2021-1-23 15:25:05

(of course, assuming effect free functions)


laurent.orseau
2021-1-23 15:29:03

Brain teaser: Predict the output of: (map map (list list) (list (list map map)))


laurent.orseau
2021-1-23 16:02:19

Another one if you hadn’t had enough: (map apply (list list map) (list (list map) (list list (list map))))


sorawee
2021-1-23 16:03:43

Brain teaser: find a normal form of ((lambda (lambda) (lambda lambda)) (lambda (lambda) (lambda lambda)))


soegaard2
2021-1-23 16:04:11

Wonder whether notjack’s tool can fix that one. :wink:


laurent.orseau
2021-1-23 16:31:52

I’ve made a generator, so now I can flood! (apply apply (list list (list (list (list map apply map)) map apply)))


ben.knoble
2021-1-23 16:32:19

idk if this was covered above, but for very simple test stats you can look at rackunit/log and (test-log)


laurent.orseau
2021-1-23 16:34:08

most fail, and most of the rest are pretty dull like (apply list ...) and (map list ...)


laurent.orseau
2021-1-23 16:34:37

Still finds (apply map (list list (list apply)))


laurent.orseau
2021-1-23 16:35:28

and (apply apply (list list list (list list))) :smile:


ben.knoble
2021-1-23 16:37:51

Is this a version of the Y-combinator? Or at least some fix-point combinator?


sorawee
2021-1-23 16:40:29

It’s known as omega. One way to look at it is that it’s a specialization of the Y combinator to make a non-terminating term.


badkins
2021-1-23 17:34:59

I also like using test submodules typically. For one thing, it allows testing private functions that aren’t exported. However, occasionally, it’s easier to create a separate file of just tests to avoid circular require dependencies.


laurent.orseau
2021-1-23 19:27:48

Here’s one convolution way to produce the empty list: (apply map (list map (list) (list)))


laurent.orseau
2021-1-23 19:30:56

Here’s an even better one: (apply apply (list map apply (list (list))))