From 176e3935a5a81ea4ee86022141169e7aefe80d70 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 19 Mar 2015 22:43:27 +1100 Subject: [PATCH] print a warning message when using junitxml and html and the jar are not on the classpath even if "verbose" is not on --- .../main/scala/org/specs2/runner/Runner.scala | 8 +++--- .../scala/org/specs2/runner/RunnerSpec.scala | 26 ++++++++++++++++++- .../org/specs2/matcher/ActionMatchers.scala | 19 +++++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/core/src/main/scala/org/specs2/runner/Runner.scala b/core/src/main/scala/org/specs2/runner/Runner.scala index 68b00d5830..a88087d460 100644 --- a/core/src/main/scala/org/specs2/runner/Runner.scala +++ b/core/src/main/scala/org/specs2/runner/Runner.scala @@ -86,13 +86,13 @@ object Runner { def createJUnitXmlPrinter(args: Arguments, loader: ClassLoader): Action[Option[Printer]] = createPrinterInstance(args, loader, JUNITXML, "org.specs2.reporter.JUnitXmlPrinter$", - "cannot create a JUnit XML printer. Please check that specs2-junit is on the classpath", + "cannot create a JUnit XML printer. Please check that specs2-junit.jar is on the classpath", "no JUnit XML printer defined") def createHtmlPrinter(args: Arguments, loader: ClassLoader): Action[Option[Printer]] = createPrinterInstance(args, loader, HTML, "org.specs2.reporter.HtmlPrinter$", - "cannot create a HTML printer. Please check that specs2-html is on the classpath", + "cannot create a HTML printer. Please check that specs2-html.jar is on the classpath", "no HTML printer defined") def createMarkdownPrinter(args: Arguments, loader: ClassLoader): Action[Option[Printer]] = @@ -123,7 +123,7 @@ object Runner { result <- instance match { case \/-(i) => Actions.ok(Some(i)) - case -\/(t) => noInstance(failureMessage, t, args.verbose) + case -\/(t) => noInstance(failureMessage, t, verbose = true) } } yield result else noInstance(noRequiredMessage, args.verbose) @@ -137,7 +137,7 @@ object Runner { instance <- Classes.createInstanceEither[T](className, loader)(m) result <- instance match { case \/-(i) => Actions.ok(Some(i)) - case -\/(t) => noInstance(failureMessage(className), t, args.verbose) + case -\/(t) => noInstance(failureMessage(className), t, verbose = true) } } yield result diff --git a/core/src/test/scala/org/specs2/runner/RunnerSpec.scala b/core/src/test/scala/org/specs2/runner/RunnerSpec.scala index 86c12b9266..0a6b737ddb 100644 --- a/core/src/test/scala/org/specs2/runner/RunnerSpec.scala +++ b/core/src/test/scala/org/specs2/runner/RunnerSpec.scala @@ -4,8 +4,10 @@ package runner import main.Arguments import control._ import Runner._ +import matcher.ActionMatchers +import org.specs2.io.StringOutput -class RunnerSpec extends Specification { def is = s2""" +class RunnerSpec extends Specification with ActionMatchers { def is = s2""" A runner creates printers based on the command line arguments the console printer must be created if there aren't other printers $console1 @@ -16,6 +18,12 @@ class RunnerSpec extends Specification { def is = s2""" from object names without $$ $objects2 from classes $classes + If a printer can not be instantiated there must be + a message $instantiationFailure + hints for specific printers + if specs2-junit jar might be missing $missingJunitJar + if specs2-html jar might be missing $missingHtmlJar + """ def console1 = @@ -33,6 +41,22 @@ class RunnerSpec extends Specification { def is = s2""" def classes = TextRunner.createSpecification("org.specs2.runner.RunnerSpec").runOption must beSome + def instantiationFailure = + createPrintersAndExpectMessage(Arguments.split("notifier missing"), "cannot create a missing notifier") + + def missingJunitJar = + createPrintersAndExpectMessage(Arguments.split("junitxml"), "cannot create a JUnit XML printer. Please check that specs2-junit.jar") + + def missingHtmlJar = + createPrintersAndExpectMessage(Arguments.split("html"), "cannot create a HTML printer. Please check that specs2-html.jar") + + def createPrintersAndExpectMessage(arguments: Arguments, message: String) = { + val output = new StringOutput {} + val consoleLogger = (s: String) => scalaz.effect.IO(output.print(s)) + ClassRunner.createPrinters(arguments, loader).run(consoleLogger).unsafePerformIO + output.messages must contain(message) + } + val loader = getClass.getClassLoader } diff --git a/matcher/src/main/scala/org/specs2/matcher/ActionMatchers.scala b/matcher/src/main/scala/org/specs2/matcher/ActionMatchers.scala index 8454d48523..bfcdf9d3f6 100644 --- a/matcher/src/main/scala/org/specs2/matcher/ActionMatchers.scala +++ b/matcher/src/main/scala/org/specs2/matcher/ActionMatchers.scala @@ -1,10 +1,11 @@ package org.specs2 package matcher -import execute.AsResult +import execute._ import control._ import scalaz.std.anyVal._ import MatchersCreation._ +import text.Regexes._ /** * Matchers for Action values @@ -23,6 +24,22 @@ trait ActionMatchers extends ValueChecks { def beOkWithValue[T](t: T): Matcher[Action[T]] = beOk(new BeEqualTo(t)) + def beKo[T]: Matcher[Action[T]] = (action: Action[T]) => + action.execute(noLogging).unsafePerformIO.foldAll( + ok => Failure("a failure was expected"), + m => Success(), + t => Success(), + (m, t) => Success() + ) + + def beKo[T](message: String): Matcher[Action[T]] = (action: Action[T]) => + action.execute(noLogging).unsafePerformIO.foldAll( + ok => Failure(s"a failure with message $message was expected"), + m => if (m matchesSafely message) Success() else Failure(s"the action failed with message $m. Expected: $message"), + throwable => if (throwable.getMessage matchesSafely message) Success() else Failure(s"the action failed with message ${throwable.getMessage}. Expected: $message"), + (m, t) => if (m matchesSafely message) Success() else Failure(s"the action failed with message $m. Expected: $message") + ) + } object ActionMatchers extends ActionMatchers