...

/

Adding Human-Readable Information

Adding Human-Readable Information

Learn how to print debug information in the test case and generate coverage reports.

Log messages

We’ve met many different ScalaTest tools so far, allowing us to assert a wide range of properties using two testing styles (assertions and matchers). However, we haven’t focused on log messages. Log messages are also very important for testing code, although not as important in applicative code. Our tests do complex operations and assert many properties, so logging information can be useful. Also, we can display information to clarify what’s being done during the test.

We can do that in three ways. The most obvious is using println statements. It works but fits poorly in the test output, as we’ll see shortly. ScalaTest offers two better ways: Informers and GivenWhenThen. In this lesson, we’ll explore these three ways.

The println statements

The most basic way of printing information during the execution of our tests is by using println statements. The following example retrofits the EducativeSpec class, adding println statements.

package mdipirro.educative.io.effectiveunitandintegrationtestinginscala.info

import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.TestSuite
import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.model.v2.{Author, Educative, FreeCourse, Lesson}

class EducativeSpec extends TestSuite:
  private val educative = Educative(Seq(
    FreeCourse("Scala for Beginners", Author("John", "Doe"), Set.empty[Lesson], Set.empty[String]),
    FreeCourse("Scala for Data Analysis", Author("Mary", "Jane"), Set.empty[Lesson], Set("Scala")),
    FreeCourse("Functional Kotlin", Author("Mary", "Jane"), Set.empty[Lesson], Set("kotlin"))
  ))

  "Educative" `should` "delete more than one course" in {
    println("Attempting to delete all courses from the Educative platform")
    val ed = educative without "scala for beginners" without "Scala for Data Analysis" without "functional Kotlin"

    println("Checking the Educative platform is not empty")
    ed.courses shouldBe empty
  }

  it `should` "not delete the course if there's no course with the same title" in {
    println("Attempting to delete a course from the Educative platform")
    val ed = educative without "Scala for Absolute Beginners"

    println("Checking the Educative platform contains some other courses")
    ed.courses should not be empty
    println("Checking the course was not deleted")
    ed.courses should contain theSameElementsAs educative.courses
  }
Retrofitting EducativeSpec to print messages

Note that we added several println statements describing in detail what’s happening in the test. If we run EducativeSpec, we’ll get the following output:

testOnly mdipirro.educative.io.effectiveunitandintegrationtestinginscala.info.EducativeSpec
Attempting to delete all courses from the Educative platform
Checking the Educative platform is not empty
Attempting to delete a course from the Educative platform
Checking the Educative platform contains some other courses
Checking the course was not deleted
[info] EducativeSpec:
[info] Educative
[info] - should delete more than one course (2 milliseconds)
[info] - should not delete the course if there's no course with the same title (1 millisecond)
[info] Run completed in 18 milliseconds.
[info] Total number of tests run: 2
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 1 s, completed Feb 28, 2023, 5:17:57 PM
[IJ]
Debug information printed out with println()

As you can see, the output is a mess. It’s unclear where the messages come from; they all appear before the test description printed by ScalaTest. This is why println shouldn’t be used to display runtime information about our tests.

Let’s assume that we incorrectly asserted ed.courses shouldBe empty in the second test case (line 26). The println statements after the unsatisfied ...