aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/scala/org/perl8/test/tap/TestBuilder.scala
blob: ac576d8a31e5d446ae1749a11b38d3d4f48db14c (plain) (blame)
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
package org.perl8.test.tap

import org.perl8.test.Utils._

class TestBuilder (
  plan:             Option[Plan],
  val indent:       String,
  private val name: Message
) {
  plan.foreach(p => println(Producer.plan(p)))

  def this (
    plan:   Plan,
    indent: String       = "",
    name:   Message      = NoMessage
  ) =
    this(Some(plan), indent, name)

  def this (
    indent: String       = "",
    name:   Message      = NoMessage
  ) =
    this(None, indent, name)

  def ok (
    test:        Boolean,
    description: Message = NoMessage,
    todo:        Message = NoMessage
  ) {
    val line = Producer.result(test, state.currentTest, description, todo)
    state.ok(test || todo.isDefined)
    println(line)
  }

  def skip (reason: Message = NoMessage) {
    val line = Producer.skip(state.currentTest, reason)
    state.ok(true)
    println(line)
  }

  def diag (message: Message) {
    message.foreach(m => println(Producer.comment(m)))
  }

  def bailOut (message: Message = NoMessage) {
    println(Producer.bailOut(message))
    throw new BailOutException(message.getOrElse(""))
  }

  def doneTesting () {
    plan match {
      case None => println(Producer.plan(state.currentTest - 1))
      case _    => ()
    }

    if (!isPassing) {
      if (!state.matchesPlan) {
        val planCount = (plan match {
          case Some(p) => p.plan
          case None    => state.currentTest - 1
        })
        val planned = planCount + " test" + (if (planCount > 1) "s" else "")
        val ran = state.currentTest - 1
        diag("Looks like you planned " + planned + " but ran " + ran + ".")
      }

      if (state.currentTest == 1) {
        diag("No tests run!")
      }

      if (state.failCount > 0) {
        val count = state.failCount
        val fails = count + " test" + (if (count > 1) "s" else "")
        val total =
          state.currentTest - 1 + (if (state.matchesPlan) "" else " run")
        diag("Looks like you failed " + fails + " of " + total + ".")
      }
    }
  }

  def isPassing: Boolean =
    state.isPassing

  def failedTests: Int =
    state.failCount

  private val state = new TestState

  private def println (str: String) {
    val indented =
      str.split("\n").map(s => indent + s).mkString("\n")
    Console.println(indented)
  }

  private class TestState {
    var passCount = 0
    var failCount = 0

    def ok (cond: Boolean) {
      if (cond) {
        passCount += 1
      }
      else {
        failCount += 1
      }
    }

    def currentTest: Int =
      failCount + passCount + 1

    def matchesPlan: Boolean = plan match {
      case Some(p) => p.plan == failCount + passCount
      case None    => true
    }

    def isPassing: Boolean =
      currentTest > 1 && failCount == 0 && matchesPlan
  }
}