]> Dogcows Code - chaz/sbt-tap/blob - src/main/scala/SbtTapReporting.scala
remove unused import
[chaz/sbt-tap] / src / main / scala / SbtTapReporting.scala
1 import java.io.{PrintWriter, StringWriter, File, FileWriter}
2 import sbt._
3 import org.scalatools.testing.{Event => TEvent, Result => TResult}
4
5 object SbtTapReporting extends Plugin {
6 def apply() = new SbtTapListener
7 }
8
9 /**
10 * Listens to sbt test listener events and writes them to a tap compatible file. Results for all groups
11 * go to a single file although it might be desirable to generate one tap file per group.
12 * <p>
13 * sbt runs tests in parallel and the protocol does not seem to provide a way to match a group to a test event. It
14 * does look line one thread calls startGroup/testEvent/endGroup sequentially and using thread local to keep
15 * the current active group might be one way to go.
16 */
17 class SbtTapListener extends TestsListener {
18 var testId = 0
19 var fileWriter: FileWriter = _
20
21 override def doInit = {
22 val filename = scala.util.Properties.envOrElse("SBT_TAP_OUTPUT", "test-results/test.tap")
23 val file = new File(filename)
24 new File(file.getParent).mkdirs
25 fileWriter = new FileWriter(file)
26 writeTap("TAP", "version", 13)
27 }
28
29 def startGroup(name: String) =
30 writeTapDiag("start", name)
31
32 def endGroup(name: String, result: TestResult.Value) =
33 writeTapDiag("end", name, "with result", result.toString.toLowerCase)
34
35 def endGroup(name: String, t: Throwable) = {
36 writeTapDiag("end", name)
37 writeTapDiag(stackTraceForError(t))
38 }
39
40 def testEvent(event: TestEvent) = this.synchronized {
41 event.detail.foreach { e: TEvent => testId += 1
42 var modified = false
43 val description = (if (e.testName.contains("#")) {
44 modified = true
45 e.testName.replaceAll("#", "")
46 } else e.testName).replaceAll("\n", "")
47 e.result match {
48 case TResult.Success =>
49 writeTap("ok", testId, "-", description)
50 case TResult.Skipped =>
51 writeTap("ok", testId, "-", description, "# SKIP")
52 case TResult.Error | TResult.Failure =>
53 writeTap("not ok", testId, "-", description)
54 // TODO: It would be nice if we could report the exact line in the test where this happened.
55 writeTapDiag(stackTraceForError(e.error))
56 }
57 if (modified) writeTapDiag("warning: hash character(s) removed from test " + testId + " description")
58 }
59 }
60
61 override def doComplete(finalResult: TestResult.Value) = {
62 writeTap("1.." + testId)
63 fileWriter.close
64 }
65
66 private def writeTap(s: Any*) = {
67 fileWriter.write(s.mkString("", " ", "\n"))
68 fileWriter.flush
69 }
70
71 private def writeTapDiag(s: Any*) =
72 writeTap("#", s.mkString("", " ", "\n").trim.replaceAll("\\n", "\n# "))
73
74 private def stackTraceForError(t: Throwable): String = {
75 val sw = new StringWriter
76 val printWriter = new PrintWriter(sw)
77 t.printStackTrace(printWriter)
78 sw.toString
79 }
80 }
This page took 0.037349 seconds and 4 git commands to generate.