Fork me on GitHub
#mount
<
2016-06-13
>
onetom13:06:10

is there any good example how to use mount (or mount-lite too, i guess) with some test framework? im actually trying to figure out how intellij's repl based testing is supposed to work and how to make it a smooth experience with mount-lite.

tolitius14:06:07

@onetom: are you looking for something specific? Usually these are used when testing: https://github.com/tolitius/mount#composing-states mostly swap and only. The idea is you would start a portion of an app that you want to test, and swap the real external resources with a mocked ones (whether it is a function or another state..)

onetom14:06:45

im looking for an example of how is it done. via some fixtures, or macros like with-components in https://github.com/stuartsierra/component/issues/6? what would i do with a datomic db for example? create a new one in every test namesapce and transact the schema into it? how does it play together with intellij's "Run test under caret in REPL" & "Run tests in current NS in REPL" features?

onetom14:06:43

or there is eftest (https://github.com/weavejester/eftest) which is also used by https://github.com/metosin/boot-alt-test which allows parallel test runs. is there a way to use them with mount/mount-lite, since they only allow one active state at a time?

onetom15:06:01

but where do i put this within a test name space?

onetom15:06:30

what happens if there is an exception in the ;; testing.. checking "sms-ch" channel part? the (mount/stop) bit wouldn't run, then, no?

onetom15:06:04

if i wrap my tests into try forms, then the tests start to be really verbose/noisy

onetom15:06:14

if i start a REPL, then i would have a real system running in it by default. but if im running tests with intellij via REPL and those tests would have (mount/start-with {...some-mocks...}), then how am i supposed to get back my real system afterwards?

tolitius17:06:47

let's start from the last question and work backwards, to make sure I follow

onetom17:06:07

ok, thanks

tolitius17:06:12

> how am i supposed to get back my real system afterwards? what do you mean get back to the real system?

tolitius17:06:30

usually: "you ran the test, you done"

tolitius17:06:01

the real system / app exists independently from the tests

tolitius17:06:33

i.e. I usually develop an app in one REPL, and run tests continuously in another

onetom17:06:45

i have this at the moment:

(deftask dev
  "Backend in development mode"
  []
  (comp
    (repl :server true)
    (watch)
    (system.boot/system
      :sys #'sys/dev
      :auto true
      :files ["sys.clj" "core.clj"])))

onetom17:06:24

so i can have access to the running real system via an nREPL client

onetom17:06:40

by real system, i mean nothing is mocked out

onetom17:06:04

my nREPL client is running from intellij

tolitius17:06:12

right, so here in dev you have nothing mocked out

tolitius17:06:31

are you trying to run the real app and the tests within the same REPL?

onetom17:06:00

since intellij supports this "Run test under caret in REPL"

onetom17:06:11

which suggests that's a normal thing to do...

onetom17:06:23

sounds very clojure-y indeed

tolitius17:06:20

I usually run tests in the separate REPL: i.e. boot watch speak test. I like it better, since things / components / app pieces are decoupled from compilation differences / configs

onetom17:06:59

that's how i was doing it in the past with midje too

onetom17:06:15

but it has no interop with intellij 😞

onetom17:06:23

which does have a quite nice clojure.test integration and it's super fast to just run specific tests and it automatically reloads the necessary changed files too

tolitius17:06:09

I never liked running tests and dev within the same REPL. at the times I used leinigen it was a no brainer, since it just works the best in two separate REPLs, "lein does not clean well" especially if new things are added in project.clj. with boot clean is no longer the problem, but boot watch speak test is just really niice, since it just works for you in a different REPL with no dev cluttering.

tolitius17:06:21

I only use IntelliJ for Java and Scala (I use VIM for Clojure), so I would appreciate if someone with Cursive knowledge jump in, but.. "you can't start two REPLs with Cursive"?

onetom17:06:16

i was also trying to run boot watch test in a terminal within intellij, but if i close the project window, boot keeps running in the background and i can't access it anymore (have to kill it manually)

onetom17:06:12

well, you can't start 2 nREPLs because there is only one .nrepl-port file....

onetom17:06:36

plus not sure how would i tell intellij which repls should it send the tests to...

onetom17:06:19

and let's not forget that most people are not RAM millionaires either. running 2 repls is not nice at all...

tolitius17:06:41

I just did start two REPLs in Cursive, and when I did "File => Close Project" it asked me twice whether I wanted to stop the REPL, you don't have the same behavior?

tolitius17:06:08

> not sure how would i tell intellij which repls should it send the tests to you don't, it is in your boot test src

onetom17:06:14

we already have a datomic transactor, a frontend project with cljs compiler & cljs-repl aaaand a backend process

tolitius17:06:21

you only have one REPL that runs all the tests

tolitius17:06:56

> a datomic transactor, a frontend project with cljs compiler & cljs-repl aaaand a backend process is this the same project?

onetom17:06:15

closing the repls is not the problem. closing the terminals which run boot watch test are the problem

onetom17:06:09

no. these are 3 JVMs. i was just mentioning it, regarding you advice to run an extra one just for the tests

onetom17:06:33

and no, frontend and backend are 2 different boot processes already (in separate source repos too)

tolitius17:06:57

so you have 3 REPLs opened at the same time, or how do you work with it?

onetom17:06:20

the datomic transactor doesnt have a repl

onetom17:06:07

so i have 2 intellij projects open 1. frontend (hoplon) 2. backend (ring app via boot-jetty)

onetom17:06:35

i run a boot dev like i showed above to have a REPL server for the backend

onetom17:06:53

i run it from iTerm

onetom17:06:04

then i run an nREPL client from intellij which connects to this backend REPL

onetom17:06:37

for the frontend i dont really use a repl much yet

onetom17:06:30

then in a test namespace i can just say cmd-shift-a "run tests in current NS in REPL"

onetom17:06:21

and it sends the tests to the boot dev process via the nREPL client but 1st reloads the modified files also via the REPL

onetom17:06:16

(im working on a green field project, that's why im trying to revise my workflow and get away from component and try use mount or mount-lite instead)

tolitius17:06:51

I see, but then why not just run tests continuously vs. say cmd-shift-a "run tests in current NS in REPL"?

tolitius17:06:12

(in the separate REPL)

onetom17:06:48

because clojure.test doesn't support 1. re-running only the last failing tests 2. running only specific tests (so i can get immediate feedback)

onetom17:06:30

3. how would i run the separate REPL? start another boot nREPL server process? and open an nREPL client to it which I would setup as a second Run configuration in IntelliJ on some hardwired port?

dm317:06:36

so you have an app running in REPL

dm317:06:10

and also want to run tests which redef the states?

dm317:06:02

then you either need a fixture to save the app state before tests/restore after

dm317:06:20

maybe could use Yurt for that?

onetom17:06:20

at least thats how i understand cursive's test support is supposed to work

dm317:06:27

yep, probably works that way

onetom17:06:26

it would be great if it could send stuff into a test pod of course, but unfortunately i have no idea what cursive is really doing in the background...

dm317:06:14

I'd think it just sends a form to the repl

onetom17:06:48

maybe we should interrogate mr fleming on that end but im not sure it worth harassing him, since this issue doesn't seem to move forward: https://github.com/cursive-ide/cursive/issues/692

dm317:06:56

he might be able to explain if it's possible to make a REPL connection for test evaluation

dm318:06:15

separately from the "main" project's REPL connection

dm318:06:31

I doubt such a feature already exists

onetom18:06:27

maybe we should ask him how does he manages state, so this feature is useful for him...

onetom18:06:32

looking into yurt in the mean time. i remember i read about it before but probably just before sleep... http://www.dotkam.com/2016/01/31/yurt-mounts-local-real-estate/ > 504 Gateway Time-out

onetom18:06:00

@tolitius: you said: > with boot clean is no longer the problem, but boot watch speak test is just really niice, since it just works for you in a different REPL with no dev cluttering. and in the yurt-mounts-local-real-estate article: > The way I do it today is simply running: >

boot watch speak test
> in a different REPL. but how boot watch speak test is a REPL? you mean different JVM process?

tolitius18:06:08

right, just running boot watch speak test in a different terminal window

tolitius18:06:22

which is a different JVM, yes

onetom18:06:03

ok, thx for the clarification

tolitius18:06:50

sure, I wish I could help you more with IntelliJ's setup, but I don't use it

onetom18:06:53

no worries, i really appreciate you spent your time on enlightening me!

onetom18:06:39

and of course thanks for mount and yurt too! 🙂

tolitius18:06:50

sure, always welcome

onetom19:06:39

as i was going thru the mount tests and also you example apps and i see this pattern everywhere: https://github.com/tolitius/stater/blob/master/smsio/test/app/test/app.clj#L14-L21 there is no exception handling for proper cleanup, like this:

(try
  (mount/start)
  ...
  (is ...)
  (finally
    (mount/stop))
without such wrapping one mistake can force you to restart the test process, because there will be a web-server started which would cause subsequent tests to fail with "Address already in use" errors, even after you fix the mistake.

onetom19:06:35

just provide an extra parameter to http/post on L19 and you will see the next test (`swapping-with-state`) will fail too

onetom19:06:38

removing the extra param should make the tests pass again, but instead of 1 error, you will get 2 and wading through the reams of log messages, you can discover the "Address already in use" error

onetom20:06:03

there is this in mount-lite which seems to mitigate the problem without the try-finally block but im not sure it's enough either: https://github.com/aroemers/mount-lite/blob/master/test/mount/lite_test.clj#L21