A good way to get started with Scalactic is to try out its type-checking ===
operator in the Scala interpreter.
First start Scala 3, including this Scalactic Jar file on the classpath:
$ scala -cp scalatest_3-3.2.19.jar Welcome to Scala version 3.3.3 (...). Type in expressions to have them evaluated. Type :help for more information.
Copy and paste this code into the interpreter:
import org.scalactic._ import TypeCheckedTripleEquals._ Some(1) === 2 Some(1) === Some(2) 1 === 1L import ConversionCheckedTripleEquals._ 1 === 1L List(1, 2, 3) === Vector(1, 2, 3) import TraversableEqualityConstraints._ List(1, 2, 3) === Vector(1, 2, 3) List(1, 2, 3) === Set(1, 2, 3)
You should see the output shown below.
By importing the members of org.scalactic.TypeCheckedTripleEquals
, you get a ===
operator that requires
the left- and right-hand types to be a subtype and/or supertype of each other:
scala> import org.scalactic._ import org.scalactic._ scala> import TypeCheckedTripleEquals._ import TypeCheckedTripleEquals._
For example, in the following expression because the left-hand type, Some[Int]
, and the right-hand type, Int
, are not in
a subtype/supertype relationship, you'll get a compiler error:
scala> Some(1) === 2 <console>:14: error: types Some[Int] and Int do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.Constraint[Some[Int],Int] Some(1) === 2 ^
By contrast, in the following expression both the left- and right-hand types are Some[Int]
. Because a type is a subtype and supertype of
itself, the code compiles (and at runtime yields false):
scala> Some(1) === Some(2) res1: Boolean = false
However, because Int
and Long
are not in a subtype/supertype relationship, the following will
generate a compiler error, even though if this were allowed to compile, it would yield true
:
scala> 1 === 1L <console>:14: error: types Int and Long do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.Constraint[Int,Long] 1 === 1L ^
The previous expression would yield true
if allowed to compile because the Int
would be implicitly
widened to Long
via an implicit conversion in scala.Predef
. Importing the members of
ConversionCheckedTripleEquals
will give you a ===
operator that requires that either the left- and right-hand
types to be a subtype or supertype of each other, or an implicit conversion exists in one direction or the other:
scala> import ConversionCheckedTripleEquals._ import ConversionCheckedTripleEquals._
Now the same expression compiles and yields true
:
scala> 1 === 1L res3: Boolean = true
The following expression does not compile, however, because List[Int]
and Vector[Int]
are not a subtype or
supertype of each other, and no implicit conversion exists between them:
scala> List(1, 2, 3) === Vector(1, 2, 3) <console>:17: error: types List[Int] and scala.collection.immutable.Vector[Int] do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.Constraint[ List[Int], scala.collection.immutable.Vector[Int]] List(1, 2, 3) === Vector(1, 2, 3) ^
Importing the members of TraversableEqualityConstraints
s provides additional implicits that enable
equality comparisons of collections that make sense for Scala. For example, any subtype of GenSeq
can be compared with any
other subtype of GenSeqs
:
scala> import TraversableEqualityConstraints._ import TraversableEqualityConstraints._ scala> List(1, 2, 3) === Vector(1, 2, 3) res5: Boolean = true
In addition, subtypes of GenSet
can be compared with each other, as can subtypes of GenMap
. But
an attempt to compare a Seq
with a Set
for equality won't compile, because it would always yield false
:
scala> List(1, 2, 3) === Set(1, 2, 3) <console>:20: error: types List[Int] and scala.collection.immutable.Set[Int] do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.Constraint[ List[Int], scala.collection.immutable.Set[Int]] List(1, 2, 3) === Set(1, 2, 3) ^
In short, Scalactic's type-checking ===
operator provides you with a tunable type check for equality comparisons. For more
information, see the documentation for TypeCheckedTripleEquals
,
ConversionCheckedTripleEquals
, and
TraversableEqualityConstraints
.
Like ScalaTest, Scalactic consists if discrete traits so that you can import only the implicits you need, minimizing potential conflicts and maximizing compiler speed. If you decide you'll want certain features of Scalactic generally, you can mix them into a singleton object and just import its members. Here's an example:
package com.mycompany.myproject import org.scalactic._ object OurScalactic extends TypeCheckedTripleEquals with TraversableEqualityConstraints with Tolerance with Explicitly with TimesOnInt
You can now import your desired Scalactic functionality in one line:
package com.mycompany.myproject import OurScalactic._ // Your code here
To include Scalactic in your sbt project, simply add this line:
libraryDependencies += "org.scalactic" % "scalactic_3" % "3.2.19"
To include Scalactic in your Maven project, use:
<dependency> <groupId>org.scalactic</groupId> <artifactId>scalactic_3</artifactId> <version>3.2.19</version> </dependency>
You are off and running! For more information, consult the user guide.
Scalactic is brought to you by Bill Venners, with
contributions from several other folks. It is sponsored by
Artima, Inc.
ScalaTest is free, open-source software
released under the Apache
2.0 license.
Copyright © 2009-2024 Artima, Inc. All Rights Reserved.