Skip to content

Testing DSL idea: Use string interpolation to mark positions in source code with strong typing. #393

Open
@retronym

Description

@retronym

I've been toying with an idea to use string interpolation to embed have strongly typed positioned assertions in fragments of source code within JUnit tests. Documenting this here for discussion.

scala>  class TestContext() {
     |     val markers = scala.collection.mutable.Buffer[Pos]()
     |     final class Pos() {
     |       markers += this
     |       var pos: Int = -1
     |       def hasCompletions(alts: String*): this.type = {
     |         // this.assertions += () => this.global.completionsAt(pos).containsAll(alts)
     |         this
     |       }
     |       def check(): Unit = ()
     |     }
     |     def check() = markers.foreach(_.check)
     |     implicit class StringContext_code(private val value: StringContext) {
     |       def code(names: Pos*): String = {
     |         var pos = 0
     |         value.parts.zipWithIndex.foreach { case (part, i) =>
     |           pos += part.length
     |           if (i > 0) names(i - 1).pos = pos
     |         }
     |         value.parts.mkString
     |       }
     |     }
     |   }
defined class TestContext

scala>   def mkContext = new TestContext()
mkContext: TestContext

scala>

scala>   val c = mkContext; import c._
c: TestContext = TestContext@14c99bf6
import c._

scala> val m1, m2, m3 = new Pos
m1: c.Pos = TestContext$Pos@661e1399
m2: c.Pos = TestContext$Pos@3ffd4b12
m3: c.Pos = TestContext$Pos@424f02b8

scala> val code: String =
     |     code"""
     |     class C {
     |       def foo = "".reverse${m1}.reverse$m2.rev${m3.hasCompletions("reverse")}
     |     }
     |     """
code: String =
"
    class C {
      def foo = "".reverse.reverse.rev
    }
    "

scala>   m2.hasCompletions("charAt")
res0: m2.type = TestContext$Pos@3ffd4b12

scala>   c.markers.foreach(m => println(m.pos))
49
53
64

scala>   c.check()

This is an alternative to the "magic comment markers" used in the presentation compiler tests, and is more general than the approach taken in https://github.com/scala/scala/blob/2.12.x/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala#L31

Different test use cases could add extension methods to Pos to work with different fragments of testing DSL.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions