package scalactic
- Source
- package.scala
- Alphabetic
- By Inheritance
- scalactic
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
-
trait
AbstractStringUniformity extends Uniformity[String]
Convenience base trait for string
Uniformity
s.Convenience base trait for string
Uniformity
s.This trait defines a
normalizedCanHandle
method that returns true if the passedAny
is aString
and anormalizedOrSame
method that normalizes any passedString
s via thenormalized
method, which is left abstract for subclasses to fill in.Here's an example in which
AbstractStringUniformity
is used to normalize strings by ensuring the first character, if any, is capitalized:val capitalized: Uniformity[String] = new AbstractStringUniformity { def normalized(s: String): String = if (s.isEmpty) "" else s.charAt(0).toUpper + s.substring(1) }
Here's an example of using the
capitalized
Uniformity
with aMatcher
expression:scala> import org.scalatest._ import org.scalatest._ scala> import Matchers._ import Matchers._ scala> import org.scalactic._ import org.scalactic._ scala> val capitalized: Uniformity[String] = | new AbstractStringUniformity { | def normalized(s: String): String = | if (s.isEmpty) "" else s.charAt(0).toUpper + s.substring(1) | } capitalized: org.scalactic.Uniformity[String] = $anon$1@65601e00 scala> "Hello" should equal ("hello") (after being capitalized)
-
trait
Accumulation extends AnyRef
Provides mechanisms that enable errors to be accumulated in “accumulating
Or
s,”Or
s whoseBad
type is anEvery
.Provides mechanisms that enable errors to be accumulated in “accumulating
Or
s,”Or
s whoseBad
type is anEvery
.The mechanisms are:
- Passing accumulating
Or
s towithGood
methods - Invoking
combined
on a container of accumulatingOr
s - Invoking
validatedBy
on a container of any type, passing in a function from that type to an accumulatingOr
- Invoking
zip
on an accumulatingOr
- Invoking
when
on an accumulatingOr
For more information and examples, see the Accumulating errors with
Or
section of the main documentation for classOr
. - Passing accumulating
-
final
case class
Bad[+B](b: B) extends Or[Nothing, B] with Product with Serializable
Contains a “bad” value.
Contains a “bad” value.
You can decide what “bad” means, but it is expected
Bad
will be commonly used to hold descriptions of an error (or several, accumulated errors). Some examples of possible error descriptions areString
error messages,Int
error codes,Throwable
exceptions, or instances of a case class hierarchy designed to describe errors.- b
the “bad” value
-
trait
Bool extends AnyRef
A trait that represent a rich-featured boolean value, which includes the following members:
A trait that represent a rich-featured boolean value, which includes the following members:
- a boolean value
- methods useful for failure messages construction
- logical expression methods that makes
Bool
composable
Bool
is used by code generated fromBooleanMacro
(whichAssertionsMacro
andRequirementsMacro
uses), it needs to be public so that the generated code can be compiled. It is expected that ScalaTest users would ever need to useBool
directly. -
abstract
class
CanEqual[A, B] extends AnyRef
Abstract class used to enforce type constraints for equality checks.
Abstract class used to enforce type constraints for equality checks.
For more information on how this class is used, see the documentation of
TripleEqualsSupport
.- Annotations
- @implicitNotFound( ... )
-
class
Catcher extends AnyRef
Convenience class for extractors that match and return
Throwable
s based on a type andBoolean
condition.Convenience class for extractors that match and return
Throwable
s based on a type andBoolean
condition.Class
Catcher
was motivated by the need to catch and handle exceptions based on more than just the exception's type as a strategy for dealing with "flickering" tests—tests that usually pass, but occasionally fail. The best strategy for dealing with flickers is to fix the test such that they stop flickering, but sometimes that is not practical. In such cases allowing the test to continue flickering can distract the team by requiring them to spend time inspecting failures to determine whether or not they are flickers or real failures that need attention. Worse, with enough flickers, team members can stop checking all failures and not notice real ones.One strategy for dealing with flickers you can't practically fix is to catch exceptions that are causing individual flickers and cancel the test when you detect them. Often this means you will need to insert a catch clause in a particular spot, or a pattern match if in a
withFixture
, looking for a particular exception with a particular message or other identifying attribute. If the same problem is causing flickers in many places, it is handy to create an extractor to detect the problem. ThisCatcher
class provides a factory method that takes a partial function fromThrowable
toBoolean
and produces such an extractor. Here's an example:val InternalServerError = Catcher { case e: DBAccessException => e.getMessage == "500:Internal Server Error" }
Using this
Catcher
in a ScalaTestwithFixture
method would look like:override def withFixture(test: NoArgTest) = { super.withFixture(test) match { case Failed(InternalServerError(ex)) => Canceled("Canceled because likely a flicker caused by intermittently flaky DB", ex) case other => other } }
-
final
class
Chain[+T] extends AnyVal
A non-empty list: an ordered, immutable, non-empty collection of elements with
LinearSeq
performance characteristics.A non-empty list: an ordered, immutable, non-empty collection of elements with
LinearSeq
performance characteristics.The purpose of
Chain
is to allow you to express in a type that aList
is non-empty, thereby eliminating the need for (and potential exception from) a run-time check for non-emptiness. For a non-empty sequence withIndexedSeq
performance, seeEvery
.Constructing
Chain
sYou can construct a
Chain
by passing one or more elements to theChain.apply
factory method:scala> Chain(1, 2, 3) res0: org.scalactic.Chain[Int] = Chain(1, 2, 3)
Alternatively you can cons elements onto the
End
singleton object, similar to making aList
starting withNil
:scala> 1 :: 2 :: 3 :: Nil res0: List[Int] = List(1, 2, 3) scala> 1 :: 2 :: 3 :: End res1: org.scalactic.Chain[Int] = Chain(1, 2, 3)
Note that although
Nil
is aList[Nothing]
,End
is not aChain[Nothing]
, because no emptyChain
exists. (A chain is a series of connected links; if you have no links, you have no chain.)scala> val nil: List[Nothing] = Nil nil: List[Nothing] = List() scala> val nada: Chain[Nothing] = End <console>:16: error: type mismatch; found : org.scalactic.End.type required: org.scalactic.Chain[Nothing] val nada: Chain[Nothing] = End ^
Working with
Chain
sChain
does not extend Scala'sSeq
orTraversable
traits because these require that implementations may be empty. For example, if you invoketail
on aSeq
that contains just one element, you'll get an emptySeq
:scala> List(1).tail res6: List[Int] = List()
On the other hand, many useful methods exist on
Seq
that when invoked on a non-emptySeq
are guaranteed to not result in an emptySeq
. For convenience,Chain
defines a method corresponding to every suchSeq
method. Here are some examples:Chain(1, 2, 3).map(_ + 1) // Result: Chain(2, 3, 4) Chain(1).map(_ + 1) // Result: Chain(2) Chain(1, 2, 3).containsSlice(Chain(2, 3)) // Result: true Chain(1, 2, 3).containsSlice(Chain(3, 4)) // Result: false Chain(-1, -2, 3, 4, 5).minBy(_.abs) // Result: -1
Chain
does not currently define any methods corresponding toSeq
methods that could result in an emptySeq
. However, an implicit converison fromChain
toList
is defined in theChain
companion object that will be applied if you attempt to call one of the missing methods. As a result, you can invokefilter
on anChain
, even thoughfilter
could result in an empty sequence—but the result type will beList
instead ofChain
:Chain(1, 2, 3).filter(_ < 10) // Result: List(1, 2, 3) Chain(1, 2, 3).filter(_ > 10) // Result: List()
You can use
Chain
s infor
expressions. The result will be anChain
unless you use a filter (anif
clause). Because filters are desugared to invocations offilter
, the result type will switch to aList
at that point. Here are some examples:scala> import org.scalactic._ import org.scalactic._ scala> for (i <- Chain(1, 2, 3)) yield i + 1 res0: org.scalactic.Chain[Int] = Chain(2, 3, 4) scala> for (i <- Chain(1, 2, 3) if i < 10) yield i + 1 res1: List[Int] = List(2, 3, 4) scala> for { | i <- Chain(1, 2, 3) | j <- Chain('a', 'b', 'c') | } yield (i, j) res3: org.scalactic.Chain[(Int, Char)] = Chain((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c)) scala> for { | i <- Chain(1, 2, 3) if i < 10 | j <- Chain('a', 'b', 'c') | } yield (i, j) res6: List[(Int, Char)] = List((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c))
- T
the type of elements contained in this
Chain
-
trait
Equality[A] extends Equivalence[A]
Defines a custom way to determine equality for a type when compared with another value of type
Any
.Defines a custom way to determine equality for a type when compared with another value of type
Any
.Equality
enables you to define alternate notions of equality for types that can be used with ScalaUtil's===
and!==
syntax and ScalaTest's matcher syntax.For example, say you have a case class that includes a
Double
value:scala> case class Person(name: String, age: Double) defined class Person
Imagine you are calculating the
age
values in such as way that occasionally tests are failing because of rounding differences that you actually don't care about. For example, you expect an age of 29.0, but you're sometimes seeing 29.0001:scala> import org.scalactic._ import org.scalactic._ scala> import TripleEquals._ import TripleEquals._ scala> Person("Joe", 29.0001) === Person("Joe", 29.0) res0: Boolean = false
The
===
operator looks for an implicitEquality[L]
, whereL
is the left-hand type: in this case,Person
. Because you didn't specifically provide an implicitEquality[Person]
,===
will fall back on default equality, which will callPerson
'sequals
method. Thatequals
method, provided by the Scala compiler becausePerson
is a case class, will declare these two objects unequal because 29.001 does not exactly equal 29.0.To make the equality check more forgiving, you could define an implicit
Equality[Person]
that compares theage
Double
s with a tolerance, like this:scala> import Tolerance._ import Tolerance._ scala> implicit val personEq = | new Equality[Person] { | def areEqual(a: Person, b: Any): Boolean = | b match { | case p: Person => a.name == p.name && a.age === p.age +- 0.0002 | case _ => false | } | } personEq: org.scalactic.Equality[Person] = $anon$1@2b29f6e7
Now the
===
operator will use your more forgivingEquality[Person]
for the equality check instead of default equality:scala> Person("Joe", 29.0001) === Person("Joe", 29.0) res1: Boolean = true
Default equality
Scalactic defines a default
Equality[T]
for all typesT
whoseareEqual
method works by first calling.deep
on any passed array, then calling==
on the left-hand object, passing in the right-hand object. You can obtain a default equality via thedefault
method of the Equality companion object, or from thedefaultEquality
method defined inTripleEqualsSupport
.About equality and equivalence
The
Equality
trait represents the Java Platform's native notion of equality, as expressed in the signature and contract of theequals
method ofjava.lang.Object
. Essentially, traitEquality
enables you to write alternateequals
method implementations for a type outside its defining class.In an
equals
method, the left-hand type is known to be the type ofthis
, but the right-hand type isAny
. As a result, you would normally perform a runtime type test to determine whether the right-hand object is of an appropriate type for equality, and if so, compare it structurally for equality with the left-hand (this
) object. An an illustration, here's a possibleequals
implementation for thePerson
case class shown in the earlier example:override def equals(other: Any): Boolean = other match { case p: Person => name = p.name && age = p.age case _ => false }
The
areEquals
method ofEquality[T]
is similar. The left-hand type is known to beT
, but the right-hand type isAny
, so normally you'd need to do a runtime type test in yourareEqual
implementation. Here's theareEqual
method implementation from the earlierEquality[Person]
example:def areEqual(a: Person, b: Any): Boolean = b match { case p: Person => a.name == p.name && a.age === p.age +- 0.0002 case _ => false }
Equality
is used byTripleEquals
, which enforces no type constraint between the left and right values, and theequal
,be
, andcontain
syntax of ScalaTest Matchers.By contrast,
TypeCheckedTripleEquals
andConversionCheckedTripleEquals
use anEquivalence
.Equivalence
differs fromEquality
in that both the left and right values are of the same type.Equivalence
works forTypeCheckedTripleEquals
because the type constraint enforces that the left type is a subtype or supertype of (or the same type as) the right type, and it widens the subtype to the supertype. So ultimately, both left and right sides are of the supertype type. Similarly,Equivalence
works forConversionCheckedTripleEquals
because the type constraint enforces that an implicit conversion exists from either the left type to the right type, or the right type to the left type, and it always converts one type to the other using the implicit conversion. (If both types are the same type, the identity implicit conversion fromPredef
is used.) Because of the conversion, both left and right sides are ultimately of the converted-to type. Here's an example of how writing anEquivalence
'sareEquivalent
method might look:def areEquivalent(a: Person, b: Person): Boolean = a.name == b.name && a.age === b.age +- 0.0002
Scalactic provides both
Equality
andEquivalence
because theAny
inEquality
can sometimes make things painful. For example, in traitTolerantNumerics
, a single generic factory method can produceEquivalence
s for anyNumeric
type, but because of theAny
, a separate factory method must be defined to produce anEquality
for eachNumeric
type.If you just want to customize the notion of equality for
===
used inBoolean
expressions, you can work withEquivalence
s instead ofEquality
s. If you do chose to write the more generalEquality
s, they can be used wherever anEquivalence
is required, becauseEquality
extendsEquivalence
, defining a final implementation ofareEquivalent
that invokesareEqual
.Note: The
Equality
type class was inspired in part by theEqual
type class of thescalaz
project.- A
the type whose equality is being customized
-
trait
Equivalence[T] extends AnyRef
Defines a custom way to determine equality for a type when compared with another value of the same type.
Defines a custom way to determine equality for a type when compared with another value of the same type.
Equivalence
enables you to define alternate notions of equality for types that can be used with ScalaUtil'sTypeCheckedTripleEquals
andConversionCheckedTripleEquals
traits. These traits can be used to perform equality comparisons with type constraints enforced at compile time using ScalaUtil's===
and!==
syntax and ScalaTest'sshould
===
syntax ofMatchers
trait.Because
Equality
extendsEquivalence
, you automatically define anEquivalence[T]
when you define anEquality[T]
. Most often you will usually want to define customEquality
s, because they will be more generally useful: they are also used by Scalactic'sTripleEquals
trait and ScalaTest'sequal
,be
, andcontain
matcher syntax. However, if you really want just anEquivalence
, and writing anEquality
is inconvenient, you can write anEquivalence
directly for a type.For example, say you have a case class that includes a
Double
value:scala> case class Person(name: String, age: Double) defined class Person
Imagine you are calculating the
age
values in such as way that occasionally tests are failing because of rounding differences that you actually don't care about. For example, you expect an age of 29.0, but you're sometimes seeing 29.0001:scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> Person("Joe", 29.0001) === Person("Joe", 29.0) res0: Boolean = false
The
===
operator ofTypeCheckedTripleEquals
looks for an implicitEquivalence[SUPER]
, whereSUPER
is either the left-hand or right-hand type, whichever one is a supertype of the other. In this case, both sides arePerson
(which is considered a supertype of itself), so the compiler will look for anEquivalence[Person]
. Because you didn't specifically provide an implicitEquivalence[Person]
,===
will fall back on default equality, because anEquality[Person]
is-anEquivalence[Person]
. The defaultEquality[Person]
will callPerson
'sequals
method. Thatequals
method, provided by the Scala compiler becausePerson
is a case class, will declare these two objects unequal because 29.001 does not exactly equal 29.0.To make the equality check more forgiving, you could define an implicit
Equivalence[Person]
that compares theage
Double
s with a tolerance, like this:scala> import Tolerance._ import Tolerance._ scala> implicit val personEq = | new Equivalence[Person] { | def areEquivalent(a: Person, b: Person): Boolean = | a.name == b.name && a.age === b.age +- 0.0002 | } personEq: org.scalactic.Equivalence[Person] = $anon$1@7892bd8
Now the
===
operator will use your more forgivingEquivalence[Person]
for the equality check instead of default equality:scala> Person("Joe", 29.0001) === Person("Joe", 29.0) res1: Boolean = true
-
type
ErrorMessage = String
Type alias for
String
. -
sealed abstract
class
Every[+T] extends PartialFunction[Int, T] with Product with Serializable
An ordered, immutable, non-empty collection of elements.
An ordered, immutable, non-empty collection of elements.
Class
Every
has two and only two subtypes:One
andMany
. AOne
contains exactly one element. AMany
contains two or more elements. Thus no way exists for anEvery
to contain zero elements.Constructing
Every
sYou can construct an
Every
by passing one or more elements to theEvery.apply
factory method:Every(1) Every(1, 2) Every(1, 2, 3)
Alternatively you can pass one element to the
One.apply
factory method, or two or more elements toMany.apply
:One(1) Many(1, 3) Many(1, 2, 3)
Working with
Every
sEvery
does not extend Scala'sSeq
orTraversable
traits because these require that implementations may be empty. For example, if you invoketail
on aSeq
that contains just one element, you'll get an emptySeq
:scala> List(1).tail res6: List[Int] = List()
On the other hand, many useful methods exist on
Seq
that when invoked on a non-emptySeq
are guaranteed to not result in an emptySeq
. For convenience,Every
defines a method corresponding to every suchSeq
method. Here are some examples:Many(1, 2, 3).map(_ + 1) // Result: Many(2, 3, 4) One(1).map(_ + 1) // Result: One(2) Every(1, 2, 3).containsSlice(Every(2, 3)) // Result: true Every(1, 2, 3).containsSlice(Every(3, 4)) // Result: false Every(-1, -2, 3, 4, 5).minBy(_.abs) // Result: -1
Every
does not currently define any methods corresponding toSeq
methods that could result in an emptySeq
. However, an implicit converison fromEvery
tocollection.immutable.IndexedSeq
is defined in theEvery
companion object that will be applied if you attempt to call one of the missing methods. As a result, you can invokefilter
on anEvery
, even thoughfilter
could result in an empty sequence—but the result type will becollection.immutable.IndexedSeq
instead ofEvery
:Every(1, 2, 3).filter(_ < 10) // Result: Vector(1, 2, 3) Every(1, 2, 3).filter(_ > 10) // Result: Vector()
You can use
Every
s infor
expressions. The result will be anEvery
unless you use a filter (anif
clause). Because filters are desugared to invocations offilter
, the result type will switch to acollection.immutable.IndexedSeq
at that point. Here are some examples:scala> import org.scalactic._ import org.scalactic._ scala> for (i <- Every(1, 2, 3)) yield i + 1 res0: org.scalactic.Every[Int] = Many(2, 3, 4) scala> for (i <- Every(1, 2, 3) if i < 10) yield i + 1 res1: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 3, 4) scala> for { | i <- Every(1, 2, 3) | j <- Every('a', 'b', 'c') | } yield (i, j) res3: org.scalactic.Every[(Int, Char)] = Many((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c)) scala> for { | i <- Every(1, 2, 3) if i < 10 | j <- Every('a', 'b', 'c') | } yield (i, j) res6: scala.collection.immutable.IndexedSeq[(Int, Char)] = Vector((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c))
Motivation for
Every
sAlthough
Every
is a general-purpose, non-empty ordered collection, it was motivated by the desire to enable easy accumulation of errors inOr
s. For examples ofEvery
used in that use case, see the Accumulating errors withOr
section in the main documentation forOr
.- T
the type of elements contained in this
Every
-
trait
Explicitly extends AnyRef
Provides ScalaTest's “explicitly DSL,” which facilitates the explicit specification of an
Equality[T]
or aUniformity[T]
whereEquality[T]
is taken implicitly.Provides ScalaTest's “explicitly DSL,” which facilitates the explicit specification of an
Equality[T]
or aUniformity[T]
whereEquality[T]
is taken implicitly.The Explicitly DSL can be used with the
===
and!==
operators of Scalactic as well as theshould
equal
,be
,contain
, and===
syntax of ScalaTest matchers.If you want to customize equality for a type in general, you would likely want to place an implicit
Equality[T]
for that type in scope (or inT
's companion object). That implicit equality definition will then be picked up and used when that type is compared for equality with theequal
,be
, andcontain
matchers in ScalaTest tests and with===
in both tests and production code. If you just want to use a custom equality for a single comparison, however, you may prefer to pass it explicitly. For example, if you have an implicitEquality[String]
in scope, you can force a comparison to use the default equality with this syntax:// In production code: if ((result === "hello")(decided by defaultEquality)) true else false // In tests: result should equal ("hello") (decided by defaultEquality)
The explicitly DSL also provides support for specifying a one-off equality that is based on a normalization. For example, Scalactic offers a
StringNormalizations
trait that provides methods such astrimmed
andlowerCased
that returnNormalization[String]
instances that normalize by trimming and lower-casing, respectively. If you bring those into scope by mixing in or importing the members ofStringNormalizations
, you could use the explicitly DSL like this:// In production code: if ((result === "hello")(after being lowerCased)) true else false // In tests: result should equal ("hello") (after being lowerCased and trimmed)
If you prefer not to use English-like DSLs in your production code, you can alternatively not use the
Explicitly
trait and instead write:// To explicitly specify an Equality instance, just specify it: if ((result === "hello")(Equality.default)) true else false // To base an Equality instance on a Uniformity, just // call toEquality on it: if ((result === "hello")(lowerCased.toEquality)) true else false
-
case class
Fail[E](error: E) extends Validation[E] with Product with Serializable
Indicates a validation failed, describing the failure with a contained error value.
Indicates a validation failed, describing the failure with a contained error value.
- E
the type of value describing a validation failure for this
Fail
- error
an error value describing the validation failure
-
trait
FutureSugar extends AnyRef
Trait providing an implicit class that adds a
validating
method toFuture
, which takes one or more validation functions and returns either the sameFuture
if either theFuture
had already failed or its value passes all the functions, orValidationFailedException
containing an error message describing the first validation that failed.Trait providing an implicit class that adds a
validating
method toFuture
, which takes one or more validation functions and returns either the sameFuture
if either theFuture
had already failed or its value passes all the functions, orValidationFailedException
containing an error message describing the first validation that failed.Here's an example validation method, which passes if the given
Int
is evenly divisible by 10 (i.e., the result will bePass
). If the value does not pass this test, the result is aFail
containing a helpful error message string.scala> import org.scalactic._ import org.scalactic._ scala> import FutureSugar._ import org.scalactic.FutureSugar._ scala> import scala.concurrent.Future import scala.concurrent.Future scala> import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global scala> def isRound(i: Int): Validation[ErrorMessage] = | if (i % 10 == 0) Pass else Fail(i + " was not a round number") isRound: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage]
Validation will be attempted on a successful
Try
. If the validation succeeds, the resultingFuture
will be the same successfulFuture
with the same value. (A "validation" only transforms theFuture
if the validation fails, otherwise it is the sameFuture
. The only difference is its value has now been proven valid.) In the following example, a successfulFuture[Int]
with the value 100 passes the validation (which checks whether 100 is evenly divisible by 10), therefore the result of thevalidating
call is the same successfulFuture
with the same value.scala> val fut100 = Future(100) fut100: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@67f9c9c6 scala> fut100.value res0: Option[scala.util.Try[Int]] = Some(Success(100)) scala> val round100 = fut100.validating(isRound) round100: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@1ac2f0d1 scala> round100.value res1: Option[scala.util.Try[Int]] = Some(Success(100))
If validation fails, the successful
Future
will be transformed into a failed one, with aValidationFailedException
that contains the error message returned by the validation function. In the following example, 42 fails the validation because it is not evenly divisible by 10:scala> val fut42 = Future(42) fut42: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@19c6e4d1 scala> fut42.value res2: Option[scala.util.Try[Int]] = Some(Success(42)) scala> val round42 = fut42.validating(isRound) round42: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@b5175d scala> round42.value res3: Option[scala.util.Try[Int]] = Some(Failure(org.scalactic.exceptions.ValidationFailedException: 42 was not a round number))
If
validating
is called on a failedFuture
, it just returns the same failedFuture
:scala> val futEx = Future[Int] { throw new Exception("oops!") } futEx: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@3ba0299c scala> futEx.value res4: Option[scala.util.Try[Int]] = Some(Failure(java.lang.Exception: oops!)) scala> val roundEx = futEx.validating(isRound) roundEx: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@22bf1acf scala> roundEx.value res5: Option[scala.util.Try[Int]] = Some(Failure(java.lang.Exception: oops!))
The
validating
method accepts one or more validation functions. If you pass more than one, they will be tried in order up until the first failure, whose error message will appear in theValidationFailedException
. In other words,validating
will short circuit at the first error and return that. It will not accumulate errors. For example, the following validation will short circuit after theisDivBy3
function fails:scala> def isDivBy3(i: Int): Validation[ErrorMessage] = | if (i % 3 == 0) Pass else Fail(i + " was not divisible by 3") isDivBy3: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage] scala> def isAnswerToLifeTheUniverseAndEverything(i: Int): Validation[ErrorMessage] = | if (i == 42) Pass else Fail(i + " did not equal 42") isAnswerToLifeTheUniverseAndEverything: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage] scala> val futShort = fut100.validating(isRound, isDivBy3, isAnswerToLifeTheUniverseAndEverything) futShort: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@30bb943e scala> futShort.value res11: Option[scala.util.Try[Int]] = Some(Failure(org.scalactic.exceptions.ValidationFailedException: 100 was not divisible by 3))
-
final
case class
Good[+G](g: G) extends Or[G, Nothing] with Product with Serializable
Contains a “good” value.
Contains a “good” value.
You can decide what “good” means, but it is expected
Good
will be commonly used to hold valid results for processes that may fail with an error instead of producing a valid result.- g
the “good” value
-
trait
LowPriorityTypeCheckedConstraint extends TripleEqualsSupport
Provides an implicit conversion that will be applied only if a higher-priority implicit conversion declared a subtrait is not applicable.
Provides an implicit conversion that will be applied only if a higher-priority implicit conversion declared a subtrait is not applicable.
The purpose of this trait is to make the
===
operator symetric. In other words, a===
invocation will be allowed if subtype relationship exists in either direction. For example, in the following expression, the left hand side is a subtype of the right hand side:List(1, 2, 3) === Seq(1, 2, 3)
But in the next expression, it the right hand side is a subtype of the left hand side
Seq(1, 2, 3) === List(1, 2, 3)
The first expression above is enabled by the implicit conversion
typeCheckedConstraint
in traitTypeCheckedTripleEquals
. The second expression above is enabled by the implicit conversionlowPriorityTypeCheckedConstraint
in this trait.The reason these two implicit methods aren't both declared in the subtraits is that if the subtype relationship existed in both directions, they would conflict. This can happen when the exact same type is on both the left and right hand sides, because a type is a subtype of itself. By placing one of them in this supertrait, the higher priority conversion will be selected.
-
final
case class
Many[+T](firstElement: T, secondElement: T, otherElements: T*) extends Every[T] with Product with Serializable
An
Every
that contains two or more elements.An
Every
that contains two or more elements.For more information and examples, see the main documentation for superclass
Every
.- T
the type of the element contained in this
Many
- firstElement
the first element (with index 0) contained in this
Many
- secondElement
the second element (with index 1) contained in this
Many
- otherElements
a varargs of zero or more other elements (with index 2, 3, ...) contained in this
Many
-
trait
MapEqualityConstraints extends AnyRef
Provides an implicit method that loosens the equality constraint defined by
TypeCheckedTripleEquals
orConversionCheckedTripleEquals
for ScalaMap
s to one that more closely matches Scala's approach toMap
equality.Provides an implicit method that loosens the equality constraint defined by
TypeCheckedTripleEquals
orConversionCheckedTripleEquals
for ScalaMap
s to one that more closely matches Scala's approach toMap
equality.Scala's approach to
Map
equality is that if both objects being compared areMap
s, the elements are compared to determine equality. This means you could compare an immutableTreeMap
and a mutableHashMap
for equality, for instance, and get true so long as the two maps contained the same key-value mappings. Here's an example:scala> import scala.collection.immutable.TreeMap import scala.collection.immutable.TreeMap scala> import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap scala> TreeMap("one" -> 1, "two" -> 2) == HashMap("one" -> 1, "two" -> 2) res0: Boolean = true
Such a comparison would not, however, compile if you used
===
under eitherTypeCheckedTripleEquals
orConversionCheckedTripleEquals
, becauseTreeMap
andHashMap
are not in a subtype/supertype relationship, nor does an implicit conversion by default exist between them:scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> 1, "two" -> 2) <console>:16: error: types scala.collection.immutable.TreeMap[String,Int] and scala.collection.mutable.HashMap[String,Int] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[scala.collection.immutable.TreeMap[String,Int], scala.collection.mutable.HashMap[String,Int]] TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> 1, "two" -> 2) ^
If you mix or import the implicit conversion provided by
MapEqualityConstraint
, however, the comparison will be allowed:scala> import MapEqualityConstraints._ import MapEqualityConstraints._ scala> TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> 1, "two" -> 2) res2: Boolean = true
The equality constraint provided by this trait requires that both left and right sides are subclasses of
scala.collection.GenMap
and that anEqualityConstraint
can be found for both key types and both value types. In the example above, both theTreeMap
andHashMap
are subclasses ofscala.collection.GenMap
, and the regularTypeCheckedTripleEquals
provides equality constraints for the key types, both of which areString
, and value types, both of which areInt
. By contrast, this trait would not allow aTreeMap[String, Int]
to be compared against aHashMap[String, java.util.Date]
, because no equality constraint will exist between the value typesInt
andDate
:scala> import java.util.Date import java.util.Date scala> TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> new Date, "two" -> new Date) <console>:20: error: types scala.collection.immutable.TreeMap[String,Int] and scala.collection.mutable.HashMap[String,java.util.Date] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[scala.collection.immutable.TreeMap[String,Int], scala.collection.mutable.HashMap[String,java.util.Date]] TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> new Date, "two" -> new Date) ^
-
trait
NormMethods extends AnyRef
Provides an implicit conversion that allows
norm
to be invoked on any value of typeT
for which an implicitNormalization[T]
exists.Provides an implicit conversion that allows
norm
to be invoked on any value of typeT
for which an implicitNormalization[T]
exists.Here's an example:
scala> import org.scalactic._ import org.scalactic._ scala> import StringNormalizations._ import StringNormalizations._ scala> implicit val stringNormalization = lowerCased and trimmed stringNormalization: org.scalactic.Uniformity[String] = org.scalactic.Uniformity$$anon$1@19ba67ec scala> import NormMethods._ import NormMethods._ scala> val s = " There " s: String = " There " scala> "Hey " + s + "!" res5: String = Hey There ! scala> "Hey " + s.norm + "!" res6: String = Hey there!
-
trait
Normalization[A] extends AnyRef
Defines a custom way to normalize instances of a type.
Defines a custom way to normalize instances of a type.
For example, to normalize
Double
s by truncating off any decimal part, you might write:import org.scalactic._ val truncated = new Normalization[Double] { def normalized(d: Double) = d.floor }
Given this definition you could use it with the
Explicitly
DSL like this:import org.scalatest._ import Matchers._ import TypeCheckedTripleEquals._ (2.1 should === (2.0)) (after being truncated)
Note that to use a
Normalization
with theExplicitly
DSL, you'll need to useTypeCheckedTripleEquals
. If you're just using plain-oldTripleEquals
, you'll need aUniformity
, aNormalization
subclass.If you make the
truncated
val
implicit and import or mix in the members ofNormMethods
, you can access the behavior by invoking.norm
onDouble
s.implicit val doubleNormalization = truncated import NormMethods._ val d = 2.1 d.norm // returns 2.0
- A
the type whose normalization is being defined
-
trait
NormalizingEquality[A] extends Equality[A]
An
Equality[A]
implementation that determines the equality of two objects by normalizing one or both objects, then comparing the results using an “after normalization” equality referenced from theafterNormalizationEquality
member.An
Equality[A]
implementation that determines the equality of two objects by normalizing one or both objects, then comparing the results using an “after normalization” equality referenced from theafterNormalizationEquality
member. By default, theafterNormalizationEquality
is an instance ofEquality.default[A]
.NormalizingEquality
is returned by theExplicitly
DSL's “after
being
” syntax, using for theafterNormalizationEquality
the implicitEquality
in scope for the type ofUniformity
passed tobeing
. Here's an example:scala> import org.scalactic._ import org.scalactic._ scala> import Explicitly._ import Explicitly._ scala> import StringNormalizations._ import StringNormalizations._ scala> after being lowerCased res0: org.scalactic.NormalizingEquality[String] = ComposedNormalizingEquality(Equality.default,lowerCased)
-
trait
NormalizingEquivalence[A] extends Equivalence[A]
An
Equivalence[A]
implementation that determines the equality of two objects by normalizing one or both objects, then comparing the results using an “after normalization”Equivalence
referenced from theafterNormalizationEquivalence
member.An
Equivalence[A]
implementation that determines the equality of two objects by normalizing one or both objects, then comparing the results using an “after normalization”Equivalence
referenced from theafterNormalizationEquivalence
member. By default, theafterNormalizationEquivalence
is an instance ofEquivalence.default[A]
.NormalizingEquivalence
is returned by theExplicitly
DSL's “after
being
” syntax, using for theafterNormalizationEquivalence
the implicitEquivalence
in scope for the type ofNormalization
passed tobeing
. Here's an example:scala> import org.scalactic._ import org.scalactic._ scala> import Explicitly._ import Explicitly._ scala> val lowerCased: Normalization[String] = StringNormalizations.lowerCased lowerCased: org.scalactic.Normalization[String] = lowerCased scala> after being lowerCased res0: org.scalactic.NormalizingEquivalence[String] = ComposedNormalizingEquivalence(Equality.default,lowerCased)
-
final
case class
One[+T](loneElement: T) extends Every[T] with Product with Serializable
An
Every
that contains exactly one element.An
Every
that contains exactly one element.For more information and examples, see the main documentation for superclass
Every
.- T
the type of the element contained in this
One
- loneElement
the lone element contained in this
One
-
trait
OptionSugar extends AnyRef
Trait providing an implicit class that adds a
toOr
method toOption
, which convertsSome
toGood
,None
toBad
.Trait providing an implicit class that adds a
toOr
method toOption
, which convertsSome
toGood
,None
toBad
.You can use the
toOr
method to record information about why a processing of nestedOption
s resulted inNone
. For example, the followingfor
expression results inNone
if either the passed optionalPerson
isNone
or else if the contained optional age isNone
:scala> case class Person(name: String, age: Option[Int]) defined class Person scala> def ageOf(person: Option[Person]) = | for { | per <- person | age <- per.age | } yield age ageOf: (person: Option[Person])Option[Int] scala> ageOf(Some(Person("Ralph", Some(32)))) res0: Option[Int] = Some(32) scala> ageOf(Some(Person("Curt", None))) res3: Option[Int] = None scala> ageOf(None) res2: Option[Int] = None
If you instead populate the
for
expression withOr
s, supplying an error message or other "bad" value to thetoOr
method in case ofNone
, you'll get an indication of which part failed if aNone
is encountered:scala> import OptionSugar._ import OptionSugar._ scala> def ageOf(person: Option[Person]) = | for { | per <- person toOr "no person here" | age <- per.age toOr "ageless person" | } yield age ageOf: (person: Option[Person])org.scalactic.Or[Int,String] scala> ageOf(Some(Person("Ralph", Some(32)))) res1: org.scalactic.Or[Int,String] = Good(32) scala> ageOf(Some(Person("Curt", None))) res2: org.scalactic.Or[Int,String] = Bad(ageless person) scala> ageOf(None) res3: org.scalactic.Or[Int,String] = Bad(no person here)
-
sealed abstract
class
Or[+G, +B] extends Product with Serializable
Represents a value that is one of two possible types, with one type being “good” and the other “bad.”
Represents a value that is one of two possible types, with one type being “good” and the other “bad.”
An
Or
will either be a “good” value wrapped in an instance ofGood
or a “bad” value wrapped in an instance ofBad
.The motivation for
Or
Or
differs from Scala'sEither
type in thatEither
treats both itsLeft
andRight
alternatives in an identical manner, whereasOr
treats its two alternatives differently: it favorsGood
overBad
. Because of this, it is more convenient to work withOr
s when you prefer one alternative over the other; for example, if one alternative represents a valid result and another represents an error.To illustrate, imagine you want to create instances this
Person
class from user input strings:case class Person(name: String, age: Int)
You might write a method that parses the name from user input string and returns an
Option[String]
:None
if the string is empty or blank, else the trimmed string wrapped in aSome
:def parseName(input: String): Option[String] = { val trimmed = input.trim if (!trimmed.isEmpty) Some(trimmed) else None }
You might also write a method that parses the age from user input string and returns an
Option[Int]
:None
if either the string is not a valid integer or it is a negative integer, else the string converted to an integer wrapped in aSome
:def parseAge(input: String): Option[Int] = { try { val age = input.trim.toInt if (age >= 0) Some(age) else None } catch { case _: NumberFormatException => None } }
With these building blocks you could write a method that parses name and age input strings and returns either a
Person
, wrapped in aSome
, orNone
if either the name or age, or both, was invalid:def parsePerson(inputName: String, inputAge: String): Option[Person] = for { name <- parseName(inputName) age <- parseAge(inputAge) } yield Person(name, age)
Here are some examples of invoking
parsePerson
:parsePerson("Bridget Jones", "29") // Result: Some(Person(Bridget Jones,29)) parsePerson("Bridget Jones", "") // Result: None parsePerson("Bridget Jones", "-29") // Result: None parsePerson("", "") // Result: None
Now imagine you want to give an error message back if the user's input is invalid. You might rewrite the parsing methods to return an
Either
instead. In this case, the desired result is a valid name or age, which by convention should be placed on the right of theEither
. The left will be aString
error message. Here's the newparseName
function, which returns anEither[String, String]
:def parseName(input: String): Either[String, String] = { val trimmed = input.trim if (!trimmed.isEmpty) Right(trimmed) else Left(s""""${input}" is not a valid name""") }
And here's the new
parseAge
function, which returns anEither[String, Int]
:def parseAge(input: String): Either[String, Int] = { try { val age = input.trim.toInt if (age >= 0) Right(age) else Left(s""""${age}" is not a valid age""") } catch { case _: NumberFormatException => Left(s""""${input}" is not a valid integer""") } }
The new
parsePerson
method will return anEither[String, Person]
:def parsePerson(inputName: String, inputAge: String): Either[String, Person] = for { name <- parseName(inputName).right age <- parseAge(inputAge).right } yield Person(name, age)
Note that
Either
requires you to add.right
at the end of each generator in thefor
expression. Although the convention is to place the valid result on the right, you must explicitly (and repetitively) indicate that you've done so by transforming theEither
to aRightProjection
by invoking.right
at each step. Given this implementation, theparsePerson
method will now short-circuit at the first sign of trouble (as it did when we used anOption
), but you now get the first error message returned in aLeft
. Here are some examples:parsePerson("Bridget Jones", "29") // Result: Right(Person(Bridget Jones,29)) parsePerson("Bridget Jones", "") // Result: Left("" is not a valid integer) parsePerson("Bridget Jones", "-29") // Result: Left("-29" is not a valid age) parsePerson("", "") // Result: Left("" is not a valid name)
An
Either
with “attitude”Because
Or
declares one alternative to be “good” and the other “bad,” it is more convenient thanEither
in this kind of situation. One difference to note withOr
is that theGood
alternative is on the left,Bad
on the right. The reason is thatOr
is designed to be written using infix notation, and placing the “happy path” first is more readable. For example, instead of writing:Or[Int, ErrorMessage]
You can write:
Int Or ErrorMessage
Here's how the
parseName
method might be written using anOr
, whereErrorMessage
is a type alias forString
declared in theorg.scalactic
package object:import org.scalactic._ def parseName(input: String): String Or ErrorMessage = { val trimmed = input.trim if (!trimmed.isEmpty) Good(trimmed) else Bad(s""""${input}" is not a valid name""") }
You can think of the
String
Or
ErrorMessage
result type like this:The
parseName
method will return a nameString
or, if the input string is not a valid name, anErrorMessage
.Here's how the
parseAge
method might be written:def parseAge(input: String): Int Or ErrorMessage = { try { val age = input.trim.toInt if (age >= 0) Good(age) else Bad(s""""${age}" is not a valid age""") } catch { case _: NumberFormatException => Bad(s""""${input}" is not a valid integer""") } }
Given these implementations, here's how you'd write the
parsePerson
method:def parsePerson(inputName: String, inputAge: String): Person Or ErrorMessage = for { name <- parseName(inputName) age <- parseAge(inputAge) } yield Person(name, age)
Because of
Or
's attitude, you need not write.good
at the end of each generator.Or
will keep going so long as each step produces aGood
, short circuiting at the first sign of aBad
. Here are a few invocations of thisparsePerson
method:parsePerson("Bridget Jones", "29") // Result: Good(Person(Bridget Jones,29)) parsePerson("Bridget Jones", "") // Result: Bad("" is not a valid integer) parsePerson("Bridget Jones", "-29") // Result: Bad("-29" is not a valid age) parsePerson("", "") // Result: Bad("" is not a valid name)
Accumulating errors with
Or
Another difference between
Or
andEither
is thatOr
enables you to accumulate errors if theBad
type is anEvery
. AnEvery
is similar to aSeq
in that it contains ordered elements, but different fromSeq
in that it cannot be empty. AnEvery
is either aOne
, which contains one and only one element, or aMany
, which contains two or more elements.Note: an
Or
whoseBad
type is anEvery
, or one of its subtypes, is called an “accumulatingOr
.”To rewrite the previous example so that errors can be accumulated, you need first to return an
Every
as theBad
type. Here's how you'd change theparseName
method:def parseName(input: String): String Or One[ErrorMessage] = { val trimmed = input.trim if (!trimmed.isEmpty) Good(trimmed) else Bad(One(s""""${input}" is not a valid name""")) }
Because
parseName
will either return a valid nameString
wrapped in aGood
, or one error message, wrapped in aBad
, you would write theBad
type asOne[ErrorMessage]
. The same is true forparseAge
:def parseAge(input: String): Int Or One[ErrorMessage] = { try { val age = input.trim.toInt if (age >= 0) Good(age) else Bad(One(s""""${age}" is not a valid age""")) } catch { case _: NumberFormatException => Bad(One(s""""${input}" is not a valid integer""")) } }
Because a
for
expression short-circuits on the firstBad
encountered, you'll need to use a different approach to write theparsePerson
method. In this example, thewithGood
method from traitAccumulation
will do the trick:import Accumulation._ def parsePerson(inputName: String, inputAge: String): Person Or Every[ErrorMessage] = { val name = parseName(inputName) val age = parseAge(inputAge) withGood(name, age) { Person(_, _) } }
Trait
Accumulation
offers overloadedwithGood
methods that take 1 to 22 accumulatingOr
s, plus a function taking the same number of correspondingGood
values. In this example, if bothname
andage
areGood
s, thewithGood
method will pass the good nameString
and ageInt
to thePerson(_, _)
function, and return the resultingPerson
object wrapped in aGood
. If eithername
andage
, or both, areBad
,withGood
will return the accumulated errors in aBad
.The result of
parsePerson
, ifBad
, will therefore contain either one or two error messages, i.e., the result will either be aOne
or aMany
. As a result, the result type ofparsePerson
must bePerson
Or
Every[ErrorMessage]
. Regardless of whether aBad
result contains one or two error messages, it will contain every error message. Here's some invocations of this accumulating version ofparsePerson
:parsePerson("Bridget Jones", "29") // Result: Good(Person(Bridget Jones,29)) parsePerson("Bridget Jones", "") // Result: Bad(One("" is not a valid integer)) parsePerson("Bridget Jones", "-29") // Result: Bad(One("-29" is not a valid age)) parsePerson("", "") // Result: Bad(Many("" is not a valid name, "" is not a valid integer))
Note that in the last example, the
Bad
contains an error message for both name and age.Other ways to accumulate errors
The
Accumlation
trait also enables other ways of accumulating errors.Using
combined
If you have a collection of accumulating
Or
s, for example, you can combine them into oneOr
usingcombined
, like this:List(parseAge("29"), parseAge("30"), parseAge("31")).combined // Result: Good(List(29, 30, 31)) List(parseAge("29"), parseAge("-30"), parseAge("31")).combined // Result: Bad(One("-30" is not a valid age)) List(parseAge("29"), parseAge("-30"), parseAge("-31")).combined // Result: Bad(Many("-30" is not a valid age, "-31" is not a valid age))
Using
validatedBy
Or if you have a collection of values and a function that transforms that type of value into an accumulating
Or
s, you can validate the values using the function usingvalidatedBy
, like this:List("29", "30", "31").validatedBy(parseAge) // Result: Good(List(29, 30, 31)) List("29", "-30", "31").validatedBy(parseAge) // Result: Bad(One("-30" is not a valid age)) List("29", "-30", "-31").validatedBy(parseAge) // Result: Bad(Many("-30" is not a valid age, "-31" is not a valid age))
Using
zip
You can also zip two accumulating
Or
s together. If both areGood
, you'll get aGood
tuple containin both originalGood
values. Otherwise, you'll get aBad
containing every error message. Here are some examples:parseName("Dude") zip parseAge("21") // Result: Good((Dude,21)) parseName("Dude") zip parseAge("-21") // Result: Bad(One("-21" is not a valid age)) parseName("") zip parseAge("-21") // Result: Bad(Many("" is not a valid name, "-21" is not a valid age))
Using
when
In addition, given an accumlating
Or
, you can pass one or more validation functions towhen
on theOr
to submit thatOr
to further scrutiny. A validation function accepts aGood
type and returns aValidation[E]
, whereE
is the type in theEvery
in theBad
type. For anInt
Or
One[ErrorMessage]
, for example the validation function type would beInt
=>
Validation[ErrorMessage]
. Here are a few examples:def isRound(i: Int): Validation[ErrorMessage] = if (i % 10 == 0) Pass else Fail(i + " was not a round number") def isDivBy3(i: Int): Validation[ErrorMessage] = if (i % 3 == 0) Pass else Fail(i + " was not divisible by 3")
If the
Or
on which you callwhen
is alreadyBad
, you get the same (Bad
)Or
back, because noGood
value exists to pass to the valiation functions:parseAge("-30").when(isRound, isDivBy3) // Result: Bad(One("-30" is not a valid age))
If the
Or
on which you callwhen
isGood
, and also passes all the validation functions (i.e., the all returnNone
), you again get the sameOr
back, but this time, aGood
one:parseAge("30").when(isRound, isDivBy3) // Result: Good(30)
If one or more of the validation functions fails, however, you'll get a
Bad
back contining every error. Here are some examples:parseAge("33").when(isRound, isDivBy3) // Result: Bad(One(33 was not a round number)) parseAge("20").when(isRound, isDivBy3) // Result: Bad(One(20 was not divisible by 3)) parseAge("31").when(isRound, isDivBy3) // Result: Bad(Many(31 was not a round number, 31 was not divisible by 3))
Note that you can use
when
to accumulate errors in afor
expression involving an accumulatingOr
, like this:for (age <- parseAge("-30") when (isRound, isDivBy3)) yield age // Result: Bad(One("-30" is not a valid age)) for (age <- parseAge("30") when (isRound, isDivBy3)) yield age // Result: Good(30) for (age <- parseAge("33") when (isRound, isDivBy3)) yield age // Result: Bad(One(33 was not a round number)) for (age <- parseAge("20") when (isRound, isDivBy3)) yield age // Result: Bad(One(20 was not divisible by 3)) for (age <- parseAge("31") when (isRound, isDivBy3)) yield age // Result: Bad(Many(31 was not a round number, 31 was not divisible by 3))
Much ado about
Nothing
Because
Or
has two types, but each of its two subtypes only takes a value of one or the other type, the Scala compiler will inferNothing
for the unspecified type:scala> Good(3) res0: org.scalactic.Good[Int,Nothing] = Good(3) scala> Bad("oops") res1: org.scalactic.Bad[Nothing,String] = Bad(oops)
Often
Nothing
will work fine, as it will be widened as soon as the compiler encounters a more specific type. Sometimes, however, you may need to specify it. In such situations you can use this syntax:scala> Good(3).orBad[String] res2: org.scalactic.Good[Int,String] = Good(3) scala> Good[Int].orBad("oops") res3: org.scalactic.Bad[Int,String] = Bad(oops)
If you want to specify both types, because you don't like the inferred type, you can do so like this:
scala> Good[AnyVal, String](3) res4: org.scalactic.Good[AnyVal,String] = Good(3) scala> Bad[Int, ErrorMessage]("oops") res5: org.scalactic.Bad[Int,org.scalactic.ErrorMessage] = Bad(oops)
But you may find the code is clearer if you instead use a type ascription, like this:
scala> Good(3): AnyVal Or String res6: org.scalactic.Or[AnyVal,String] = Good(3) scala> Bad("oops"): Int Or ErrorMessage res7: org.scalactic.Or[Int,org.scalactic.ErrorMessage] = Bad(oops)
Note: The
Or
hierarchy was inspired in part by the disjoint union (\/
) andValidation
types ofscalaz
, theProcessResult
type of Typesafe Activator, and theResult
type of ScalaKittens. -
trait
Prettifier extends Serializable
A function that given any object will produce a “pretty” string representation of that object, where “pretty” is in the eye of the implementer.
A function that given any object will produce a “pretty” string representation of that object, where “pretty” is in the eye of the implementer.
Scala's
Any
type declares atoString
that will convert any object to aString
representation. ThisString
representation is primarily intended for programmers, and is usually sufficient. However, sometimes it can be helpful to provide an alternative implementation oftoString
for certain types. For example, thetoString
implementation onString
prints out the value of theString
:scala> "1".toString res0: String = 1
If the error message that resulted from comparing
Int
1 withString
"1"
in a ScalaTest assertion usedtoString
, therefore, the error message would be:1 did not equal 1
To make it quicker to figure out why the assertion failed, ScalaTest prettifies the objects involved in the error message. The default
Prettifier
will place double quotes on either side of aString
stoString
result:scala> import org.scalactic._ import org.scalactic._ scala> Prettifier.default("1") res1: String = "1"
Thus the error message resulting from comparing
Int
1 withString
"1"
, in a ScalaTest assertion is:1 did not equal "1"
If you wish to prettify an object in production code, for example, to issue a profoundly clear debug message, you can use
PrettyMethods
and invokepretty
. Here's an example:scala> import PrettyMethods._ import PrettyMethods._ scala> 1.pretty res2: String = 1 scala> "1".pretty res3: String = "1"
For example, the default
Prettifier
,Prettifier.default
, transforms:Null
to:null
Unit
to:<() the Unit value>
String
to:"string"
(thetoString
result surrounded by double quotes)Char
to:'c'
(thetoString
result surrounded by single quotes)Array
to:Array("1", "2", "3")
scala.Some
to:Some("3")
scala.util.Left
to:Left("3")
scala.util.Right
to:Right("3")
scala.util.Success
to:Success("3")
org.scalactic.Good
to:Good("3")
org.scalactic.Bad
to:Bad("3")
org.scalactic.One
to:One("3")
org.scalactic.Many
to:Many("1", "2", "3")
scala.collection.GenTraversable
to:List("1", "2", "3")
java.util.Collection
to:["1", "2", "3"]
java.util.Map
to:{1="one", 2="two", 3="three"}
For anything else, the default
Prettifier
returns the result of invokingtoString
.Note:
Prettifier
is not parameterized (i.e.,Prettifier[T]
, whereT
is the type to prettify) because assertions (including matcher expressions) in ScalaTest would then need to look upPrettifier
s implicitly by type. This would slow compilation even though most (let's guess 99.9%) of the time in practice assertions do not fail, and thus 99.9% of the time no error messages need to be generated. If no error messages are needed 99.9% of the time, no prettification is needed 99.9% of the time, so the slow down in compile time for the implicit look ups is unlikely to be worth the benefit. Only a few types in practice usually need prettification for testing error message purposes, and those will be covered by the defaultPrettifier
. A future version of ScalaTest will provide a simple mechanism to replace the defaultPrettifier
with a custom one when a test actually fails. -
trait
PrettyMethods extends AnyRef
Provides an implicit conversion that enables
pretty
to be invoked on any object, to transform that object into aString
representation. -
trait
Requirements extends AnyRef
Trait that contains
require
, andrequireState
, andrequireNonNull
methods for checking pre-conditions that give descriptive error messages extracted via a macro.Trait that contains
require
, andrequireState
, andrequireNonNull
methods for checking pre-conditions that give descriptive error messages extracted via a macro.These methods of trait
Requirements
aim to improve error messages provided when a pre-condition check fails at runtime in production code. Although it is recommended practice to supply helpful error messages when doing pre-condition checks, often people don't. Instead of this:scala> val length = 5 length: Int = 5 scala> val idx = 6 idx: Int = 6 scala> require(idx >= 0 && idx <= length, "index, " + idx + ", was less than zero or greater than or equal to length, " + length) java.lang.IllegalArgumentException: requirement failed: index, 6, was less than zero or greater than or equal to length, 5 at scala.Predef$.require(Predef.scala:233) ...
People write simply:
scala> require(idx >= 0 && idx <= length) java.lang.IllegalArgumentException: requirement failed at scala.Predef$.require(Predef.scala:221) ...
Note that the detail message of the
IllegalArgumentException
thrown by the previous line of code is simply,"requirement failed"
. Such messages often end up in a log file or bug report, where a better error message can save time in debugging the problem. By importing the members ofRequirements
(or mixing in its companion trait), you'll get a more helpful error message extracted by a macro, whether or not a clue message is provided:scala> import org.scalactic._ import org.scalactic._ scala> import Requirements._ import Requirements._ scala> require(idx >= 0 && idx <= length) java.lang.IllegalArgumentException: 6 was greater than or equal to 0, but 6 was not less than or equal to 5 at org.scalactic.Requirements$RequirementsHelper.macroRequire(Requirements.scala:56) ... scala> require(idx >= 0 && idx <= length, "(hopefully that helps)") java.lang.IllegalArgumentException: 6 was greater than or equal to 0, but 6 was not less than or equal to 5 (hopefully that helps) at org.scalactic.Requirements$RequirementsHelper.macroRequire(Requirements.scala:56) ...
The
requireState
method provides identical error messages torequire
, but throwsIllegalStateException
instead ofIllegalArgumentException
:scala> val connectionOpen = false connectionOpen: Boolean = false scala> requireState(connectionOpen) java.lang.IllegalStateException: connectionOpen was false at org.scalactic.Requirements$RequirementsHelper.macroRequireState(Requirements.scala:71) ...
Thus, whereas the
require
methods throw the Java platform's standard exception indicating a passed argument violated a precondition,IllegalArgumentException
, therequireState
methods throw the standard exception indicating an object's method was invoked when the object was in an inappropriate state for that method,IllegalStateException
.The
requireNonNull
method takes one or more variables as arguments and throwsNullArgumentException
with an error messages that includes the variable names if any arenull
. Here's an example:scala> val e: String = null e: String = null scala> val f: java.util.Date = null f: java.util.Date = null scala> requireNonNull(a, b, c, d, e, f) org.scalactic.exceptions.NullArgumentException: e and f were null at org.scalactic.Requirements$RequirementsHelper.macroRequireNonNull(Requirements.scala:101) ...
Although trait
Requirements
can help you debug problems that occur in production, bear in mind that a much better alternative is to make it impossible for such events to occur at all. Use the type system to ensure that all pre-conditions are met so that the compiler can find broken pre-conditions and point them out with compiler error messages. When this is not possible or practical, however, traitRequirements
is helpful. -
trait
SeqEqualityConstraints extends AnyRef
Provides an implicit method that loosens the equality constraint defined by
TypeCheckedTripleEquals
orConversionCheckedTripleEquals
for ScalaSeq
s to one that more closely matches Scala's approach toSeq
equality.Provides an implicit method that loosens the equality constraint defined by
TypeCheckedTripleEquals
orConversionCheckedTripleEquals
for ScalaSeq
s to one that more closely matches Scala's approach toSeq
equality.Scala's approach to
Seq
equality is that if both objects being compared areSeq
s, the elements are compared to determine equality. This means you could compare an immutableVector
and a mutableListBuffer
for equality, for instance, and get true so long as the twoSeq
s contained the same elements in the same order. Here's an example:scala> import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer scala> Vector(1, 2) == ListBuffer(1, 2) res0: Boolean = true
Such a comparison would not, however, compile if you used
===
under eitherTypeCheckedTripleEquals
orConversionCheckedTripleEquals
, becauseVector
andListBuffer
are not in a subtype/supertype relationship, nor does an implicit conversion by default exist between them:scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> Vector(1, 2) === ListBuffer(1, 2) <console>:16: error: types scala.collection.immutable.Vector[Int] and scala.collection.mutable.ListBuffer[Int] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[scala.collection.immutable.Vector[Int], scala.collection.mutable.ListBuffer[Int]] Vector(1, 2) === ListBuffer(1, 2) ^
If you mix or import the implicit conversion provided by
SeqEqualityConstraint
, however, the comparison will be allowed:scala> import SeqEqualityConstraints._ import SeqEqualityConstraints._ scala> Vector(1, 2) === ListBuffer(1, 2) res2: Boolean = true
The equality constraint provided by this trait requires that both left and right sides are subclasses of
scala.collection.GenSeq
and that anEqualityConstraint
can be found for the element types. In the example above, both theVector
andListBuffer
are subclasses ofscala.collection.GenSeq
, and the regularTypeCheckedTripleEquals
provides equality constraints for the element types, both of which areInt
. By contrast, this trait would not allow aVector[Int]
to be compared against aListBuffer[java.util.Date]
, because no equality constraint will exist between the element typesInt
andDate
:scala> import java.util.Date import java.util.Date scala> Vector(1, 2) === ListBuffer(new Date, new Date) <console>:20: error: types scala.collection.immutable.Vector[Int] and scala.collection.mutable.ListBuffer[java.util.Date] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[scala.collection.immutable.Vector[Int], scala.collection.mutable.ListBuffer[java.util.Date]] Vector(1, 2) === ListBuffer(new Date, new Date) ^
-
trait
SetEqualityConstraints extends AnyRef
Provides an implicit method that loosens the equality constraint defined by
TypeCheckedTripleEquals
orConversionCheckedTripleEquals
for ScalaSet
s to one that more closely matches Scala's approach toSet
equality.Provides an implicit method that loosens the equality constraint defined by
TypeCheckedTripleEquals
orConversionCheckedTripleEquals
for ScalaSet
s to one that more closely matches Scala's approach toSet
equality.Scala's approach to
Set
equality is that if both objects being compared areSet
s, the elements are compared to determine equality. This means you could compare an immutableTreeSet
and a mutableHashSet
for equality, for instance, and get true so long as the twoSet
s contained the same elements in the same order. Here's an example:scala> import scala.collection.immutable.TreeSet import scala.collection.immutable.TreeSet scala> import scala.collection.mutable.HashSet import scala.collection.mutable.HashSet scala> TreeSet(1, 2) == HashSet(1, 2) res0: Boolean = true
Such a comparison would not, however, compile if you used
===
under eitherTypeCheckedTripleEquals
orConversionCheckedTripleEquals
, becauseTreeSet
andHashSet
are not in a subtype/supertype relationship, nor does an implicit conversion by default exist between them:scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> TreeSet(1, 2) === HashSet(1, 2) <console>:16: error: types scala.collection.immutable.TreeSet[Int] and scala.collection.mutable.HashSet[Int] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[scala.collection.immutable.TreeSet[Int], scala.collection.mutable.HashSet[Int]] TreeSet(1, 2) === HashSet(1, 2) ^
If you mix or import the implicit conversion provided by
SetEqualityConstraint
, however, the comparison will be allowed:scala> import SetEqualityConstraints._ import SetEqualityConstraints._ scala> TreeSet(1, 2) === HashSet(1, 2) res2: Boolean = true
The equality constraint provided by this trait requires that both left and right sides are subclasses of
scala.collection.GenSet
and that anEqualityConstraint
can be found for the element types. In the example above, both theTreeSet
andHashSet
are subclasses ofscala.collection.GenSet
, and the regularTypeCheckedTripleEquals
provides equality constraints for the element types, both of which areInt
. By contrast, this trait would not allow aTreeSet[Int]
to be compared against aHashSet[java.util.Date]
, because no equality constraint will exist between the element typesInt
andDate
:scala> import java.util.Date import java.util.Date scala> TreeSet(1, 2) === HashSet(new Date, new Date) <console>:20: error: types scala.collection.immutable.TreeSet[Int] and scala.collection.mutable.HashSet[java.util.Date] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[scala.collection.immutable.TreeSet[Int], scala.collection.mutable.HashSet[java.util.Date]] TreeSet(1, 2) === HashSet(new Date, new Date) ^
-
final
case class
Snapshot(name: String, value: Any) extends Product with Serializable
Case class that stores the name and value of a variable or expression.
Case class that stores the name and value of a variable or expression.
See the main documentation for trait
Snapshots
for more information and examples.- name
the name of the expression
- value
the value of the expression
-
final
class
SnapshotSeq extends IndexedSeq[Snapshot]
An
IndexedSeq[Snapshot]
providingtoString
andlines
methods that can be useful for debug and log messages about program state.An
IndexedSeq[Snapshot]
providingtoString
andlines
methods that can be useful for debug and log messages about program state.See the main documentation for trait
Snapshots
for more information and examples. -
trait
Snapshots extends AnyRef
Trait that provides a
snap
method that takes one or more arguments and results in aSnapshotSeq
, whosetoString
lists the names and values of each argument.Trait that provides a
snap
method that takes one or more arguments and results in aSnapshotSeq
, whosetoString
lists the names and values of each argument.The intended use case of this trait is to help you write debug and log messages that give a "snapshot" of program state. Here's an example:
scala> import Snapshots._ import Snapshots._ scala> snap(a, b, c, d, e, f) res3: org.scalactic.SnapshotSeq = a was 1, b was 2, c was 3, d was 4, e was null, f was null
SnapshotSeq
offers alines
method that places each variable name/value pair on its own line:scala> snap(a, b, c, d, e, f).lines res4: String = a was 1 b was 2 c was 3 d was 4 e was null f was null
Or, because a
SnapshotSeq
is aIndexedSeq[Snapshot]
, you can process it just like any otherSeq
, for example:scala> snap(a, b, c, d, e, f).mkString("Wow! ", ", and ", ". That's so awesome!") res6: String = Wow! a was 1, and b was 2, and c was 3, and d was 4, and e was null, and f was null. That's so awesome!
-
trait
StringNormalizations extends AnyRef
Provides methods that produce
Uniformity[String]
instances for various ways to normalize strings for equality comparisons. -
trait
TimesOnInt extends AnyRef
Trait providing an implicit conversion that adds a
times
method toInt
s that will repeat a given side-effecting operation multiple times.Trait providing an implicit conversion that adds a
times
method toInt
s that will repeat a given side-effecting operation multiple times.Here's an example in which a friendly greeting is printed three times:
3 times println("Hello again, world!")
Running the above code would yield this output:
Hello again, world! Hello again, world! Hello again, world!
If you need to repeat a block of statements multiple times, just enclose them in parentheses, like this:
2 times { print("Hello ") print("again, ") println("world!") }
Running the above code would yield:
Hello again, world! Hello again, world!
This trait enables
times
to be invoked on 0 and any positive integer, but attempting to invoketimes
on a negative integer will result in anIllegalArgumentException
. -
trait
Tolerance extends AnyRef
Trait containing an implicit conversion that adds a
+-
method toNumeric
types, which enables spreads to be expressed in terms of a pivot and tolerance.Trait containing an implicit conversion that adds a
+-
method toNumeric
types, which enables spreads to be expressed in terms of a pivot and tolerance.For example, the
TripleEquals
trait (and its type-checking siblingsTypeCheckedTripleEquals
andConversionCheckedTripleEquals
) enable you to write:a === (1.0 +- 0.1)
-
trait
TolerantNumerics extends AnyRef
Provides
Equality
andEquivalence
instances forNumeric
types that compare for equality with a given tolerance.Provides
Equality
andEquivalence
instances forNumeric
types that compare for equality with a given tolerance.Here's an example:
scala> import org.scalactic._ import org.scalactic._ scala> import TripleEquals._ import TripleEquals._ scala> 2.001 === 2.0 res0: Boolean = false scala> implicit val doubleEquality = TolerantNumerics.tolerantDoubleEquality(0.01) doubleEquality: org.scalactic.Equality[Double] = org.scalactic.TolerantNumerics$$anon$1@16c2bd13 scala> 2.001 === 2.0 res1: Boolean = true
-
trait
TraversableEqualityConstraints extends SeqEqualityConstraints with SetEqualityConstraints with MapEqualityConstraints
Provides three implicit methods that loosen the equality constraint defined by
TypeCheckedTripleEquals
for ScalaTraversable
s to one that more closely matches Scala's approach toTraversable
equality.Provides three implicit methods that loosen the equality constraint defined by
TypeCheckedTripleEquals
for ScalaTraversable
s to one that more closely matches Scala's approach toTraversable
equality.Scala's approach to
Traversable
equality is that if the objects being compared are ether bothSeq
s, bothSet
s, or bothMap
s, the elements are compared to determine equality. This means you could compare an immutableVector
and a mutableListBuffer
for equality, for instance, and get true so long as the twoSeq
s contained the same elements in the same order. Here's an example:scala> import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer scala> Vector(1, 2) == ListBuffer(1, 2) res0: Boolean = true
Such a comparison would not, however, compile if you used
===
underTypeCheckedTripleEquals
, becauseVector
andListBuffer
are not in a subtype/supertype relationship:scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> Vector(1, 2) === ListBuffer(1, 2) <console>:16: error: types scala.collection.immutable.Vector[Int] and scala.collection.mutable.ListBuffer[Int] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[scala.collection.immutable.Vector[Int], scala.collection.mutable.ListBuffer[Int]] Vector(1, 2) === ListBuffer(1, 2) ^
If you mix or import the implicit conversion provided by
TraversableEqualityConstraint
, however, the comparison will be allowed:scala> import TraversableEqualityConstraints._ import TraversableEqualityConstraints._ scala> Vector(1, 2) === ListBuffer(1, 2) res2: Boolean = true
The equality constraints provided by this trait require that left and right sides are both subclasses of either
scala.collection.GenSeq
,scala.collection.GenSet
, orscala.collection.GenMap
, and that anCanEqual
can be found for the element types forSeq
andSet
, or the key and value types forMap
s. In the example above, both theVector
andListBuffer
are subclasses ofscala.collection.GenSeq
, and the regularTypeCheckedTripleEquals
provides equality constraints for the element types, both of which areInt
. By contrast, this trait would not allow aVector[Int]
to be compared against aListBuffer[java.util.Date]
, because no equality constraint will exist between the element typesInt
andDate
:scala> import java.util.Date import java.util.Date scala> Vector(1, 2) === ListBuffer(new Date, new Date) <console>:20: error: types scala.collection.immutable.Vector[Int] and scala.collection.mutable.ListBuffer[java.util.Date] do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[scala.collection.immutable.Vector[Int], scala.collection.mutable.ListBuffer[java.util.Date]] Vector(1, 2) === ListBuffer(new Date, new Date) ^
This trait simply mixes together
SeqEqualityConstraints
,SetEqualityConstraints
, andMapEqualityConstraints
. -
trait
TripleEquals extends TripleEqualsSupport
Provides
===
and!==
operators that returnBoolean
, delegate the equality determination to anEquality
type class, and require no relationship between the types of the two values compared.Provides
===
and!==
operators that returnBoolean
, delegate the equality determination to anEquality
type class, and require no relationship between the types of the two values compared.Recommended Usage: Trait TripleEquals
is useful (in both production and test code) when you need determine equality for a type of object differently than itsequals
method: either you can't change theequals
method, or theequals
method is sensible generally, but you are in a special situation where you need something else. You can use the SuperSafe Community Edition compiler plugin to get a compile-time safety check of types being compared with===
. In situations where you need a stricter type check, you can useTypeCheckedTripleEquals
.This trait will override or hide implicit methods defined by its sibling traits,
ConversionCheckedTripleEquals
orTypeCheckedTripleEquals
, and can therefore be used to temporarily turn of type checking in a limited scope. Here's an example, in whichTypeCheckedTripleEquals
will cause a compiler error:import org.scalactic._ import TypeCheckedTripleEquals._ object Example { def cmp(a: Int, b: Long): Int = { if (a === b) 0 // This line won't compile else if (a < b) -1 else 1 } def cmp(s: String, t: String): Int = { if (s === t) 0 else if (s < t) -1 else 1 } }
Because
Int
andLong
are not in a subtype/supertype relationship, comparing1
and1L
in the context ofTypeCheckedTripleEquals
will generate a compiler error:Example.scala:9: error: types Int and Long do not adhere to the equality constraint selected for the === and !== operators; they must either be in a subtype/supertype relationship, or, if ConversionCheckedTripleEquals is in force, implicitly convertible in one direction or the other; the missing implicit parameter is of type org.scalactic.Constraint[Int,Long] if (a === b) 0 // This line won't compile ^ one error found
You can “turn off” the type checking locally by importing the members of
TripleEquals
in a limited scope:package org.scalactic.examples.tripleequals import org.scalactic._ import TypeCheckedTripleEquals._ object Example { def cmp(a: Int, b: Long): Int = { import TripleEquals._ if (a === b) 0 else if (a < b) -1 else 1 } def cmp(s: String, t: String): Int = { if (s === t) 0 else if (s < t) -1 else 1 } }
With the above change, the
Example.scala
file compiles fine. Type checking is turned off only inside the firstcmp
method that takes anInt
and aLong
.TypeCheckedTripleEquals
is still enforcing its type constraint, for example, for thes === t
expression in the other overloadedcmp
method that takes strings.Because the methods in
TripleEquals
(and its siblings)override all the methods defined in supertypeTripleEqualsSupport
, you can achieve the same kind of nested tuning of equality constraints whether you mix in traits, import from companion objects, or use some combination of both.In short, you should be able to select a primary constraint level via either a mixin or import, then change that in nested scopes however you want, again either through a mixin or import, without getting any implicit conversion ambiguity. The innermost constraint level in scope will always be in force.
-
trait
TripleEqualsSupport extends AnyRef
Trait that defines abstract methods used to enforce compile-time type constraints for equality comparisons, and defines
===
and!==
operators used by matchers.Trait that defines abstract methods used to enforce compile-time type constraints for equality comparisons, and defines
===
and!==
operators used by matchers.The abstract methods of this trait are selectively implemented as implicit by subclasses to enable a spectrum of type constraints for the
===
and!==
operators. As an illustration, if in the expression,a === b
, the type ofa
isA
andb
isB
, the following three levels of compile-time checking can be obtained fromTripleEqualsSupport
subtraits:Unchecked -
A
andB
can be any two types. This constraint level is available from subtraitTripleEquals
.Statically-checked -
A
must be a subtype ofB
, or vice versa, or must cooperate such that the equality laws stated in theequals
contract are preserved. This (intermediate) constraint level is available by using subtraitTripleEquals
and installing the SuperSafe Community Edition Scala compiler plugin.Type-checked -
A
must be a subtype ofB
, or vice versa. (BothA
andB
can be the same type, because a type is considered a subtype of itself.) This (strongest) constraint level is available from subtraitTypeCheckedTripleEquals
.This trait defines all methods that need to be defined implicitly by the subtraits so that if multiple subtraits are used together, the inner-most subtrait in scope can not only enable the implicits it needs by overriding or hiding those methods (currently-in-scope as regular, non-implicit methods) and making them implicit, it can also disable any implicits enabled by its sibling subtraits in enclosing scopes. For example, if your test class mixes in
TypeCheckedTripleEquals
, inside your test class the following methods will be implicit:convertToCheckingEqualizer
typeCheckedConstraint
lowPriorityTypeCheckedConstraint
convertEquivalenceToAToBConstraint
convertEquivalenceToBToAConstraint
If in the body of a test you want to turn off the type checking, you can import the members of
TripleEquals
in the body of that test. This will not only hide non-implicit methodsconvertToEqualizer
unconstrainedEquality
ofTypeCheckedTripleEquals
, replacing those with implicit ones defined inTripleEquals
, it will also hide the three methods made implicit inTypeCheckedTripleEquals
(and listed above), replacing them by non-implicit ones.In short, you should be able to select a primary constraint level via either a mixin or import, then change that in nested scopes however you want, again either through a mixin or import, without getting any implicit conversion ambiguity. The innermost constraint level in scope will always be in force.
-
trait
TrySugar extends AnyRef
Trait providing an implicit class that adds a
toOr
method toTry
, which convertsSuccess
toGood
, andFailure
toBad
, as well as avalidating
method, which takes one or more validation functions and returns either the sameTry
if either theTry
had already failed or its value passes all the functions, orValidationFailedException
containing an error message describing the first validation that failed.Trait providing an implicit class that adds a
toOr
method toTry
, which convertsSuccess
toGood
, andFailure
toBad
, as well as avalidating
method, which takes one or more validation functions and returns either the sameTry
if either theTry
had already failed or its value passes all the functions, orValidationFailedException
containing an error message describing the first validation that failed.Here's an example validation method, which passes if the given
Int
is evenly divisible by 10 (i.e., the result will bePass
). If the value does not pass this test, the result is aFail
containing a helpful error message string.scala> import org.scalactic._ import org.scalactic._ scala> import TrySugar._ import TrySugar._ scala> import scala.util.Try import scala.util.Try scala> def isRound(i: Int): Validation[ErrorMessage] = | if (i % 10 == 0) Pass else Fail(i + " was not a round number") isRound: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage]
Validation will be attempted on a successful
Try
. If the validation succeeds, the resultingTry
will be the same successfulTry
with the same value. (A "validation" only transforms theTry
if the validation fails, otherwise it is the sameTry
. The only difference is its value has now been proven valid.) In the following example, a successfulTry[Int]
with the value 100 passes the validation (which checks whether 100 is evenly divisible by 10), therefore the result of thevalidating
call is the same successfulTry
with the same value.scala> val try100 = Try(100) try100: scala.util.Try[Int] = Success(100) scala> val round100 = try100.validating(isRound) round100: scala.util.Try[Int] = Success(100)
If validation fails, the successful
Try
will be transformed into a failed one, with aValidationFailedException
that contains the error message returned by the validation function. In the following example, 42 fails the validation because it is not evenly divisible by 10:scala> val try42 = Try(42) try42: scala.util.Try[Int] = Success(42) scala> val round42 = try42.validating(isRound) round42: scala.util.Try[Int] = Failure(org.scalactic.exceptions.ValidationFailedException: 42 was not a round number)
If
validating
is called on a failedTry
, it just returns the same failedTry
:scala> val tryEx = Try[Int] { throw new Exception("oops!") } tryEx: scala.util.Try[Int] = Failure(java.lang.Exception: oops!) scala> val roundEx = tryEx.validating(isRound) roundEx: scala.util.Try[Int] = Failure(java.lang.Exception: oops!)
The
validating
method accepts one or more validation functions. If you pass more than one, they will be tried in order up until the first failure, whose error message will appear in theValidationFailedException
. In other words,validating
will short circuit at the first error and return that. It will not accumulate errors. For example, the following validation will short circuit after theisDivBy3
function fails:scala> def isDivBy3(i: Int): Validation[ErrorMessage] = | if (i % 3 == 0) Pass else Fail(i + " was not divisible by 3") isDivBy3: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage] scala> def isAnswerToLifeTheUniverseAndEverything(i: Int): Validation[ErrorMessage] = | if (i == 42) Pass else Fail(i + " did not equal 42") isAnswerToLifeTheUniverseAndEverything: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage] scala> try100.validating(isRound, isDivBy3, isAnswerToLifeTheUniverseAndEverything) res0: scala.util.Try[Int] = Failure(org.scalactic.exceptions.ValidationFailedException: 100 was not divisible by 3)
Here are some examples of the
toOr
method:scala> try100.toOr res1: org.scalactic.Or[Int,Throwable] = Good(100) scala> tryEx.toOr res2: org.scalactic.Or[Int,Throwable] = Bad(java.lang.Exception: oops!)
-
trait
TypeCheckedTripleEquals extends LowPriorityTypeCheckedConstraint
Provides
===
and!==
operators that returnBoolean
, delegate the equality determination to anEquality
type class, and require the types of the two values compared to be in a subtype/supertype relationship.Provides
===
and!==
operators that returnBoolean
, delegate the equality determination to anEquality
type class, and require the types of the two values compared to be in a subtype/supertype relationship.Recommended Usage: Trait TypeCheckedTripleEquals
is useful (in both production and test code) when you need a stricter type check than is provided by the SuperSafe Community Edition compiler plugin forTripleEquals
. For example, if you are developing a library that uses advanced features of Scala's type system, you may want to enforce in your tests that the types appearing in equality comparisons match exactly.By default under
TripleEquals
, any use of===
will compile, just like the==
operator:scala> import org.scalactic._ import org.scalactic._ scala> import TripleEquals._ import TripleEquals._ scala> 1L === 1 // A Long can equal an Int res0: Boolean = true scala> List(1, 2, 3) === Vector(1, 2, 3) // A List can equal a Vector res1: Boolean = true scala> "hi" === 1 // Likely a bug, because a String can never equal an Int res2: Boolean = false
With SuperSafe Community Edition installed, the first two expressions above will be allowed to compile, but the third (which represents a likely bug) will not:
scala> import org.scalactic._ import org.scalactic._ scala> import TripleEquals._ import TripleEquals._ scala> 1L === 1 res0: Boolean = true scala> List(1, 2, 3) === Vector(1, 2, 3) res1: Boolean = true scala> "hi" === 1 // SuperSafe catches the bug at compile time <console>:17: error: [Artima SuperSafe] Values of type String and Int may not be compared with the === operator. If you really want to compare them for equality, configure Artima SuperSafe to allow those types to be compared for equality. For more information on this kind of error, see: http://www.artima.com/supersafe_user_guide.html#safer-equality "hi" === 1 ^
By contrast,
TypeCheckedTripleEquals
will prevent any of the above three expressions from compiling:scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> 1L === 1 <console>:17: error: types Long and Int do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[Long,Int] 1L === 1 ^ scala> List(1, 2, 3) === Vector(1, 2, 3) <console>:17: error: types List[Int] and scala.collection.immutable.Vector[Int] do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[List[Int],scala.collection.immutable.Vector[Int]] List(1, 2, 3) === Vector(1, 2, 3) ^ scala> "hi" === 1 <console>:17: error: types String and Int do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[String,Int] "hi" === 1 ^
Trait
TypeCheckedTripleEquals
rejects comparisons of typesInt
andLong
,List[Int]
andVector[Int]
, andString
andInt
, because none have a direct subtype/supertype relationship. To compare two types that are unrelated by inheritance underTypeCheckedTripleEquals
, you could convert one of them to the other type (because a type is both a subtype and supertype of itself). Here's an example:scala> 1L === 1.toLong // Now both sides are Long res0: Boolean = true scala> List(1, 2, 3) === Vector(1, 2, 3).toList // Now both sides are List[Int] res1: Boolean = true
Nevertheless, a better (and the recommended) way to deal with this situation is to use a widening type ascription. A type ascription is simply a colon and a type placed next to a variable, usually surrounded by parentheses. For example, because
AnyVal
is a common supertype ofInt
andLong
, you could solve the type error by widening the type of one side or the other toAnyVal
. BecauseAnyVal
is a supertype of bothInt
andLong
, the type constraint will be satisfied:scala> 1 === (1L: AnyVal) res2: Boolean = true scala> (1: AnyVal) === 1L res3: Boolean = true
Similarly, since
Seq[Int]
is a common supertype of bothVector[Int]
andList[Int]
, the type constraint can be satisfied by widening either to their common supertype,Seq[Int]
:scala> List(1, 2, 3) === (Vector(1, 2, 3): Seq[Int]) res4: Boolean = true scala> (List(1, 2, 3): Seq[Int]) === Vector(1, 2, 3) res5: Boolean = true
The primary intended use case for
TypeCheckedTripleEquals
is to enable tests to be very strict about which types can compared for equality, but it can also be used with production code where this level of strictness is desired.Forcing implicit conversions before equality checks
You can also use a type ascription to force an implicit conversion before a value participates in an equality comparison. For example, although
JavaConversions
provides an implicit conversion betweenjava.util.Set
andscala.collection.mutable.Set
, underTypeCheckedTripleEquals
an equality comparison between those two types will not be allowed:scala> import collection.JavaConversions._ import collection.JavaConversions._ scala> import collection.mutable import collection.mutable scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> mutable.Set.empty[String] === new java.util.HashSet[String] <console>:36: error: types scala.collection.mutable.Set[String] and java.util.HashSet[String] do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[scala.collection.mutable.Set[String],java.util.HashSet[String]] mutable.Set.empty[String] === new java.util.HashSet[String] ^
To force an implicit conversion of the Java
HashSet
to a Scalamutable.Set
, after which the type constraint will be satisfied, you can use a type ascription:scala> mutable.Set.empty[String] === (new java.util.HashSet[String]: mutable.Set[String]) res0: Boolean = true
Scoping equality policies
This trait will override or hide implicit methods defined by
TripleEquals
and can therefore be used to temporarily turn on or off type checking in a limited scope. Here's an example, in whichTypeCheckedTripleEquals
will cause a compiler error:import org.scalactic._ import TypeCheckedTripleEquals._ object Example { def cmp(a: Int, b: Long): Int = { if (a === b) 0 // This line won't compile else if (a < b) -1 else 1 } def cmp(s: String, t: String): Int = { if (s === t) 0 else if (s < t) -1 else 1 } }
Because
Int
andLong
are not in a subtype/supertype relationship, comparing1
and1L
in the context ofTypeCheckedTripleEquals
will generate a compiler error:Example.scala:9: error: types Int and Long do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[Int,Long] if (a === b) 0 // This line won't compile ^ one error found
You can “relax” the type checking locally by importing the members of
TripleEquals
in a limited scope:package org.scalactic.examples.conversioncheckedtripleequals import org.scalactic._ import TypeCheckedTripleEquals._ object Example { def cmp(a: Int, b: Long): Int = { import TripleEquals._ if (a === b) 0 else if (a < b) -1 else 1 } def cmp(s: String, t: String): Int = { if (s === t) 0 else if (s < t) -1 else 1 } }
With the above change, the
Example.scala
file compiles fine. The strict checking is disabled only inside the firstcmp
method that takes anInt
and aLong
.TypeCheckedTripleEquals
is still enforcing its type constraint, for example, for thes === t
expression in the other overloadedcmp
method that takes strings.Because the methods
TripleEquals
andTypeCheckedTripleEquals
override all the methods defined in supertypeTripleEqualsSupport
, you can achieve the same kind of nested tuning of equality constraints whether you mix in traits, import from companion objects, or use some combination of both.In short, you should be able to select a primary constraint level via either a mixin or import, then change that in nested scopes however you want, again either through a mixin or import, without getting any implicit conversion ambiguity. The innermost constraint level in scope will always be in force.
-
trait
Uniformity[A] extends Normalization[A]
Defines a custom way to normalize instances of a type that can also handle normalization of that type when passed as
Any
.Defines a custom way to normalize instances of a type that can also handle normalization of that type when passed as
Any
.For example, to normalize
Double
s by truncating off any decimal part, you might write:import org.scalactic._ val truncated = new Uniformity[Double] { def normalized(d: Double) = d.floor def normalizedCanHandle(o: Any) = o.isInstanceOf[Double] def normalizedOrSame(o: Any): Any = o match { case d: Double => normalized(d) case _ => o } }
Given this definition you could use it with the
Explicitly
DSL like this:import org.scalatest._ import Matchers._ 2.1 should equal (2.0) (after being truncated)
If you make the
truncated
val
implicit and import or mix in the members ofNormMethods
, you can access the behavior by invoking.norm
onDouble
s.implicit val doubleUniformity = truncated import NormMethods._ val d = 2.1 d.norm // returns 2.0
Note that by creating a
Uniformity
rather than just an instance of its supertype,Normalization
, it can be used more generally. For example,Uniformity
s allow you to theExplicitly
DSL withTripleEquals
, whereasNormalization
s requireTypeCheckedTripleEquals
.Uniformity
s also enable you to use theExplicitly
DSL with ScalaTest'sshould
===
,equal
, andcontain
matcher syntax, whereas a plainNormalization
can only be used withshould
===
, and only underTypeCheckedTripleEquals
.- A
the type whose uniformity is being defined
-
sealed
trait
Validation[+E] extends Product with Serializable
Represents the result of a validation, either the object
Pass
if the validation succeeded, else an instance ofFail
containing an error value describing the validation failure.Represents the result of a validation, either the object
Pass
if the validation succeeded, else an instance ofFail
containing an error value describing the validation failure.Validation
s are used to filterOr
s infor
expressions orfilter
method calls. For example, consider these methods:import org.scalactic._ def isRound(i: Int): Validation[ErrorMessage] = if (i % 10 == 0) Pass else Fail(i + " was not a round number") def isDivBy3(i: Int): Validation[ErrorMessage] = if (i % 3 == 0) Pass else Fail(i + " was not divisible by 3")
Because
isRound
andisDivBy3
take anInt
and return aValidation[ErrorMessage]
, you can use them in filters infor
expressions involvingOr
s of typeInt
Or
ErrorMessage
. Here's an example:for (i <- Good(3) if isRound(i) && isDivBy3(i)) yield i // Result: Bad(3 was not a round number)
Validation
s can also be used to accumulate error usingwhen
, a method that's made available by traitAccumulation
on accumualtingOr
s (Or
s whoseBad
type is anEvery[T]
). Here are some examples:import Accumulation._ for (i <- Good(3) when (isRound, isDivBy3)) yield i // Result: Bad(One(3 was not a round number)) for (i <- Good(4) when (isRound, isDivBy3)) yield i // Result: Bad(Many(4 was not a round number, 4 was not divisible by 3))
Note: You can think of
Validation
as an “Option
with attitude,” wherePass
is aNone
that indicates validation success andFail
is aSome
whose value describes the validation failure.- E
the type of error value describing a validation failure for this
Validation
-
type
Constraint[A, B] = CanEqual[A, B]
- Annotations
- @deprecated
- Deprecated
Constraint has been deprecated and will be removed in a future version of Scalactic. Please use its new name, CanEqual, instead.
-
trait
ConversionCheckedTripleEquals extends LowPriorityConversionCheckedConstraint
Trait
ConversionCheckedTripleEquals
has been deprecated and will be removed in a future version of Scalactic. Please useTypeCheckedTripleEquals
with a type annotation instead.Trait
ConversionCheckedTripleEquals
has been deprecated and will be removed in a future version of Scalactic. Please useTypeCheckedTripleEquals
with a type annotation instead.Trait
ConversionCheckedTripleEquals
has been deprecated because code that uses it can break if you change the equality policy toTripleEquals
. For example, becauseJavaConversions
provides an implicit conversion betweenjava.util.Set
andscala.collection.mutable.Set
, an equality comparison underConversionCheckedTripleEquals
can yieldtrue
:scala> import collection.JavaConversions._ import collection.JavaConversions._ scala> import collection.mutable import collection.mutable scala> import ConversionCheckedTripleEquals._ import ConversionCheckedTripleEquals._ scala> mutable.Set.empty[String] === new java.util.HashSet[String] res0: Boolean = true
If code written under
ConversionCheckedTripleEquals
is left unchanged, but the policy is changed toTripleEquals
, the equality comparison will now yieldfalse
:scala> import TripleEquals._ import TripleEquals._ scala> mutable.Set.empty[String] === (new java.util.HashSet[String]) res1: Boolean = false
The above change from
true
tofalse
happens without any warning or complaint from the compiler. Thus it is quite error prone. A better way to achieve equality comparisons after an implicit conversion is to do soexplicitly
, by forcing the implicit conversion via a type annotation (following an expression with a colon and the desired type). Here's an example:scala> mutable.Set.empty[String] === (new java.util.HashSet[String]: mutable.Set[String]) res3: Boolean = true
To get rid of the deprecation warning, you can use
TypeCheckedTripleEquals
instead ofConversionCheckedTripleEquals
, and add explicit type annotations where needed:scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> mutable.Set.empty[String] === new java.util.HashSet[String] <console>:27: error: types scala.collection.mutable.Set[String] and java.util.HashSet[String] do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[scala.collection.mutable.Set[String],java.util.HashSet[String]] mutable.Set.empty[String] === (new java.util.HashSet[String]) ^ scala> mutable.Set.empty[String] === (new java.util.HashSet[String]: mutable.Set[String]) res4: Boolean = true
- Annotations
- @deprecated
- Deprecated
ConversionCheckedTripleEquals has been deprecated and will be removed in a future version of Scalactic. Please use TypeCheckedTripleEquals with a type annotation instead
-
trait
DeprecatedPrettyMethods extends AnyRef
This trait is the 2.2.6 PrettyMethods trait renamed to DeprecatedPrettyMethods. It is a quick way to get old code working again that defined an implicit
PrettifierConfig
, but before the deprecation cycle is over please change the implicitPrettifierConfig
to an implicitPrettifier
. Provides an implicit conversion that enablespretty
to be invoked on any object, to transform that object into aString
representation.This trait is the 2.2.6 PrettyMethods trait renamed to DeprecatedPrettyMethods. It is a quick way to get old code working again that defined an implicit
PrettifierConfig
, but before the deprecation cycle is over please change the implicitPrettifierConfig
to an implicitPrettifier
. Provides an implicit conversion that enablespretty
to be invoked on any object, to transform that object into aString
representation.- Annotations
- @deprecated
- Deprecated
Please use PrettyMethods instead.
-
trait
LowPriorityConversionCheckedConstraint extends TripleEqualsSupport
Provides an implicit conversion that will be applied only if a higher-priority implicit conversion declared a subtrait is not applicable.
Provides an implicit conversion that will be applied only if a higher-priority implicit conversion declared a subtrait is not applicable.
This trait, which supports
ConversionCheckedTripleEquals
, will no longer be necessary once the deprecation cycle forConversionCheckedTripleEquals
has completed. At that time it will be removed.The purpose of this trait is to make the
===
operator symetric. In other words, a===
invocation will be allowed if an implicit conversion exists in either direction. For example, the implicit widening conversion fromInt
toLong
will be applied on the left hand side in this expression:1 === 1L
But in the next expression, it will be applied on the right hand side:
1L === 1
The first expression above is enabled by the implicit conversion
conversionCheckedConstraint
in traitConversionCheckedTripleEquals
. The second expression above is enabled by the implicit conversionlowPriorityConversionCheckedConstraint
in this trait.The reason these two implicit methods aren't both declared in the subtraits is that if implicit conversions were available in both directions, they would conflict. By placing one of them in this supertrait, the higher priority conversion will be selected.
- Annotations
- @deprecated
- Deprecated
Trait LowPriorityConversionCheckedConstraint is deprecated and will be removed after the deprecation period of ConversionCheckedTripleEquals has completed.
Value Members
-
val
ScalacticVersion: String
The version number of Scalactic.
The version number of Scalactic.
- returns
the Scalactic version number.
-
def
attempt[R](f: ⇒ R): Or[R, Throwable]
Returns the result of evaluating the given block
f
, wrapped in aGood
, or if an exception is thrown, theThrowable
, wrapped in aBad
.Returns the result of evaluating the given block
f
, wrapped in aGood
, or if an exception is thrown, theThrowable
, wrapped in aBad
.Here are some examples:
scala> import org.scalactic._ import org.scalactic._ scala> attempt { 2 / 1 } res0: org.scalactic.Or[Int,Throwable] = Good(2) scala> attempt { 2 / 0 } res1: org.scalactic.Or[Int,Throwable] = Bad(java.lang.ArithmeticException: / by zero)
- f
the block to attempt to evaluate
- returns
the result of evaluating the block, wrapped in a
Good
, or the thrown exception, wrapped in aBad
-
object
Accumulation extends Accumulation
Companion object to trait
Accumulation
that allowsAccumulation
's members to be imported rather than mixed in, and also contains nested traits used by implicit conversions declared in traitAccumulations
.Companion object to trait
Accumulation
that allowsAccumulation
's members to be imported rather than mixed in, and also contains nested traits used by implicit conversions declared in traitAccumulations
.For more information and examples, see the Accumulating errors with
Or
section of the main documentation for classOr
. -
object
Bool
Bool
companion object that provides factory methods to create different sub types ofBool
Bool
companion object that provides factory methods to create different sub types ofBool
Bool
is used by code generated fromBooleanMacro
(whichAssertionsMacro
andRequirementsMacro
uses), it needs to be public so that the generated code can be compiled. It is expected that ScalaTest users would ever need to useBool
directly. -
object
Catcher
Companion object for
Catcher
that provides a factory method for creatingThrowable
extractors. -
object
Chain
Companion object for class
Chain
. -
object
End
Object that can be used as an endpoint for
Chain
construction expressions that use the cons (::
) operator.Object that can be used as an endpoint for
Chain
construction expressions that use the cons (::
) operator.Here's an example:
scala> 1 :: 2 :: 3 :: End res0: org.scalactic.Chain[Int] = Chain(1, 2, 3)
Note that unlike
Nil
, which is an instance ofList[Nothing]
,End
is not an instance ofChain[Nothing]
, because there is no emptyChain
:scala> Nil.isInstanceOf[List[_]] res0: Boolean = true scala> End.isInstanceOf[Chain[_]] res1: Boolean = false
-
object
Equality
Companion object for trait
Equality
that provides factory methods for producingEquality
instances. -
object
Equivalence
Companion object for trait
Equivalence
that provides a factory method for producing defaultEquivalence
instances. -
object
Every extends Serializable
Companion object for abstract class
Every
. -
object
Explicitly extends Explicitly
Companion object for
Explicitly
, which enables the Scalactic explicitly DSL to be imported rather than mixed in, like this:Companion object for
Explicitly
, which enables the Scalactic explicitly DSL to be imported rather than mixed in, like this:import org.scalactic._ import Explicitly._ // Use the explicitly DSL...
-
object
FutureSugar extends FutureSugar
Companion object for
FutureSugar
enabling its members to be imported as an alternative to mixing them in. -
object
Good extends Serializable
Companion object for
Good
that offers, in addition to the standard factory method forGood
that takes single “good” type, an parameterless apply used to narrow theGood
type when creating aBad
.Companion object for
Good
that offers, in addition to the standard factory method forGood
that takes single “good” type, an parameterless apply used to narrow theGood
type when creating aBad
. -
object
MapEqualityConstraints extends MapEqualityConstraints
Companion object that facilitates the importing of
MapEqualityConstraints
members as an alternative to mixing it in.Companion object that facilitates the importing of
MapEqualityConstraints
members as an alternative to mixing it in. One use case is to importMapEqualityConstraints
members so you can use them in the Scala interpreter. -
object
NormMethods extends NormMethods
Companion object for
NormMethods
enabling its members to be imported as an alternative to mixing them in. -
object
OptionSugar extends OptionSugar
Companion object for
OptionSugar
enabling its members to be imported as an alternative to mixing them in. -
object
Or extends Serializable
The companion object for
Or
providing factory methods for creatingOr
s fromEither
s andTry
s. -
object
Pass extends Validation[Nothing] with Product with Serializable
Indicates a validation succeeded.
-
object
Prettifier extends Serializable
Companion object for
Prettifier
that provides a defaultPrettifier
implementation. -
object
PrettyMethods extends PrettyMethods
Companion object for trait
PrettyMethods
enabling its members to be imported as an alternative to mixing them in. -
object
Requirements extends Requirements
Companion object that facilitates the importing of
Requirements
members as an alternative to mixing it in.Companion object that facilitates the importing of
Requirements
members as an alternative to mixing it in. One use case is to importRequirements
members so you can use them in the Scala interpreter:$scala -classpath scalatest.jar Welcome to Scala version 2.10.3.final (Java HotSpot(TM) Client VM, Java xxxxxx). Type in expressions to have them evaluated. Type :help for more information. scala> import org.scalactic.Requirements._ import org.scalactic.Requirements._ scala> val a = 1 a: Int = 1 scala> require(a == 2) java.lang.IllegalArgumentException: 1 did not equal 2 at org.scalactic.Requirements$RequirementsHelper.macroRequire(Requirements.scala:56) at .<init>(<console>:20) at .<clinit>(<console>) at .<init>(<console>:7) at .<clinit>(<console>) at $print(<console>) at sun.reflect.NativeMethodAccessorImpl.invoke...
-
object
SeqEqualityConstraints extends SeqEqualityConstraints
Companion object that facilitates the importing of
SeqEqualityConstraints
members as an alternative to mixing it in.Companion object that facilitates the importing of
SeqEqualityConstraints
members as an alternative to mixing it in. One use case is to importSeqEqualityConstraints
members so you can use them in the Scala interpreter. -
object
SetEqualityConstraints extends SetEqualityConstraints
Companion object that facilitates the importing of
SetEqualityConstraints
members as an alternative to mixing it in.Companion object that facilitates the importing of
SetEqualityConstraints
members as an alternative to mixing it in. One use case is to importSetEqualityConstraints
members so you can use them in the Scala interpreter. - object SnapshotSeq
-
object
Snapshots extends Snapshots
Companion object that facilitates the importing of
Snapshots
members as an alternative to mixing it in.Companion object that facilitates the importing of
Snapshots
members as an alternative to mixing it in. One use case is to importSnapshots
members so you can use them in the Scala interpreter:$scala -classpath scalatest.jar Welcome to Scala version 2.10.3.final (Java HotSpot(TM) Client VM, Java xxxxxx). Type in expressions to have them evaluated. Type :help for more information. scala> import org.scalactic.Snapshots._ import org.scalatest.Snapshots._ scala> val a = 8 a: Int = 8 scala> snap(a) res0: scala.collection.immutable.Vector[org.scalactic.Snapshot] = Vector(a = 8)
-
object
StringNormalizations extends StringNormalizations
Companion object to trait
StringNormalizations
that provides an alternative to mixing it in. -
object
TimesOnInt extends TimesOnInt
Companion object that facilitates the importing of
TimesOnInt
members as an alternative to mixing it in.Companion object that facilitates the importing of
TimesOnInt
members as an alternative to mixing it in.One use case of this companion object is to import
TimesOnInt
members so you can use them in the Scala interpreter. Here's an example:scala> import org.scalatest.TimesOnInt._ import org.scalatest.TimesOnInt._ scala> 3 times println("Hello again, world!") Hello again, world! Hello again, world! Hello again, world!
-
object
Tolerance extends Tolerance
Companion object to trait
Tolerance
that facilitates the importing ofTolerance
members as an alternative to mixing it in.Companion object to trait
Tolerance
that facilitates the importing ofTolerance
members as an alternative to mixing it in. One use case is to importTolerance
members so you can use them in the Scala interpreter:$ scala -classpath scalactic.jar Welcome to Scala version 2.10.0 Type in expressions to have them evaluated. Type :help for more information. scala> import org.scalactic._ import org.scalactic._ scala> import Tolerance._ import Tolerance._ scala> 1.0 +- 0.1 res0: org.scalactic.TripleEqualsSupport.Spread[Double] = Spread(1.0,0.1)
-
object
TolerantNumerics extends TolerantNumerics
Companion object for
TolerantNumerics
that enables its members to be imported as an alternative to mixing them in. -
object
TraversableEqualityConstraints extends TraversableEqualityConstraints
Companion object that facilitates the importing of
TraversableEqualityConstraints
members as an alternative to mixing it in.Companion object that facilitates the importing of
TraversableEqualityConstraints
members as an alternative to mixing it in. One use case is to importTraversableEqualityConstraints
members so you can use them in the Scala interpreter. -
object
TripleEquals extends TripleEquals
Companion object to trait
TripleEquals
that facilitates the importing ofTripleEquals
members as an alternative to mixing it in.Companion object to trait
TripleEquals
that facilitates the importing ofTripleEquals
members as an alternative to mixing it in. One use case is to importTripleEquals
members so you can use them in the Scala interpreter:$ scala -classpath scalatest.jar Welcome to Scala version 2.10.0 Type in expressions to have them evaluated. Type :help for more information. scala> import org.scalactic._ import org.scalactic._ scala> import TripleEquals._ import TripleEquals._ scala> 1 + 1 === 2 res0: Boolean = true
- object TripleEqualsSupport
-
object
TrySugar extends TrySugar
Companion object for
TrySugar
enabling its members to be imported as an alternative to mixing them in. -
object
TypeCheckedTripleEquals extends TypeCheckedTripleEquals
Companion object to trait
TypeCheckedTripleEquals
that facilitates the importing ofTypeCheckedTripleEquals
members as an alternative to mixing it in.Companion object to trait
TypeCheckedTripleEquals
that facilitates the importing ofTypeCheckedTripleEquals
members as an alternative to mixing it in. One use case is to importTypeCheckedTripleEquals
members so you can use them in the Scala interpreter:$ scala -classpath scalatest.jar Welcome to Scala version 2.10.0 Type in expressions to have them evaluated. Type :help for more information. scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._ scala> 1 + 1 === 2 res0: Boolean = true
Deprecated Value Members
-
object
ConversionCheckedTripleEquals extends ConversionCheckedTripleEquals
Object
ConversionCheckedTripleEquals
has been deprecated and will be removed in a future version of Scalactic. Please useTypeCheckedTripleEquals
with a type annotation instead.Object
ConversionCheckedTripleEquals
has been deprecated and will be removed in a future version of Scalactic. Please useTypeCheckedTripleEquals
with a type annotation instead.For more information and examples, please see the documentation for the
ConversionCheckedTripleEqals
companion trait.- Annotations
- @deprecated
- Deprecated
ConversionCheckedTripleEquals has been deprecated and will be removed in a future version of Scalactic. Please use TypeCheckedTripleEquals with a type annotation instead
-
object
DeprecatedPrettyMethods extends DeprecatedPrettyMethods
This object is the 2.2.6 PrettyMethods object renamed to DeprecatedPrettyMethods. Please change DeprecatedPrettyMethods to PrettyMethods, as DeprecatedPrettyMethods is deprecated and will be removed in a future version of ScalaTest.
This object is the 2.2.6 PrettyMethods object renamed to DeprecatedPrettyMethods. Please change DeprecatedPrettyMethods to PrettyMethods, as DeprecatedPrettyMethods is deprecated and will be removed in a future version of ScalaTest.
- Annotations
- @deprecated
- Deprecated
Please use PrettyMethods instead.