Scalactic User Guide

Custom equality

Default equality

Constrained equality



The Explicitly DSL

Or and Every





The Requirements 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 NullPointerException 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) java.lang.NullPointerException: 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.

Next, learn about Snapshots.

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.