Skip to content

Instantly share code, notes, and snippets.

@dallaylaen
Created May 17, 2017 13:16
Show Gist options
  • Save dallaylaen/75359a9cf4cb488b8973652e121716b8 to your computer and use it in GitHub Desktop.
Save dallaylaen/75359a9cf4cb488b8973652e121716b8 to your computer and use it in GitHub Desktop.
class Contract {
var log: List[Pair[Int,String]] = List()
var count = 0
var failed: List[Int] = List()
var lock = false
// MUTATORS
def refute( cond: Option[Any], message: String ): Boolean = {
modif
count += 1
cond match {
case Some(oops) => {
failed = failed :+ count
say( 0, "not ok "+count+" - "+message )
// TODO file, line
diag( "Reason: "+oops )
false
}
case None => {
say( 0, "ok "+count+" - "+message )
true
}
}
}
def refute( cond: Unit => Option[Any], message: String ): Boolean = {
refute( cond(), message )
}
def say( level: Int, message: String ): Unit = {
modif
for (m <- message.split("\n")) {
log = log :+ (level->m)
}
}
def diag( message: String): Unit = { say(1, message) }
def note( message: String): Unit = { say(2, message) }
def finish(): Unit = {
say(0,"1.."+count)
if (!isValid) {
diag("Failed tests: "+failed.mkString(", "))
}
lock = true
}
def modif(): Unit = {
if(lock) {
throw new Exception("Postmortem modification accepted")
}
}
// GETTERS
def isValid(): Boolean = { failed.length == 0 }
def signature(): String = {
"t"+(1 to count).map( n => if (failed.contains(n)) { "E" } else { "." }).mkString("")+"d"
}
def report(): String = { report(1) }
def report(level: Int): String = {
log.filter( x => x._1 <= level ).map( x => if(x._1 > 0) { "# " + x._2 } else { x._2 } ).mkString("\n")
}
}
object ContractEngine {
var stack: List[Contract] = List()
def getCurrent(): Contract = {
if (stack.length == 0) {
throw new Exception("Not currently testing anything")
}
stack.head
}
def contract(fun: Unit => Any): Contract = {
var c = new Contract
stack = c :: stack
try {
fun()
} catch {
case e: Exception => c.refute(Option(e), "Unexpected exception in contract")
}
c.finish
stack = stack.tail
c
}
}
object ContractCheck {
def is(got: Any, exp: Any, mess: String): Boolean = {
ContractEngine.getCurrent.refute( {
if( got == exp ) {
None
} else {
Option( "Got: "+got+"\nExp: "+exp )
}
}, mess );
}
}
object RefuteTest {
def main(args: Array[String]): Unit = {
var c = ContractEngine.contract( None => {
println("Test in progress...")
ContractCheck.is (42, 137, "Life is fine")
ContractCheck.is (List(1,2,3), 1::List(2,3), "Compare list")
} )
println( c.signature )
println( c.report )
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment