Skip to main content

Introduction

Difflicious is a library that produces nice readable diffs in your tests.

  • Readable and Actionable diffs
  • Customizability: supporting all kinds of tweaks you'd want to do such as ignoring fields or compare lists independent of element order.

Here's a motivational example!

import difflicious.*
import difflicious.implicits.*

sealed trait HousePet {
def name: String
}
object HousePet {
case class Dog(name: String, age: Int) extends HousePet
case class Cat(name: String, livesLeft: Int) extends HousePet

implicit val differ: Differ[HousePet] = Differ.derived
}

import HousePet.{Cat, Dog}

val petsDiffer = Differ[List[HousePet]]
.pairBy(_.name) // Match pets in the list by name for comparison
.ignoreAt(_.each.subType[Cat].livesLeft) // Don't worry about livesLeft for cats when comparing

petsDiffer.diff(
obtained = List(
Dog("Andy", 12),
Cat("Dr.Evil", 8),
Dog("Lucky", 5),
),
expected = List(
Dog("Lucky", 6),
Cat("Dr.Evil", 9),
Cat("Andy", 12),
)
)

And this is the diffs you will see:

List( Dog != Cat === Obtained === Dog( name: "Andy", age: 12, ) === Expected === Cat( name: "Andy", livesLeft: [IGNORED], ), Cat( name: "Dr.Evil", livesLeft: [IGNORED], ), Dog( name: "Lucky", age: 5 -> 6, ), )

In the example, we can see that:

  • Difflicious spots that Andy is not a Dog but instead a Cat!!
  • The cat Dr.Evil is considered to be the same on both sides, because we decided to not check how many lives the cats have left.
  • A diff is produced showing us that Lucky's age is wrong.