snapshot_testing 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Gemfile +0 -1
- data/README.md +6 -2
- data/Rakefile +12 -3
- data/examples/__snapshots__/named.minitest.spec.txt +1 -0
- data/examples/__snapshots__/named.minitest.test.txt +1 -0
- data/examples/__snapshots__/named.rspec.txt +1 -0
- data/examples/__snapshots__/named.unit.txt +1 -0
- data/examples/minitest.rb +10 -2
- data/examples/rspec.rb +4 -0
- data/examples/test_unit.rb +4 -0
- data/lib/snapshot_testing.rb +3 -0
- data/lib/snapshot_testing/minitest.rb +11 -10
- data/lib/snapshot_testing/recorder.rb +87 -42
- data/lib/snapshot_testing/rspec.rb +19 -23
- data/lib/snapshot_testing/test_unit.rb +7 -4
- data/lib/snapshot_testing/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a09c878dab9b37cfb19478f2647d404fc1091840
|
4
|
+
data.tar.gz: 83d05b1d4a199a08f44e0c4a3d5a01b3e07f9754
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d630db5ee68d5dcb9df88b29f6991eacbdee0f150c03282f6e6121eb434bf9476985111e71438e5b8ae8d66af1c29d12d50078f6fd18b558ecd3bf77281ed0a
|
7
|
+
data.tar.gz: 44402a6591987118f01cdc357e5b089625a0406850da4e8e2e16c8134a7571102d02f3594dc3d0212dc423115abf20b3b0a3e54acd8ee270e705904e66a8976a
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -47,6 +47,7 @@ RSpec.describe "Example" do
|
|
47
47
|
it "takes a snapshot" do
|
48
48
|
expect("hello").to match_snapshot
|
49
49
|
expect("goodbye").to match_snapshot
|
50
|
+
expect("hello").to match_snapshot("hello.txt")
|
50
51
|
end
|
51
52
|
end
|
52
53
|
```
|
@@ -63,6 +64,7 @@ class ExampleTest < Minitest::Test
|
|
63
64
|
def test_takes_a_snapshot
|
64
65
|
assert_snapshot "hello"
|
65
66
|
assert_snapshot "goodbye"
|
67
|
+
assert_snapshot "hello.txt", "hello"
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
@@ -70,8 +72,9 @@ class ExampleSpec < Minitest::Spec
|
|
70
72
|
include SnapshotTesting::Minitest
|
71
73
|
|
72
74
|
it "takes a snapshot" do
|
73
|
-
"hello".must_match_snapshot
|
74
|
-
"goodbye".must_match_snapshot
|
75
|
+
_("hello").must_match_snapshot
|
76
|
+
_("goodbye").must_match_snapshot
|
77
|
+
_("hello").must_match_snapshot "hello.txt"
|
75
78
|
end
|
76
79
|
end
|
77
80
|
```
|
@@ -88,6 +91,7 @@ class ExampleTest < Test::Unit::TestCase
|
|
88
91
|
def test_snapshot
|
89
92
|
assert_snapshot "hello"
|
90
93
|
assert_snapshot "goodbye"
|
94
|
+
assert_snapshot "hello.txt", "hello"
|
91
95
|
end
|
92
96
|
end
|
93
97
|
```
|
data/Rakefile
CHANGED
@@ -3,10 +3,19 @@ require "rspec/core/rake_task"
|
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
+
def info(message)
|
7
|
+
puts "\033[1m#{message}\033[0m"
|
8
|
+
end
|
9
|
+
|
6
10
|
task :examples do
|
7
|
-
|
8
|
-
ruby
|
9
|
-
|
11
|
+
info "==>> Running RSpec..."
|
12
|
+
ruby "examples/rspec.rb -f progress"
|
13
|
+
|
14
|
+
info "\n\n==>> Running Minitest..."
|
15
|
+
ruby "examples/minitest.rb"
|
16
|
+
|
17
|
+
info "\n\n==>> Running TestUnit..."
|
18
|
+
ruby "examples/test_unit.rb"
|
10
19
|
end
|
11
20
|
|
12
21
|
task :default => :spec
|
@@ -0,0 +1 @@
|
|
1
|
+
named
|
@@ -0,0 +1 @@
|
|
1
|
+
named
|
@@ -0,0 +1 @@
|
|
1
|
+
named
|
@@ -0,0 +1 @@
|
|
1
|
+
named
|
data/examples/minitest.rb
CHANGED
@@ -9,13 +9,21 @@ class ExampleTest < Minitest::Test
|
|
9
9
|
assert_snapshot "hello"
|
10
10
|
assert_snapshot "goodbye"
|
11
11
|
end
|
12
|
+
|
13
|
+
def test_named_snapshot
|
14
|
+
assert_snapshot "named.minitest.test.txt", "named"
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
class ExampleSpec < Minitest::Spec
|
15
19
|
include SnapshotTesting::Minitest
|
16
20
|
|
17
21
|
it "takes a snapshot" do
|
18
|
-
"hello".must_match_snapshot
|
19
|
-
"goodbye".must_match_snapshot
|
22
|
+
_("hello").must_match_snapshot
|
23
|
+
_("goodbye").must_match_snapshot
|
24
|
+
end
|
25
|
+
|
26
|
+
it "takes a named snapshot" do
|
27
|
+
_("named").must_match_snapshot "named.minitest.spec.txt"
|
20
28
|
end
|
21
29
|
end
|
data/examples/rspec.rb
CHANGED
data/examples/test_unit.rb
CHANGED
data/lib/snapshot_testing.rb
CHANGED
@@ -2,17 +2,10 @@ require "snapshot_testing"
|
|
2
2
|
|
3
3
|
module SnapshotTesting
|
4
4
|
module Minitest
|
5
|
-
def self.included(_)
|
6
|
-
return unless defined?(::Minitest::Expectations)
|
7
|
-
return if ::Minitest::Expectations.method_defined?(:must_match_snapshot)
|
8
|
-
::Minitest::Expectations.infect_an_assertion(:assert_snapshot, :must_match_snapshot, true)
|
9
|
-
end
|
10
|
-
|
11
5
|
def before_setup
|
12
6
|
@__snapshot_recorder__ = SnapshotTesting::Recorder.new(
|
13
7
|
name: name,
|
14
|
-
path: method(name).source_location.first
|
15
|
-
update: !ENV['UPDATE_SNAPSHOTS'].nil?
|
8
|
+
path: method(name).source_location.first
|
16
9
|
)
|
17
10
|
super
|
18
11
|
end
|
@@ -22,8 +15,16 @@ module SnapshotTesting
|
|
22
15
|
@__snapshot_recorder__.commit
|
23
16
|
end
|
24
17
|
|
25
|
-
def assert_snapshot(actual)
|
26
|
-
|
18
|
+
def assert_snapshot(name = nil, actual)
|
19
|
+
if name.nil?
|
20
|
+
assert_equal(@__snapshot_recorder__.record(actual), actual)
|
21
|
+
else
|
22
|
+
assert_equal(@__snapshot_recorder__.record_file(name, actual), actual)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if respond_to? :infect_an_assertion
|
27
|
+
infect_an_assertion :assert_snapshot, :must_match_snapshot
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
@@ -2,80 +2,125 @@ require "fileutils"
|
|
2
2
|
|
3
3
|
module SnapshotTesting
|
4
4
|
class Recorder
|
5
|
-
def initialize(name:, path:, update:)
|
5
|
+
def initialize(name:, path:, update: SnapshotTesting.update?)
|
6
6
|
@name = name
|
7
7
|
@path = path
|
8
8
|
@update = update
|
9
|
-
@
|
9
|
+
@visited = []
|
10
|
+
@added = 0
|
11
|
+
@updated = 0
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
File.join(File.
|
14
|
-
end
|
15
|
-
|
16
|
-
def snapshot_file
|
17
|
-
File.join(snapshot_dir, "#{File.basename(@path)}.snap")
|
14
|
+
def snapshot_path
|
15
|
+
File.join(snapshots_path, "#{File.basename(path)}.snap")
|
18
16
|
end
|
19
17
|
|
20
18
|
def snapshots
|
21
19
|
@snapshots ||= begin
|
22
|
-
Snapshot.load_file(
|
20
|
+
Snapshot.load_file(snapshot_path)
|
23
21
|
rescue Errno::ENOENT
|
24
22
|
{}
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
26
|
+
def record_file(name, actual)
|
27
|
+
expected = begin
|
28
|
+
read(name)
|
29
|
+
rescue Errno::ENOENT
|
30
|
+
write(name, actual)
|
31
|
+
log(1, :written)
|
32
|
+
actual
|
33
|
+
end
|
34
|
+
|
35
|
+
if update? && actual != expected
|
36
|
+
write(name, actual)
|
37
|
+
log(1, :updated)
|
38
|
+
actual
|
39
|
+
else
|
40
|
+
expected
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
28
44
|
def record(actual)
|
29
|
-
key = "#{
|
45
|
+
key = "#{name} #{visited.length + 1}"
|
30
46
|
|
31
|
-
|
32
|
-
@state[key] = actual
|
47
|
+
self.visited << key
|
33
48
|
|
34
|
-
|
35
|
-
|
49
|
+
unless snapshots.key?(key)
|
50
|
+
self.added += 1
|
51
|
+
self.snapshots[key] = actual
|
52
|
+
end
|
36
53
|
|
37
|
-
|
38
|
-
|
54
|
+
if update? && actual != snapshots[key]
|
55
|
+
self.updated += 1
|
56
|
+
self.snapshots[key] = actual
|
57
|
+
end
|
39
58
|
|
40
|
-
# otherwise, compare actual to the snapshot
|
41
59
|
snapshots[key]
|
42
60
|
end
|
43
61
|
|
44
62
|
def commit
|
45
|
-
|
46
|
-
|
47
|
-
removed
|
48
|
-
|
49
|
-
|
63
|
+
removed = snapshots.keys - visited
|
64
|
+
removed = removed.grep(/^#{name}\s\d+$/)
|
65
|
+
removed.each { |key| snapshots.delete(key) }
|
66
|
+
|
67
|
+
write_snapshots(snapshots) if write?
|
68
|
+
log(added, :written) unless added.zero?
|
69
|
+
log(updated, :updated) unless updated.zero?
|
70
|
+
log(removed.length, :removed) if update? && !removed.empty?
|
71
|
+
log(removed.length, :obsolete) if !update? && !removed.empty?
|
72
|
+
end
|
50
73
|
|
51
|
-
|
52
|
-
result = result.merge(changed) if @update
|
53
|
-
result = result.reject { |k, _| removed.include?(k) } if @update
|
74
|
+
protected
|
54
75
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
76
|
+
# the number of added snapshots
|
77
|
+
attr_accessor :added
|
78
|
+
|
79
|
+
# the number of updated snapshots
|
80
|
+
attr_accessor :updated
|
81
|
+
|
82
|
+
# all snapshots that have been compared
|
83
|
+
attr_reader :visited
|
61
84
|
|
62
85
|
private
|
63
86
|
|
64
|
-
|
87
|
+
# the name of the current test
|
88
|
+
attr_reader :name
|
89
|
+
|
90
|
+
# the file location of the current test
|
91
|
+
attr_reader :path
|
92
|
+
|
93
|
+
# should we update failing snapshots?
|
94
|
+
def update?
|
95
|
+
@update
|
96
|
+
end
|
97
|
+
|
98
|
+
# should we write to the filesystem?
|
99
|
+
def write?
|
100
|
+
update? || !added.zero?
|
101
|
+
end
|
102
|
+
|
103
|
+
def snapshots_path
|
104
|
+
File.join(File.dirname(path), "__snapshots__")
|
105
|
+
end
|
106
|
+
|
107
|
+
def log(count, status)
|
65
108
|
label = count == 1 ? "snapshot" : "snapshots"
|
66
|
-
|
109
|
+
warn "\e[33m#{count} #{label} #{status}\e[0m"
|
110
|
+
end
|
67
111
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
112
|
+
def read(name)
|
113
|
+
File.read(File.join(snapshots_path, name))
|
114
|
+
end
|
115
|
+
|
116
|
+
def write(name, data)
|
117
|
+
FileUtils.mkdir_p(snapshots_path)
|
118
|
+
File.write(File.join(snapshots_path, name), data)
|
74
119
|
end
|
75
120
|
|
76
|
-
def
|
77
|
-
FileUtils.mkdir_p(
|
78
|
-
File.write(
|
121
|
+
def write_snapshots(snapshots)
|
122
|
+
FileUtils.mkdir_p(snapshots_path)
|
123
|
+
File.write(snapshot_path, Snapshot.dump(snapshots))
|
79
124
|
end
|
80
125
|
end
|
81
126
|
end
|
@@ -2,12 +2,13 @@ require "snapshot_testing"
|
|
2
2
|
|
3
3
|
module SnapshotTesting
|
4
4
|
module RSpec
|
5
|
+
extend ::RSpec::Matchers::DSL
|
6
|
+
|
5
7
|
def self.included(base)
|
6
8
|
base.let :__snapshot_recorder__ do |example|
|
7
9
|
SnapshotTesting::Recorder.new(
|
8
10
|
name: example.description,
|
9
|
-
path: example.metadata[:absolute_file_path]
|
10
|
-
update: !ENV['UPDATE_SNAPSHOTS'].nil?
|
11
|
+
path: example.metadata[:absolute_file_path]
|
11
12
|
)
|
12
13
|
end
|
13
14
|
|
@@ -16,35 +17,30 @@ module SnapshotTesting
|
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
matcher :match_snapshot do |name|
|
21
|
+
match do |actual|
|
22
|
+
@expected = if name.nil?
|
23
|
+
__snapshot_recorder__.record(actual)
|
24
|
+
else
|
25
|
+
__snapshot_recorder__.record_file(name, actual)
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
@recorder = recorder
|
28
|
+
@expected == actual
|
28
29
|
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
@expected = @recorder.record(@actual)
|
33
|
-
@actual == @expected
|
34
|
-
end
|
31
|
+
diffable
|
32
|
+
description { "match snapshot #{expected_formatted}"}
|
35
33
|
|
36
|
-
|
37
|
-
|
38
|
-
actual = ::RSpec::Support::ObjectFormatter.format(@actual)
|
39
|
-
"\nexpected: #{expected}\n got: #{actual}\n\n(compared using ==)\n"
|
34
|
+
failure_message do |actual|
|
35
|
+
"\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using ==)\n"
|
40
36
|
end
|
41
37
|
|
42
|
-
def
|
43
|
-
|
38
|
+
def expected_formatted
|
39
|
+
::RSpec::Support::ObjectFormatter.format(@expected)
|
44
40
|
end
|
45
41
|
|
46
|
-
def
|
47
|
-
|
42
|
+
def actual_formatted
|
43
|
+
::RSpec::Support::ObjectFormatter.format(@actual)
|
48
44
|
end
|
49
45
|
end
|
50
46
|
end
|
@@ -5,8 +5,7 @@ module SnapshotTesting
|
|
5
5
|
def setup
|
6
6
|
@__snapshot_recorder__ = SnapshotTesting::Recorder.new(
|
7
7
|
name: method_name,
|
8
|
-
path: method(method_name).source_location.first
|
9
|
-
update: !ENV['UPDATE_SNAPSHOTS'].nil?
|
8
|
+
path: method(method_name).source_location.first
|
10
9
|
)
|
11
10
|
super
|
12
11
|
end
|
@@ -16,8 +15,12 @@ module SnapshotTesting
|
|
16
15
|
@__snapshot_recorder__.commit
|
17
16
|
end
|
18
17
|
|
19
|
-
def assert_snapshot(actual)
|
20
|
-
|
18
|
+
def assert_snapshot(name = nil, actual)
|
19
|
+
if name.nil?
|
20
|
+
assert_equal(@__snapshot_recorder__.record(actual), actual)
|
21
|
+
else
|
22
|
+
assert_equal(@__snapshot_recorder__.record_file(name, actual), actual)
|
23
|
+
end
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snapshot_testing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ray Zane
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-12-
|
11
|
+
date: 2019-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -110,6 +110,10 @@ files:
|
|
110
110
|
- bin/console
|
111
111
|
- bin/setup
|
112
112
|
- examples/__snapshots__/minitest.rb.snap
|
113
|
+
- examples/__snapshots__/named.minitest.spec.txt
|
114
|
+
- examples/__snapshots__/named.minitest.test.txt
|
115
|
+
- examples/__snapshots__/named.rspec.txt
|
116
|
+
- examples/__snapshots__/named.unit.txt
|
113
117
|
- examples/__snapshots__/rspec.rb.snap
|
114
118
|
- examples/__snapshots__/test_unit.rb.snap
|
115
119
|
- examples/minitest.rb
|