Collection-Based Matchers
Learn about DSL in ScalaTest by writing assertions on collections.
We'll cover the following...
Collections
In this lesson, we’ll work with collections and collection-based assertions. We’ll start by extending our code a bit and implementing functionality to add and delete a course. When adding a course, we want its title to be unique. Similarly, we want to avoid duplicates when adding lessons and tags to a course. The latter can be achieved by replacing Seq
with Set
. The former is a bit trickier.
sealed trait Course:val title: Stringval author: Authorval lessons: Set[Lesson]val tags: Set[String]case class FreeCourse(override val title: String,override val author: Author,override val lessons: Set[Lesson],override val tags: Set[String]) extends Coursecase class PaidCourse(override val title: String,override val author: Author,override val lessons: Set[Lesson],override val tags: Set[String]) extends Courseclass Educative(val courses: Seq[Course]):def courseByName(courseTitle: String): Option[Course] = courses find (_.title == courseTitle)infix def `with`(newCourse: Course): Either[String, Educative] =courses find (_.title.equalsIgnoreCase(newCourse.title)) matchcase Some(_) => Left(s"A course with title ${newCourse.title} already exists")case None => Right(Educative(courses :+ newCourse))infix def without(courseTitle: String): Educative = Educative(courses = courses filterNot (_.title.equalsIgnoreCase(courseTitle)))def filterByTag(tag: String): Seq[Course] = courses filter (_.tags.exists(_.equalsIgnoreCase(tag)))
The Educative#with
tag returns an Either[String, Educative]
, where the left projection (String
) represents an error message and the right one (Educative
) contains a new instance of the Educative platform with the new course if there’s no existing course with the same title. The implementation of Educative#without
simply relies on Seq#filter
to filter out a course with the same title. Note that Educative#without
returns a copy of itself even if the course doesn’t exist.
We could have implemented it differently by returning this
; however, that’s an implementation detail, and we won’t focus on it in this lesson. Both with
and without
are declared infix
, so we can invoke them without .
and ()
. In the snippet above, we also added a method to filter the courses by tag.
Plain assertions on collections
Before looking at some collection matchers, let’s see how we can use the plain old assert
function to verify that our implementations of ...