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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 269ffc7ffb370219902eab20adbb33123e12de62
4
- data.tar.gz: eeae047d47e866671da62f7fb2f6c5723cf9e935
2
+ SHA256:
3
+ metadata.gz: ae30490620e0407789851f3b58ecdbf8c0de16b4ec6695b19a77d1809cadfe59
4
+ data.tar.gz: a00b708d6ded4b931c75858c41040e10fc4362d3fbeb55c2f6f63ee8eaf20164
5
5
  SHA512:
6
- metadata.gz: 826869c482e6c5a60b9b6132e19dd64296be1d7aafa12d66e580d309f624806ee43724bc3cebc2ff78039eca8362e6cde7fe798eba9b351f570b26240ca206cd
7
- data.tar.gz: b76a7c7ceec440089b683436969a73b88730a28e670ce0e4565dd79d0f0192f116fae79c4f3bcf1d7dd0a48a5648b29a24b247c66cce5ae1f144601d954a42b3
6
+ metadata.gz: 35619bf1f55bdb50a50f69e90483c233236cec6bce7f721dcf8e007533653cadec5b492499d795de648af323d31c4d4142a60daac2386d37641ee41a354c7fa9
7
+ data.tar.gz: 47a9e874d8da2f0d5b623b5077487d1b07138a6d74d04eae2ee32c873f841332cc4ffc26e9cc61c36402176a6636ba2c0b14b56985a24136475261b709b3a9af
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ### v2.8.0
4
+
5
+ * Add new diff-* executables for matching JSON & CSV files on the command line
6
+
3
7
  ### v2.7.1
4
8
 
5
9
  * Use `failure_message` from RSpec matchers in diff output. (denyago)
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/playup/diff_matcher/master/doc/diff_matcher.gif)
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
@@ -12,3 +12,7 @@ ie. by matching `actual` against an `expected` value/pattern/class/proc.
12
12
  Wed Dec 14 2011
13
13
  - underline
14
14
  - string diff
15
+
16
+
17
+ Sat Nov 14 2020
18
+ - add tests for exe/diff-* executables
@@ -22,4 +22,6 @@ EOF
22
22
  s.files = `git ls-files`.split("\n")
23
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
24
  s.require_paths = ["lib"]
25
+ s.bindir = "exe"
26
+ s.executables = s.files.grep(%r{^#{s.bindir}/}) { |f| File.basename(f) }
25
27
  end
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
@@ -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
@@ -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
@@ -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}:[${color}m $msg" 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
@@ -1,3 +1,3 @@
1
1
  module DiffMatcher
2
- VERSION = "2.7.1"
2
+ VERSION = "2.8.0"
3
3
  end
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.7.1
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - locochris
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-02 00:00:00.000000000 Z
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.2.5
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: