diff --git a/README.md b/README.md index c843307e..491bcb51 100644 --- a/README.md +++ b/README.md @@ -239,10 +239,6 @@ If you're only changing `.md` files, you can run `sbt '~docs/mdoc'`. Note that the site will look a tiny bit different because to build a versioned website we have some machinery in the script running on CI - but you don't have to worry about that. -### IntelliJ plugin - -The code of the IntelliJ plugin lives [there](https://github.com/disneystreaming/weaver-intellij) - ### PR Guidelines Please: diff --git a/build.sbt b/build.sbt index f1597f09..a9fa3b5e 100644 --- a/build.sbt +++ b/build.sbt @@ -64,7 +64,6 @@ lazy val allModules = Seq( framework.projectRefs, scalacheck.projectRefs, discipline.projectRefs, - intellijRunner.projectRefs, effectCores, effectFrameworks ).flatten @@ -271,19 +270,6 @@ lazy val cats = projectMatrix testFrameworks := Seq(new TestFramework("weaver.framework.CatsEffect")) ) -// ################################################################################################# -// Intellij -// ################################################################################################# - -lazy val intellijRunner = projectMatrix - .sparse(withJS = false, withScala3 = false) - .in(file("modules/intellij-runner")) - .dependsOn(core, framework, framework % "test->compile") - .settings(WeaverPlugin.simpleLayout) - .settings( - name := "intellij-runner" - ) - // ################################################################################################# // Misc // ################################################################################################# diff --git a/docs/intellij.md b/docs/intellij.md deleted file mode 100644 index 2e94a977..00000000 --- a/docs/intellij.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: intellij -title: IntelliJ integration ---- - -Starting with version 0.6.0, weaver provides IntelliJ integration by means of a JUnit runner that IntelliJ picks up automatically. - -## Note regarding the previous IntelliJ integration - -We (the maintainers) had tried to build an IntelliJ plugin. It worked but its maintenance became problematic quickly for us. We have made the decision to deprecate that plugin, sacrificing a little bit of UX in favour of an approach that is more compatible with our time constraints. - -## Installation - -Ensure the JUnit plugin is enabled in IntelliJ. Nothing else is needed (as long as weaver is declared correctly in your build). - -## Usage - -### Running suites - -When test suites are open in IntelliJ, buttons appear to the left of the editor (next to the line number of the suite declaration), letting you run individual suites from the IDE. - -![](../img/intellij_usage.png) - -### Ignorning individual tests - -An `.ignore` extension method is provided on strings, and can be used when declaring tests. All tests that are tagged with `.ignore` will be ignored in the test suite, including any that are tagged with `.only`. - -```scala mdoc   -import weaver._ -import cats.effect._ - -object MyIgnoreSuite extends SimpleIOSuite { - - test("test this") { - IO(success) - } - - test("do not test this".ignore) { - IO.raiseError(new Throwable("Boom")) - } - -} -``` - -### Running individual tests - -A `.only` extension method is provided on strings, and can be used when declaring tests. When at least one test is "tagged" as such in a suite, weaver will ignore all tests but the ones that have the "only" tag. Note: `.ignore` has precedence over `.only`. - -```scala mdoc -import weaver._ -import cats.effect._ - -object MyOnlySuite extends SimpleIOSuite { - - test("test this".only) { - IO(success) - } - - test("do not test this") { - IO.raiseError(new Throwable("Boom")) - } - -} -``` - -### Note regarding test durations - -Because of inherently modelling incompatibilities between weaver and IntelliJ, we had to implement the JUnit runner in a way that makes it impossible for durations to be reported correctly by the IDE. We apologise for the inconvenience. diff --git a/modules/intellij-runner/src/weaver/intellij/runner/TeamCity.scala b/modules/intellij-runner/src/weaver/intellij/runner/TeamCity.scala deleted file mode 100644 index 5458de0d..00000000 --- a/modules/intellij-runner/src/weaver/intellij/runner/TeamCity.scala +++ /dev/null @@ -1,67 +0,0 @@ -package weaver.intellij.runner - -import java.io.{ PrintWriter, StringWriter } - -import weaver.{ TestOutcome, TestStatus } - -object TeamCity { - - def testOutcome( - result: TestOutcome, - parentId: Int, - id: Int): List[TeamCityEvent] = { - import result._ - - def teamCity(eventName: String, attributes: (String, Any)*) = - new TeamCityEvent(eventName, id, attributes) - - val start = - teamCity("testStarted", "name" -> name, "parentNodeId" -> parentId) - - def error(message: String): List[TeamCityEvent] = { - val details = cause.fold("")(ex => s"${stackTrace(ex)}") - val errorMessage = cause.fold(message)(_.getMessage) - - List( - teamCity("testFailed", - "message" -> errorMessage, - "details" -> details, - "duration" -> duration.toMillis), - teamCity("testStdOut", "out" -> formatted(TestOutcome.Verbose)) - ) - } - - start :: (status match { - case TestStatus.Success => - List(teamCity("testFinished", "duration" -> duration.toMillis)) - case TestStatus.Exception => error("Error") - case TestStatus.Failure => error("Failure") - case TestStatus.Ignored => - List(teamCity("testIgnored", - "name" -> name, - "parentNodeId" -> parentId)) - case TestStatus.Cancelled => - List(teamCity("testFailed", "message" -> "Cancelled")) - }) - } - - def suiteStarted(id: Int, testClass: String): TeamCityEvent = - TeamCityEvent("testSuiteStarted", - id, - "parentNodeId" -> 0, - "name" -> testClass) - - def suiteFinished(id: Int, testClass: String): TeamCityEvent = - TeamCityEvent("testSuiteFinished", - id, - "parentNodeId" -> 0, - "name" -> testClass) - - private def stackTrace(throwable: Throwable): String = { - val sw = new StringWriter - val pw = new PrintWriter(sw, true) - throwable.printStackTrace(pw) - sw.getBuffer.toString - } - -} diff --git a/modules/intellij-runner/src/weaver/intellij/runner/TeamCityEvent.scala b/modules/intellij-runner/src/weaver/intellij/runner/TeamCityEvent.scala deleted file mode 100644 index 9f41c9a9..00000000 --- a/modules/intellij-runner/src/weaver/intellij/runner/TeamCityEvent.scala +++ /dev/null @@ -1,39 +0,0 @@ -package weaver.intellij.runner - -// TODO get rid of Any -class TeamCityEvent( - eventName: String, - nodeId: Int, - attributes: Seq[(String, Any)]) { - - def show = { - s"##teamcity[$eventName nodeId='$nodeId' ${attributes.map(showAttr).mkString(" ")}]" - } - - private def showAttr(attr: (String, Any)): String = { - val (key, value) = attr - s"$key='${escapeString(value.toString())}'" - } - - private def escapeString(str: String): String = { - if (str != null) - str - .replaceAll("[|]", "||") - .replaceAll("[']", "|'") - .replaceAll("[\n]", "|n") - .replaceAll("[\r]", "|r") - .replaceAll("]", "|]") - .replaceAll("\\[", "|[") - else "" - } - -} - -object TeamCityEvent { - def apply( - eventName: String, - id: Int, - attributes: (String, Any)*): TeamCityEvent = - new TeamCityEvent(eventName, id, attributes) - -} diff --git a/modules/intellij-runner/src/weaver/intellij/runner/WeaverTestRunner.scala b/modules/intellij-runner/src/weaver/intellij/runner/WeaverTestRunner.scala deleted file mode 100644 index 2a23f46f..00000000 --- a/modules/intellij-runner/src/weaver/intellij/runner/WeaverTestRunner.scala +++ /dev/null @@ -1,72 +0,0 @@ -package weaver -package intellij.runner - -import java.util.concurrent.atomic.AtomicInteger - -import weaver._ - -object WeaverTestRunner { self => - - def main(args: Array[String]): Unit = { - val config = parse(args.toList) - validate(config) - val idCounter = new AtomicInteger(1) - val testClassesWithId = config.testClasses.map { testClass => - val id = idCounter.getAndIncrement() - id -> testClass - } - testClassesWithId.foreach { case (parentId, testClass) => - report(TeamCity.suiteStarted(parentId, testClass)) - run(testClass, config.testName) { outcome => - val nodeId = idCounter.getAndIncrement() - TeamCity.testOutcome(outcome, parentId, nodeId).foreach(report) - } - report(TeamCity.suiteFinished(parentId, testClass)) - } - } - - private def run(name: String, testName: Option[String])( - report: TestOutcome => Unit - ): Unit = { - import weaver.internals.Reflection._ - val suite = - cast[RunnableSuite[Any]](loadModule(name, - self.getClass().getClassLoader())) - val args = - testName.fold[List[String]](Nil)(n => "-o" :: ((name + "." + n) :: Nil)) - suite.runUnsafe(args)(report) - } - - def report(event: TeamCityEvent): Unit = println(event.show) - - case class Config( - testClasses: List[String], - showProgressMessages: Boolean, // What is this supposed to do? - testName: Option[String]) - - private def parse( - args: List[String], - config: Config = Config(Nil, false, None)): Config = - args match { - case "-s" :: testClass :: rest => - parse(rest, config.copy(testClasses = config.testClasses :+ testClass)) - case "-testName" :: testName :: rest => - parse(rest, config.copy(testName = Some(testName))) - case "-showProgressMessages" :: "true" :: rest => - parse(rest, config.copy(showProgressMessages = true)) - case "-showProgressMessages" :: "false" :: rest => - parse(rest, config.copy(showProgressMessages = false)) - case Nil => config - case _ => - throw new IllegalArgumentException( - s"Invalid arguments in [${args.mkString(" ")}]") - } - - def validate(config: Config): Unit = - if (config.testName.isDefined && config.testClasses.size != 1) { - throw new UnsupportedOperationException( - "testName can only be used with exactly one testClass" - ) - } - -} diff --git a/website/sidebars.json b/website/sidebars.json index b1842ffb..2b268a9b 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -24,9 +24,6 @@ "multiple_suites_success", "multiple_suites_failures", "multiple_suites_logging" - ], - "IDE integrations": [ - "intellij" ] } } diff --git a/website/static/intellij.xml b/website/static/intellij.xml deleted file mode 100644 index 2d2b37ca..00000000 --- a/website/static/intellij.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - -