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

test SlackApiClient hangs #3393

Open
ekskimn opened this issue Dec 23, 2024 · 6 comments
Open

test SlackApiClient hangs #3393

ekskimn opened this issue Dec 23, 2024 · 6 comments
Labels
bug Something isn't working needs reproduction requires scoping Issue requires a spike to revalidate it and assign an up-to date scope for its requirements.

Comments

@ekskimn
Copy link

ekskimn commented Dec 23, 2024

Version(s)
1.5.4

Describe the bug
When running tests with munit or scalatest, the tests execute and complete but the process hangs at the end and never finishes

To Reproduce
this is using slack-scala-client_3-1.0.1

import munit.FunSuite
import slack.api.SlackApiClient

class SlackAPITest extends FunSuite  {
  implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global
  val slackApiClient: SlackApiClient = SlackApiClient(slackTokenUAT)

  test("post message") {
    slackApiClient.postChatMessage(channelId, text)
  }
}

when I run scala-cli test with this i see

slack.SlackAPITest:
  + post message 0.705s

but then nothing after it.

Expected behaviour
The cli should end the process and return back

@ekskimn ekskimn added the bug Something isn't working label Dec 23, 2024
@Gedochao Gedochao changed the title scala-cli test hangs test SlackApiClient hangs Dec 30, 2024
@Gedochao
Copy link
Contributor

@ekskimn ok, so we'll need some more context/minimization here.
munit/scalatest integration most certainly works on its own, so something else is going on here.
I'd suspect it's the SlackApiClient that's hanging instead, for some reason.
Are you sure it's set up correctly?
Does it work outside of Scala CLI?

BTW when posting the reproduction code, please provide the full example, including dependency directives - it may be important what exactly are you using and with what version.
I'm not familiar with the Slack integration, so some guidance on how to set up the reproduction on our side would also be useful.

@Gedochao Gedochao added requires scoping Issue requires a spike to revalidate it and assign an up-to date scope for its requirements. needs reproduction labels Dec 30, 2024
@lsissoko
Copy link

lsissoko commented Jan 4, 2025

I see the same behavior for version 1.5.4, but I'm testing a Pekko HTTP server with Pekko HTTP Testkit.

My source file Main.scala:

//> using dep com.softwaremill.sttp.tapir::tapir-core:1.11.11
//> using dep com.softwaremill.sttp.tapir::tapir-pekko-http-server:1.11.11
//> using dep ch.qos.logback:logback-classic:1.5.15

// TODO replace "dep" with "test.dep" after moving tests to /src/test
//> using dep org.scalatest::scalatest::3.2.19
//> using dep org.apache.pekko::pekko-stream-testkit:1.1.2
//> using dep org.apache.pekko::pekko-http-testkit:1.1.0

import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.http.scaladsl.Http
import org.apache.pekko.http.scaladsl.server.Route
import sttp.tapir._
import sttp.tapir.server.pekkohttp.PekkoHttpServerInterpreter

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

object Service {
  implicit val system: ActorSystem = ActorSystem()
  import system.dispatcher

  val helloWorld =
    endpoint.get.in("hello").in(query[String]("name")).out(stringBody)

  val routes = PekkoHttpServerInterpreter().toRoute(
    helloWorld.serverLogic(name => Future(Right(s"Hello, $name!")))
  )
}

import org.apache.pekko.http.scaladsl.model.StatusCodes._
import org.apache.pekko.http.scaladsl.server._
import org.apache.pekko.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.testkit.ScalatestRouteTest
import org.apache.pekko.testkit.TestKit
import org.scalatest.BeforeAndAfterAll
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers
class ServiceSpec extends AnyFunSpec with Matchers with ScalatestRouteTest {
  import Service._

  describe("GET /hello") {
    val name1 = "Bart"

    it("should respond to name query") {
      Get(s"/hello?name=$name1") ~> routes ~> check {
        status shouldBe OK
        responseAs[String] shouldBe s"Hello, $name1!"
      }
    }
  }
}

If I run the test with scala-cli, I see the test pass as well as a CoordinatedShutdown but the process continues to hang afterwards:

$ scala-cli test Main.scala 
Compiling project (Scala 3.5.2, JVM (17))
Compiled project (Scala 3.5.2, JVM (17))
ServiceSpec:
GET /hello
16:36:37.093 [ServiceSpec-pekko.actor.default-dispatcher-6] DEBUG sttp.tapir.server.pekkohttp.PekkoHttpServerInterpreter$ -- Request: GET /helloname=Bart, handled by: GET /hello, took: 92ms; response: 200
- should respond to name query
[INFO] [01/04/2025 16:36:37.141] [main] [CoordinatedShutdown(pekko://ServiceSpec)] Running CoordinatedShutdown with reason [ActorSystemTerminateReason]
Run completed in 830 milliseconds.
Total number of tests run: 1
Suites: completed 1, aborted 0
Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
All tests passed.

# The process doesn't end here
# I have to press <Ctrl+C> to exit

@Gedochao
Copy link
Contributor

Gedochao commented Jan 8, 2025

@lsissoko are you sure the actor system/Pekko is shutdown after the tests are completed?
I'm not convinced this is the same issue at this stage. 🤔

@ekskimn
Copy link
Author

ekskimn commented Jan 8, 2025

@Gedochao

Sorry for the late reply, i was occupied with a different fire.

I also wanted to tinker a bit more and get you more information. So it wasn't a slack related error after all. It is when I use a future in my test.

There are other tests which execute futures and which are successful and properly end. But some reason, this test class and another

Here is a more simplified version of the test

class MyTest extends FunSuite {
  implicit val ec: scala.concurrent.ExecutionContext = ExecutionContext.global
  private val logger = Logger(getClass.getName)
  
  test("myTest") {
    Future {
      logger.info("test")
    }
  }
}

But actually when done this way

import scala.concurrent.ExecutionContext.Implicits.global

class MyTest extends FunSuite {
  private val logger = Logger(getClass.getName)
  
  test("myTest") {
    Future {
      logger.info("test")
    }
  }
}

it works as expected and the tests complete. I think the docs however have it as the former rather than the latter

https://scalameta.org/munit/docs/tests.html#declare-async-test

Curious to know if others have the same issue?

@ekskimn
Copy link
Author

ekskimn commented Jan 8, 2025

@Gedochao and @lsissoko
Yes I've also run into this when using pekko or akka. I added this and it fixed it

  override def afterAll(): Unit = {
    Await.result(system.terminate(), Duration(1000, TimeUnit.MILLISECONDS))
    logger.info(s"Done all")
  }

@ekskimn
Copy link
Author

ekskimn commented Jan 8, 2025

@Gedochao actually no that actually did not work...sorry for the false alarm.

I will try to get better information soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs reproduction requires scoping Issue requires a spike to revalidate it and assign an up-to date scope for its requirements.
Projects
None yet
Development

No branches or pull requests

3 participants