Closed Deraen closed 8 years ago
@Deraen, good point added.
It's an interesting one. I am currently testing by only starting the states of the app that I need, here is an example.
While I find isolation parts on an app for testing very useful, I do see the convenience of multiple systems. Although thinking about multiple systems during testing may come from inability to test a system/app by parts :)
Can you share a use case that makes testing with multiple systems great?
I confess that I had to think a moment about what is a case where I absolutely need multiple systems, but I can specify at least once case:
While developing the project, I want to run just one JVM and Clojure runtime. For development I keep a system running and I work on it using both reloaded.repl workflow and reloading specific namespaces or functions from editor. This application is using a database where I keep some data available for manually testing and checking the UI.
In addition to this system, I have tests which test the HTTP API (I also have unit tests testing the functions directly etc.). Separate tests presume that the database is empty and insert necessary fixtures before the tests. This is easy to achieve by using parametrized systems which use a separate database.
that's an interesting use case.
is it necessary to run tests from within the same REPL that you explore things? The answer is probably, not necessary, but preferable, still I though I'd ask.
I believe this will be possible after swapping alternate implementations is in, which needs more thinking, but already 65% done in my head :)
Your tests will:
(mount/start-with {:conn #'app.test.db/conn})
And in REPL you can restart all the states without touching a DB (might not be needed, depending whether you clean DB between restarts):
(mount/start-without #'app.db/conn)
which is already in.
This is preliminary thinking, let me know if this would work for your development flow.
One way to approach the issue might be to provide the ability to supply custom :start
/:stop
functions to the start
function that would override the defaults. For example, you could have something like:
(defstate conn :start (create-conn)
:stop (disconnect conn))
(mount/start [#'conn
{:start (fn [] :mock-connection)
:stop (fn [_] :ok)}])
Now the conn
state will be set to the mock connection value instead of the one that would normally be generated. While not as nice as having multiple independent states, it would largely address the problem of running tests with a different connection.
Since the idea is that the app should be reloadable, it would be fine to have the tests replace the connection while they're running, then once they finish you could start the real connection again.
oh yeah I guess that would totally do it :)
@Deraen, I added more ways to start/stop states to Multiple separate systems including swapping alternate implementations.
Let me know if this solves a separate database
use case.
Yeah, I think so. I've been using it for the past week and it's been an extreme pleasure to work with so far.
@tolitius Sorry, I was going to write here sooner but forgot.
I'm still using Component myself and I'm not planning on moving from it just now. I am just interested in the alternatives and I created the issue to open discussion about the this difference and to get it documented.
As this has now been documented, and new ways enables most of use cases, I think this is solved and can be closed.
@yogthos, @Deraen: thanks for your feedback, much appreciated :)
Hi,
One feature of Component is that multiple separate systems can be started in the same Clojure runtime with different settings. This is very useful for running tests against system.
As Mount attaches the state to namespaces, I presume that it's not possible to have multiple separate applications running in one Clojure runtime?
Would be great if you could mention this on differences to component documentation.