Skip to content

Instantly share code, notes, and snippets.

@EdgeCaseBerg
Last active January 8, 2016 21:47
Show Gist options
  • Select an option

  • Save EdgeCaseBerg/136c3d5946cdcc21e770 to your computer and use it in GitHub Desktop.

Select an option

Save EdgeCaseBerg/136c3d5946cdcc21e770 to your computer and use it in GitHub Desktop.
How to automatically test if you're providing appropriate matches if you need to parse string to some case objects without reflection in your code. Pretty fun stuff I think
package com.github.edgecaseberg.test {
import scala.reflect.runtime.universe
import scala.reflect.runtime.universe.typeOf
import scala.util.Random
import org.scalatest._
trait ParsingTest extends FlatSpec with Matchers {
val random = new Random()
def randomCase(s: String): String = {
s.toList.map { c =>
if (random.nextBoolean()) {
c.toString.toUpperCase
} else {
c.toString.toLowerCase
}
}.mkString.toString
}
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
def getSubclassesOf(t: universe.Type) = t.typeSymbol.asClass.knownDirectSubclasses
def getObjectForCompanion(fullName: String) = {
val module = runtimeMirror.staticModule(fullName)
runtimeMirror.reflectModule(module)
}
}
}
package com.github.edgecaseberg {
import scala.reflect.runtime.universe.typeOf
import org.scalatest._
sealed abstract class MyAutomatic
case object V0 extends MyAutomatic
case object V1 extends MyAutomatic
object MyAutomatic {
val defaultVal = V0
/** Defaults to currentVersion if no match is found */
def fromString(s: String) = s.toLowerCase.trim match {
case "v1" => V1
case "v0" => V0
case _ => defaultVal
}
}
class MyAutomaticTest extends ParsingTest {
"MyAutomatic" should "parse unknown text to a default value" in {
assertResult(MyAutomatic.currentVersion) {
MyAutomatic.fromString("hfhaskldjfhasldfjaskdjfhasdljkfskdjfals")
}
}
val subClasses = getSubclassesOf[MyAutomatic]
for (symbol <- subClasses) {
val obj = getObjectForCompanion(symbol.fullName)
it should s"convert ${symbol.name} to the correct enum" in {
assertResult(obj.instance) {
MyAutomatic.fromString(symbol.name.toString)
}
}
it should s"convert ${symbol.name} regardless of case to the correct enum" in {
val randomCases: List[String] = (1 to 10).map(i => randomCase(symbol.name.toString)).toList
randomCases.map { r =>
assertResult(obj.instance) {
MyAutomatic.fromString(r)
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment