aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/scala/com/iinteractive/test/harness/TestHarness.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/com/iinteractive/test/harness/TestHarness.scala')
-rw-r--r--src/main/scala/com/iinteractive/test/harness/TestHarness.scala110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/main/scala/com/iinteractive/test/harness/TestHarness.scala b/src/main/scala/com/iinteractive/test/harness/TestHarness.scala
new file mode 100644
index 0000000..7b8f4ae
--- /dev/null
+++ b/src/main/scala/com/iinteractive/test/harness/TestHarness.scala
@@ -0,0 +1,110 @@
+package com.iinteractive.test.harness
+
+/** This is the entry point to running tests written with this library from
+ * the command line. Note that this library also implements the
+ * [[https://github.com/harrah/test-interface common testing interface]] for
+ * test libraries, so tests should also just work with `sbt test`.
+ *
+ * If this application is run and given just a single test class name, it
+ * will run that test and write its TAP stream to the console.
+ *
+ * {{{
+ * $ scala com.iinteractive.test.harness.TestHarness MyTest
+ * ok 1
+ * ok 2
+ * 1..2
+ * }}}
+ *
+ * If this application is run and given multiple test class names, it will
+ * run each of those tests, and present a summary report, similar to the one
+ * produces by
+ * [[https://metacpan.org/module/Test::Harness Perl's Test::Harness]].
+ *
+ * {{{
+ * $ scala com.iinteractive.test.harness.TestHarness MyTest1 MyTest2
+ * MyTest1 .. ok
+ * MyTest2 .. ok
+ * All tests successful.
+ * Files=2, Tests=4
+ * Result: PASS
+ * }}}
+ *
+ * This application also accepts a few command line options to customize its
+ * behavior:
+ *
+ * - `-r`: Alternative [[com.iinteractive.test.harness.Reporter Reporter]]
+ * class to use for running a single test.
+ * - `-R`: Alternative
+ * [[com.iinteractive.test.harness.MultiTestReporter MultiTestReporter]]
+ * class to use for running a group of tests. Also enables using the
+ * MultiTestReporter for a single test.
+ * - `--help`: Prints usage information.
+ */
+object TestHarness {
+ import com.iinteractive.test.Test
+
+ /** Entry point for the harness application. */
+ def main (args: Array[String]) {
+ val opts = parseOpts(args.toList)
+ val single = opts("prefer-single").asInstanceOf[Boolean]
+
+ val exitCode = if (single) {
+ val reporterName = opts("single-reporter").asInstanceOf[String]
+ val testName = opts("test-classes").asInstanceOf[List[String]].apply(0)
+ val reporter = newInstance[Reporter](reporterName)
+ reporter.run(testName)
+ }
+ else {
+ val reporterName = opts("multi-reporter").asInstanceOf[String]
+ val testNames = opts("test-classes").asInstanceOf[List[String]]
+ val reporter = newInstance[MultiTestReporter](reporterName)
+ reporter.run(testNames)
+ }
+
+ sys.exit(exitCode)
+ }
+
+ protected def parseOpts (args: List[String]): Map[String, Any] = args match {
+ case Nil => Map(
+ "single-reporter" -> "com.iinteractive.test.harness.TAPReporter",
+ "multi-reporter" -> "com.iinteractive.test.harness.SummaryReporter",
+ "prefer-single" -> true,
+ "test-classes" -> Nil
+ )
+
+ case "-r" :: singleReporter :: rest =>
+ parseOpts(rest) + ("single-reporter" -> singleReporter)
+
+ case "-R" :: multiReporter :: rest =>
+ parseOpts(rest) ++ Map(
+ "multi-reporter" -> multiReporter,
+ "prefer-single" -> false
+ )
+
+ case "--help" :: rest =>
+ usage(0)
+
+ case `unknownOption` :: rest =>
+ usage(1)
+
+ case testClass :: rest => {
+ val opts = parseOpts(rest)
+ val tests = opts("test-classes").asInstanceOf[List[String]]
+ opts ++ Map(
+ "test-classes" -> (testClass :: tests),
+ "prefer-single" -> tests.isEmpty
+ )
+ }
+ }
+
+ protected def usage (exitCode: Int) = {
+ val out = if (exitCode == 0) Console.out else Console.err
+ out.println("harness [-r <single-reporter-class>]\n" +
+ " [-R <multi-reporter-class>]\n" +
+ " [--help]\n" +
+ " <test-class> [<test-class>...]\n")
+ sys.exit(exitCode)
+ }
+
+ private val unknownOption = """^-.*""".r
+}