Skip to main content

Tag: Scala

Basic Validation of Collections

Writing tests of collections in ScalaTest is easy. In this post, I’ll cover a few of the very simplest cases. Of course the simplest case is equality, something along the lines of validating two collections are equal. "using equality" must "validate collections" in { val expected: Seq[Int] = Seq(1,2,3) Seq(1,2,3) mustBe expected } But the limitation of using equality if of course besides the same elements being in both the actual and expected, the number and order of the elements must match.

Quick Selenium Demo

Using Selenium in Scala is pretty easy. For this demo, I am using a remote browser which I made available by using the standalone-chrome docker image. To start a container locally, you can simply run the following. docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome I’ll be using Selenium 3.141.59, which is the latest stable version at the time I wrote this post. Version 4.0.0 is in alpha, and I will be sure to be checking that out really soon.

Akka TestKit Quick Introduction

This is a quick introduction to setting up an asynchronous test of akka actor using TestKit and ScalaTest. With the Akka 2.6 release, Akka Typed becomes the default and the actors we’ve been using prior to the 2.6 release are now “Akka Classic.” I’ll be covering Akka Typed in some forthcoming posts. But for now, I’ll use Akka Classic to do a quick example of the basic usage of TestKit. I’m going to demo this using a really simple actor that replies to a Ping message with a Pong.

Reusing Tests with Behavior Functions

ScalaTest provides domain specific language to allow you to write behavior functions to share the same tests amongst different fixture objects. What does this mean? If you are repeating the same tests in multiple specs, you can create some very readable and compact syntax to encapsulate and reuse the tests. Create a function that encapsulates those tests. For most of the TestSuites, you use “behave like” to call that function and execute all the tests.

DRYer Tests

How you write your test code is subtly different than how you write your production code. Your tests should execute quickly, as fast tests provide fast feedback. Yet the performance of your test code isn’t as critical as your production code. Your test code should emphasize readability over uniqueness. It should minimize the amount of mental computation required for a reader to understand a test. So the bar for “DRY” test code is lower than your production code.

Testing the Future

ScalaTest’s async test suites provide an easy and very readable way to write tests for your methods that return a Future. Using Await.ready can really clutter your tests. ScalaTest’s async test suites parallel the standard suites. For example, use AsyncFlatSpec instead of AnyFlatSpec, AsyncFeatureSpec instead of AnyFeatureSpec, etc. I’ll be using AsyncFlatSpec throughout the rest of this post. The first thing to know about the async test suites are that each test must end in either an Assertion or a Future[Assertion].

OptionValues, EitherValues, and TryValues

Another way to keep your ScalaTest specs concise and readable is to use the OptionValues, EitherValues, and TryValues traits when testing Option, Either, or Try types. When testing options that should have a value, we could validate a value is defined and then use get to validate the value. "An option" must "have a value" in { val some: Option[Int] = Some(1) some mustBe defined some.get mustBe 1 } Or by extending the org.

ScalaTest – Looking Inside

ScalaTest’s Inside trait is a great way to keep your tests very expressive, clear, and readable. For the sake of example, let’s say we have the following traits and classes to test. object SalesData { trait Address trait Order case class CustomerAddress(streetAddress: String, city: String, stateProvince: String, postalCode: String, country: String) extends Address case class Customer(firstName: String, lastName: String) case class SalesOrder(customer: Customer, shipToAddress: Address) extends Order } A blunt force approach to writing a test which validates an address is a CustomerAddress, and then validates data in the address using only matchers might look as follows.

Get a Clue

The withClue function in ScalaTest allows you to prepend an additional message to the test failure exception’s message. The message is only output on a test failure. package com.dumpsterfireproject.withClue import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.must.Matchers class ExampleSpec extends AnyFlatSpec with Matchers { "Increasing a person's age" must "be done in single year increments" in { withClue("The age of") { 21 mustBe 20 } } } Produces the following output. The age of 21 was not equal to 20 ScalaTestFailureLocation: com.

ScalaTest – On Test Fixtures

A test fixture is something used to consistently test your code. It’s the test data and/or resources used in your tests. It may be some constant data, or it may be data or resources that require some set up prior to the test and clean up/tear down after the test. Each of your tests needs to run reliably whether it’s run as part of a suite or whether it’s run alone.