A textual diff looks like this:
Actual : foosball \0
Diff : ---- ++++
Expected: ballroom\0
- Minus (
-
) denotes a character that needs to be removed fromActual
. - Space (
Actual
andExpected
. - Plus (
+
) denotes a character that needs to be added toActual
. - "Diff" is omitted for lines that are identical.
- When
-
is present,Actual
is padded to line up vertically withExpected
. - When
+
is present,Expected
is padded to line up vertically withActual
. - The padding is not part of
Actual
andExpected
's value, respectively. Read on for concrete examples. - Lines always end with
\n
or\0
. The former denotes a newline. The latter denotes the end of the string. - Lines ending with "\n\n" or "\0\0" represents the literal string "\n" followed by a newline character, or the literal string "\0" followed by the end of string, respectively.
Actual = ""
Expected = "text"
results in the following diff:
Actual : \0
Diff : ++++
Expected: text\0
Meaning, to go from Actual
to Expected
we need to insert "text".
Actual = "text"
Expected = ""
results in the following diff:
Actual : text\0
Diff : ----
Expected: \0
Meaning, to go from Actual
to Expected
we need to delete "text".
Actual = "foo"
Expected = " foo"
results in the following diff:
Actual : foo\0
Diff : +++
Expected: foo\0
Meaning:
- To go from
Actual
toExpected
we need to insert three spaces at the beginning ofActual
. - There is no whitespace in
Expected
in front of "foo". This padding is used to line up the strings vertically.
Actual = "foosball"
Expected = "ballroom"
results in the following diff:
Actual : foosball \0
Diff : ---- ++++
Expected: ballroom\0
Meaning, we need to:
- Delete "foos".
- Keep "ball".
- Insert "room".
- There is no whitespace before "ballroom" or after "foosball". This padding is used to line up the strings vertically.
- If objects are not equal, and their
toString()
values differ, we output their String representations. - If the
toString()
values are equal, but their types differ, we output the string representation ofActual
followed by the two types (i.e.Type.of(Actual)
vsType.of(Expected)
).
For example,
Actual = "null"
Expected = null
results in the following diff:
Actual : null
Type.of(Actual) : string \0
Diff : ------++++
Type.of(Expected): null\0
When comparing multi-line strings:
- We display the diff on a per-line basis.
Actual
andExpected
are followed by a 0-based line number.- Lines that are identical (except the first and last line) are omitted.
For example,
Actual = "first\nsecond\nfoo\nforth\nfifth"
Expected = "first\nsecond\nbar\nforth\nfifth"
results in the following diff:
Actual@0 : first\n
Expected@0: first\n
[...]
Actual@2 : foo \n
Diff : ---+++
Expected@2: bar\n
[...]
Actual@4 : fifth\0
Expected@4: fifth\0
Meaning:
- Lines 1-2 were equal.
- On line 3, we need to delete "foo" and insert "bar".
- Lines 4-5 were equal.
When Actual
or Expected
contain a line that does not have a corresponding line on the other side we omit
the
latter's line number.
Actual = "Foo\nBar"
Expected = "Bar"
results in the following diff:
Actual@0 : Foo\n
Diff : -----
Expected@0: Bar\0
Actual@1 : Bar\0
Expected :
Meaning:
Actual
contained more lines thanExpected
.Expected
did not have a line that corresponded toActual
line 1.- We need to delete line 1 and retain line 2 unchanged.
When comparing lists or arrays:
- We display the diff on a per-element basis.
Actual
andExpected
are followed by the element's index number.- Indexes that are identical (except the first and last line) are omitted.
For example,
Actual =List.
of("1","foo\nbar","3");
Expected =List.
of("1","bar\nfoo","3");
results in the following diff:
Actual[0] : 1\0
Expected[0] : 1\0
Actual[1]@0 : foo\n
Diff : ----- ++
Expected[1]@0: bar\n
Actual[1]@1 : bar \0
Diff : +++
Expected[1]@1: foo\0
Actual[2] : 3\0
Expected[2] : 3\0
Meaning:
- Index 0 was equal.
- On index 1 line 0, we need to delete "foo\n".
- On index 1 line 1, we need to insert "\n" after "bar".
- On index 1 line 1, we need to insert "foo" before the end of string.
- Index 2 was equal.