1. Introduction
ScalaTest is one of the most popular testing libraries in Scala. ScalaTest matchers provide many easy-to-use and powerful ways to verify the results. In this tutorial, we’ll look at different ways to compare collection contents using ScalaTest.
2. Set-Up
Let’s first add the ScalaTest dependency to our build.sbt file:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15" % Test
3. Comparing Collection Contents
Let’s start by looking at different ways to compare the collection contents using ScalaTest. These approaches are similar for different types like List, Seq, Set, etc. For this tutorial, we’ll be using the AnyFlatSpec suite along with Should matchers.
3.1. Check for Exactness
To check if two collections contain exact elements in the same order, we can use the shouldBe method:
val intList = List(1, 2, 3, 4)
val expected = List(1, 2, 3, 4)
intList shouldBe expected
If the order of elements is not the same, the test will fail. This will work the same for a list of case class objects as well:
case class Country(name:String, code:String)
val countries = List(Country("Germany", "DE"), Country("India", "IN"))
val expected = List(Country("Germany", "DE"), Country("India", "IN"))
countries shouldBe expected
3.2. Check for the Same Elements
We can check if two collections contain the same elements in any order using the method theSameElementsAs:
val cities = List("Barcelona", "Hamburg")
val cities2 = List("Barcelona", "Hamburg")
Random.shuffle(cities) should contain theSameElementsAs (cities2)
However, it will fail if there are more elements in one of the collections, even if it is a duplicate element. In such cases, we’ll use the only method to ignore duplicate elements while comparing:
val cities = List("Barcelona", "Hamburg")
val cities2 = cities ++ cities
cities should contain only (cities2: _*)
The only() method expects the parameters as a variable argument. Therefore, we’re converting the list cities2 using :_*, also known as the splat operator.
3.3. Check for the Elements in the Same Order
The theSameElementsAs method will not consider the order of elements. If the ordering of the elements in the collection is important, we can use theSameElementsInOrderAs instead:
val cities = List("Barcelona", "Hamburg")
val cities2 = List("Barcelona", "Hamburg")
cities should contain theSameElementsInOrderAs (cities2)
3.4. At Least One Element Overlap
There are scenarios where we need to check if there is at least one element overlap between two collections. We can use the atLeastOneElementOf method to handle such scenarios:
val capitalCities = List("Berlin", "Paris", "Brussels", "Bern")
val cities = List("Zurich", "Geneva", "Munich", "Paris")
capitalCities should contain atLeastOneElementOf (cities)
3.5. At Most One Element Overlap
We can also check if two collections have an overlap of a maximum of one element using the atMostOneElementOf method:
val capitalCities = List("Berlin", "Paris", "Brussels", "Bern")
val cities = List("Zurich", "Geneva", "Munich", "Paris")
capitalCities should contain atMostOneElementOf (cities)
3.6. No Element Overlap
To check if there is no overlap between two collections, we can make use of the method noElementsOf and noneOf:
val cities = List("Barcelona", "Hamburg", "Amsterdam")
val scandinavian = List("Oslo", "Stockholm", "Copenhagen")
cities should contain noneOf ("Oslo", "Stockholm", "Copenhagen")
cities should contain noElementsOf (scandinavian)
The method noElementsOf expects a collection as a parameter, whereas noneOf expects a varargs parameter.
3.7. Exactly One Element Overlap
To check for exactly one element overlap we can use the oneOf method:
val asianCountries = List("india", "china", "russia")
asianCountries should contain oneOf ("germany", "italy", "russia")
4. Map Key and Value Verification
Additionally, ScalaTest provides matchers for checking keys and values in Map types.
4.1. Check if Key Exists in a Map
We can check if a Map contains a particular key:
val capitalMap = Map("India" -> "New Delhi", "Germany" -> "Berlin", "France" -> "Paris")
capitalMap should contain key "India"
Additionally, we can combine the keyword not to check for non-availability of a key as:
capitalMap should not contain key ("USA")
4.2. Check if Value Exists in a Map
To check if the Map contains a particular value, we can use:
val capitalMap = Map("India" -> "New Delhi", "Germany" -> "Berlin", "France" -> "Paris")
capitalMap should contain value "Berlin"
Similarly, we can add the keyword not to verify if a value is missing in the Map:
capitalMap should not contain value ("Munich")
5. Conclusion
In this tutorial, we looked at some different ways in which we can verify collection elements using ScalaTest. As always, the code samples used in this tutorial are available over on GitHub.