From 5680800baf1694988a43ffbf418bb6f2ac522fc3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 11 Mar 2017 14:14:41 +0100 Subject: [PATCH] Add `vader#assert#diff` to describe differences in lists/dicts Ref: https://github.com/junegunn/vader.vim/pull/120#issuecomment-283041246 --- autoload/vader/assert.vim | 56 +++++++++++++++++++++++++++++++++++++++ test/feature/diff.vader | 41 ++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 test/feature/diff.vader diff --git a/autoload/vader/assert.vim b/autoload/vader/assert.vim index 2e29b86..4143b72 100644 --- a/autoload/vader/assert.vim +++ b/autoload/vader/assert.vim @@ -114,3 +114,59 @@ function! vader#assert#throws(exp) else | throw 'Exception expected but not raised: '.a:exp endif endfunction + +function! vader#assert#diff(Exp, Got, ...) abort + let desc_only = a:0 ? a:1 : 0 " used for recursion with lists. + if type(a:Exp) !=# type(a:Got) + return printf("type mismatch: %s (%s) should be equal to %s (%s)", + \ string(a:Got), get(s:type_names, type(a:Got), type(a:Got)), + \ string(a:Exp), get(s:type_names, type(a:Exp), type(a:Exp))) + endif + + if a:Exp ==# a:Got + return '' + endif + + if type(a:Exp) == type({}) + let desc = {'only in expected': [], 'only in gotten': [], 'diff': []} + for [k, V] in items(a:Exp) + if !has_key(a:Got, k) + call add(desc['only in expected'], k) + continue + endif + if type(V) !=# type(a:Got[k]) || V !=# a:Got[k] + call add(desc['diff'], printf('%s (%s / %s)', k, string(a:Got[k]), string(V))) + endif + endfor + for [k, V] in items(a:Got) + if !has_key(a:Exp, k) + call add(desc['only in gotten'], k) + endif + endfor + let desc = join(values(map(filter(desc, '!empty(v:val)'), "v:key.': '.join(v:val, ', ')")), '; ') + if desc_only + return 'unequal dicts: '.desc + endif + return printf('%s should be equal to %s (%s)', string(a:Got), string(a:Exp), desc) + elseif type(a:Exp) == type([]) + let msg = '' + if len(a:Exp) != len(a:Got) + let desc = 'different lengths' + else + let idx = 0 + for V in a:Exp + if type(V) != type(a:Got[idx]) || V !=# a:Got[idx] + let desc = printf('diff at index %d: %s', idx, vader#assert#diff(V, a:Got[idx], 1)) + break + endif + let idx += 1 + endfor + endif + if desc_only + return 'unequal lists: '.desc + endif + return printf('%s should be equal to %s (%s)', string(a:Got), string(a:Exp), desc) + else + return printf('%s should be equal to %s', string(a:Got), string(a:Exp)) + endif +endfunction diff --git a/test/feature/diff.vader b/test/feature/diff.vader new file mode 100644 index 0000000..7af4f83 --- /dev/null +++ b/test/feature/diff.vader @@ -0,0 +1,41 @@ +Execute (Recursive comparison / diff description): + runtime autoload/vader/assert.vim + + AssertEqual vader#assert#diff({}, {}), '' + AssertEqual vader#assert#diff({'left': 1}, {}), + \ '{} should be equal to {''left'': 1} (only in expected: left)' + + AssertEqual vader#assert#diff({'left': 1}, {'right': 2}), + \ '{''right'': 2} should be equal to {''left'': 1} '. + \ '(only in expected: left; only in gotten: right)' + + AssertEqual vader#assert#diff({'a': '1'}, {'a': 1}), + \ '{''a'': 1} should be equal to {''a'': ''1''} '. + \ '(diff: a (1 / ''1''))' + + AssertEqual vader#assert#diff([1, 2], [2, 1]), + \ '[2, 1] should be equal to [1, 2] '. + \ '(diff at index 0: 2 should be equal to 1)' + + AssertEqual vader#assert#diff([1, 2, []], [1, 2]), + \ '[1, 2] should be equal to [1, 2, []] '. + \ '(different lengths)' + + AssertEqual vader#assert#diff(['1'], [1]), + \ '[1] should be equal to [''1''] '. + \ '(diff at index 0: type mismatch: 1 (Number) should be equal to ''1'' (String))' + + AssertEqual vader#assert#diff([1, 2], {}), + \ 'type mismatch: {} (Dictionary) should be equal to [1, 2] (List)' + + let l1 = [{'lnum': 1, 'bufnr': 1, 'col': 0}, {'lnum': 6, 'bufnr': 1, 'col': 0}] + let l2 = [{'lnum': 2, 'bufnr': 4, 'col': 0, 'more': 1}, {'lnum': 7, 'bufnr': 4, 'col': 0}] + AssertEqual vader#assert#diff(l1, l2), + \ string(l2).' should be equal to '.string(l1).' '. + \ "(diff at index 0: unequal dicts: only in gotten: more; diff: lnum (2 / 1), bufnr (4 / 1))" + + AssertEqual vader#assert#diff([{1: 2}], [{3: 4}]), + \ '[{''3'': 4}] should be equal to [{''1'': 2}] (diff at index 0: unequal dicts: only in expected: 1; only in gotten: 3)' + + AssertEqual vader#assert#diff([{1: 2}], [{3: 4}, 2]), + \ '[{''3'': 4}, 2] should be equal to [{''1'': 2}] (different lengths)'