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.
@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..)
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?
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?
for example i saw this: https://github.com/tolitius/mount/blob/master/README.md#swapping-alternate-implementations
but where do i put this within a test name space?
what happens if there is an exception in the ;; testing.. checking "sms-ch" channel
part?
the (mount/stop)
bit wouldn't run, then, no?
if i wrap my tests into try
forms, then the tests start to be really verbose/noisy
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?
let's start from the last question and work backwards, to make sure I follow
ok, thanks
> how am i supposed to get back my real system afterwards? what do you mean get back to the real system?
usually: "you ran the test, you done"
the real system / app exists independently from the tests
nope
i.e. I usually develop an app in one REPL, and run tests continuously in another
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"])))
so i can have access to the running real system via an nREPL client
by real system, i mean nothing is mocked out
my nREPL client is running from intellij
right, so here in dev you have nothing mocked out
yes
are you trying to run the real app and the tests within the same REPL?
yes
since intellij supports this "Run test under caret in REPL"
which suggests that's a normal thing to do...
sounds very clojure-y indeed
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
that's how i was doing it in the past with midje too
but it has no interop with intellij 😞
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
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.
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"?
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)
well, you can't start 2 nREPLs because there is only one .nrepl-port
file....
plus not sure how would i tell intellij which repls should it send the tests to...
and let's not forget that most people are not RAM millionaires either. running 2 repls is not nice at all...
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?
> 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
we already have a datomic transactor, a frontend project with cljs compiler & cljs-repl aaaand a backend process
you only have one REPL that runs all the tests
> a datomic transactor, a frontend project with cljs compiler & cljs-repl aaaand a backend process is this the same project?
closing the repls is not the problem. closing the terminals which run boot watch test
are the problem
no. these are 3 JVMs. i was just mentioning it, regarding you advice to run an extra one just for the tests
and no, frontend and backend are 2 different boot processes already (in separate source repos too)
so you have 3 REPLs opened at the same time, or how do you work with it?
the datomic transactor doesnt have a repl
so i have 2 intellij projects open 1. frontend (hoplon) 2. backend (ring app via boot-jetty)
i run a boot dev
like i showed above to have a REPL server for the backend
i run it from iTerm
then i run an nREPL client from intellij which connects to this backend REPL
for the frontend i dont really use a repl much yet
then in a test namespace i can just say cmd-shift-a "run tests in current NS in REPL"
and it sends the tests to the boot dev
process via the nREPL client but 1st reloads the modified files also via the REPL
as documented here: https://cursive-ide.com/userguide/testing.html
(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)
I see, but then why not just run tests continuously vs. say cmd-shift-a "run tests in current NS in REPL"
?
(in the separate REPL)
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)
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?
so you have an app running in REPL
and also want to run tests which redef the states?
yup
then you either need a fixture to save the app state before tests/restore after
maybe could use Yurt for that?
at least thats how i understand cursive's test support is supposed to work
yep, probably works that way
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...
I'd think it just sends a form to the repl
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
he might be able to explain if it's possible to make a REPL connection for test evaluation
separately from the "main" project's REPL connection
I doubt such a feature already exists
maybe we should ask him how does he manages state, so this feature is useful for him...
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
@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?right, just running boot watch speak test
in a different terminal window
which is a different JVM, yes
ok, thx for the clarification
sure, I wish I could help you more with IntelliJ's setup, but I don't use it
no worries, i really appreciate you spent your time on enlightening me!
and of course thanks for mount
and yurt
too! 🙂
sure, always welcome
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.just provide an extra parameter to http/post
on L19 and you will see the next test (`swapping-with-state`) will fail too
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
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