Search code examples
scalaintellij-ideascalatest

IntelliJ IDEA + Scala: how to navigate to broken test easily


I have construct like this in my Scala tests:

class ExpressionsTest extends AnyFunSpec {
  describe("simple literals") {
    describe("valid") {
      it("123") {
        runTest("123")
      }

      it("123.456") {
        runTest("123.456")
      }

      // gazillions of other tests here
    }
  }

  def runTest(ex: String) {
    // some repetitive implementation of a test
    // includes assertions, which sometimes break
  }
}

... and there a lot of instances of it(...) which provide structure of test cases, every one of them calling runTest(...) internally. However, when a test breaks, Intellij IDEA navigates to inner lines of runTest(...) (which are normally not broken), and I want it to navigate to test case itself — i.e. it(...) line.

Two alternative ways I'm aware of are:

  • Obviously, copying runTest(...) into every single method — ugly and error-prone
  • Macros, effectively doing these same embedding of runTest(...) into it(...), which seems to be a huge overkill here

Is there any way to achieve nicer developer's experience with IntelliJ IDEA here?


Solution

  • You can pass an implicit Position to the runTest method (which is provided by Scalatest and uses macros to give you the file/line coordinate for the error), like so:

    import org.scalactic.source.Position
    import org.scalatest.funspec.AnyFunSpec
    
    class ExpressionsTest extends AnyFunSpec {
      describe("simple literals") {
        describe("valid") {
          it("123") {
            runTest("123")
          }
    
          it("123.456") {
            runTest("123.456")
          }
    
          // gazillions of other tests here
        }
      }
    
      // Passing an implicit `Position` here allows an assertion failure to
      // be reported at the caller's file and line number
      def runTest(ex: String)(implicit pos: Position) = {
        // some repetitive implementation of a test
        // includes assertions, which sometimes break
        assert(ex == "123")
      }
    }
    

    Running this test results in the following error:

    "123[.456]" did not equal "123[]"
    ScalaTestFailureLocation: ExpressionsTest at (ExpressionsTest.scala:12)
    Expected :"123[]"
    

    Clicking on the ExpressionsTest.scala:12 through the IntelliJ IDEA UI navigates to the line that says runTest("123.456") (without the implicit Position, the result would have been that you would have been pointed to line 21, going to the runTest method instead).

    Position is part of Scalactic, a dependency of ScalaTest (created by the same author). You can read more about the Position class here.