msg247883 - (view) |
Author: Chris Jerdonek (chris.jerdonek) *  |
Date: 2015-08-02 16:49 |
When newlines are present, the error message displayed by unittest's self.assertEqual() to show where strings differ can be nonsensical. For example, the caret symbol can show up in a strange location.
The first example below shows a case where things work correctly. The second shows a newline case with the confusing display.
======================================================================
FAIL: test1
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/chris/***/test.py", line 66, in test1
self.assertEqual("abc", "abd")
AssertionError: 'abc' != 'abd'
- abc
? ^
+ abd
? ^
======================================================================
FAIL: test2
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/chris/***/test.py", line 69, in test2
self.assertEqual("\nabcx", "\nabdx")
AssertionError: '\nabcx' != '\nabdx'
- abcx? ^
+ abdx? ^
|
msg247947 - (view) |
Author: R. David Murray (r.david.murray) *  |
Date: 2015-08-03 19:44 |
In this particular case the problem is the lack of a trailing newline on the input string. It might be possible to improve the extended display algorithm by making sure there is a new line before the carrot line, but care must be taken to account for the cases where one string ends with newline and the other doesn't. I think this problem only applies to strings that have no trailing newline.
|
msg258132 - (view) |
Author: anchal agarwal (pynewbie) |
Date: 2016-01-13 06:04 |
There is another case where the error message displayed by self.assertEqual() is weird.
======================================================================
FAIL: test_newline_1 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 9, in test_newline_1
self.assertEqual("\n abc", "\n abd")
AssertionError: '\n abc' != '\n abd'
- abc? ^
+ abd? ^
======================================================================
FAIL: test_newline_2 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 12, in test_newline_2
self.assertEqual("\nabc", "\nabd")
AssertionError: '\nabc' != '\nabd'
- abc+ abd
----------------------------------------------------------------------
There is a difference in between "\nabc" and "\n abc" and hence the difference between output
|
msg258466 - (view) |
Author: Elena Oat (Elena.Oat) * |
Date: 2016-01-17 13:42 |
The issue is not related only to the caret. In fact, as seen in the below output, the issue occurs anytime there's a newline character in the beginning or middle of the string to be compared.
In short, if a newline is present in the string and it's in the beginning or middle, a newline character should be put at the end of the string, too. This will make the output look sensible. If, however, the newline is not present at the end, the output is not really readable (the new line is missing).
As we (me and Manvi B.) understand, the caret appears in the output only when the strings are similar enough, i.e. their similarity ratio is high enough. Otherwise, compare function doesn't show the carets in places of difference. This can also be seen in test case test_trailingnewline_2.
This issue occurs, probably, due to using splitlines method.
FFFFFFFF
======================================================================
FAIL: test_notrailingnewline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 8, in test_notrailingnewline_0
self.assertEqual("abcDefehiJkl", "abcdefGhijkl")
AssertionError: 'abcDefehiJkl' != 'abcdefGhijkl'
- abcDefehiJkl
? ^ ^ ^
+ abcdefGhijkl
? ^ ^ ^
======================================================================
FAIL: test_notrailingnewline_1 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 14, in test_notrailingnewline_1
self.assertEqual("a\nbcdf", "a\nbddf")
AssertionError: 'a\nbcdf' != 'a\nbddf'
a
- bcdf? ^
+ bddf? ^
======================================================================
FAIL: test_notrailingnewline_2 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 18, in test_notrailingnewline_2
self.assertEqual("a\nbcdf", "a\nbddg")
AssertionError: 'a\nbcdf' != 'a\nbddg'
a
- bcdf+ bddg
======================================================================
FAIL: test_starting_and_ending_newline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 12, in test_starting_and_ending_newline_0
self.assertEqual("\nabcDefehiJkl\n", "\nabcdefGhijkl\n")
AssertionError: '\nabcDefehiJkl\n' != '\nabcdefGhijkl\n'
- abcDefehiJkl
? ^ ^ ^
+ abcdefGhijkl
? ^ ^ ^
======================================================================
FAIL: test_startingnewline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 10, in test_startingnewline_0
self.assertEqual("\nabcDefehiJkl", "\nabcdefGhijkl")
AssertionError: '\nabcDefehiJkl' != '\nabcdefGhijkl'
- abcDefehiJkl? ^ ^ ^
+ abcdefGhijkl? ^ ^ ^
======================================================================
FAIL: test_trailingnewline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 6, in test_trailingnewline_0
self.assertEqual("abcDefehiJkl\n", "abcdefGhijkl\n")
AssertionError: 'abcDefehiJkl\n' != 'abcdefGhijkl\n'
- abcDefehiJkl
? ^ ^ ^
+ abcdefGhijkl
? ^ ^ ^
======================================================================
FAIL: test_trailingnewline_1 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 16, in test_trailingnewline_1
self.assertEqual("a\nbcdf\n", "a\nbddf\n")
AssertionError: 'a\nbcdf\n' != 'a\nbddf\n'
a
- bcdf
? ^
+ bddf
? ^
======================================================================
FAIL: test_trailingnewline_2 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 20, in test_trailingnewline_2
self.assertEqual("a\nbcdf\n", "a\nbddg\n")
AssertionError: 'a\nbcdf\n' != 'a\nbddg\n'
a
- bcdf
+ bddg
----------------------------------------------------------------------
Ran 8 tests in 0.007s
FAILED (failures=8)
|
msg259375 - (view) |
Author: Anish Shah (anish.shah) * |
Date: 2016-02-02 10:39 |
I would like to work on this..
|
msg259403 - (view) |
Author: Anish Shah (anish.shah) * |
Date: 2016-02-02 16:59 |
The problem is in `difflib.ndiff` function. When the string does not have a trailing newline, we get an unreadable output.
After applying my patch, the following is the output of test2.py (submitted by Elena.Oat).
FFFFFFFF
======================================================================
FAIL: test_notrailingnewline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 8, in test_notrailingnewline_0
self.assertEqual("abcDefehiJkl", "abcdefGhijkl")
AssertionError: 'abcDefehiJkl' != 'abcdefGhijkl'
- abcDefehiJkl
? ^ ^ ^
+ abcdefGhijkl
? ^ ^ ^
======================================================================
FAIL: test_notrailingnewline_1 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 14, in test_notrailingnewline_1
self.assertEqual("a\nbcdf", "a\nbddf")
AssertionError: 'a\nbcdf' != 'a\nbddf'
a
- bcdf
? ^
+ bddf
? ^
======================================================================
FAIL: test_notrailingnewline_2 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 18, in test_notrailingnewline_2
self.assertEqual("a\nbcdf", "a\nbddg")
AssertionError: 'a\nbcdf' != 'a\nbddg'
a
- bcdf
+ bddg
======================================================================
FAIL: test_starting_and_ending_newline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 12, in test_starting_and_ending_newline_0
self.assertEqual("\nabcDefehiJkl\n", "\nabcdefGhijkl\n")
AssertionError: '\nabcDefehiJkl\n' != '\nabcdefGhijkl\n'
- abcDefehiJkl
? ^ ^ ^
+ abcdefGhijkl
? ^ ^ ^
======================================================================
FAIL: test_startingnewline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 10, in test_startingnewline_0
self.assertEqual("\nabcDefehiJkl", "\nabcdefGhijkl")
AssertionError: '\nabcDefehiJkl' != '\nabcdefGhijkl'
- abcDefehiJkl
? ^ ^ ^
+ abcdefGhijkl
? ^ ^ ^
======================================================================
FAIL: test_trailingnewline_0 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 6, in test_trailingnewline_0
self.assertEqual("abcDefehiJkl\n", "abcdefGhijkl\n")
AssertionError: 'abcDefehiJkl\n' != 'abcdefGhijkl\n'
- abcDefehiJkl
? ^ ^ ^
+ abcdefGhijkl
? ^ ^ ^
======================================================================
FAIL: test_trailingnewline_1 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 16, in test_trailingnewline_1
self.assertEqual("a\nbcdf\n", "a\nbddf\n")
AssertionError: 'a\nbcdf\n' != 'a\nbddf\n'
a
- bcdf
? ^
+ bddf
? ^
======================================================================
FAIL: test_trailingnewline_2 (__main__.AssertEqualTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 20, in test_trailingnewline_2
self.assertEqual("a\nbcdf\n", "a\nbddg\n")
AssertionError: 'a\nbcdf\n' != 'a\nbddg\n'
a
- bcdf
+ bddg
----------------------------------------------------------------------
Ran 8 tests in 0.004s
FAILED (failures=8)
|
msg261713 - (view) |
Author: Robert Collins (rbcollins) *  |
Date: 2016-03-14 02:28 |
Thanks for the patch; reviewed in rietvald.
|
msg275942 - (view) |
Author: Adrian Chan (adchanw) |
Date: 2016-09-12 03:42 |
Is this still being worked on? I have a potential fix for this.
|
msg276633 - (view) |
Author: Adrian Chan (adchanw) |
Date: 2016-09-15 22:29 |
I've attached a potential fix for this issue.
While trying to fix this, I noticed that I coudn't assume that I just need to ensure that each line has a newline. If I always ensure each line in diffline has a newline, then the fourth test in testAssertMultilineEqual (in Lib/unittest/test/test_assertions.py) fails because standardMsg in assertMultiLineEqual in Lib/unittest/case.py is just one line without a newline. To sidestep this problem, I made it so that I only ensure there is a newline for each line if and only if there is more than one line in difflines. However, I'm not sure that I can assume there should be a newline in cases similar to the fourth test (where longMessage is set to true and a 'msg' is passed) in testAssertMultilineEqual but where there is more than one line in standardMsg in assertMultiLineEqual.
|
msg333277 - (view) |
Author: Karthikeyan Singaravelan (xtreak) *  |
Date: 2019-01-09 04:25 |
Looking at the patch and the relevant function this doesn't seem to be a problem with difflib.ndiff but with unittest's display algorithm. This causes confusion about the issue and I propose changing the subject to reflect this unless difflib maintainers think this is an issue with ndiff.
|
msg333289 - (view) |
Author: Chris Jerdonek (chris.jerdonek) *  |
Date: 2019-01-09 06:12 |
When I first created the issue, the title I chose was about unittest ("unittest assertEqual difference output foiled by newlines"), but someone else changed it for some reason. You're welcome to change it back to something more like the original.
|
msg333295 - (view) |
Author: Karthikeyan Singaravelan (xtreak) *  |
Date: 2019-01-09 10:07 |
Thanks @chris.jerdonek. I have reverted the title to original report. Since CPython now accepts PR if any one of the original authors can convert their patch to a PR with tests then it will be great.
|
msg333584 - (view) |
Author: Joannah Nanjekye (nanjekyejoannah) *  |
Date: 2019-01-14 06:21 |
I have opened a PR for this.
|
msg333627 - (view) |
Author: Karthikeyan Singaravelan (xtreak) *  |
Date: 2019-01-14 15:30 |
Sorry, I just stumbled upon issue2142 which is a similar report for unique_diff producing wrong output due to missing trailing newlines and could have been the original reason where the title was changed. But since there is a PR now towards adding a newline I think it's good to fix this on unittest side.
|
|
Date |
User |
Action |
Args |
2022-04-11 14:58:19 | admin | set | github: 68968 |
2019-01-14 15:30:04 | xtreak | set | messages:
+ msg333627 |
2019-01-14 06:21:25 | nanjekyejoannah | set | nosy:
+ nanjekyejoannah messages:
+ msg333584
|
2019-01-14 06:18:29 | nanjekyejoannah | set | stage: needs patch -> patch review pull_requests:
+ pull_request11170 |
2019-01-14 06:18:15 | nanjekyejoannah | set | stage: needs patch -> needs patch pull_requests:
+ pull_request11169 |
2019-01-14 06:17:56 | nanjekyejoannah | set | stage: needs patch -> needs patch pull_requests:
+ pull_request11168 |
2019-01-09 10:07:44 | xtreak | set | messages:
+ msg333295 title: difflib.ndiff produces unreadable output when input missing trailing newline -> unittest assertEqual difference output foiled by newlines |
2019-01-09 06:12:31 | chris.jerdonek | set | messages:
+ msg333289 |
2019-01-09 04:25:06 | xtreak | set | messages:
+ msg333277 |
2019-01-09 01:55:07 | xtreak | set | nosy:
+ xtreak
versions:
+ Python 3.7, Python 3.8, - Python 3.5, Python 3.6 |
2016-09-17 18:31:29 | rhettinger | set | nosy:
+ tim.peters, loewis
|
2016-09-15 22:29:38 | adchanw | set | files:
+ fix_24780.patch
messages:
+ msg276633 |
2016-09-15 20:19:57 | ppperry | set | components:
- Tests title: unittest assertEqual difference output foiled by newlines -> difflib.ndiff produces unreadable output when input missing trailing newline |
2016-09-12 03:42:37 | adchanw | set | nosy:
+ adchanw messages:
+ msg275942
|
2016-03-14 02:28:06 | rbcollins | set | messages:
+ msg261713 |
2016-02-02 16:59:20 | anish.shah | set | files:
+ issue24780.patch keywords:
+ patch messages:
+ msg259403
|
2016-02-02 10:39:11 | anish.shah | set | nosy:
+ anish.shah messages:
+ msg259375
|
2016-01-17 13:42:40 | Elena.Oat | set | files:
+ test2.py nosy:
+ Elena.Oat messages:
+ msg258466
|
2016-01-17 01:31:21 | abarry | set | components:
+ Tests stage: test needed -> needs patch |
2016-01-17 01:22:51 | pynewbie | set | files:
+ test.py |
2016-01-13 06:04:19 | pynewbie | set | nosy:
+ pynewbie messages:
+ msg258132
|
2016-01-04 00:06:50 | ezio.melotti | set | keywords:
+ easy nosy:
+ rbcollins, ezio.melotti, michael.foord stage: test needed
versions:
- Python 3.4 |
2015-08-03 19:44:13 | r.david.murray | set | nosy:
+ r.david.murray
messages:
+ msg247947 versions:
+ Python 2.7, Python 3.5, Python 3.6 |
2015-08-02 16:49:29 | chris.jerdonek | create | |