org.scalactic.Explicitly.scala Maven / Gradle / Ivy
/*
* Copyright 2001-2013 Artima, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.scalactic
/**
* 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
*
*
* @author Bill Venners
*/
trait Explicitly {
/**
* This class is part of the Scalactic “explicitly DSL”. Please
* see the documentation for Explicitly
for an overview of
* the explicitly DSL.
*
* @author Bill Venners
*/
class DecidedWord {
/**
* This method enables the following syntax:
*
*
* result should equal ("hello") (decided by defaultEquality)
* ^
*
*/
infix
def by[A](equality: Equality[A]): DecidedByEquality[A] = new DecidedByEquality[A](equality)
}
/**
* This field enables syntax such as the following:
*
*
* result should equal ("hello") (decided by defaultEquality)
* ^
*
*/
val decided = new DecidedWord
/**
* This class is part of the Scalactic “explicitly DSL”. Please
* see the documentation for Explicitly
for an overview of
* the explicitly DSL.
*
* @author Bill Venners
*/
class DeterminedWord {
/**
* This method enables the following syntax, given an Equivalence[String]
* named myStringEquivalence
:
*
*
* result should equal ("hello") (determined by myStringEquivalence)
* ^
*
*
*/
infix
def by[A](equivalence: Equivalence[A]): DeterminedByEquivalence[A] = new DeterminedByEquivalence[A](equivalence)
}
/**
* This field enables syntax such as the following, given an
* Equivalence[String]
named myStringEquivalence
:
*
*
* result should equal ("hello") (determined by myStringEquivalence)
* ^
*
*/
val determined = new DeterminedWord
/**
* This class is part of the Scalactic “explicitly DSL”. Please
* see the documentation for Explicitly
for an overview of
* the explicitly DSL.
*
*
* Instances of this class are returned via the decided
by
<an Equality>
* syntax, and enables afterBeing
to be invoked on it. Here's an example, given an
* Equality[String]
named myStringEquality
:
*
*
*
* result should equal ("hello") (decided by myStringEquality afterBeing lowerCased)
*
*
* @author Bill Venners
*/
class DecidedByEquality[A](equality: Equality[A]) extends Equality[A] {
/**
* Indicates whether the objects passed as a
and b
are equal by
* delegating to the areEqual
method of the Equality[T]
passed to
* this class's constructor.
*
* @param a a left-hand-side object being compared with another (right-hand-side one) for equality (e.g., a == b
)
* @param b a right-hand-side object being compared with another (left-hand-side one) for equality (e.g., a == b
)
* @return true if the passed objects are "equal," as defined by this Equality
instance
*/
def areEqual(a: A, b: Any): Boolean = equality.areEqual(a, b)
/**
* This method enables syntax such as the following, given an
* Equality[String]
named myStringEquality
:
*
*
* result should equal ("hello") (decided by myStringEquality afterBeing lowerCased)
* ^
*
*
* @param uniformity A Uniformity
with which to normalize objects of type A
* before comparing them for equality using the Equality[A]
passed to this object's
* constructor.
*/
infix
def afterBeing(uniformity: Uniformity[A]): NormalizingEquality[A] =
new ComposedNormalizingEquality[A](equality, uniformity)
}
/**
* This class is part of the Scalactic “explicitly DSL”. Please
* see the documentation for Explicitly
for an overview of
* the explicitly DSL.
*
*
* Instances of this class are returned via the decided
by
<an Equivalence>
* syntax, and enables afterBeing
to be invoked on it. Here's an example, given an
* Equivalence[String]
named myStringEquivalence
:
*
*
*
* result should equal ("hello") (determined by myStringEquivalence afterBeing lowerCased)
*
*
* @author Bill Venners
*/
class DeterminedByEquivalence[T](equivalence: Equivalence[T]) extends Equivalence[T] {
/**
* Indicates whether the objects passed as a
and b
are equal by
* delegating to the areEquivalent
method of the Equivalence[T]
passed to
* this class's constructor.
*
* @param a a left-hand-side object being compared with another (right-hand-side one) for equality (e.g., a == b
)
* @param b a right-hand-side object being compared with another (left-hand-side one) for equality (e.g., a == b
)
* @return true if the passed objects are "equal," as defined by this Equality
instance
*/
def areEquivalent(a: T, b: T): Boolean = equivalence.areEquivalent(a, b)
/**
* This method enables syntax such as the following, given an
* Equivalence[String]
named myStringEquivalence
:
*
*
* result should equal ("hello") (determined by myStringEquivalence afterBeing lowerCased)
* ^
*
*
* @param normalization A Normalization
with which to normalize objects of type T
* before comparing them for equality using the Equivalence[T]
passed to this object's
* constructor.
*/
infix
def afterBeing(normalization: Normalization[T]): NormalizingEquivalence[T] =
new ComposedNormalizingEquivalence[T](equivalence, normalization)
}
/**
* This class is part of the Scalactic “explicitly DSL”. Please
* see the documentation for Explicitly
for an overview of
* the explicitly DSL.
*
* @author Bill Venners
*/
class TheAfterWord {
/**
* This method enables syntax such as the following:
*
*
* result should equal ("hello") (after being lowerCased)
* ^
*
*
* @param uniformity a Uniformity
with which to normalize an object of type N
* before comparing it for equality with another N
using the implicitly
* passed Equality[N]
.
*/
infix
def being[N](uniformity: Uniformity[N])(implicit equality: Equality[N]): NormalizingEquality[N] =
new ComposedNormalizingEquality[N](equality, uniformity)
/**
* This method enables syntax such as the following, given a Normalization[String]
named
* capitalized
(and assuming the members of
* TypeCheckedTripleEquals
or
* ConversionCheckedTripleEquals
are in scope:
*
*
* result should === ("hello") (after being capitalized)
* ^
*
*
* @param normalization a Normalization
with which to normalize an object of type N
* before comparing it for equality with another N
using the implicitly
* passed Equivalence[N]
.
*/
infix
def being[N](normalization: Normalization[N])(implicit equivalence: Equivalence[N]): NormalizingEquivalence[N] =
new ComposedNormalizingEquivalence[N](equivalence, normalization)
}
/**
* This field enables syntax such as the following:
*
*
* result should equal ("hello") (after being lowerCased)
* ^
*
*/
val after = new TheAfterWord
}
/**
* Companion object for Explicitly
, which enables the Scalactic explicitly DSL to
* be imported rather than mixed in, like this:
*
*
* import org.scalactic._
* import Explicitly._
*
* // Use the explicitly DSL...
*
*/
object Explicitly extends Explicitly