Scalactic quick start

A good way to get started with Scalactic is to try out its type-checking === operator in the Scala interpreter. First start Scala 2.13, including this Scalactic Jar file on the classpath:

$ scala -cp scalatest_2.13-3.2.18.jar
Welcome to Scala version 2.13.12 (...).
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 TraversableEqualityConstraintss 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_2.13" % "3.2.18"

To include Scalactic in your Maven project, use:

<dependency>
<groupId>org.scalactic</groupId>
<artifactId>scalactic_2.13</artifactId>
<version>3.2.18</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.

artima