Skip to content

Commit

Permalink
feature: made adjustments to the display of diffs and failures
Browse files Browse the repository at this point in the history
  • Loading branch information
symbiont-eric-torreborre committed Aug 16, 2021
1 parent 959ba62 commit fac1ee0
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 28 deletions.
6 changes: 6 additions & 0 deletions common/src/main/scala/org/specs2/text/Indent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ object Indent:
/** @return the spaces indenting the last line of text */
def lastLineIndentation(text: String): String =
text.split("\n", -1).lastOption.map(_.takeWhile(_ == ' ')).getOrElse("")


extension (s: String)
def indentWith(indent: String): String =
val lines = s.split("\n", -1)
(lines.toList.map(indent + _)).mkString("\n")
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ presentation

def d3 =
s2"""e1 ${"abcdeabcdeabcdeabcdeabcde" must ===("adcdeadcdeadcdeadcdeadcde")}""" `contains`
"""|[error] Actual: a[b]cdea[b]cdea[b]cdea[b]cdea[b]cde
|[error] Expected: a[d]cdea[d]cdea[d]cdea[d]cdea[d]cde"""
"""|[error] Actual: a[b]cdea[b]cdea[b]cdea[b]cdea[b]cde
|[error] Expected: a[d]cdea[d]cdea[d]cdea[d]cdea[d]cde"""

case class A(s: String) { override def equals(a: Any) = false }

Expand Down Expand Up @@ -348,6 +348,7 @@ table ${"a" | "b" |>
|[info]__+_example_1
|[info]__x_example 2
|[error]__ko_(Result.scala:365)
|[error]
|[info]
|[info]_Total_for_specification_TextPrinterSpec""".stripMargin

Expand Down
25 changes: 12 additions & 13 deletions core/src/main/scala/org/specs2/reporter/TextPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ case class TextPrinter(env: Env) extends Printer {
else Nil

case Fragment(Code(text), e, l) =>
if args.canShow("-") then List(indentText(text, indentation, indentationSize(args)).info)
if args.canShow("-") then List(indentText(text, indentation, args).info)
else Nil

case Fragment(d, e, l) =>
if args.canShow("-") then List(indentText(d.show, indentation, indentationSize(args)).info)
if args.canShow("-") then List(indentText(d.show, indentation, args).info)
else Nil
}
}
Expand All @@ -120,7 +120,7 @@ case class TextPrinter(env: Env) extends Printer {
if args.canShow(result.status) then {
val text = description.show
val show =
indentText(showTime(statusAndDescription(text, result)(args), timer, args), indentation, indentationSize(args))
indentText(showTime(statusAndDescription(text, result)(args), timer, args), indentation, args)

def printResult(desc: String, r: Result): List[LogLine] =
r match {
Expand All @@ -141,7 +141,7 @@ case class TextPrinter(env: Env) extends Printer {
case d: DataTable =>
// display the full table if it is an auto-example
if Description.isCode(description) then
printResult(indentText(r.message, indentation, indentationSize(args)), r.setMessage(""))
printResult(indentText(r.message, indentation, args), r.setMessage(""))
else printResult(show, r)

case other => printResult(show, result)
Expand All @@ -161,7 +161,8 @@ case class TextPrinter(env: Env) extends Printer {
List((show + "\n").failure) ++
printMessage(show, failure, fragmentLocation, FailureLine.apply, args) ++
printStacktrace(failure.stackTrace, print = args.failtrace, FailureLine.apply, args) ++
printFailureDetails(args)(failure.details)
printFailureDetails(args)(failure.details) ++
List("\n".failure)

def printSuccess(show: String, success: execute.Success, args: Arguments): List[LogLine] = {
val expected = if success.exp.nonEmpty then "\n" + success.exp else ""
Expand Down Expand Up @@ -238,19 +239,17 @@ case class TextPrinter(env: Env) extends Printer {
val (actualDiff, expectedDiff) = args.diffs.showDiffs(actual, expected)
val shortDiff =
if actualDiff != expectedDiff then
List(s"Actual: $actualDiff\n".failure, s"Expected: $expectedDiff\n".failure)
else List()
List("\n", s" Actual: $actualDiff\n", s" Expected: $expectedDiff").map(_.failure)
else Nil

val fullDiff =
(if args.diffs.showFull then
List(s"Actual (full): $actual\n".failure, s"Expected (full): $expected\n".failure)
List("\n", s" Actual (full): $actual\n", s" Expected (full): $expected").map(_.failure)
else Nil)

List("\n".failure) ++
shortDiff ++
List("\n".failure) ++
fullDiff ++
List("\n".info)
fullDiff

case _ => Nil
}
Expand All @@ -276,9 +275,9 @@ case class TextPrinter(env: Env) extends Printer {
s"(${fragmentLocation.fileName}:${fragmentLocation.lineNumber})"
else s"($resultLocation)"

def indentText(text: String, indentation: Int, indentationSize: Int) =
def indentText(text: String, indentation: Int, args: Arguments) =
if text.isEmpty then text
else text.split("\n").toIndexedSeq.map((" " * (indentation * indentationSize)) + _).mkString("\n")
else text.split("\n").toIndexedSeq.map((" " * (indentation * indentationSize(args))) + _).mkString("\n")
}

object TextPrinter {
Expand Down
6 changes: 3 additions & 3 deletions matcher/src/main/scala/org/specs2/matcher/TypedEqual.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ trait TypedEqual:

/** A value can be tested against another with the === operator. It is equivalent to writing a must ==(b)
*/
extension [T](t: =>T)(using not: NotGiven[NoTypedEqual])
extension [T: Diffable](t: =>T)(using not: NotGiven[NoTypedEqual])
/** equality matcher on Expectables */
def ===(other: =>T): Result =
createExpectable(t).applyMatcher[T](new BeEqualTo(other))
createExpectable(t).applyMatcher[T](new EqualityMatcher(other))

/** ! equality matcher on Expectables */
def !==(other: =>T): Result =
createExpectable(t).applyMatcher[T](new BeEqualTo(other).not)
createExpectable(t).applyMatcher[T](new EqualityMatcher(other).not)

object TypedEqual extends TypedEqual with ExpectationsCreation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import java.io.{PrintWriter, StringWriter}
import org.specs2.matcher.describe.ComparisonResultOps.*
import org.specs2.text.Quote.*
import org.specs2.text.NotNullStrings.*
import org.specs2.text.Indent.*

/** Render the result of a comparison for different types: primitives, throwables, collections,...
*
Expand Down Expand Up @@ -166,8 +167,10 @@ case class OtherIdentical(actual: Any, expected: Any) extends IdenticalCompariso

case class OtherDifferent(actual: Any, expected: Any) extends DifferentComparisonResult:
def render: String =
s"${actual.renderAny(showAll = comparingPrimitiveWithObject(actual, expected))} != " +
s"${expected.renderAny(showAll = comparingPrimitiveWithObject(actual, expected))}"
val actualRendered = s"${actual.renderAny(showAll = comparingPrimitiveWithObject(actual, expected))}"
val expectedRendered = s"${expected.renderAny(showAll = comparingPrimitiveWithObject(actual, expected))}"
if actualRendered.contains("\n") || actualRendered.contains("\n") then s"${actualRendered}\n !=\n$expectedRendered"
else s"$actualRendered != $expectedRendered"

private[specs2] def comparingPrimitiveWithObject(a: Any, e: Any): Boolean =
val (classA, classB) = classOf(a) -> classOf(e)
Expand Down Expand Up @@ -277,13 +280,21 @@ object ComparisonResultOps:
if s.isEmpty then None else Some(s)

class ProductComparisonResult(typeName: String, results: List[(String, ComparisonResult)]) extends ComparisonResult:
private val typeNameIndent = " " * (typeName.length + 1)

def identical: Boolean =
results.forall(_._2.identical)

override def render(indent: String): String =
typeName+"("+results.map { case (fieldName, fieldResult) =>
fieldName+": "+fieldResult.render }.
mkString("\n"+indent)+")"

typeName + "(" + results
.map { case (fieldName, fieldResult) =>
val fieldResultRendered = fieldResult.render
val indented =
if fieldResultRendered.contains("\n") then "\n" + fieldResultRendered.indentWith(indent + " " * 2)
else " "+fieldResultRendered
s"$fieldName:$indented"
}
.mkString("\n" + indent) + ")"

def render: String =
render(" " * (typeName.length + 1))
render(typeNameIndent)
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ case class LinesComparisonResult[T: Diffable](actual: List[T], expected: List[T]
case Del(line) => List(color("- " + line, red))
case Subst(line1, line2) => List(color("- " + line1, red), color("+ " + line2, green))
}
.mkString("\n", "\n", "\n")
.mkString("", "\n", "")
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ class BeEqualToMatcherSpec extends Spec with ResultMatchers with ShouldMatchers
${Seq(1, 2) must be_==(Seq(1, 2))}
${(Seq(1, 2) must be_==(Seq(2, 3))).normalized ===
"""|List(1, 2) != List(2, 3)
|
|- 1
|+ 2
|- 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ class ComparisonResultSpec extends Spec {
def th3 = {
removeColors(ThrowableDifferentStackTrace(LinesComparisonResult(List("m1"), List("m2"))).render).trim must ===(
"""|the stacktrace is incorrect
|
|- m1
|+ m2""".stripMargin
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.specs2.matcher.describe

import org.specs2.Spec
import org.specs2.text.AnsiColors.*
import org.specs2.text.Whitespace.*

import scala.util.Failure

Expand Down Expand Up @@ -36,6 +38,19 @@ class DiffablePlusSpec extends Spec {
"""|Foo(x: 'a' != 'b'
| y: 1 != 2)""".stripMargin
}
additional test case ${
val actual = Book("Programming in Scala", Seq("Odersky", "me", "Venners"), 2008)
val expected = Book("Programming in Scala", Seq("Odersky", "Spoon", "Venners"), 2009)
Diffable.diff(actual, expected).render.removeColors.showSpaces ===
"""|Book(title: 'Programming in Scala'
| authors:
| Odersky
| - me
| + Spoon
| Venners
| pubYear: 2008 != 2009)""".stripMargin.showSpaces

}



Expand All @@ -50,3 +65,5 @@ case class EmptyCaseClass()

case class Foo(x: String, y: Int)
case class Bar(foo: Foo)

case class Book(title: String, authors: Seq[String], pubYear: Int)

0 comments on commit fac1ee0

Please sign in to comment.