attestify 0.1.0.pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rubocop.yml +37 -0
- data/.travis.yml +8 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +75 -0
- data/Rakefile +5 -0
- data/attestify.gemspec +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/attestify +3 -0
- data/lib/attestify.rb +20 -0
- data/lib/attestify/assertion_results.rb +93 -0
- data/lib/attestify/assertions.rb +334 -0
- data/lib/attestify/assertions/output_assertion.rb +62 -0
- data/lib/attestify/cli.rb +84 -0
- data/lib/attestify/color_reporter.rb +127 -0
- data/lib/attestify/mock.rb +118 -0
- data/lib/attestify/rake_task.rb +29 -0
- data/lib/attestify/reporter.rb +171 -0
- data/lib/attestify/skipped_error.rb +6 -0
- data/lib/attestify/test.rb +89 -0
- data/lib/attestify/test_list.rb +162 -0
- data/lib/attestify/test_runner.rb +46 -0
- data/lib/attestify/timer.rb +30 -0
- data/lib/attestify/version.rb +3 -0
- metadata +115 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
require "attestify"
|
2
|
+
|
3
|
+
module Attestify
|
4
|
+
# This is the base class for all Attestify tests.
|
5
|
+
class Test
|
6
|
+
include Attestify::Assertions
|
7
|
+
|
8
|
+
def initialize(method)
|
9
|
+
@_test_method = method
|
10
|
+
@_assertions = Attestify::AssertionResults.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.inherited(test_class)
|
14
|
+
tests << test_class
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.tests
|
18
|
+
@tests ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.run(reporter, filter = nil)
|
22
|
+
runnable_methods.each do |method|
|
23
|
+
run_one_method(self, method, reporter, filter)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.run_one_method(test_class, method, reporter, filter = nil)
|
28
|
+
return if filter && !filter.run?(test_class, method)
|
29
|
+
reporter.record test_class.new(method).run
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.runnable_methods
|
33
|
+
instance_methods.select { |method| method.to_s.start_with?("test_") }
|
34
|
+
end
|
35
|
+
|
36
|
+
def setup
|
37
|
+
end
|
38
|
+
|
39
|
+
def teardown
|
40
|
+
end
|
41
|
+
|
42
|
+
def assertions
|
43
|
+
@_assertions
|
44
|
+
end
|
45
|
+
|
46
|
+
def name
|
47
|
+
"#{self.class.name}##{@_test_method}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def passed?
|
51
|
+
assertions.passed?
|
52
|
+
end
|
53
|
+
|
54
|
+
def errored?
|
55
|
+
assertions.errored?
|
56
|
+
end
|
57
|
+
|
58
|
+
def failed?
|
59
|
+
assertions.failed?
|
60
|
+
end
|
61
|
+
|
62
|
+
def result_code # rubocop:disable Metrics/MethodLength
|
63
|
+
if passed?
|
64
|
+
"."
|
65
|
+
elsif skipped?
|
66
|
+
"S"
|
67
|
+
elsif errored?
|
68
|
+
"E"
|
69
|
+
elsif failed?
|
70
|
+
"F"
|
71
|
+
else
|
72
|
+
"?"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def run
|
77
|
+
begin
|
78
|
+
setup
|
79
|
+
send @_test_method
|
80
|
+
ensure
|
81
|
+
teardown
|
82
|
+
end
|
83
|
+
rescue => e
|
84
|
+
assertions.error = e
|
85
|
+
ensure
|
86
|
+
return self # rubocop:disable Lint/EnsureReturn
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module Attestify
|
2
|
+
# Holds the tests that will be loaded for a test run.
|
3
|
+
class TestList
|
4
|
+
attr_reader :dir, :test_helper_file
|
5
|
+
|
6
|
+
def initialize(files = nil, dir: nil)
|
7
|
+
@dir = dir || "./test"
|
8
|
+
@provided_files = files
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_helper_file
|
12
|
+
@test_helper_file_path ||= File.join(dir, "test_helper.rb")
|
13
|
+
@test_helper_file_path if File.file?(@test_helper_file_path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_files
|
17
|
+
@test_files ||= test_filters.map(&:file)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run?(test_class, method)
|
21
|
+
test_filters.any? { |filter| filter.run?(test_class, method) }
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def test_filters
|
27
|
+
@test_filters ||=
|
28
|
+
begin
|
29
|
+
if provided_files?
|
30
|
+
@provided_files.map { |path| all_file_filters_for(path) }.flatten.compact
|
31
|
+
else
|
32
|
+
all_file_filters_for(dir) || []
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def provided_files?
|
38
|
+
@provided_files && !@provided_files.empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
def all_file_filters_for(path)
|
42
|
+
if File.directory?(path)
|
43
|
+
Dir[File.join(path, "**/*_test.rb")].map { |file| Attestify::TestList::FileFilter.new(file) }
|
44
|
+
elsif File.file?(path)
|
45
|
+
Attestify::TestList::FileFilter.new(path)
|
46
|
+
elsif path =~ /:\d+\z/
|
47
|
+
Attestify::TestList::FileFilter.with_line(path)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Filters tests that aren't defined in the provided file. If a
|
52
|
+
# line is provided, then only the test defined above that line
|
53
|
+
# will not be filtered.
|
54
|
+
class FileFilter
|
55
|
+
attr_reader :file, :line
|
56
|
+
|
57
|
+
def initialize(file, line = nil)
|
58
|
+
@file = file
|
59
|
+
@line = line
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.with_line(path_with_line)
|
63
|
+
match = /\A(.*):(\d+)\z/.match(path_with_line)
|
64
|
+
return unless File.file?(match[1])
|
65
|
+
new(match[1], match[2].to_i)
|
66
|
+
end
|
67
|
+
|
68
|
+
def run?(test_class, method)
|
69
|
+
file_matches?(test_class, method) && line_matches?(test_class, method)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def file_matches?(test_class, method)
|
75
|
+
real_file == Attestify::TestList::RealSourceLocationCache[test_class].real_file(method)
|
76
|
+
end
|
77
|
+
|
78
|
+
def line_matches?(test_class, method)
|
79
|
+
if line
|
80
|
+
Attestify::TestList::RealSourceLocationCache[test_class].in_method?(method, line)
|
81
|
+
else
|
82
|
+
true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def real_file
|
87
|
+
@real_file ||= File.realpath(file)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Helper class to keep track of source locations of methods for
|
92
|
+
# tests.
|
93
|
+
class TestClassSourceLocations
|
94
|
+
def initialize(test_class)
|
95
|
+
@test_class = test_class
|
96
|
+
end
|
97
|
+
|
98
|
+
def real_file(method)
|
99
|
+
real_source_locations[method].first
|
100
|
+
end
|
101
|
+
|
102
|
+
def in_method?(method, line)
|
103
|
+
method_at(line) == method
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def method_at(line)
|
109
|
+
result = nil
|
110
|
+
|
111
|
+
runnable_method_lines.each do |source_location|
|
112
|
+
return result if source_location.last > line
|
113
|
+
result = source_location.first
|
114
|
+
end
|
115
|
+
|
116
|
+
result
|
117
|
+
end
|
118
|
+
|
119
|
+
def runnable_methods
|
120
|
+
@runnable_methods ||= @test_class.runnable_methods
|
121
|
+
end
|
122
|
+
|
123
|
+
def runnable_method_lines
|
124
|
+
@runnable_method_lines ||= runnable_methods.map do |runnable_method|
|
125
|
+
[runnable_method] + real_source_locations[runnable_method]
|
126
|
+
end.sort do |a, b| # rubocop:disable Style/MultilineBlockChain
|
127
|
+
if a != b
|
128
|
+
a.last <=> b.last
|
129
|
+
else
|
130
|
+
a.first <=> b.first
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def real_source_locations
|
136
|
+
@real_source_locations ||= Hash.new do |hash, method|
|
137
|
+
hash[method] = @test_class.instance_method(method).source_location.tap do |result|
|
138
|
+
result[0] = File.realpath(result[0])
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Helper class to cache source locations TestClassSourceLocations
|
145
|
+
# for classes.
|
146
|
+
class RealSourceLocationCache
|
147
|
+
class << self
|
148
|
+
def [](test_class)
|
149
|
+
hash[test_class]
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def hash
|
155
|
+
Thread.current[:Attestify_TestList_RealSourceLocationCache] ||= Hash.new do |hash, test_class|
|
156
|
+
hash[test_class] = Attestify::TestList::TestClassSourceLocations.new(test_class)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "attestify"
|
2
|
+
|
3
|
+
module Attestify
|
4
|
+
# A basic test runner to run all tests.
|
5
|
+
class TestRunner
|
6
|
+
attr_reader :test_list, :reporter
|
7
|
+
|
8
|
+
def initialize(test_list, reporter)
|
9
|
+
@test_list = test_list
|
10
|
+
@reporter = reporter
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
require_helper
|
15
|
+
require_tests
|
16
|
+
run_tests
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def require_helper
|
22
|
+
require_real_file test_list.test_helper_file
|
23
|
+
end
|
24
|
+
|
25
|
+
def require_tests
|
26
|
+
test_list.test_files.each { |f| require_real_file f }
|
27
|
+
end
|
28
|
+
|
29
|
+
# If we don't require via realpath, some relative paths will be
|
30
|
+
# rejected as not being in Ruby's path.
|
31
|
+
def require_real_file(file)
|
32
|
+
return unless file
|
33
|
+
require File.realpath(file)
|
34
|
+
end
|
35
|
+
|
36
|
+
def run_tests
|
37
|
+
Attestify::Test.tests.each do |test|
|
38
|
+
test.run(reporter, test_list)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def report_tests
|
43
|
+
reporter.report
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Attestify
|
2
|
+
# A timer for keeping track of the timing of code.
|
3
|
+
class Timer
|
4
|
+
attr_reader :duration, :result
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
start_time = Time.new
|
8
|
+
@result = yield
|
9
|
+
ensure
|
10
|
+
end_time = Time.new
|
11
|
+
@duration = end_time - start_time
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.time
|
15
|
+
Timer.new do
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
if duration < 1.0
|
22
|
+
format("%.1f milliseconds", duration * 1000.0)
|
23
|
+
elsif duration < 60.0
|
24
|
+
format("%.1f seconds", duration)
|
25
|
+
else
|
26
|
+
format("%.2f minutes", duration / 60.0)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: attestify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.pre.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Virata-Stone
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.40.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.40.0
|
55
|
+
description: A small framework for testing your code. It keeps track of assertion
|
56
|
+
failures as well as test failures.
|
57
|
+
email:
|
58
|
+
- mike@virata-stone.com
|
59
|
+
executables:
|
60
|
+
- attestify
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- ".gitignore"
|
65
|
+
- ".rubocop.yml"
|
66
|
+
- ".travis.yml"
|
67
|
+
- CODE_OF_CONDUCT.md
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE.txt
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- attestify.gemspec
|
73
|
+
- bin/console
|
74
|
+
- bin/setup
|
75
|
+
- exe/attestify
|
76
|
+
- lib/attestify.rb
|
77
|
+
- lib/attestify/assertion_results.rb
|
78
|
+
- lib/attestify/assertions.rb
|
79
|
+
- lib/attestify/assertions/output_assertion.rb
|
80
|
+
- lib/attestify/cli.rb
|
81
|
+
- lib/attestify/color_reporter.rb
|
82
|
+
- lib/attestify/mock.rb
|
83
|
+
- lib/attestify/rake_task.rb
|
84
|
+
- lib/attestify/reporter.rb
|
85
|
+
- lib/attestify/skipped_error.rb
|
86
|
+
- lib/attestify/test.rb
|
87
|
+
- lib/attestify/test_list.rb
|
88
|
+
- lib/attestify/test_runner.rb
|
89
|
+
- lib/attestify/timer.rb
|
90
|
+
- lib/attestify/version.rb
|
91
|
+
homepage: https://github.com/smellsblue/attestify
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 1.3.1
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.5.1
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: A new way to test your code
|
115
|
+
test_files: []
|