Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can't run spec objects when the object is a companion of a trait #466

Open
eyalfa opened this issue Mar 20, 2024 · 4 comments
Open

can't run spec objects when the object is a companion of a trait #466

eyalfa opened this issue Mar 20, 2024 · 4 comments

Comments

@eyalfa
Copy link

eyalfa commented Mar 20, 2024

we use a pattern of writing our test suits as objects (best practice I guess) which works fine.
however sometimes we also define an empty trait with the same name just so we can get access to its slf4j logger using the class name (the companion has a trailing $):

trait JdbcDirectZTest {}

object JdbcDirectZTest
  extends ZIOSpecDefault
    with TestServices {

  val logger: Logger = Logger[JdbcDirectZTest]
  ...

The plugin does recognize the object as a test suit (adds the 'play' buttons on the object and tests), however when attempting to run the suite, we get this failure:

Run Configuration Error: Class 'com.datorama.pluto.sql.JdbcDirectZTest' is not inheritor of Suite trait

@eyalfa
Copy link
Author

eyalfa commented Mar 20, 2024

@hmemcpy if u give me an initial direction I may be able to come up with a PR for this

@eyalfa eyalfa changed the title can run spec objects when the object is a companion of a trait can't run spec objects when the object is a companion of a trait Mar 21, 2024
@hmemcpy
Copy link
Collaborator

hmemcpy commented Apr 3, 2024

Thanks for reporting! Sorry, I'm just now getting around to looking at those issues.
I'm not 100% sure offhand how to best implement this, I'll see if there are some extensions for how IntelliJ looks up test classes.

Thanks again!

@hmemcpy
Copy link
Collaborator

hmemcpy commented Apr 3, 2024

Hmm.. this is an interesting issue, but I'm not so sure it can be solved. The problem is with how Scala generates the corresponding .java/.class files. Since Java doesn't really have static objects, by default, when you compile an object JdbcDirectZTest in Scala, it generates two files: JdbcDirectZTest.class and JdbcDirectZTest$.class

The JdbcDirectZTest$.class contains a singleton instance, held in a java static field called MODULE$, and the JdbcDirectZTest.class contains "forwarders", method implementations calling to e.g. MODULE$.runner().

By default, when you have just the object, the generated JdbcDirectZTest.class will be generated as a public final class JdbcDirectZTest, but when you add a trait, it will be generated as public interface JdbcDirectZTest.

Since the test runner tries to load the class with reflection, eventually, it fails to find the class instance for JdbcDirectZTest, thus failing the entire thing.

Other than blocking such attempts in the UI I'm not sure if it's possible to fix this. I'll sleep on this and see if I can come up with a better solution.

BTW, you could use Logger[JdbcDirectZTest.type] as the type name, however if your logger uses reflection it will append the $ character anyway to the name...

@eyalfa
Copy link
Author

eyalfa commented Apr 4, 2024

thanks @hmemcpy for looking into this! and even better for the deep investigation + explanation.
I eventually eliminated the trait and used a hard coded string with the object's FQN (minus the $).

I think it'd be nice to see what scalaTest does in this scenario, perhaps someone already solved this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants