/
TestReportListener.scala
121 lines (113 loc) · 3.71 KB
/
TestReportListener.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Steven Blundy, Mark Harrah
*/
package sbt
import org.scalatools.testing.{Logger => TLogger, Event => TEvent, Result => TResult}
trait TestReportListener
{
/** called for each class or equivalent grouping */
def startGroup(name: String)
/** called for each test method or equivalent */
def testEvent(event: TestEvent)
/** called if there was an error during test */
def endGroup(name: String, t: Throwable)
/** called if test completed */
def endGroup(name: String, result: TestResult.Value)
/** Used by the test framework for logging test results*/
def contentLogger(test: TestDefinition): Option[ContentLogger] = None
}
trait TestsListener extends TestReportListener
{
/** called once, at beginning. */
def doInit
/** called once, at end. */
def doComplete(finalResult: TestResult.Value)
}
abstract class TestEvent extends NotNull
{
def result: Option[TestResult.Value]
def detail: Seq[TEvent] = Nil
}
object TestEvent
{
def apply(events: Seq[TEvent]): TestEvent =
{
val overallResult = (TestResult.Passed /: events) { (sum, event) =>
val result = event.result
if(sum == TestResult.Error || result == TResult.Error) TestResult.Error
else if(sum == TestResult.Failed || result == TResult.Failure) TestResult.Failed
else TestResult.Passed
}
new TestEvent {
val result = Some(overallResult)
override val detail = events
}
}
}
object TestLogger
{
def apply(logger: sbt.Logger, logTest: TestDefinition => sbt.Logger, buffered: Boolean): TestLogger =
new TestLogger(new TestLogging(wrap(logger), tdef => contentLogger(logTest(tdef), buffered)) )
def contentLogger(log: sbt.Logger, buffered: Boolean): ContentLogger =
{
val blog = new BufferedLogger(FullLogger(log))
if(buffered) blog.record()
new ContentLogger(wrap(blog), () => blog.stopQuietly())
}
def wrap(logger: sbt.Logger): TLogger =
new TLogger
{
def error(s: String) = log(Level.Error, s)
def warn(s: String) = log(Level.Warn, s)
def info(s: String) = log(Level.Info, s)
def debug(s: String) = log(Level.Debug, s)
def trace(t: Throwable) = logger.trace(t)
private def log(level: Level.Value, s: String) = logger.log(level, s)
def ansiCodesSupported() = true//logger.ansiCodesSupported
}
}
final class TestLogging(val global: TLogger, val logTest: TestDefinition => ContentLogger)
final class ContentLogger(val log: TLogger, val flush: () => Unit)
class TestLogger(val logging: TestLogging) extends TestsListener
{
import logging.{global => log, logTest}
protected var skipped, errors, passed, failures = 0
def startGroup(name: String) {}
def testEvent(event: TestEvent): Unit = event.detail.foreach(count)
def endGroup(name: String, t: Throwable)
{
log.trace(t)
log.error("Could not run test " + name + ": " + t.toString)
}
def endGroup(name: String, result: TestResult.Value) {}
protected def count(event: TEvent): Unit =
{
event.result match
{
case TResult.Error => errors +=1
case TResult.Success => passed +=1
case TResult.Failure => failures +=1
case TResult.Skipped => skipped += 1
}
}
def doInit
{
failures = 0
errors = 0
passed = 0
skipped = 0
}
/** called once, at end. */
def doComplete(finalResult: TestResult.Value): Unit =
{
val totalCount = failures + errors + skipped + passed
val postfix = ": Total " + totalCount + ", Failed " + failures + ", Errors " + errors + ", Passed " + passed + ", Skipped " + skipped
finalResult match
{
case TestResult.Error => log.error("Error" + postfix)
case TestResult.Passed => log.info("Passed: " + postfix)
case TestResult.Failed => log.error("Failed: " + postfix)
}
}
override def contentLogger(test: TestDefinition): Option[ContentLogger] = Some(logTest(test))
}