Package

org

scalactic

Permalink

package scalactic

Source
package.scala
Linear Supertypes
AnyRef, Any
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. scalactic
  2. AnyRef
  3. Any
  1. Hide All
  2. Show all
Visibility
  1. Public
  2. All

Type Members

  1. trait AbstractStringUniformity extends Uniformity[String]

    Permalink

    Convenience base trait for string Uniformitys.

    Convenience base trait for string Uniformitys.

    This trait defines a normalizedCanHandle method that returns true if the passed Any is a String and a normalizedOrSame method that normalizes any passed Strings via the normalized 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 a Matcher 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)
    

  2. trait Accumulation extends AnyRef

    Permalink

    Provides mechanisms that enable errors to be accumulated in “accumulating Ors,” Ors whose Bad type is an Every.

    Provides mechanisms that enable errors to be accumulated in “accumulating Ors,” Ors whose Bad type is an Every.

    The mechanisms are:

    • Passing accumulating Ors to withGood methods
    • Invoking combined on a container of accumulating Ors
    • Invoking validatedBy on a container of any type, passing in a function from that type to an accumulating Or
    • Invoking zip on an accumulating Or
    • Invoking when on an accumulating Or

    For more information and examples, see the Accumulating errors with Or section of the main documentation for class Or.

  3. final case class Bad[+B](b: B) extends Or[Nothing, B] with Product with Serializable

    Permalink

    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 are String error messages, Int error codes, Throwable exceptions, or instances of a case class hierarchy designed to describe errors.

    b

    the “bad” value

  4. trait Bool extends AnyRef

    Permalink

    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 from BooleanMacro (which AssertionsMacro and RequirementsMacro uses), it needs to be public so that the generated code can be compiled. It is expected that ScalaTest users would ever need to use Bool directly.

  5. abstract class CanEqual[A, B] extends AnyRef

    Permalink

    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( ... )
  6. class Catcher extends AnyRef

    Permalink

    Convenience class for extractors that match and return Throwables based on a type and Boolean condition.

    Convenience class for extractors that match and return Throwables based on a type and Boolean 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. This Catcher class provides a factory method that takes a partial function from Throwable to Boolean 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 ScalaTest withFixture 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
      }
    }
    

  7. final class Chain[+T] extends AnyVal

    Permalink

    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 a List is non-empty, thereby eliminating the need for (and potential exception from) a run-time check for non-emptiness. For a non-empty sequence with IndexedSeq performance, see Every.

    Constructing Chains

    You can construct a Chain by passing one or more elements to the Chain.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 a List starting with Nil:

    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 a List[Nothing], End is not a Chain[Nothing], because no empty Chain 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 Chains

    Chain does not extend Scala's Seq or Traversable traits because these require that implementations may be empty. For example, if you invoke tail on a Seq that contains just one element, you'll get an empty Seq:

    scala> List(1).tail
    res6: List[Int] = List()
    

    On the other hand, many useful methods exist on Seq that when invoked on a non-empty Seq are guaranteed to not result in an empty Seq. For convenience, Chain defines a method corresponding to every such Seq 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 to Seq methods that could result in an empty Seq. However, an implicit converison from Chain to List is defined in the Chain companion object that will be applied if you attempt to call one of the missing methods. As a result, you can invoke filter on an Chain, even though filter could result in an empty sequence—but the result type will be List instead of Chain:

    Chain(1, 2, 3).filter(_ < 10) // Result: List(1, 2, 3)
    Chain(1, 2, 3).filter(_ > 10) // Result: List()
    

    You can use Chains in for expressions. The result will be an Chain unless you use a filter (an if clause). Because filters are desugared to invocations of filter, the result type will switch to a List 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

  8. trait ConversionCheckedTripleEquals extends LowPriorityConversionCheckedConstraint

    Permalink

    Provides === and !== operators that return Boolean, delegate the equality determination to an Equality type class, and require that either the types of the two values compared are in a subtype/supertype relationship, or that an implicit conversion is available that can convert from one type to the other.

    Provides === and !== operators that return Boolean, delegate the equality determination to an Equality type class, and require that either the types of the two values compared are in a subtype/supertype relationship, or that an implicit conversion is available that can convert from one type to the other.

    Recommended Usage: Trait ConversionCheckedTripleEquals is useful (in both production and test code) when you need determine equality for a type of object differently than its equals method—either you can't change the equals method, or the equals method is sensible generally, but you're in a special situation where you need something else—and/or you want a compile-time type check that allows types that are implicitly convertable in either (or both) directions.

    This trait is the middle ground of the three triple equals traits, in between TripleEquals, the most lenient, and TypeCheckedTripleEquals, the most strict. If TripleEquals is mixed in or imported, the === can be used with any two types and still compile. If TypeCheckedTripleEquals is mixed in or imported, however, only types in a subtype or supertype relationship with each other (including when both types are exactly the same) will compile. ConversionCheckedTripleEquals is slightly more accomodating, because in addition to compiling any use of === that will compile under TypeCheckedTripleEquals, it will also compile type types that would be rejected by TypeCheckedTripleEquals, so long as an implicit conversion (in either direction) from one type to another is available.

    For example, under TypeCheckedTripleEquals, the following use of === will not compile, because Int and Long are not in a subtype/supertype relationship. (I.e., Int is not a subtype or supertype of Long):

    scala> import org.scalactic._
    import org.scalactic._
    
    scala> import TypeCheckedTripleEquals._
    import TypeCheckedTripleEquals._
    
    scala> 1 === 1L
    <console>:14: 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.CanEqual[Int,Long]
                  1 === 1L
                    ^
    

    Trait TypeCheckedTripleEquals rejects types Int and Long because they are not directly related via subtyping. However, an implicit widening conversion from Int to Long does exist (imported implicitly from scala.Predef), so ConversionCheckedTripleEquals will allow it:

    scala> import ConversionCheckedTripleEquals._
    import ConversionCheckedTripleEquals._
    
    scala> 1 === 1L
    res1: Boolean = true
    

    The implicit conversion can go in either direction: from the left type to the right type, or vice versa. In the above expression the implicit conversion goes from left to right (the Int on the left to the Long on the right). It also works the other way:

    scala> 1L === 1
    res2: Boolean = true
    

    This trait will override or hide implicit methods defined by its sibling traits, TripleEquals or TypeCheckedTripleEquals, and can therefore be used to temporarily turn on or off conversion checking in a limited scope. Here's an example, in which TypeCheckedTripleEquals 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 and Long are not in a subtype/supertype relationship, comparing 1 and 1L in the context of TypeCheckedTripleEquals 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.CanEqual[Int,Long]
        if (a === b) 0      // This line won't compile
              ^
    one error found
    

    You can “relax” the type checking (i.e., by additionally allowing implicitly convertible types) locally by importing the members of ConversionCheckedTripleEquals in a limited scope:

    package org.scalactic.examples.conversioncheckedtripleequals
    
    import org.scalactic._
    import TypeCheckedTripleEquals._
    
    object Example {
    
      def cmp(a: Int, b: Long): Int = {
        import ConversionCheckedTripleEquals._
        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. Conversion checking is enabled only inside the first cmp method that takes an Int and a Long. TypeCheckedTripleEquals is still enforcing its type constraint, for example, for the s === t expression in the other overloaded cmp method that takes strings.

    Because the methods in ConversionCheckedTripleEquals (and its siblings) override all the methods defined in supertype TripleEqualsSupport, 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.

    An alternative way to solve an unwanted compiler error caused by an over-zealous type constraint is with a widening type ascription. Here are some examples:

    scala> import org.scalactic._
    import org.scalactic._
    
    scala> import ConversionCheckedTripleEquals._
    import ConversionCheckedTripleEquals._
    
    scala> List(1, 2, 3) === Vector(1, 2, 3)
    <console>:14: error: types List[Int] and scala.collection.immutable.Vector[Int] do not adhere to the equality 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)
                                ^
    

    Although you could solve the above type error with TraversableEqualityConstraints, you could also simply widen the type of one side or the other to Any. Because Any is a supertype of everything, the type constraint will be satisfied:

    scala> List(1, 2, 3) === (Vector(1, 2, 3): Any)
    res1: Boolean = true
    
    scala> (List(1, 2, 3): Any) === Vector(1, 2, 3)
    res2: Boolean = true
    

    You could alternatively widen a type to a more specific common supertype than Any. For example, since List[Int] and Vector[Int] are both subtypes of Seq[Int], so you could widen either type to Seq[Int] to satisfy the type checker:

    scala> List(1, 2, 3) === (Vector(1, 2, 3): Seq[Int])
    res3: Boolean = true
    
    scala> (List(1, 2, 3): Seq[Int]) === Vector(1, 2, 3)
    res4: Boolean = true
    

  9. trait Equality[A] extends Equivalence[A]

    Permalink

    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 implicit Equality[L], where L is the left-hand type: in this case, Person. Because you didn't specifically provide an implicit Equality[Person], === will fall back on default equality, which will call Person's equals method. That equals method, provided by the Scala compiler because Person 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 the age Doubles 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 forgiving Equality[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 types T whose areEqual 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 the default method of the Equality companion object, or from the defaultEquality method defined in TripleEqualsSupport.

    About equality and equivalence

    The Equality trait represents the Java Platform's native notion of equality, as expressed in the signature and contract of the equals method of java.lang.Object. Essentially, trait Equality enables you to write alternate equals method implementations for a type outside its defining class.

    In an equals method, the left-hand type is known to be the type of this, but the right-hand type is Any. 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 possible equals implementation for the Person 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 of Equality[T] is similar. The left-hand type is known to be T, but the right-hand type is Any, so normally you'd need to do a runtime type test in your areEqual implementation. Here's the areEqual method implementation from the earlier Equality[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 by TripleEquals, which enforces no type constraint between the left and right values, and the equal, be, and contain syntax of ScalaTest Matchers.

    By contrast, TypeCheckedTripleEquals and ConversionCheckedTripleEquals use an Equivalence. Equivalence differs from Equality in that both the left and right values are of the same type. Equivalence works for TypeCheckedTripleEquals 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 for ConversionCheckedTripleEquals 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 from Predef 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 an Equivalence's areEquivalent method might look:

    def areEquivalent(a: Person, b: Person): Boolean =
         a.name == b.name && a.age === b.age +- 0.0002
    

    Scalactic provides both Equality and Equivalence because the Any in Equality can sometimes make things painful. For example, in trait TolerantNumerics, a single generic factory method can produce Equivalences for any Numeric type, but because of the Any, a separate factory method must be defined to produce an Equality for each Numeric type.

    If you just want to customize the notion of equality for === used in Boolean expressions, you can work with Equivalences instead of Equalitys. If you do chose to write the more general Equalitys, they can be used wherever an Equivalence is required, because Equality extends Equivalence, defining a final implementation of areEquivalent that invokes areEqual.

    Note: The Equality type class was inspired in part by the Equal type class of the scalaz project.

    A

    the type whose equality is being customized

  10. trait Equivalence[T] extends AnyRef

    Permalink

    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's TypeCheckedTripleEquals and ConversionCheckedTripleEquals traits. These traits can be used to perform equality comparisons with type constraints enforced at compile time using ScalaUtil's === and !== syntax and ScalaTest's should === syntax of Matchers trait.

    Because Equality extends Equivalence, you automatically define an Equivalence[T] when you define an Equality[T]. Most often you will usually want to define custom Equalitys, because they will be more generally useful: they are also used by Scalactic's TripleEquals trait and ScalaTest's equal, be, and contain matcher syntax. However, if you really want just an Equivalence, and writing an Equality is inconvenient, you can write an Equivalence 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 of TypeCheckedTripleEquals looks for an implicit Equivalence[SUPER], where SUPER is either the left-hand or right-hand type, whichever one is a supertype of the other. In this case, both sides are Person (which is considered a supertype of itself), so the compiler will look for an Equivalence[Person]. Because you didn't specifically provide an implicit Equivalence[Person], === will fall back on default equality, because an Equality[Person] is-an Equivalence[Person]. The default Equality[Person] will call Person's equals method. That equals method, provided by the Scala compiler because Person 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 the age Doubles 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 forgiving Equivalence[Person] for the equality check instead of default equality:

    scala> Person("Joe", 29.0001) === Person("Joe", 29.0)
    res1: Boolean = true
    

  11. type ErrorMessage = String

    Permalink

    Type alias for String.

    Type alias for String.

  12. sealed abstract class Every[+T] extends PartialFunction[Int, T] with Serializable

    Permalink

    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 and Many. A One contains exactly one element. A Many contains two or more elements. Thus no way exists for an Every to contain zero elements.

    Constructing Everys

    You can construct an Every by passing one or more elements to the Every.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 to Many.apply:

    One(1)
    Many(1, 3)
    Many(1, 2, 3)
    

    Working with Everys

    Every does not extend Scala's Seq or Traversable traits because these require that implementations may be empty. For example, if you invoke tail on a Seq that contains just one element, you'll get an empty Seq:

    scala> List(1).tail
    res6: List[Int] = List()
    

    On the other hand, many useful methods exist on Seq that when invoked on a non-empty Seq are guaranteed to not result in an empty Seq. For convenience, Every defines a method corresponding to every such Seq 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 to Seq methods that could result in an empty Seq. However, an implicit converison from Every to collection.immutable.IndexedSeq is defined in the Every companion object that will be applied if you attempt to call one of the missing methods. As a result, you can invoke filter on an Every, even though filter could result in an empty sequence—but the result type will be collection.immutable.IndexedSeq instead of Every:

    Every(1, 2, 3).filter(_ < 10) // Result: Vector(1, 2, 3)
    Every(1, 2, 3).filter(_ > 10) // Result: Vector()
    

    You can use Everys in for expressions. The result will be an Every unless you use a filter (an if clause). Because filters are desugared to invocations of filter, the result type will switch to a collection.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 Everys

    Although Every is a general-purpose, non-empty ordered collection, it was motivated by the desire to enable easy accumulation of errors in Ors. For examples of Every used in that use case, see the Accumulating errors with Or section in the main documentation for Or.

    T

    the type of elements contained in this Every

  13. trait Explicitly extends AnyRef

    Permalink

    Provides ScalaTest's “explicitly DSL,” which facilitates the explicit specification of an Equality[T] or a Uniformity[T] where Equality[T] is taken implicitly.

    Provides ScalaTest's “explicitly DSL,” which facilitates the explicit specification of an Equality[T] or a Uniformity[T] where Equality[T] is taken implicitly.

    The Explicitly DSL can be used with the === and !== operators of Scalactic as well as the should 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 in T's companion object). That implicit equality definition will then be picked up and used when that type is compared for equality with the equal, be, and contain 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 implicit Equality[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 as trimmed and lowerCased that return Normalization[String] instances that normalize by trimming and lower-casing, respectively. If you bring those into scope by mixing in or importing the members of StringNormalizations, 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
    

  14. case class Fail[E](error: E) extends Validation[E] with Product with Serializable

    Permalink

    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

  15. trait FutureSugar extends AnyRef

    Permalink

    Trait providing an implicit class that adds a validating method to Future, which takes one or more validation functions and returns either the same Future if either the Future had already failed or its value passes all the functions, or ValidationFailedException containing an error message describing the first validation that failed.

    Trait providing an implicit class that adds a validating method to Future, which takes one or more validation functions and returns either the same Future if either the Future had already failed or its value passes all the functions, or ValidationFailedException 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 be Pass). If the value does not pass this test, the result is a Fail 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 resulting Future will be the same successful Future with the same value. (A "validation" only transforms the Future if the validation fails, otherwise it is the same Future. The only difference is its value has now been proven valid.) In the following example, a successful Future[Int] with the value 100 passes the validation (which checks whether 100 is evenly divisible by 10), therefore the result of the validating call is the same successful Future 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 a ValidationFailedException 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 failed Future, it just returns the same failed Future:

    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 the ValidationFailedException. 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 the isDivBy3 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))
    

  16. final case class Good[+G](g: G) extends Or[G, Nothing] with Product with Serializable

    Permalink

    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

  17. trait LowPriorityConversionCheckedConstraint extends TripleEqualsSupport

    Permalink

    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 an implicit conversion exists in either direction. For example, the implicit widening conversion from Int to Long 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 traits ConversionCheckedTripleEquals and ConversionCheckedLegacyTripleEquals. The second expression above is enabled by the implicit conversion lowPriorityConversionCheckedConstraint 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.

  18. trait LowPriorityTypeCheckedConstraint extends TripleEqualsSupport

    Permalink

    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 traits TypeCheckedTripleEquals and TypeCheckedLegacyTripleEquals. The second expression above is enabled by the implicit conversion lowPriorityTypeCheckedConstraint 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.

  19. final case class Many[+T](firstElement: T, secondElement: T, otherElements: T*) extends Every[T] with Product with Serializable

    Permalink

    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

  20. trait MapEqualityConstraints extends AnyRef

    Permalink

    Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Maps to one that more closely matches Scala's approach to Map equality.

    Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Maps to one that more closely matches Scala's approach to Map equality.

    Scala's approach to Map equality is that if both objects being compared are Maps, the elements are compared to determine equality. This means you could compare an immutable TreeMap and a mutable HashMap 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 either TypeCheckedTripleEquals or ConversionCheckedTripleEquals, because TreeMap and HashMap 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 an EqualityConstraint can be found for both key types and both value types. In the example above, both the TreeMap and HashMap are subclasses of scala.collection.GenMap, and the regular TypeCheckedTripleEquals provides equality constraints for the key types, both of which are String, and value types, both of which are Int. By contrast, this trait would not allow a TreeMap[String, Int] to be compared against a HashMap[String, java.util.Date], because no equality constraint will exist between the value types Int and Date:

    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)
                                                  ^
    

  21. trait NormMethods extends AnyRef

    Permalink

    Provides an implicit conversion that allows norm to be invoked on any value of type T for which an implicit Normalization[T] exists.

    Provides an implicit conversion that allows norm to be invoked on any value of type T for which an implicit Normalization[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!
    

  22. trait Normalization[A] extends AnyRef

    Permalink

    Defines a custom way to normalize instances of a type.

    Defines a custom way to normalize instances of a type.

    For example, to normalize Doubles 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 the Explicitly DSL, you'll need to be using either TypeCheckedTripleEquals or ConversionCheckedTripleEquals. If you're just using plain-old TripleEquals, you'll need a Uniformity, a Normalization subclass.

    If you make the truncated val implicit and import or mix in the members of NormMethods, you can access the behavior by invoking .norm on Doubles.

    implicit val doubleNormalization = truncated
    import NormMethods._
    
    val d = 2.1
    d.norm // returns 2.0
    

    A

    the type whose normalization is being defined

  23. trait NormalizingEquality[A] extends Equality[A]

    Permalink

    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 the afterNormalizationEquality 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 the afterNormalizationEquality member. By default, the afterNormalizationEquality is an instance of Equality.default[A].

    NormalizingEquality is returned by the Explicitly DSL's “after being” syntax, using for the afterNormalizationEquality the implicit Equality in scope for the type of Uniformity passed to being. 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)
    

  24. trait NormalizingEquivalence[A] extends Equivalence[A]

    Permalink

    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 the afterNormalizationEquivalence 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 the afterNormalizationEquivalence member. By default, the afterNormalizationEquivalence is an instance of Equivalence.default[A].

    NormalizingEquivalence is returned by the Explicitly DSL's “after being” syntax, using for the afterNormalizationEquivalence the implicit Equivalence in scope for the type of Normalization passed to being. 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)
    

  25. final case class One[+T](loneElement: T) extends Every[T] with Product with Serializable

    Permalink

    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

  26. trait OptionSugar extends AnyRef

    Permalink

    Trait providing an implicit class that adds a toOr method to Option, which converts Some to Good, None to Bad.

    Trait providing an implicit class that adds a toOr method to Option, which converts Some to Good, None to Bad.

    You can use the toOr method to record information about why a processing of nested Options resulted in None. For example, the following for expression results in None if either the passed optional Person is None or else if the contained optional age is None:

    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 with Ors, supplying an error message or other "bad" value to the toOr method in case of None, you'll get an indication of which part failed if a None 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)
    

  27. sealed abstract class Or[+G, +B] extends AnyRef

    Permalink

    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 of Good or a “bad” value wrapped in an instance of Bad.

    The motivation for Or

    Or differs from Scala's Either type in that Either treats both its Left and Right alternatives in an identical manner, whereas Or treats its two alternatives differently: it favors Good over Bad. Because of this, it is more convenient to work with Ors 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 a Some:

    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 a Some:

    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 a Some, or None 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 the Either. The left will be a String error message. Here's the new parseName function, which returns an Either[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 an Either[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 an Either[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 the for 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 the Either to a RightProjection by invoking .right at each step. Given this implementation, the parsePerson method will now short-circuit at the first sign of trouble (as it did when we used an Option), but you now get the first error message returned in a Left. 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 than Either in this kind of situation. One difference to note with Or is that the Good alternative is on the left, Bad on the right. The reason is that Or 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 an Or, where ErrorMessage is a type alias for String declared in the org.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 name String or, if the input string is not a valid name, an ErrorMessage.

    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 a Good, short circuiting at the first sign of a Bad. Here are a few invocations of this parsePerson 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 and Either is that Or enables you to accumulate errors if the Bad type is an Every. An Every is similar to a Seq in that it contains ordered elements, but different from Seq in that it cannot be empty. An Every is either a One, which contains one and only one element, or a Many, which contains two or more elements.

    Note: an Or whose Bad type is an Every, or one of its subtypes, is called an “accumulating Or.”

    To rewrite the previous example so that errors can be accumulated, you need first to return an Every as the Bad type. Here's how you'd change the parseName 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 name String wrapped in a Good, or one error message, wrapped in a Bad, you would write the Bad type as One[ErrorMessage]. The same is true for parseAge:

    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 first Bad encountered, you'll need to use a different approach to write the parsePerson method. In this example, the withGood method from trait Accumulation 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 overloaded withGood methods that take 1 to 22 accumulating Ors, plus a function taking the same number of corresponding Good values. In this example, if both name and age are Goods, the withGood method will pass the good name String and age Int to the Person(_, _) function, and return the resulting Person object wrapped in a Good. If either name and age, or both, are Bad, withGood will return the accumulated errors in a Bad.

    The result of parsePerson, if Bad, will therefore contain either one or two error messages, i.e., the result will either be a One or a Many. As a result, the result type of parsePerson must be Person Or Every[ErrorMessage]. Regardless of whether a Bad result contains one or two error messages, it will contain every error message. Here's some invocations of this accumulating version of parsePerson:

    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 Ors, for example, you can combine them into one Or using combined, 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 Ors, you can validate the values using the function using validatedBy, 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 Ors together. If both are Good, you'll get a Good tuple containin both original Good values. Otherwise, you'll get a Bad 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 to when on the Or to submit that Or to further scrutiny. A validation function accepts a Good type and returns a Validation[E], where E is the type in the Every in the Bad type. For an Int Or One[ErrorMessage], for example the validation function type would be Int => 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 call when is already Bad, you get the same (Bad) Or back, because no Good 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 call when is Good, and also passes all the validation functions (i.e., the all return None), you again get the same Or back, but this time, a Good 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 a for expression involving an accumulating Or, 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 infer Nothing 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 (\/) and Validation types of scalaz, the ProcessResult type of Typesafe Activator, and the Result type of ScalaKittens.

  28. trait Prettifier extends (Any) ⇒ String

    Permalink

    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 a toString that will convert any object to a String representation. This String representation is primarily intended for programmers, and is usually sufficient. However, sometimes it can be helpful to provide an alternative implementation of toString for certain types. For example, the toString implementation on String prints out the value of the String:

    scala> "1".toString
    res0: String = 1
    

    If the error message that resulted from comparing Int 1 with String "1" in a ScalaTest assertion used toString, 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 a Strings toString result:

    scala> import org.scalactic._
    import org.scalactic._
    
    scala> Prettifier.default("1")
    res1: String = "1"
    

    Thus the error message resulting from comparing Int 1 with String "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 invoke pretty. 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" (the toString result surrounded by double quotes)
    • Char to: 'c' (the toString 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 invoking toString.

    Note: Prettifier is not parameterized (i.e., Prettifier[T], where T is the type to prettify) because assertions (including matcher expressions) in ScalaTest would then need to look up Prettifiers 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 default Prettifier. A future version of ScalaTest will provide a simple mechanism to replace the default Prettifier with a custom one when a test actually fails.

  29. trait PrettyMethods extends AnyRef

    Permalink

    Provides an implicit conversion that enables pretty to be invoked on any object, to transform that object into a String representation.

    Provides an implicit conversion that enables pretty to be invoked on any object, to transform that object into a String representation.

  30. trait Requirements extends AnyRef

    Permalink

    Trait that contains require, and requireState, and requireNonNull methods for checking pre-conditions that give descriptive error messages extracted via a macro.

    Trait that contains require, and requireState, and requireNonNull 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 of Requirements (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 to require, but throws IllegalStateException instead of IllegalArgumentException:

    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, the requireState 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 throws NullArgumentException with an error messages that includes the variable names if any are null. 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, trait Requirements is helpful.

  31. trait SeqEqualityConstraints extends AnyRef

    Permalink

    Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Seqs to one that more closely matches Scala's approach to Seq equality.

    Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Seqs to one that more closely matches Scala's approach to Seq equality.

    Scala's approach to Seq equality is that if both objects being compared are Seqs, the elements are compared to determine equality. This means you could compare an immutable Vector and a mutable ListBuffer for equality, for instance, and get true so long as the two Seqs 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 either TypeCheckedTripleEquals or ConversionCheckedTripleEquals, because Vector and ListBuffer 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 an EqualityConstraint can be found for the element types. In the example above, both the Vector and ListBuffer are subclasses of scala.collection.GenSeq, and the regular TypeCheckedTripleEquals provides equality constraints for the element types, both of which are Int. By contrast, this trait would not allow a Vector[Int] to be compared against a ListBuffer[java.util.Date], because no equality constraint will exist between the element types Int and Date:

    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)
                               ^
    

  32. trait SetEqualityConstraints extends AnyRef

    Permalink

    Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Sets to one that more closely matches Scala's approach to Set equality.

    Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Sets to one that more closely matches Scala's approach to Set equality.

    Scala's approach to Set equality is that if both objects being compared are Sets, the elements are compared to determine equality. This means you could compare an immutable TreeSet and a mutable HashSet for equality, for instance, and get true so long as the two Sets 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 either TypeCheckedTripleEquals or ConversionCheckedTripleEquals, because TreeSet and HashSet 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 an EqualityConstraint can be found for the element types. In the example above, both the TreeSet and HashSet are subclasses of scala.collection.GenSet, and the regular TypeCheckedTripleEquals provides equality constraints for the element types, both of which are Int. By contrast, this trait would not allow a TreeSet[Int] to be compared against a HashSet[java.util.Date], because no equality constraint will exist between the element types Int and Date:

    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)
                                ^
    

  33. final case class Snapshot(name: String, value: Any) extends Product with Serializable

    Permalink

    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

  34. final class SnapshotSeq extends IndexedSeq[Snapshot]

    Permalink

    An IndexedSeq[Snapshot] providing toString and lines methods that can be useful for debug and log messages about program state.

    An IndexedSeq[Snapshot] providing toString and lines 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.

  35. trait Snapshots extends AnyRef

    Permalink

    Trait that provides a snap method that takes one or more arguments and results in a SnapshotSeq, whose toString lists the names and values of each argument.

    Trait that provides a snap method that takes one or more arguments and results in a SnapshotSeq, whose toString 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 a lines 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 a IndexedSeq[Snapshot], you can process it just like any other Seq, 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!
    

  36. trait StringNormalizations extends AnyRef

    Permalink

    Provides methods that produce Uniformity[String] instances for various ways to normalize strings for equality comparisons.

    Provides methods that produce Uniformity[String] instances for various ways to normalize strings for equality comparisons.

  37. trait TimesOnInt extends AnyRef

    Permalink

    Trait providing an implicit conversion that adds a times method to Ints that will repeat a given side-effecting operation multiple times.

    Trait providing an implicit conversion that adds a times method to Ints 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 invoke times on a negative integer will result in an IllegalArgumentException.

  38. trait Tolerance extends AnyRef

    Permalink

    Trait containing an implicit conversion that adds a +- method to Numeric types, which enables spreads to be expressed in terms of a pivot and tolerance.

    Trait containing an implicit conversion that adds a +- method to Numeric types, which enables spreads to be expressed in terms of a pivot and tolerance.

    For example, the TripleEquals trait (and its type-checking siblings TypeCheckedTripleEquals and ConversionCheckedTripleEquals) enable you to write:

    a === (1.0 +- 0.1)
    

  39. trait TolerantNumerics extends AnyRef

    Permalink

    Provides Equality and Equivalence instances for Numeric types that compare for equality with a given tolerance.

    Provides Equality and Equivalence instances for Numeric 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
    

  40. trait TraversableEqualityConstraints extends SeqEqualityConstraints with SetEqualityConstraints with MapEqualityConstraints

    Permalink

    Provides three implicit methods that loosen the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Traversables to one that more closely matches Scala's approach to Traversable equality.

    Provides three implicit methods that loosen the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals for Scala Traversables to one that more closely matches Scala's approach to Traversable equality.

    Scala's approach to Traversable equality is that if the objects being compared are ether both Seqs, both Sets, or both Maps, the elements are compared to determine equality. This means you could compare an immutable Vector and a mutable ListBuffer for equality, for instance, and get true so long as the two Seqs 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 either TypeCheckedTripleEquals or ConversionCheckedTripleEquals, because Vector and ListBuffer 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 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, or scala.collection.GenMap, and that an EqualityConstraint can be found for the element types for Seq and Set, or the key and value types for Maps. In the example above, both the Vector and ListBuffer are subclasses of scala.collection.GenSeq, and the regular TypeCheckedTripleEquals provides equality constraints for the element types, both of which are Int. By contrast, this trait would not allow a Vector[Int] to be compared against a ListBuffer[java.util.Date], because no equality constraint will exist between the element types Int and Date:

    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)
                               ^
    

    This trait simply mixes together SeqEqualityConstraints, SetEqualityConstraints, and MapEqualityConstraints.

  41. trait TripleEquals extends TripleEqualsSupport

    Permalink

    Provides === and !== operators that return Boolean, delegate the equality determination to an Equality type class, and require no relationship between the types of the two values compared.

    Provides === and !== operators that return Boolean, delegate the equality determination to an Equality 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 its equals method: either you can't change the equals method, or the equals method is sensible generally, but you are in a special situation where you need something else. If you also want a compile-time type check, however, you should use one of TripleEquals sibling traits: ConversionCheckedTripleEquals or TypeCheckedTripleEquals.

    This trait will override or hide implicit methods defined by its sibling traits, ConversionCheckedTripleEquals or TypeCheckedTripleEquals, and can therefore be used to temporarily turn of type checking in a limited scope. Here's an example, in which TypeCheckedTripleEquals 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 and Long are not in a subtype/supertype relationship, comparing 1 and 1L in the context of TypeCheckedTripleEquals 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 first cmp method that takes an Int and a Long. TypeCheckedTripleEquals is still enforcing its type constraint, for example, for the s === t expression in the other overloaded cmp method that takes strings.

    Because the methods in TripleEquals (and its siblings)override all the methods defined in supertype TripleEqualsSupport, 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.

  42. trait TripleEqualsSupport extends AnyRef

    Permalink

    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 of a is A and b is B, the following three levels of compile-time checking can be obtained from TripleEqualsSupport subtraits:

    Unchecked - A and B can be any two types. This (weakest) constraint level is available from subtraits TripleEquals.

    Conversion checked - A must be a subtype of B, or vice versa, or an implicit conversion must be available that converts A to B, or vice versa. (Both A and B can be the same type, because a type is considered a subtype of itself.) This (intermediate) constraint level is available from subtraits ConversionCheckedTripleEquals.

    Type checked - A must be a subtype of B, or vice versa. (Both A and B can be the same type, because a type is considered a subtype of itself.) This (strongest) constraint level is available from subtraits TypeCheckedTripleEquals.

    This trait defines all methods that need to be defined implicitly by the six 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 methods convertToEqualizer unconstrainedEquality of TypeCheckedTripleEquals, replacing those with implicit ones defined in TripleEquals, it will also hide the three methods made implicit in TypeCheckedTripleEquals (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.

  43. trait TrySugar extends AnyRef

    Permalink

    Trait providing an implicit class that adds a toOr method to Try, which converts Success to Good, and Failure to Bad, as well as a validating method, which takes one or more validation functions and returns either the same Try if either the Try had already failed or its value passes all the functions, or ValidationFailedException containing an error message describing the first validation that failed.

    Trait providing an implicit class that adds a toOr method to Try, which converts Success to Good, and Failure to Bad, as well as a validating method, which takes one or more validation functions and returns either the same Try if either the Try had already failed or its value passes all the functions, or ValidationFailedException 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 be Pass). If the value does not pass this test, the result is a Fail 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 resulting Try will be the same successful Try with the same value. (A "validation" only transforms the Try if the validation fails, otherwise it is the same Try. The only difference is its value has now been proven valid.) In the following example, a successful Try[Int] with the value 100 passes the validation (which checks whether 100 is evenly divisible by 10), therefore the result of the validating call is the same successful Try 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 a ValidationFailedException 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 failed Try, it just returns the same failed Try:

    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 the ValidationFailedException. 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 the isDivBy3 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!)
    

  44. trait TypeCheckedTripleEquals extends LowPriorityTypeCheckedConstraint

    Permalink

    Provides === and !== operators that return Boolean, delegate the equality determination to an Equality type class, and require the types of the two values compared to be in a subtype/supertype relationship.

    Provides === and !== operators that return Boolean, delegate the equality determination to an Equality 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 determine equality for a type of object differently than its equals method—either you can't change the equals method, or the equals method is sensible generally, but you're in a special situation where you need something else—and/or you want to enforce at compile-time that the types of the compared values are in a subtype/supertype relationship.

    This trait is the strictest of the three triple equals traits, enforcing a stronger constraint than both TripleEquals (the most lenient) and ConversionCheckedTripleEquals (the middle ground). If TripleEquals is mixed in or imported, the === can be used with any two types and still compile. If TypeCheckedTripleEquals is mixed in or imported, however, only types in a subtype or supertype relationship with each other (including when both types are exactly the same) will compile. ConversionCheckedTripleEquals is slightly more accomodating, because in addition to compiling any use of === that will compile under TypeCheckedTripleEquals, it will also compile type types that would be rejected by TypeCheckedTripleEquals, so long as an implicit conversion (in either direction) from one type to another is available.

    For example, under TypeCheckedTripleEquals, the following use of === will not compile, because Int and Long are not in a subtype/supertype relationship. (I.e., Int is not a subtype or supertype of Long):

    scala> import org.scalactic._
    import org.scalactic._
    
    scala> import TypeCheckedTripleEquals._
    import TypeCheckedTripleEquals._
    
    scala> 1 === 1L
    <console>:14: 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.CanEqual[Int,Long]
                  1 === 1L
                    ^
    

    Trait TypeCheckedTripleEquals rejects types Int and Long because they are not directly related via subtyping. However, an implicit widening conversion from Int to Long does exist (imported implicitly from scala.Predef), so ConversionCheckedTripleEquals will allow it:

    scala> import ConversionCheckedTripleEquals._
    import ConversionCheckedTripleEquals._
    
    scala> 1 === 1L
    res1: Boolean = true
    

    The implicit conversion can go in either direction: from the left type to the right type, or vice versa. In the above expression the implicit conversion goes from left to right (the Int on the left to the Long on the right). It also works the other way:

    scala> 1L === 1
    res2: Boolean = true
    

    This trait will override or hide implicit methods defined by its sibling traits, TripleEquals or ConversionCheckedTripleEquals, and can therefore be used to temporarily turn on or off conversion checking in a limited scope. Here's an example, in which TypeCheckedTripleEquals 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 and Long are not in a subtype/supertype relationship, comparing 1 and 1L in the context of TypeCheckedTripleEquals 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.CanEqual[Int,Long]
        if (a === b) 0      // This line won't compile
              ^
    one error found
    

    You can “relax” the type checking (i.e., by additionally allowing implicitly convertible types) locally by importing the members of ConversionCheckedTripleEquals in a limited scope:

    package org.scalactic.examples.conversioncheckedtripleequals
    
    import org.scalactic._
    import TypeCheckedTripleEquals._
    
    object Example {
    
      def cmp(a: Int, b: Long): Int = {
        import ConversionCheckedTripleEquals._
        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. Conversion checking is enabled only inside the first cmp method that takes an Int and a Long. TypeCheckedTripleEquals is still enforcing its type constraint, for example, for the s === t expression in the other overloaded cmp method that takes strings.

    Because the methods in ConversionCheckedTripleEquals (and its siblings) override all the methods defined in supertype TripleEqualsSupport, 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.

    An alternative way to solve an unwanted compiler error caused by an over-zealous type constraint is with a widening type ascription. Here are some examples:

    scala> import org.scalactic._
    import org.scalactic._
    
    scala> import TypeCheckedTripleEquals._
    import TypeCheckedTripleEquals._
    
    scala> 1 === 1L
    <console>:14: error: types Int and Long do not adhere to the equality constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[Int,Long]
                  1 === 1L
                    ^
    

    Although you could solve the above type error with ConversionCheckedTripleEquals, you could also simply widen the type of one side or the other to Any. Because Any is a supertype of everything, the type constraint will be satisfied:

    scala> 1 === (1L: Any)
    res1: Boolean = true
    
    scala> (1: Any) === 1L
    res2: Boolean = true
    

    You could alternatively widen a type to a more specific common supertype than Any. For example, since Int and Long are both subtypes of AnyVal, you could widen either type to AnyVal to satisfy the type checker:

    scala> 1 === (1L: AnyVal)
    res3: Boolean = true
    
    scala> (1: AnyVal) === 1L
    res4: Boolean = true
    

  45. trait Uniformity[A] extends Normalization[A]

    Permalink

    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 Doubles 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 of NormMethods, you can access the behavior by invoking .norm on Doubles.

    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, Uniformitys allow you to the Explicitly DSL with TripleEquals, whereas Normalizations require TypeCheckedTripleEquals or ConversionCheckedTripleEquals. Uniformitys also enable you to use the Explicitly DSL with ScalaTest's should ===, equal, and contain matcher syntax, whereas a plain Normalization can only be used with should ===, and only under either TypeCheckedTripleEquals or ConversionCheckedTripleEquals.

    A

    the type whose uniformity is being defined

  46. sealed trait Validation[+E] extends AnyRef

    Permalink

    Represents the result of a validation, either the object Pass if the validation succeeded, else an instance of Fail 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 of Fail containing an error value describing the validation failure.

    Validations are used to filter Ors in for expressions or filter 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 and isDivBy3 take an Int and return a Validation[ErrorMessage], you can use them in filters in for expressions involving Ors of type Int 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)
    

    Validations can also be used to accumulate error using when, a method that's made available by trait Accumulation on accumualting Ors (Ors whose Bad type is an Every[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,” where Pass is a None that indicates validation success and Fail is a Some whose value describes the validation failure.

    E

    the type of error value describing a validation failure for this Validation

  47. type Constraint[A, B] = CanEqual[A, B]

    Permalink
    Annotations
    @deprecated
    Deprecated

    Constraint has been deprecated and will be removed in a future version of Scalactic. Please use its new name, CanEqual, instead.

Value Members

  1. object Accumulation extends Accumulation

    Permalink

    Companion object to trait Accumulation that allows Accumulation's members to be imported rather than mixed in, and also contains nested traits used by implicit conversions declared in trait Accumulations.

    Companion object to trait Accumulation that allows Accumulation's members to be imported rather than mixed in, and also contains nested traits used by implicit conversions declared in trait Accumulations.

    For more information and examples, see the Accumulating errors with Or section of the main documentation for class Or.

  2. object Bool

    Permalink

    Bool companion object that provides factory methods to create different sub types of Bool

    Bool companion object that provides factory methods to create different sub types of Bool

    Bool is used by code generated from BooleanMacro (which AssertionsMacro and RequirementsMacro uses), it needs to be public so that the generated code can be compiled. It is expected that ScalaTest users would ever need to use Bool directly.

  3. object Catcher

    Permalink

    Companion object for Catcher that provides a factory method for creating Throwable extractors.

    Companion object for Catcher that provides a factory method for creating Throwable extractors.

  4. object Chain

    Permalink

    Companion object for class Chain.

    Companion object for class Chain.

  5. object ConversionCheckedTripleEquals extends ConversionCheckedTripleEquals

    Permalink

    Companion object to trait ConversionCheckedTripleEquals that facilitates the importing of ConversionCheckedTripleEquals members as an alternative to mixing it in.

    Companion object to trait ConversionCheckedTripleEquals that facilitates the importing of ConversionCheckedTripleEquals members as an alternative to mixing it in. One use case is to import ConversionCheckedTripleEquals 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 ConversionCheckedTripleEquals._
    import ConversionCheckedTripleEquals._
    
    scala> 1 === 1L
    res0: Boolean = true
    

  6. object End

    Permalink

    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 of List[Nothing], End is not an instance of Chain[Nothing], because there is no empty Chain:

    scala> Nil.isInstanceOf[List[_]]
    res0: Boolean = true
    
    scala> End.isInstanceOf[Chain[_]]
    res1: Boolean = false
    

  7. object Equality

    Permalink

    Companion object for trait Equality that provides factory methods for producing Equality instances.

    Companion object for trait Equality that provides factory methods for producing Equality instances.

  8. object Equivalence

    Permalink

    Companion object for trait Equivalence that provides a factory method for producing default Equivalence instances.

    Companion object for trait Equivalence that provides a factory method for producing default Equivalence instances.

  9. object Every extends Serializable

    Permalink

    Companion object for abstract class Every.

    Companion object for abstract class Every.

  10. object Explicitly extends Explicitly

    Permalink

    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...
    

  11. object FutureSugar extends FutureSugar

    Permalink

    Companion object for FutureSugar enabling its members to be imported as an alternative to mixing them in.

    Companion object for FutureSugar enabling its members to be imported as an alternative to mixing them in.

  12. object Good extends Serializable

    Permalink

    Companion object for Good that offers, in addition to the standard factory method for Good that takes single “good” type, an parameterless apply used to narrow the Good type when creating a Bad.

    Companion object for Good that offers, in addition to the standard factory method for Good that takes single “good” type, an parameterless apply used to narrow the Good type when creating a Bad.

  13. object MapEqualityConstraints extends MapEqualityConstraints

    Permalink

    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 import MapEqualityConstraints members so you can use them in the Scala interpreter.

  14. object NormMethods extends NormMethods

    Permalink

    Companion object for NormMethods enabling its members to be imported as an alternative to mixing them in.

    Companion object for NormMethods enabling its members to be imported as an alternative to mixing them in.

  15. object OptionSugar extends OptionSugar

    Permalink

    Companion object for OptionSugar enabling its members to be imported as an alternative to mixing them in.

    Companion object for OptionSugar enabling its members to be imported as an alternative to mixing them in.

  16. object Or

    Permalink

    The companion object for Or providing factory methods for creating Ors from Eithers and Trys.

    The companion object for Or providing factory methods for creating Ors from Eithers and Trys.

  17. object Pass extends Validation[Nothing] with Product with Serializable

    Permalink

    Indicates a validation succeeded.

  18. object Prettifier

    Permalink

    Companion object for Prettifier that provides a default Prettifier implementation.

    Companion object for Prettifier that provides a default Prettifier implementation.

  19. object PrettyMethods extends PrettyMethods

    Permalink

    Companion object for trait PrettyMethods enabling its members to be imported as an alternative to mixing them in.

    Companion object for trait PrettyMethods enabling its members to be imported as an alternative to mixing them in.

  20. object Requirements extends Requirements

    Permalink

    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 import Requirements 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...
    

  21. val ScalacticVersion: String

    Permalink

    The version number of Scalactic.

    The version number of Scalactic.

    returns

    the Scalactic version number.

  22. object SeqEqualityConstraints extends SeqEqualityConstraints

    Permalink

    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 import SeqEqualityConstraints members so you can use them in the Scala interpreter.

  23. object SetEqualityConstraints extends SetEqualityConstraints

    Permalink

    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 import SetEqualityConstraints members so you can use them in the Scala interpreter.

  24. object SnapshotSeq

    Permalink
  25. object Snapshots extends Snapshots

    Permalink

    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 import Snapshots 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)
    

  26. object StringNormalizations extends StringNormalizations

    Permalink

    Companion object to trait StringNormalizations that provides an alternative to mixing it in.

    Companion object to trait StringNormalizations that provides an alternative to mixing it in.

  27. object TimesOnInt extends TimesOnInt

    Permalink

    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!
    

  28. object Tolerance extends Tolerance

    Permalink

    Companion object to trait Tolerance that facilitates the importing of Tolerance members as an alternative to mixing it in.

    Companion object to trait Tolerance that facilitates the importing of Tolerance members as an alternative to mixing it in. One use case is to import Tolerance 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)
    

  29. object TolerantNumerics extends TolerantNumerics

    Permalink

    Companion object for TolerantNumerics that enables its members to be imported as an alternative to mixing them in.

    Companion object for TolerantNumerics that enables its members to be imported as an alternative to mixing them in.

  30. object TraversableEqualityConstraints extends TraversableEqualityConstraints

    Permalink

    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 import TraversableEqualityConstraints members so you can use them in the Scala interpreter.

  31. object TripleEquals extends TripleEquals

    Permalink

    Companion object to trait TripleEquals that facilitates the importing of TripleEquals members as an alternative to mixing it in.

    Companion object to trait TripleEquals that facilitates the importing of TripleEquals members as an alternative to mixing it in. One use case is to import TripleEquals 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
    

  32. object TripleEqualsSupport

    Permalink
  33. object TrySugar extends TrySugar

    Permalink

    Companion object for TrySugar enabling its members to be imported as an alternative to mixing them in.

    Companion object for TrySugar enabling its members to be imported as an alternative to mixing them in.

  34. object TypeCheckedTripleEquals extends TypeCheckedTripleEquals

    Permalink

    Companion object to trait TypeCheckedTripleEquals that facilitates the importing of TypeCheckedTripleEquals members as an alternative to mixing it in.

    Companion object to trait TypeCheckedTripleEquals that facilitates the importing of TypeCheckedTripleEquals members as an alternative to mixing it in. One use case is to import TypeCheckedTripleEquals 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
    

  35. package anyvals

    Permalink
  36. def attempt[R](f: ⇒ R): Or[R, Throwable]

    Permalink

    Returns the result of evaluating the given block f, wrapped in a Good, or if an exception is thrown, the Throwable, wrapped in a Bad.

    Returns the result of evaluating the given block f, wrapped in a Good, or if an exception is thrown, the Throwable, wrapped in a Bad.

    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 a Bad

  37. package exceptions

    Permalink

Inherited from AnyRef

Inherited from Any

Ungrouped