X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fscala%2FSbtTapReporting.scala;h=8d90fbeccace323b9691ef5d9b7369ee70f35fc5;hb=HEAD;hp=2524bda33ddaa57f11667d840c5f497120fbc4dd;hpb=edbf311f88823359d167c75600086d9f93dc63ed;p=chaz%2Fsbt-tap diff --git a/src/main/scala/SbtTapReporting.scala b/src/main/scala/SbtTapReporting.scala index 2524bda..8d90fbe 100644 --- a/src/main/scala/SbtTapReporting.scala +++ b/src/main/scala/SbtTapReporting.scala @@ -1,16 +1,9 @@ -package sbttap - +import java.io.{PrintWriter, StringWriter, File, FileWriter} import sbt._ import org.scalatools.testing.{Event => TEvent, Result => TResult} -import Keys._ -import java.util.concurrent.atomic.AtomicInteger -import java.io.{File, FileWriter} - object SbtTapReporting extends Plugin { - override def settings = Seq( - testListeners ++= Seq(new SbtTapListener) - ) + def apply() = new SbtTapListener } /** @@ -22,39 +15,66 @@ object SbtTapReporting extends Plugin { * the current active group might be one way to go. */ class SbtTapListener extends TestsListener { - var testId = new AtomicInteger(0) + var testId = 0 var fileWriter: FileWriter = _ - override def doInit { - new File("test-results").mkdirs() - - fileWriter = new FileWriter("test-results/test.tap") + override def doInit = { + val filename = scala.util.Properties.envOrElse("SBT_TAP_OUTPUT", "test-results/test.tap") + val file = new File(filename) + new File(file.getParent).mkdirs + fileWriter = new FileWriter(file) + writeTap("TAP", "version", 13) } - def startGroup(name: String) {} + def startGroup(name: String) = + writeTapDiag("start", name) + + def endGroup(name: String, result: TestResult.Value) = + writeTapDiag("end", name, "with result", result.toString.toLowerCase) + + def endGroup(name: String, t: Throwable) = { + writeTapDiag("end", name) + writeTapDiag(stackTraceForError(t)) + } - def testEvent(event: TestEvent) { - event.detail.foreach { e: TEvent => + def testEvent(event: TestEvent) = this.synchronized { + event.detail.foreach { e: TEvent => testId += 1 + var modified = false + val description = (if (e.testName.contains("#")) { + modified = true + e.testName.replaceAll("#", "") + } else e.testName).replaceAll("\n", "") e.result match { - case TResult.Success => writeTapFields("ok", testId.incrementAndGet(), "-", e.testName()) - case TResult.Error | TResult.Failure => - writeTapFields("not ok", testId.incrementAndGet(), "-", e.testName()) - // TODO: for exceptions, write stack trace to tap file. + case TResult.Success => + writeTap("ok", testId, "-", description) case TResult.Skipped => - // it doesn't look like this framework distinguishes between pending and ignored. - writeTapFields("ok", testId.incrementAndGet(), "#", "skip", e.testName()) + writeTap("ok", testId, "-", description, "# SKIP") + case TResult.Error | TResult.Failure => + writeTap("not ok", testId, "-", description) + // TODO: It would be nice if we could report the exact line in the test where this happened. + writeTapDiag(stackTraceForError(e.error)) } + if (modified) writeTapDiag("warning: hash character(s) removed from test " + testId + " description") } } - override def doComplete(finalResult: TestResult.Value) { - writeTapFields("1.." + testId.get) - fileWriter.close() + override def doComplete(finalResult: TestResult.Value) = { + writeTap("1.." + testId) + fileWriter.close } - private def writeTapFields(s: Any*) { fileWriter.write(s.mkString("", " ", "\n")) } + private def writeTap(s: Any*) = { + fileWriter.write(s.mkString("", " ", "\n")) + fileWriter.flush + } - def endGroup(name: String, t: Throwable) { } + private def writeTapDiag(s: Any*) = + writeTap("#", s.mkString("", " ", "\n").trim.replaceAll("\\n", "\n# ")) - def endGroup(name: String, result: TestResult.Value) { } + private def stackTraceForError(t: Throwable): String = { + val sw = new StringWriter + val printWriter = new PrintWriter(sw) + t.printStackTrace(printWriter) + sw.toString + } }