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

Add cats-effect support for FunSuite and FunFixtures #134

Closed
wants to merge 4 commits into from

Conversation

milanvdm
Copy link

@milanvdm milanvdm commented May 25, 2020

Goal

  • I tried to keep the changes as minimal as possible and reuse as much as possible of the existing code

Remarks

  • I am not a cats-effect expert and I created this PR with my own use-case in mind. Would love if someone could have a second look and see if this PR makes sense

Still to do

  • Create a real module structure and a separate artifact
  • Check cross-compilation and tests

Copy link
Member

@olafurpg olafurpg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this contribution! Just a few quick high-level comments. I'm not at all familiar with cats-effect so it would be great if somebody else could review those bits

),
skip in publish := true
)
lazy val tests = crossProject(JSPlatform, JVMPlatform)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep the tests project unchanged and introduce instead new source directories like src/test/non-native for the parts of the cross-build that cats-effect supports. Use .jvmConfigure(_.dependsOn(munitCatsEffect)).jsConfigure(_.dependsOn(munitCatsEffect)) to skip the native dependency

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also fine to have a src/test/cats-effect directory if that simplifies things. I want to avoid multiple test projects because it's easiest to reason about the build when you can run testsJVM/test to run all tests.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I completely understand what you mean :)

I currently have created a new directory munit-cats-effect at the root of the project.
Would you like to have a new directory in the tests folder? Or where do you see this new non-native source directory in the project?


import scala.concurrent.Promise

trait CatsEffectFunFixtures extends FunFixtures { self: CatsEffectSuite =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if we could somehow support suite-local and test-local resources via Fixture[T]. The problem is that Fixture[T] doesn't support async before/after methods but I wonder if that is something we should consider adding to improve this use-case 🤔

I am concerned it would have to be a breaking change unless we introduce something like AsyncFixture[T], but I would love to avoid having separate types for sync/async fixtures.

I personally prefer Fixture[T] over FunFixture[T] because 1) it's easier to compose them when you have many and 2) they require less boilerplate per test case. It's also useful to have suite-local resources like a database connection.

This doesn't have to be blocking for this PR, I'm just thinking out loud here. We could go ahead and merge this change for now and add Fixture[T] support separately.


FunFixture.async(
setup = { testOptions =>
implicit val ec = munitExecutionContext
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it OK/expected that munitExecutionContext is parasitic by default? Users can always override it if they want something else. I felt that a parasitic EC was the best default to 1) have deterministic test behaviors and 2) keep stack traces clean.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any issue with the parasitic EC :)

Copy link

@SystemFw SystemFw Jan 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, as it turns out, this causes deadlock so you are forced to override it. It also doesn't make for a great default imho (at least not for cats-effect), because the failure mode is "oh no there is a deadlock", and you don't expect it to come from your test framework so it can be baffling

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's where I'm coming from typelevel/munit-cats-effect#65

I don't expect munit to take any action at this point (I would have opened a PR), but I thought it was interesting to share if someone else comes across the discussion :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, disregard my comment then :)

Copy link
Contributor

@Kazark Kazark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am certainly hungry for this.


import cats.effect.{ContextShift, IO, Timer}

abstract class CatsEffectSuite extends FunSuite {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still have some open questions on this before I can continue :)

@mpilquist
Copy link

@milanvdm FYI, I'm using the ValueTransform integration from this PR in FS2 now. I added another for SyncIO integration. https://github.com/functional-streams-for-scala/fs2/blob/main/core/shared/src/test/scala/fs2/Fs2Suite.scala

@milanvdm milanvdm requested a review from olafurpg August 4, 2020 10:03
@milanvdm milanvdm marked this pull request as ready for review August 4, 2020 10:04
@milanvdm
Copy link
Author

milanvdm commented Aug 4, 2020

@mpilquist Are you fine if I add your SyncIO to this PR as well? :)

@mpilquist
Copy link

Go for it :)

@larsrh
Copy link
Contributor

larsrh commented Aug 4, 2020

While I endorse the goal of this PR, I would like to strongly suggest to not add this code as a module to this repository; instead keeping it as a separate project. The reason for this is twofold:

  1. The library ecosystem should stay stratified; that is, foundational libraries such as test frameworks should strive to have as few dependencies as possible.
  2. Concretely, since Preliminary Munit port typelevel/cats#3538 landed, cats has a dependency on munit. This means that when this PR is merged, we now have a cyclic dependency (munit → cats-effect → cats → munit). Such a test framework/library cycle has happened in the past and was resolved by the test framework (specs2) shipping its own copy of the library which I think should be avoided at all costs.

Again, I (and others) believe providing this integration is very worthwhile. To quote a cats-effect maintainer:

I would dearly love these test frameworks to have first-class support for CE

I'm happy to provide any kind of resource or support you need for this integration to happen, as long as it lives in a separate repository with a separate release lifecycle.

@milanvdm
Copy link
Author

milanvdm commented Aug 5, 2020

@larsrh Do you want to add this repository to the scalameta/typelevel/... org specifically?

Not sure if I completely understand the reasoning behind having this in a separate repository vs a separate module in munit itself. It feels to me like the arguments you mention are also solved by having it in a separate module but I could be missing something.

One reason to keep it in munit would be to make sure the cats-effect module would always be up-to-date with the latest munit changes.

In the end, I don't care too much how this is organized tbh :) As long as it happens ¯_(ツ)_/¯

Concretely, next steps:

  1. Create a new repo in some org/user
  2. I'll have to check how to structure what you suggest (if someone else doesn't do it before me) as I have very little experience with open-source projects/releases (but would love to get that experience)
  3. Write some code that may or may not do things

@larsrh
Copy link
Contributor

larsrh commented Aug 6, 2020

Do you want to add this repository to the scalameta/typelevel/... org specifically?

I can offer to host it on typelevel, if you like.

Not sure if I completely understand the reasoning behind having this in a separate repository vs a separate module in munit itself. It feels to me like the arguments you mention are also solved by having it in a separate module but I could be missing something.

In principle the separate module breaks the dependency cycle. But since all the modules in a repository are typically released together, this is still a problem. The release workflow would look like this:

  1. release munit-core
  2. release cats
  3. release cats-effect
  4. release munit-cats-effect

Concretely, next steps:

  1. Create a new repo in some org/user
  2. I'll have to check how to structure what you suggest (if someone else doesn't do it before me) as I have very little experience with open-source projects/releases (but would love to get that experience)
  3. Write some code that may or may not do things

Happy to help with all of that, just let me know. I suggest typelevel/munit-cats-effect.

@milanvdm
Copy link
Author

milanvdm commented Aug 6, 2020

@larsrh Thanks a lot for the information :)

A typelevel repo feels the most logical place to add this library.

@larsrh
Copy link
Contributor

larsrh commented Aug 6, 2020

Excellent! I've created a repository, sent you an invite, and created a ticket for me to set up the project boilerplate (typelevel/munit-cats-effect#1). I'll ping you once that's complete.

@olafurpg
Copy link
Member

olafurpg commented Aug 8, 2020

@larsrh thank you for pitching in! I sounds like a good idea to maintain the cats-effect integration in a separate repo 👍

@milanvdm
Copy link
Author

milanvdm commented Aug 8, 2020

Closing in favor of https://github.com/typelevel/munit-cats-effect

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

Successfully merging this pull request may close these issues.

6 participants