VirtusLab / scala-cli

Scala CLI is a command-line tool to interact with the Scala language. It lets you compile, run, test, and package your Scala code (and more!)
https://scala-cli.virtuslab.org
Apache License 2.0
539 stars 126 forks source link

There is no command to run a main method in test scope #2728

Open bishabosha opened 6 months ago

bishabosha commented 6 months ago

Is your feature request related to a problem? Please describe.

Currently the only way to run a main method in test scope is through the IDE (e.g. Metals code lens for run|debug). It would be good to have a programmatic way to do this from the scala command.

Describe the solution you'd like The run command should accept the --test flag, like you can do in the compile command. Then this does not try to invoke test frameworks, rather scans for main methods in test scope, in the same manner that run currently looks for main methods in the main scope.

I guess this should filter out any main methods possibly included from main scope, but it is not a strong requirement.

Describe alternatives you've considered N/A

Additional context Here is a forum request for this feature (equivalent of Test/runMain in sbt): https://users.scala-lang.org/t/getting-started-with-scala-cli/9788

Gedochao commented 6 months ago

Indeed, we should enable including test scope in main scope runs, so that the main classes in the test scope are reachable (although it's a bit of an edge case IMO).

For now, here's a 2-step workaround:

scala-cli compile . --test -d out
# Compiling project (test, Scala 3.3.1, JVM (17))
# Compiled project (test, Scala 3.3.1, JVM (17))
scala-cli run --classpath out
# test scope main

You generally can compile with --test enabled and then run the output directly.

charpov commented 6 months ago

The workaround doesn't work for me. First, I need scala-cli compile . -d out in addition to scala-cli compile . --test -d out to generate all the necessary byte code. Second, and more importantly, out is not enough as a class path because it does not include the dependencies.

I've used this:

java -cp $(scala-cli compile --test . -p) Grade

(where Grade is my main class). It works, but shows downloading/downloaded messages with every run.

Gedochao commented 6 months ago

Yeah, I can see what you're getting at... printing the classpath with -p would indeed work. You can also go with

scala-cli run -cp $(scala-cli compile --test . -p) --main-class Grade

and retain the ability to switch between JVMs and so on for the running. but yeah, that's not convenient.

Gedochao commented 6 months ago

Btw. @charpov what is your use case? Why does the main class need to be in the test scope? I'd assume we don't support this at the moment, as it doesn't seem like a natural use of the test sources.

charpov commented 6 months ago

I've described my workflow in the original Scala Users post. Basically, I use Scalatest to write tests (duh!) but I run them with a customized runner that produces a grade (along with a few other customizations). On the one hand, it makes sense that my grading code, which consists of tests, live in the test scope. On the other hand, I do use Scalatest for something other than its original purpose, for which I need my own runner.

I briefly looked at the --test-framework option, but documentation is minimal, and writing a "framework" seems to be more involved than my simple runner.

charpov commented 6 months ago

Yeah, I can see what you're getting at... printing the classpath with -p would indeed work. You can also go with

scala-cli run -cp $(scala-cli compile --test . -p) --main-class Grade

and retain the ability to switch between JVMs and so on for the running. but yeah, that's not convenient.

I like that (instead of using plain java). Do you know where these downloading messages come from? I assume everything should be cached by Coursier.

SethTisue commented 6 months ago

what is your use case? Why does the main class need to be in the test scope?

I have used Test/runMain fairly often over the years for automating development tasks. In my experience it's not uncommon to want to automate something but a standalone script won't do — calling into project code is necessary.

lbialy commented 6 months ago

Same here. Sadly, project utilities and specialized local main classes for akka cluster apps often end up in test scope.

On Mon 12. Feb 2024 at 17:09, Seth Tisue @.***> wrote:

what is your use case? Why does the main class need to be in the test scope?

I have used Test/runMain fairly often over the years for automating development tasks. In my experience it's not uncommon to want to automate something but a standalone script won't do — calling into project code is necessary.

— Reply to this email directly, view it on GitHub https://github.com/VirtusLab/scala-cli/issues/2728#issuecomment-1939003873, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACBVNUUOIBD7PRWF5WXOAYDYTI5EFAVCNFSM6AAAAABDDPFIJCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZZGAYDGOBXGM . You are receiving this because you are subscribed to this thread.Message ID: @.***>