diff_matcher 2.7.1 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +4 -0
- data/README.md +70 -1
- data/TODO.txt +4 -0
- data/diff_matcher.gemspec +2 -0
- data/doc/builtin_complex_matcher.png +0 -0
- data/doc/diff_matcher.png +0 -0
- data/doc/even_more_tapas_spec.rb +13 -0
- data/doc/more_tapas_spec.rb +11 -0
- data/exe/diff-csv +89 -0
- data/exe/diff-json +14 -0
- data/exe/diff-mysql +93 -0
- data/lib/diff_matcher/version.rb +1 -1
- metadata +15 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ae30490620e0407789851f3b58ecdbf8c0de16b4ec6695b19a77d1809cadfe59
|
4
|
+
data.tar.gz: a00b708d6ded4b931c75858c41040e10fc4362d3fbeb55c2f6f63ee8eaf20164
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35619bf1f55bdb50a50f69e90483c233236cec6bce7f721dcf8e007533653cadec5b492499d795de648af323d31c4d4142a60daac2386d37641ee41a354c7fa9
|
7
|
+
data.tar.gz: 47a9e874d8da2f0d5b623b5077487d1b07138a6d74d04eae2ee32c873f841332cc4ffc26e9cc61c36402176a6636ba2c0b14b56985a24136475261b709b3a9af
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -34,7 +34,7 @@ actual = { :a=>{ :a1=>10, :a2=>12 }, :b=>[ 21 ], :c=>'3' , :d=>4 , :e=
|
|
34
34
|
puts DiffMatcher::difference(expected, actual, :color_scheme=>:white_background)
|
35
35
|
```
|
36
36
|
|
37
|
-
![example output](https://raw.github.com/
|
37
|
+
![example output](https://raw.github.com/diff-matcher/diff_matcher/master/doc/diff_matcher.gif)
|
38
38
|
|
39
39
|
|
40
40
|
Installation
|
@@ -437,6 +437,75 @@ Finished in 0.00601 seconds
|
|
437
437
|
```
|
438
438
|
|
439
439
|
|
440
|
+
Comparing to built-in rspec matcher
|
441
|
+
---
|
442
|
+
RSpec 3 now has a built-in complex matcher:
|
443
|
+
``` ruby
|
444
|
+
RSpec.describe "a complex example" do
|
445
|
+
let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
|
446
|
+
company: {name: "Table XI", url: "www.tablexi.com"}}}
|
447
|
+
|
448
|
+
it "gets the right response" do
|
449
|
+
expect(response).to match({
|
450
|
+
person: {first_name: "Avdi", last_name: "Grim"},
|
451
|
+
company: {name: "ShipRise", url: a_string_matching(/tablexi/)}
|
452
|
+
})
|
453
|
+
end
|
454
|
+
end
|
455
|
+
```
|
456
|
+
|
457
|
+
With `--color` set, will result in:
|
458
|
+
|
459
|
+
![built-in complex matcher](https://raw.github.com/diff-matcher/diff_matcher/master/doc/builtin_complex_matcher.png)
|
460
|
+
|
461
|
+
|
462
|
+
But using `diff_matcher`:
|
463
|
+
``` ruby
|
464
|
+
require "diff_matcher/rspec_3"
|
465
|
+
|
466
|
+
RSpec.describe "a complex example" do
|
467
|
+
let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
|
468
|
+
company: {name: "Table XI", url: "www.tablexi.com"}}}
|
469
|
+
|
470
|
+
it "gets the right response" do
|
471
|
+
expect(response).to be_matching({
|
472
|
+
person: {first_name: "Avdi", last_name: "Grim"},
|
473
|
+
company: {name: "ShipRise", url: /tablexi/}
|
474
|
+
}).with_options(quiet: false)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
```
|
478
|
+
|
479
|
+
With `--color` set, will result in:
|
480
|
+
|
481
|
+
![diff-matcher](https://raw.github.com/diff-matcher/diff_matcher/master/doc/diff_matcher.png)
|
482
|
+
|
483
|
+
ie. by making these changes:
|
484
|
+
``` diff
|
485
|
+
--- more_tapas_spec.rb 2017-03-02 19:51:26.000000000 +1100
|
486
|
+
+++ even_more_tapas_spec.rb 2017-03-02 20:41:52.000000000 +1100
|
487
|
+
@@ -1,11 +1,13 @@
|
488
|
+
+require "diff_matcher/rspec_3"
|
489
|
+
+
|
490
|
+
RSpec.describe "a complex example" do
|
491
|
+
let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
|
492
|
+
company: {name: "Table XI", url: "www.tablexi.com"}}}
|
493
|
+
|
494
|
+
it "gets the right response" do
|
495
|
+
- expect(response).to match({
|
496
|
+
+ expect(response).to be_matching({
|
497
|
+
person: {first_name: "Avdi", last_name: "Grim"},
|
498
|
+
- company: {name: "ShipRise", url: a_string_matching(/tablexi/)}
|
499
|
+
- })
|
500
|
+
+ company: {name: "ShipRise", url: /tablexi/}
|
501
|
+
+ }).with_options(quiet: false)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
```
|
505
|
+
|
506
|
+
NB. Its not as easy to see with RSpec's built-in complex matcher that the url actually matched in the above example.
|
507
|
+
|
508
|
+
|
440
509
|
Contributing
|
441
510
|
---
|
442
511
|
|
data/TODO.txt
CHANGED
data/diff_matcher.gemspec
CHANGED
Binary file
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "diff_matcher/rspec_3"
|
2
|
+
|
3
|
+
RSpec.describe "a complex example" do
|
4
|
+
let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
|
5
|
+
company: {name: "Table XI", url: "www.tablexi.com"}}}
|
6
|
+
|
7
|
+
it "gets the right response" do
|
8
|
+
expect(response).to be_matching({
|
9
|
+
person: {first_name: "Avdi", last_name: "Grim"},
|
10
|
+
company: {name: "ShipRise", url: /tablexi/}
|
11
|
+
}).with_options(quiet: false)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
RSpec.describe "a complex example" do
|
2
|
+
let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
|
3
|
+
company: {name: "Table XI", url: "www.tablexi.com"}}}
|
4
|
+
|
5
|
+
it "gets the right response" do
|
6
|
+
expect(response).to match({
|
7
|
+
person: {first_name: "Avdi", last_name: "Grim"},
|
8
|
+
company: {name: "ShipRise", url: a_string_matching(/tablexi/)}
|
9
|
+
})
|
10
|
+
end
|
11
|
+
end
|
data/exe/diff-csv
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Given:
|
3
|
+
# --- languages-v1.tsv ---
|
4
|
+
# id name author first_appeared stable_release
|
5
|
+
# 1 ruby Yukihiro Matsumoto 1995 2.7.1
|
6
|
+
# 2 python Guido van Rossum 1991 3.9.0
|
7
|
+
# 3 jq Stephen Dolan 2013 1.6
|
8
|
+
# --- languages-v1.tsv ---
|
9
|
+
#
|
10
|
+
# --- languages-v2.tsv ---
|
11
|
+
# id name author first_appeared stable_release
|
12
|
+
# 1 ruby Yukihiro Matsumoto 1995 2.7.2
|
13
|
+
# 2 python Guido van Rossum 1991 3.9.0
|
14
|
+
# 3 jq Stephen Dolan 2013 1.6
|
15
|
+
# --- languages-v2.tsv ---
|
16
|
+
#
|
17
|
+
# Examples:
|
18
|
+
# > diff-csv languages-v1.tsv languages-v2.tsv
|
19
|
+
# {
|
20
|
+
# 1=>{
|
21
|
+
# "stable_release"=>- "2.7.1"+ "2.7.2"
|
22
|
+
# }
|
23
|
+
# }
|
24
|
+
# Where, - 1 missing, + 1 additional
|
25
|
+
#
|
26
|
+
# > VERBOSE=1 diff-csv languages-v{1,2}.tsv
|
27
|
+
# {
|
28
|
+
# 1=>{
|
29
|
+
# "name"=>"ruby",
|
30
|
+
# "author"=>"Yukihiro Matsumoto",
|
31
|
+
# "first_appeared"=>1995,
|
32
|
+
# "stable_release"=>- "2.7.1"+ "2.7.2"
|
33
|
+
# },
|
34
|
+
# 2=>{
|
35
|
+
# "name"=>"python",
|
36
|
+
# "author"=>"Guido van Rossum",
|
37
|
+
# "first_appeared"=>1991,
|
38
|
+
# "stable_release"=>"3.9.0"
|
39
|
+
# },
|
40
|
+
# 3=>{
|
41
|
+
# "name"=>"jq",
|
42
|
+
# "author"=>"Stephen Dolan",
|
43
|
+
# "first_appeared"=>2013,
|
44
|
+
# "stable_release"=>1.6
|
45
|
+
# }
|
46
|
+
# }
|
47
|
+
# Where, - 1 missing, + 1 additional
|
48
|
+
#
|
49
|
+
# > KEY=name diff-csv languages-v{1,2}.tsv
|
50
|
+
# {
|
51
|
+
# "ruby"=>{
|
52
|
+
# "stable_release"=>- "2.7.1"+ "2.7.2"
|
53
|
+
# }
|
54
|
+
# }
|
55
|
+
# Where, - 1 missing, + 1 additional
|
56
|
+
|
57
|
+
require 'csv'
|
58
|
+
require 'diff_matcher'
|
59
|
+
|
60
|
+
COL_SEP=ENV.fetch("COL_SEP", "\t")
|
61
|
+
KEY=ENV.fetch("KEY", "id")
|
62
|
+
|
63
|
+
|
64
|
+
def fix_nulls(h)
|
65
|
+
h.each { |k, v| h[k] = (v == 'NULL' ? nil : v) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def records(file, key=KEY, col_sep=COL_SEP)
|
69
|
+
CSV(file, col_sep: COL_SEP, headers: true, converters: :all).inject({}) do |h, row|
|
70
|
+
data = fix_nulls(row.to_hash)
|
71
|
+
h.update(data.delete(key)=> data)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
data0 = records(File.open(ARGV[0]))
|
76
|
+
data1 = records(File.open(ARGV[1]))
|
77
|
+
|
78
|
+
diff_opts = {
|
79
|
+
color_enabled: true,
|
80
|
+
ignore_additional: ENV['IGNORE_ADDITIONAL'],
|
81
|
+
quiet: !ENV['VERBOSE']
|
82
|
+
}
|
83
|
+
|
84
|
+
diff=DiffMatcher.difference(data0, data1, diff_opts)
|
85
|
+
|
86
|
+
if diff
|
87
|
+
puts diff
|
88
|
+
exit 1
|
89
|
+
end
|
data/exe/diff-json
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'diff_matcher'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
expected, actual = ARGV.first(2).map do |f|
|
6
|
+
JSON.parse(File.read(f))
|
7
|
+
end
|
8
|
+
|
9
|
+
diff=DiffMatcher.difference(expected, actual, color_scheme: :default)
|
10
|
+
|
11
|
+
if diff
|
12
|
+
puts diff
|
13
|
+
exit 1
|
14
|
+
end
|
data/exe/diff-mysql
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/bin/bash -e
|
2
|
+
# Examples:
|
3
|
+
# # Show diff between the TABLES in two databases
|
4
|
+
# TABLES="languages" diff-mysql database1 database2
|
5
|
+
#
|
6
|
+
# # Show diff between languages TABLES skipping any output containing 'python'
|
7
|
+
# FILTER_CMD='grep -v python' TABLES=languages diff-mysql database{1,2}
|
8
|
+
#
|
9
|
+
# # Filter at the database level instead
|
10
|
+
# FILTER_SQL="WHERE languages.name = 'python'" TABLES=languages diff-mysql database{1,2}
|
11
|
+
#
|
12
|
+
set -eo pipefail
|
13
|
+
|
14
|
+
DB_USERNAME=${DB_USERNAME:-root}
|
15
|
+
DB_PASSWORD=${DB_PASSWORD:-password}
|
16
|
+
DB_HOST=${DB_HOST:-localhost}
|
17
|
+
|
18
|
+
MAX_ROW_COUNT=${MAX_ROW_COUNT:-100}
|
19
|
+
SKIP=${SKIP:-messages}
|
20
|
+
|
21
|
+
DB_NAME1=$1
|
22
|
+
DB_NAME2=$2
|
23
|
+
|
24
|
+
puts() { local color=$1; local prefix=$2; local msg=$3
|
25
|
+
echo -e "[$(date +%Y%m%d%H%M%S)] [${color};1m${prefix}:[0m[${color}m $msg[0m" 1>&2
|
26
|
+
}
|
27
|
+
|
28
|
+
info() { local msg=$*; puts 34 INFO "$msg" ; }
|
29
|
+
success() { local msg=$*; puts 32 SUCCESS "$msg"; }
|
30
|
+
error() { local msg=$*; puts 31 ERROR "$msg" ; }
|
31
|
+
|
32
|
+
skip() { local name=$1
|
33
|
+
for skip_name in $SKIP; do
|
34
|
+
[ "$skip_name" == "$name" ] && return 0
|
35
|
+
done
|
36
|
+
return 1
|
37
|
+
}
|
38
|
+
|
39
|
+
do_mysql() { local db_name="$1"; shift
|
40
|
+
mysql "$@" --user="$DB_USERNAME" --password="$DB_PASSWORD" --host="$DB_HOST" "$db_name" 2> /dev/null
|
41
|
+
}
|
42
|
+
|
43
|
+
do_mysql_silent() { local db_name=$1
|
44
|
+
do_mysql "$db_name" --silent
|
45
|
+
}
|
46
|
+
|
47
|
+
tables() { local db_name=$1
|
48
|
+
info "Fetching table names from database $db_name (host '$DB_HOST') ..."
|
49
|
+
echo "show tables" |
|
50
|
+
do_mysql_silent "$db_name"
|
51
|
+
}
|
52
|
+
TABLES=${TABLES:-$(tables "$DB_NAME1")}
|
53
|
+
|
54
|
+
count_rows() { local table=$1; local db_name=$2
|
55
|
+
echo "select count(id) from $table" |
|
56
|
+
do_mysql_silent "$db_name"
|
57
|
+
}
|
58
|
+
|
59
|
+
diff_cmd() {
|
60
|
+
#diff -u $@
|
61
|
+
COLOR_ENABLED=1 ${DIFF_CMD:-diff-csv} "$@"
|
62
|
+
}
|
63
|
+
|
64
|
+
filter_cmd() {
|
65
|
+
${FILTER_CMD:-cat}
|
66
|
+
}
|
67
|
+
|
68
|
+
dump_table() { local table=$1; local db_name=$2
|
69
|
+
echo "$(echo 'SELECT *') FROM $table ${FILTER_SQL}" |
|
70
|
+
do_mysql "$db_name" |
|
71
|
+
filter_cmd
|
72
|
+
}
|
73
|
+
|
74
|
+
table_diff() { local table="$1"
|
75
|
+
info "Diffing $table ($DB_NAME1 vs $DB_NAME2)"
|
76
|
+
diff_cmd <(dump_table "$table" {"$DB_NAME1","$DB_NAME2"})
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
exit_code=0
|
81
|
+
for table in $TABLES; do
|
82
|
+
row_count=$(count_rows "$table" "$DB_NAME1")
|
83
|
+
if [ $row_count -lt $MAX_ROW_COUNT ]; then
|
84
|
+
if skip "$table"; then
|
85
|
+
info "Skipping $table (as it was referenced in SKIP)"
|
86
|
+
else
|
87
|
+
table_diff "$table" || exit_code=$?
|
88
|
+
fi
|
89
|
+
else
|
90
|
+
info "Skipping $table (as row count exceeds MAX_ROW_COUNT, $row_count > $MAX_ROW_COUNT)"
|
91
|
+
fi
|
92
|
+
done
|
93
|
+
exit $exit_code
|
data/lib/diff_matcher/version.rb
CHANGED
metadata
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diff_matcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- locochris
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
DiffMatcher matches input data (eg. from a JSON API) against values,
|
15
15
|
ranges, classes, regexes, procs, custom matchers and/or easily composed,
|
16
16
|
nested combinations thereof to produce an easy to read diff string.
|
17
17
|
email: chris@locomote.com.au
|
18
|
-
executables:
|
18
|
+
executables:
|
19
|
+
- diff-csv
|
20
|
+
- diff-json
|
21
|
+
- diff-mysql
|
19
22
|
extensions: []
|
20
23
|
extra_rdoc_files: []
|
21
24
|
files:
|
@@ -28,8 +31,15 @@ files:
|
|
28
31
|
- Rakefile
|
29
32
|
- TODO.txt
|
30
33
|
- diff_matcher.gemspec
|
34
|
+
- doc/builtin_complex_matcher.png
|
31
35
|
- doc/diff_matcher.gif
|
36
|
+
- doc/diff_matcher.png
|
37
|
+
- doc/even_more_tapas_spec.rb
|
32
38
|
- doc/example_output.png
|
39
|
+
- doc/more_tapas_spec.rb
|
40
|
+
- exe/diff-csv
|
41
|
+
- exe/diff-json
|
42
|
+
- exe/diff-mysql
|
33
43
|
- lib/diff_matcher.rb
|
34
44
|
- lib/diff_matcher/difference.rb
|
35
45
|
- lib/diff_matcher/escape_to_html.rb
|
@@ -66,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
76
|
version: '0'
|
67
77
|
requirements: []
|
68
78
|
rubyforge_project:
|
69
|
-
rubygems_version: 2.
|
79
|
+
rubygems_version: 2.7.6
|
70
80
|
signing_key:
|
71
81
|
specification_version: 4
|
72
82
|
summary: Generates a diff by matching against user-defined matchers written in ruby.
|
@@ -74,4 +84,3 @@ test_files:
|
|
74
84
|
- spec/diff_matcher/difference_spec.rb
|
75
85
|
- spec/diff_matcher/rspec/matchers/diff_matcher_spec.rb
|
76
86
|
- spec/spec_helper.rb
|
77
|
-
has_rdoc:
|