All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatestplus.scalacheck.CheckerAsserting.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2001-2013 Artima, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.scalatestplus.scalacheck

import org.scalactic.{Resources => _, FailureMessages => _, UnquotedString => _, _}
import NameUtil.getSimpleNameOfAnObjectsClass
import org.scalacheck.Prop
import org.scalacheck.Prop.Arg
import org.scalacheck.Test
import org.scalacheck.util.Pretty
import org.scalatest.Assertion
//import org.scalatest.Expectation
import org.scalatest.Fact
import org.scalatest.Succeeded
import org.scalatest.exceptions.StackDepthException
import org.scalatestplus.scalacheck.FailureMessages.decorateToStringValue
import org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException
import org.scalatest.exceptions.StackDepth

/**
 * Supertrait for CheckerAsserting typeclasses, which are used to implement and determine the result
 * type of [[org.scalatest.prop.GeneratorDrivenPropertyChecks GeneratorDrivenPropertyChecks]]'s apply and forAll method.
 *
 * 

* Currently, an [[org.scalatest.prop.GeneratorDrivenPropertyChecks GeneratorDrivenPropertyChecks]] expression will have result type Assertion, if the function passed has result type Assertion, * else it will have result type Unit. *

*/ trait CheckerAsserting[T] { /** * The result type of the check method. */ type Result def succeed(result: T): (Boolean, Option[Throwable]) /** * Perform the property check using the given Prop and Test.Parameters. * * @param p the Prop to be used to check * @param prms the Test.Parameters to be used to check * @param prettifier the Prettifier to be used to prettify error message * @param pos the Position of the caller site * @param argNames the list of argument names * @return the Result of the property check. */ def check(p: Prop, prms: Test.Parameters, prettifier: Prettifier, pos: source.Position, argNames: Option[List[String]] = None): Result } /** * Class holding lowest priority CheckerAsserting implicit, which enables [[org.scalatest.prop.GeneratorDrivenPropertyChecks GeneratorDrivenPropertyChecks]] expressions that have result type Unit. */ abstract class UnitCheckerAsserting { /** * Abstract subclass of CheckerAsserting that provides the bulk of the implementations of CheckerAsserting * check method. */ /* protected[scalatest]*/ abstract class CheckerAssertingImpl[T] extends CheckerAsserting[T] { import CheckerAsserting._ /** * Check the given Prop and Test.Parameters by calling [[http://www.scalacheck.org ScalaCheck]]'s Test.check. * If the check succeeds, call indicateSuccess, else call indicateFailure. * * * @param p the Prop to be used to check * @param prms the Test.Parameters to be used to check * @param prettifier the Prettifier to be used to prettify error message * @param pos the Position of the caller site * @param argNames the list of argument names * @return the Result of the property check. */ def check(p: Prop, prms: Test.Parameters, prettifier: Prettifier, pos: source.Position, argNames: Option[List[String]] = None): Result = { val result = Test.check(prms, p) if (!result.passed) { val (args, labels) = argsAndLabels(result) (result.status: @unchecked) match { case Test.Exhausted => val failureMsg = if (result.succeeded == 1) FailureMessages.propCheckExhaustedAfterOne(prettifier, result.discarded) else FailureMessages.propCheckExhausted(prettifier, result.succeeded, result.discarded) indicateFailure( sde => failureMsg, failureMsg, args, labels, None, pos ) case Test.Failed(scalaCheckArgs, scalaCheckLabels) => val stackDepth = 1 indicateFailure( sde => FailureMessages.propertyException(prettifier, UnquotedString(sde.getClass.getSimpleName)) + "\n" + ( sde.failedCodeFileNameAndLineNumberString match { case Some(s) => " (" + s + ")"; case None => "" }) + "\n" + " " + FailureMessages.propertyFailed(prettifier, result.succeeded) + "\n" + ( sde match { case sd: StackDepth if sd.failedCodeFileNameAndLineNumberString.isDefined => " " + FailureMessages.thrownExceptionsLocation(prettifier, UnquotedString(sd.failedCodeFileNameAndLineNumberString.get)) + "\n" case _ => "" } ) + " " + FailureMessages.occurredOnValues + "\n" + prettyArgs(getArgsWithSpecifiedNames(argNames, scalaCheckArgs), prettifier) + "\n" + " )" + getLabelDisplay(scalaCheckLabels), FailureMessages.propertyFailed(prettifier, result.succeeded), scalaCheckArgs, scalaCheckLabels.toList, None, pos ) case Test.PropException(scalaCheckArgs, e, scalaCheckLabels) => indicateFailure( sde => FailureMessages.propertyException(prettifier, UnquotedString(e.getClass.getSimpleName)) + "\n" + " " + FailureMessages.thrownExceptionsMessage(prettifier, if (e.getMessage == null) "None" else UnquotedString(e.getMessage)) + "\n" + ( e match { case sd: StackDepth if sd.failedCodeFileNameAndLineNumberString.isDefined => " " + FailureMessages.thrownExceptionsLocation(prettifier, UnquotedString(sd.failedCodeFileNameAndLineNumberString.get)) + "\n" case _ => "" } ) + " " + FailureMessages.occurredOnValues + "\n" + prettyArgs(getArgsWithSpecifiedNames(argNames, scalaCheckArgs), prettifier) + "\n" + " )" + getLabelDisplay(scalaCheckLabels), FailureMessages.propertyException(prettifier, UnquotedString(e.getClass.getName)), scalaCheckArgs, scalaCheckLabels.toList, Some(e), pos ) } } else indicateSuccess(FailureMessages.propertyCheckSucceeded) } private[scalacheck] def indicateSuccess(message: => String): Result private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Result } /** * Provides support of [[org.scalatest.enablers.CheckerAsserting CheckerAsserting]] for Unit. Do nothing when the check succeeds, * but throw [[org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException GeneratorDrivenPropertyCheckFailedException]] * when check fails. */ implicit def assertingNatureOfT[T]: CheckerAsserting[T] { type Result = Unit } = new CheckerAssertingImpl[T] { type Result = Unit def succeed(result: T) = (true, None) private[scalacheck] def indicateSuccess(message: => String): Unit = () private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Unit = { throw new GeneratorDrivenPropertyCheckFailedException( messageFun, optionalCause, pos, None, undecoratedMessage, scalaCheckArgs, None, scalaCheckLabels.toList ) } } } /** * Abstract class that in the future will hold an intermediate priority CheckerAsserting implicit, which will enable inspector expressions * that have result type Expectation, a more composable form of assertion that returns a result instead of throwing an exception when it fails. */ abstract class ExpectationCheckerAsserting extends UnitCheckerAsserting { /*implicit def assertingNatureOfExpectation(implicit prettifier: Prettifier): CheckerAsserting[Expectation] { type Result = Expectation } = { new CheckerAssertingImpl[Expectation] { type Result = Expectation def succeed(result: Expectation) = (result.isYes, result.cause) private[scalacheck] def indicateSuccess(message: => String): Expectation = Fact.Yes(message)(prettifier) private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Expectation = { val gdpcfe = new GeneratorDrivenPropertyCheckFailedException( messageFun, optionalCause, pos, None, undecoratedMessage, scalaCheckArgs, None, scalaCheckLabels.toList ) val message: String = gdpcfe.getMessage Fact.No(message)(prettifier) } } }*/ } /** * Companion object to CheckerAsserting that provides two implicit providers, a higher priority one for passed functions that have result * type Assertion, which also yields result type Assertion, and one for any other type, which yields result type Unit. */ object CheckerAsserting extends ExpectationCheckerAsserting { /** * Provides support of [[org.scalatest.enablers.CheckerAsserting CheckerAsserting]] for Assertion. Returns [[org.scalatest.Succeeded Succeeded]] when the check succeeds, * but throw [[org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException GeneratorDrivenPropertyCheckFailedException]] * when check fails. */ implicit def assertingNatureOfAssertion: CheckerAsserting[Assertion] { type Result = Assertion } = { new CheckerAssertingImpl[Assertion] { type Result = Assertion def succeed(result: Assertion) = (true, None) private[scalacheck] def indicateSuccess(message: => String): Assertion = Succeeded private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Assertion = { throw new GeneratorDrivenPropertyCheckFailedException( messageFun, optionalCause, pos, None, undecoratedMessage, scalaCheckArgs, None, scalaCheckLabels.toList ) } } } private[scalacheck] def getArgsWithSpecifiedNames(argNames: Option[List[String]], scalaCheckArgs: List[Arg[Any]]) = { if (argNames.isDefined) { // length of scalaCheckArgs should equal length of argNames val zipped = argNames.get zip scalaCheckArgs zipped map { case (argName, arg) => arg.copy(label = argName) } } else scalaCheckArgs } private[scalacheck] def getLabelDisplay(labels: Set[String]): String = if (labels.size > 0) "\n " + (if (labels.size == 1) Resources.propCheckLabel else Resources.propCheckLabels) + "\n" + labels.map(" " + _).mkString("\n") else "" private[scalacheck] def argsAndLabels(result: Test.Result): (List[Any], List[String]) = { val (scalaCheckArgs, scalaCheckLabels) = result.status match { case Test.Proved(args) => (args.toList, List()) case Test.Failed(args, labels) => (args.toList, labels.toList) case Test.PropException(args, _, labels) => (args.toList, labels.toList) case _ => (List(), List()) } val args: List[Any] = for (scalaCheckArg <- scalaCheckArgs.toList) yield scalaCheckArg.arg // scalaCheckLabels is a Set[String], I think val labels: List[String] = for (scalaCheckLabel <- scalaCheckLabels.iterator.toList) yield scalaCheckLabel (args, labels) } // TODO: Internationalize these, and make them consistent with FailureMessages stuff (only strings get quotes around them, etc.) private[scalacheck] def prettyTestStats(result: Test.Result, prettifier: Prettifier) = result.status match { case Test.Proved(args) => "OK, proved property: \n" + prettyArgs(args, prettifier) case Test.Passed => "OK, passed " + result.succeeded + " tests." case Test.Failed(args, labels) => "Falsified after " + result.succeeded + " passed tests:\n" + prettyLabels(labels) + prettyArgs(args, prettifier) case Test.Exhausted => "Gave up after only " + result.succeeded + " passed tests. " + result.discarded + " tests were discarded." case Test.PropException(args, e, labels) => FailureMessages.propertyException(prettifier, UnquotedString(e.getClass.getSimpleName)) + "\n" + prettyLabels(labels) + prettyArgs(args, prettifier) } private[scalacheck] def prettyLabels(labels: Set[String]) = { if (labels.isEmpty) "" else if (labels.size == 1) "Label of failing property: " + labels.iterator.next + "\n" else "Labels of failing property: " + labels.mkString("\n") + "\n" } // // If scalacheck arg contains a type that // decorateToStringValue processes, then let // decorateToStringValue handle it. Otherwise use its // prettyArg method to generate the display string. // // Passes 0 as verbosity value to prettyArg function. // private[scalacheck] def decorateArgToStringValue(arg: Arg[_], prettifier: Prettifier): String = arg.arg match { case null => decorateToStringValue(prettifier, arg.arg) case _: Unit => decorateToStringValue(prettifier, arg.arg) case _: String => decorateToStringValue(prettifier, arg.arg) case _: Char => decorateToStringValue(prettifier, arg.arg) case _: Array[_] => decorateToStringValue(prettifier, arg.arg) case _ => arg.prettyArg(new Pretty.Params(0)) } private[scalacheck] def prettyArgs(args: List[Arg[_]], prettifier: Prettifier) = { val strs = for((a, i) <- args.zipWithIndex) yield ( " " + (if (a.label == "") "arg" + i else a.label) + " = " + decorateArgToStringValue(a, prettifier) + (if (i < args.length - 1) "," else "") + (if (a.shrinks > 0) " // " + a.shrinks + (if (a.shrinks == 1) " shrink" else " shrinks") else "") ) strs.mkString("\n") } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy