cursive
cursive copied to clipboard
Stay on the root module in Polylith workspaces
Since issue #2554 we have much better support for working with Polylith codebases in Cursive, by checking "Resolve over whole project":
We need one more change to get the integration to work well, and that is to be able to set the "root" module, which will be used when running tests from the IDE. In Polylith, tests are always executed from the root module, e.g. "polylith" for the polylith codebase itself, as an example.
As it is now, if we execute a test from e.g. the shell brick, it will use "shell" as module, and the test will fail. Right now I need to manually change the module to "polylith" and run the test again, which doesn't give a nice user experience.
+1
running tests from the IDE
@tengstrand there are a few different ways of running tests in Cursive, which one is causing you this problem?
When I click on the green arrow for a test, e.g. the check test function in select-candidates-test
from the shell
component, and run the test:
I get this error:
If I go and look in the configuration that Cursive created for me, then it has set "Module" to shell
and "Working dir" to /Users/joakimtengstrand/source/polylith/components/shell
:
If I change "Module" to polylith
it will also set "Working dir" to /Users/joakimtengstrand/source/polylith
for me. If I now run the test again, by clicking the "run test" icon, at the top of the page, it will run the test again:
And they will be green.
All these steps can be hard to figure out for someone new to Polylith, but it's also a really bad default behaviour, regardless of how experienced user you are. For example, if I choose to run another test, I have to repeat the steps, and if I want to reuse a test configuration, I have to look it up in the growing list of test configurations.
@tengstrand interesting! Do you prefer this way of running tests to running them in the repl and if yes, why?
I always use a repl + the actions to run the test under caret or tests in the namespace in the repl and never this one you showed. What I dislike about this one is that it starts a separate java process and so feedback is slower compared to just executing in the already running repl process.
I guess it's just an old habit, that originates from the time when I used IntelliJ/IDEA to program in Java! I should probably switch to your style of working. But regardless of that, I think it's important that the integration works.
Here's how you can do this. You need to edit the template for test configurations, which is used to create new configurations including the temporary ones created by clicking on the gutter icons:
Then set the module in the template for the clojure.test type:
The one caveat with this is that it's a per-project setting, so you'll have to do this once for each new Polylith project. I don't think there's a good way around this unfortunately.
After I have clicked "Add new configuration", I can't see "Run IDE" in the list:
I'm using this at the moment: "IntelliJ IDEA 2023.2.1 (Community Edition) Build #IC-232.9559.62, built on August 23, 2023 Runtime version: 17.0.8+7-b1000.8 aarch64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. macOS 14.0 GC: G1 Young Generation, G1 Old Generation Memory: 2048M Cores: 10 Metal Rendering is ON Non-Bundled Plugins: com.paperetto.dash (3.3) org.asciidoctor.intellij.asciidoc (0.38.20) com.cursiveclojure.cursive (1.13.1-eap3-2023.2)
Sorry, Run IDE is just what happened to be open when I opened the dialog. The first screenshot is to indicate the "Edit configuration templates..." link, which should be there whatever type you have selected. Then, in the next screen where you're actually editing the templates, you need to select the clojure.test type.
Okay cool, I misunderstood.
If I open a file, e.g. components/common/test/polylith/clj/core/common/brick_names_to_test.clj
:
And then click on the green arrow for the first all-bricks function, and run the test:
It will create this configuration for me, and use it to run the test:
The test will now fail, because it uses common
as module:
If I now change the module for that test to polylith
:
I can run the test:
But if I run another test in-between and click on the green triangle again, then it will create a new configuration for me, and forget that it should run the test from the polylith
module, and the test will fail. If I run many test this way, the list of configured tests will grow, and it takes a lot of time to find the correct configuration each time.
I didn't manage to create a configuration for the common
component, that it will use every time I execute the all-bricks
function, but maybe you know how to do it? For Polylith codebases, it would be much better if Cursive could create a clojure.test configuration where module was set to polylith
, regardless which test that was executed, but as you said, this seems not to be doable. It's just that it would be great if the user experience could be improved compared to how it works today!
Ok, here is what I am doing:
- I import a freshly-cloned copy of polylith.
- I open
components/common/test/polylith/clj/core/common/brick_names_to_test.clj
. - I run the
all-bricks
test, and indeed it fails, and checking I can see that the config is created in thecommon
module. - I delete the temporary configuration created by running the test, since it might interfere with the next steps.
- I "Edit Configurations..." and then "Edit configuration templates...." as shown in my comment above.
- In the clojure.test template configuration, I change the Module setting from "No default module" to "polylith".
- Apply, OK, etc...
- Now, when I run the
all-bricks
test, it works correctly.
What step 6 does is reconfigure the template that is cloned when any new run config of that type is created in this project. That's why in step 4 I delete the previous temporary config, to ensure that it is not re-used since we want IntelliJ to create a new one based on the modified template. From this point forward, any clojure.test run config which is created in this project will be created with "polylith" as its module. However, pre-existing ones will not be corrected.
If there's a reliable way to detect that a project uses polylith, then I might be able to detect it, prompt the user to ensure that it's what they want, and then update the template automatically - I'm not sure if it's possible to programmatically update the template configurations, I'd have to investigate. I could also at that point detect any test configs that have a different module set, and prompt the user which they would like to update to use the main module.
Now it works, thanks! Sorry that I wasn't able to follow your pretty clear instructions!
The brick-names-to-test
lives here:
.
├── bases
├── components
│ ├── common
│ │ ├── deps.edn
│ │ ├── src
│ │ └── test
│ │ └── polylith
│ │ └── clj
│ │ └── core
│ │ └── common
│ │ ├── brick_names_to_test.clj
├── deps.edn
├── development
├── projects
│ ├── poly
│ │ ├── deps.edn
└── workspace.edn
What identifies this as a Polylith workspace, is that there is a workspace.edn
config file a few levels up from brick-names-to-test
, which is considered the root for the workspace. We could also check that workspace.edn
contains a :top-namespace
key.
A workspace can either live at the root, or in a directory or sub directory, see the high-level description of workspaces.
In addition to components
, tests can also live under the bases
and projects
directories and possible (but rarely) under development
.
If you want, you can read more about how the poly
tool handles workspaces here or just ask me if you have questions.