speckle 0.1.2

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.
Files changed (67) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +39 -0
  6. data/Rakefile +230 -0
  7. data/bin/speckle +12 -0
  8. data/lib/dsl.riml +29 -0
  9. data/lib/expectation.riml +34 -0
  10. data/lib/matchers/above_matcher.riml +13 -0
  11. data/lib/matchers/atleast_matcher.riml +13 -0
  12. data/lib/matchers/atmost_matcher.riml +13 -0
  13. data/lib/matchers/below_matcher.riml +13 -0
  14. data/lib/matchers/between_matcher.riml +19 -0
  15. data/lib/matchers/boolean_matcher.riml +13 -0
  16. data/lib/matchers/dict_key_matcher.riml +14 -0
  17. data/lib/matchers/equality_matcher.riml +13 -0
  18. data/lib/matchers/existance_matcher.riml +13 -0
  19. data/lib/matchers/length_matcher.riml +14 -0
  20. data/lib/matchers/match_item.riml +8 -0
  21. data/lib/matchers/match_tester.riml +33 -0
  22. data/lib/matchers/matchers.riml +72 -0
  23. data/lib/matchers/regexp_matcher.riml +14 -0
  24. data/lib/matchers/within_matcher.riml +28 -0
  25. data/lib/reporters/base_reporter.riml +126 -0
  26. data/lib/reporters/dotmatrix_reporter.riml +47 -0
  27. data/lib/reporters/min_reporter.riml +13 -0
  28. data/lib/reporters/reporter_factory.riml +15 -0
  29. data/lib/reporters/spec_reporter.riml +58 -0
  30. data/lib/reporters/tap_reporter.riml +38 -0
  31. data/lib/runners/runner.riml +49 -0
  32. data/lib/runners/spec_runner.riml +96 -0
  33. data/lib/speckle/cli/app.rb +18 -0
  34. data/lib/speckle/cli/controller.rb +67 -0
  35. data/lib/speckle/cli/environment.rb +148 -0
  36. data/lib/speckle/cli/rake_app.rb +146 -0
  37. data/lib/speckle/cli/router.rb +16 -0
  38. data/lib/speckle/loader.rb +10 -0
  39. data/lib/speckle/version.rb +3 -0
  40. data/lib/speckle.rb +4 -0
  41. data/lib/speckle.riml +148 -0
  42. data/lib/utils/spec_meta.riml +30 -0
  43. data/lib/utils/spec_timer.riml +30 -0
  44. data/lib/utils/statistician.riml +70 -0
  45. data/lib/writers/buffer_writer.riml +37 -0
  46. data/lib/writers/console_writer.riml +28 -0
  47. data/lib/writers/file_writer.riml +31 -0
  48. data/lib/writers/writer_factory.riml +13 -0
  49. data/spec/after_hooks_spec.riml +58 -0
  50. data/spec/before_hooks_spec.riml +38 -0
  51. data/spec/matchers/above_matcher_spec.riml +27 -0
  52. data/spec/matchers/atleast_matcher_spec.riml +28 -0
  53. data/spec/matchers/atmost_matcher_spec.riml +29 -0
  54. data/spec/matchers/below_matcher_spec.riml +28 -0
  55. data/spec/matchers/between_matcher_spec.riml +17 -0
  56. data/spec/matchers/boolean_matcher_spec.riml +27 -0
  57. data/spec/matchers/custom_matcher_spec.riml +47 -0
  58. data/spec/matchers/dict_key_matcher_spec.riml +19 -0
  59. data/spec/matchers/equality_matcher_spec.riml +31 -0
  60. data/spec/matchers/existance_matcher_spec.riml +17 -0
  61. data/spec/matchers/length_matcher_spec.riml +18 -0
  62. data/spec/matchers/regexp_matcher_spec.riml +31 -0
  63. data/spec/matchers/within_matcher_spec.riml +18 -0
  64. data/spec/spec_helper.rb +1 -0
  65. data/spec/speckle/cli/environment_spec.rb +296 -0
  66. data/speckle.gemspec +30 -0
  67. metadata +210 -0
@@ -0,0 +1,148 @@
1
+ module Speckle
2
+
3
+ module CLI
4
+
5
+ require 'optparse'
6
+ require 'ostruct'
7
+
8
+ class Environment
9
+ include Loader
10
+
11
+ def load(args)
12
+ options = OpenStruct.new
13
+ options.libs = nil
14
+ options.grep_pattern = nil
15
+ options.grep_invert = false
16
+ options.reporter = 'dot'
17
+ options.args = args
18
+ options.verbose = false
19
+ options.vim = 'vim'
20
+ options.cwd = Dir.pwd
21
+ options.root_dir = ROOT_DIR
22
+ options.speckle_build_dir = "#{ROOT_DIR}/build"
23
+ options.speckle_lib_dir = "#{ROOT_DIR}/lib"
24
+ options.skip_vimrc = false
25
+ options.slow_threshold = 10
26
+ options.colorize = true
27
+ options.bail = false
28
+
29
+ parser = OptionParser.new do |opts|
30
+ options.opts = opts
31
+
32
+ opts.banner = "Usage: speckle [options] [file(s) OR directory]"
33
+ opts.separator ''
34
+ opts.separator 'Options:'
35
+ opts.separator ''
36
+
37
+ opts.on_head('-c', '--compile', 'Only compile tests') do
38
+ options.action = :compile
39
+ end
40
+
41
+ opts.on_head('-t', '--test', 'Only run tests') do
42
+ options.action = :test
43
+ end
44
+
45
+ opts.on_head('-a', '--all', 'Compile and run tests (default)') do
46
+ options.action = :compile_and_test
47
+ end
48
+
49
+ opts.on('-I', '--libs <libs>', 'Specify additional riml library path(s)') do |libs|
50
+ options.libs = libs
51
+ end
52
+
53
+ opts.on('-g', '--grep <pattern>', 'Only run tests matching the pattern') do |pattern|
54
+ options.grep_pattern = pattern.strip
55
+ end
56
+
57
+ opts.on('-i', '--invert', 'Inverts --grep matches') do
58
+ options.grep_invert = true
59
+ end
60
+
61
+ opts.on('-r', '--reporter <reporter>', 'Specify the reporter to use (spec, min, dot, tap)') do |reporter|
62
+ options.reporter = reporter.strip
63
+ end
64
+
65
+ opts.on('-b', '--bail', 'Bail on first test failure') do
66
+ options.bail = true
67
+ end
68
+
69
+ opts.on('-w', '--watch', 'Watch tests for changes') do
70
+ options.action = :watch
71
+ end
72
+
73
+ opts.on('-m', '--vim <vim>', 'Vim program used to test, default(vim)') do |vim|
74
+ options.vim = vim.strip
75
+ end
76
+
77
+ opts.on('-s', '--slow-threshold <ms>', Integer, 'Threshold in milliseconds to indicate slow tests') do |ms|
78
+ options.slow_threshold = ms
79
+ end
80
+
81
+ opts.on('-k', '--skip-vimrc', 'Does not load ~/.vimrc file') do
82
+ options.skip_vimrc = true
83
+ end
84
+
85
+ opts.on('-C', '--no-colors', 'Disable color output') do
86
+ options.colorize = false
87
+ end
88
+
89
+ opts.on('-v', '--verbose', 'Display verbose output') do
90
+ options.verbose = true
91
+ end
92
+
93
+ opts.on('-D', '--debug', 'Display debug output') do
94
+ options.verbose = true
95
+ options.debug = true
96
+ end
97
+
98
+ opts.on_tail('-V', '--version', 'Print Speckle version') do
99
+ options.action = :show_version
100
+ end
101
+
102
+ opts.on_tail('-h', '--help', 'Print Speckle help') do
103
+ options.action = :show_help
104
+ end
105
+ end
106
+
107
+ begin
108
+ parser.parse!(args)
109
+
110
+ if options.action.nil?
111
+ spec_dir = "#{options.cwd}/spec"
112
+ if File.directory?(spec_dir)
113
+ args << 'spec'
114
+ options.action = :compile_and_test
115
+ else
116
+ options.action = :show_no_spec_dir
117
+ end
118
+ elsif action_needs_args?(options.action) and args.empty?
119
+ spec_dir = "#{options.cwd}/spec"
120
+ if File.directory?(spec_dir)
121
+ args << 'spec'
122
+ options.action = :compile_and_test
123
+ end
124
+ end
125
+
126
+ options.inputs = args
127
+ rescue OptionParser::InvalidOption => e
128
+ options.error = e
129
+ options.action = :show_invalid_option
130
+ rescue OptionParser::MissingArgument => e
131
+ options.error = e
132
+ options.action = :show_missing_args
133
+ rescue OptionParser::ParseError => e
134
+ options.error = e
135
+ options.action = :show_parser_error
136
+ end
137
+
138
+ options
139
+ end
140
+
141
+ def action_needs_args?(action)
142
+ [:compile_and_test, :compile, :test].include? action
143
+ end
144
+ end
145
+
146
+
147
+ end
148
+ end
@@ -0,0 +1,146 @@
1
+ module Speckle
2
+ module CLI
3
+
4
+ require 'rake'
5
+
6
+ class RakeApp
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def inputs
12
+ @options.inputs
13
+ end
14
+
15
+ def verbose
16
+ @options.verbose
17
+ end
18
+
19
+ def debug
20
+ @options.debug
21
+ end
22
+
23
+ def rake
24
+ if @rake_app
25
+ return @rake_app
26
+ end
27
+
28
+ configure_rake
29
+ Dir.chdir @options.root_dir
30
+
31
+ @rake_app = Rake.application
32
+ @rake_app.init
33
+ @rake_app.load_rakefile
34
+
35
+ Dir.chdir @options.cwd
36
+ @rake_app
37
+ end
38
+
39
+ def invoke_task(name)
40
+ rake.invoke_task("speckle:#{name.to_s}")
41
+ end
42
+
43
+ def rake_env(key, value)
44
+ unless value.nil?
45
+ ENV[key] = if value.is_a?(Array) then value.join(';') else value end
46
+ puts "rake_env: #{key} = #{ENV[key]}" if debug
47
+ end
48
+ end
49
+
50
+ def configure_rake
51
+ rake_env('TEST_SOURCES', test_sources)
52
+ rake_env('TEST_LIBS', test_libs)
53
+ rake_env('BUILD_DIR', test_build_dir)
54
+ rake_env('TEST_COMPILED', test_compiled)
55
+ rake_env('TEST_VIM', @options.vim)
56
+ rake_env('TEST_REPORTER', @options.reporter)
57
+ rake_env('SLOW_THRESHOLD', @options.slow_threshold.to_s)
58
+ rake_env('SKIP_VIMRC', to_int(@options.skip_vimrc))
59
+ rake_env('COLORIZE', to_int(@options.colorize))
60
+ rake_env('BAIL', to_int(@options.bail))
61
+
62
+ if @options.verbose
63
+ rake_env('VERBOSE', 'yes')
64
+ end
65
+
66
+ if @options.debug
67
+ rake_env('DEBUG', 'yes')
68
+ end
69
+ end
70
+
71
+ def to_int(option)
72
+ option ? '1' : '0'
73
+ end
74
+
75
+ def test_build_dir
76
+ "#{@options.cwd}/build"
77
+ end
78
+
79
+ def test_compiled
80
+ compiled = test_sources.map do |s|
81
+ s.ext('vim')
82
+ end
83
+
84
+ compiled
85
+ end
86
+
87
+ def test_sources
88
+ sources = []
89
+ grep_pattern = @options.grep_pattern
90
+ grep_invert = @options.grep_invert
91
+ unless grep_pattern.nil?
92
+ regex = Regexp.new(grep_pattern)
93
+ end
94
+
95
+ inputs.each do |input|
96
+ if File.directory?(input)
97
+ if grep_pattern.nil?
98
+ sources << "#{input}/**/*_spec.riml"
99
+ else
100
+ sources = Dir.glob("#{input}/**/*_spec.riml")
101
+ sources.keep_if do |source|
102
+ matched = regex.match(source)
103
+ if grep_invert
104
+ matched = !matched
105
+ end
106
+
107
+ matched
108
+ end
109
+ end
110
+ else
111
+ if grep_pattern.nil?
112
+ sources << input
113
+ else
114
+ matched = regex.match(input)
115
+ if grep_invert
116
+ matched = !matched
117
+ end
118
+ sources << input if matched
119
+ end
120
+ end
121
+ end
122
+
123
+ sources
124
+ end
125
+
126
+ def test_libs
127
+ input_libs = @options.libs
128
+ return nil if input_libs.nil?
129
+
130
+ input_libs = input_libs.split(':')
131
+ input_libs << 'spec'
132
+ if File.directory?(@options.speckle_lib_dir)
133
+ input_libs << @options.speckle_lib_dir
134
+ end
135
+
136
+ libs = []
137
+ input_libs.each do |lib|
138
+ libs << File.absolute_path(lib)
139
+ end
140
+
141
+ libs.join(':')
142
+ end
143
+
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,16 @@
1
+ module Speckle
2
+ module CLI
3
+
4
+ require_relative 'rake_app'
5
+ require_relative 'controller'
6
+
7
+ class Router
8
+ def route(action, options)
9
+ rake_app = RakeApp.new(options)
10
+ controller = Controller.new(options, rake_app)
11
+ controller.send(action)
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ module Speckle
2
+
3
+ module Loader
4
+ ROOT_DIR = File.expand_path('../../../', __FILE__)
5
+ LIB_DIR = File.join(ROOT_DIR, 'lib')
6
+
7
+ $:.unshift(LIB_DIR) unless $:.include? LIB_DIR
8
+ end
9
+
10
+ end
@@ -0,0 +1,3 @@
1
+ module Speckle
2
+ VERSION = "0.1.2"
3
+ end
data/lib/speckle.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "speckle/version"
2
+
3
+ module Speckle
4
+ end
data/lib/speckle.riml ADDED
@@ -0,0 +1,148 @@
1
+ "" utils
2
+ riml_include 'spec_timer.riml'
3
+ riml_include 'spec_meta.riml'
4
+ riml_include 'statistician.riml'
5
+
6
+ "" matchers
7
+ riml_include 'equality_matcher.riml'
8
+ riml_include 'boolean_matcher.riml'
9
+ riml_include 'existance_matcher.riml'
10
+ riml_include 'above_matcher.riml'
11
+ riml_include 'below_matcher.riml'
12
+ riml_include 'between_matcher.riml'
13
+ riml_include 'length_matcher.riml'
14
+ riml_include 'atleast_matcher.riml'
15
+ riml_include 'atmost_matcher.riml'
16
+ riml_include 'within_matcher.riml'
17
+ riml_include 'regexp_matcher.riml'
18
+ riml_include 'dict_key_matcher.riml'
19
+
20
+ "" matcher internals
21
+ riml_include 'match_item.riml'
22
+ riml_include 'match_tester.riml'
23
+ riml_include 'matchers.riml'
24
+
25
+ "" writers
26
+ riml_include 'file_writer.riml'
27
+ riml_include 'console_writer.riml'
28
+ riml_include 'buffer_writer.riml'
29
+ riml_include 'writer_factory.riml'
30
+
31
+ "" reporters
32
+ riml_include 'base_reporter.riml'
33
+ riml_include 'spec_reporter.riml'
34
+ riml_include 'min_reporter.riml'
35
+ riml_include 'tap_reporter.riml'
36
+ riml_include 'dotmatrix_reporter.riml'
37
+ riml_include 'reporter_factory.riml'
38
+
39
+ "" runners
40
+ riml_include 'spec_runner.riml'
41
+ riml_include 'runner.riml'
42
+
43
+ "" dsl
44
+ riml_include 'expectation.riml'
45
+
46
+ "" main entry point
47
+ class Speckle
48
+ defm configure()
49
+ options_map = {
50
+ \ 'output_file': '"speckle.log"',
51
+ \ 'file_mode': '0',
52
+ \ 'reporter_name': '"spec"',
53
+ \ 'slow_threshold': '10',
54
+ \ 'colorize': '1',
55
+ \ 'bail': '0'
56
+ \}
57
+
58
+ self.options(options_map)
59
+ end
60
+
61
+ defm options(options_map)
62
+ for [name, value] in items(options_map)
63
+ self.option(name, value)
64
+ end
65
+ end
66
+
67
+ defm option(variable, default)
68
+ if !exists("g:speckle_#{variable}")
69
+ execute("let g:speckle_#{variable} = #{default}")
70
+ end
71
+ end
72
+
73
+ defm get_writer()
74
+ factory = new WriterFactory()
75
+ writer = factory.get_writer('buffer')
76
+
77
+ if self.is_file_mode()
78
+ writer.set_output_file(self.get_output_file())
79
+ end
80
+
81
+ return writer
82
+ end
83
+
84
+ defm get_reporter(writer)
85
+ factory = new ReporterFactory()
86
+ reporter = factory.get_reporter(self.get_reporter_name())
87
+ reporter.set_writer(writer)
88
+
89
+ return reporter
90
+ end
91
+
92
+ defm is_file_mode
93
+ return g:speckle_file_mode
94
+ end
95
+
96
+ defm get_output_file
97
+ return g:speckle_output_file
98
+ end
99
+
100
+ defm get_reporter_name
101
+ return g:speckle_reporter_name
102
+ end
103
+
104
+ defm get_slow_threshold
105
+ return g:speckle_slow_threshold
106
+ end
107
+
108
+ defm get_colorize
109
+ return g:speckle_colorize
110
+ end
111
+
112
+ defm get_bail
113
+ return g:speckle_bail
114
+ end
115
+
116
+ defm run()
117
+ self.configure()
118
+
119
+ writer = self.get_writer()
120
+ stats = new Statistician()
121
+ reporter = self.get_reporter(writer)
122
+ reporter.set_colorize_output(self.get_colorize())
123
+ runner = new Runner()
124
+ runner.set_bail(self.get_bail())
125
+ functions = ''
126
+
127
+ :redir => functions
128
+ :silent function /SpecConstructor$/
129
+ :redir END
130
+
131
+ self.add_specs(runner, functions)
132
+
133
+ runner.start(reporter, stats)
134
+
135
+ if self.is_file_mode()
136
+ writer.flush()
137
+ end
138
+ end
139
+
140
+ defm add_specs(runner, lines)
141
+ classes = split(lines, "\n")
142
+ map(classes, "substitute(v:val, 'function ', '', '')")
143
+
144
+ for klass in classes
145
+ eval("a:runner.add(#{klass})")
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,30 @@
1
+ class SpecMeta
2
+ def initialize(context, method)
3
+ self.context = context
4
+ self.method = method
5
+ end
6
+
7
+ defm get_context()
8
+ return self.context
9
+ end
10
+
11
+ defm get_method()
12
+ return self.method
13
+ end
14
+
15
+ defm get_sentence()
16
+ return substitute(self.get_method(), '_', ' ', 'g')
17
+ end
18
+
19
+ defm set_duration(duration)
20
+ self.duration = duration
21
+ end
22
+
23
+ defm get_duration()
24
+ return self.duration
25
+ end
26
+
27
+ defm is_slow()
28
+ return self.get_duration() > g:speckle_slow_threshold
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ class SpecTimer
2
+ def initialize()
3
+ self.start_time = 0
4
+ self.end_time = 0
5
+ end
6
+
7
+ defm start()
8
+ self.start_time = reltime()
9
+ end
10
+
11
+ defm stop()
12
+ self.end_time = reltime()
13
+ self.duration = self.time_to_ms(reltime(self.start_time))
14
+ end
15
+
16
+ defm get_duration()
17
+ return self.duration
18
+ end
19
+
20
+ defm time_to_ms(time)
21
+ duration_str = reltimestr(time)
22
+ duration_split = split(duration_str, '\.')
23
+ seconds = str2nr(duration_split[0])
24
+ microseconds = str2nr(duration_split[1])
25
+ milliseconds = (seconds * 1000) + (microseconds / 1000)
26
+
27
+ return milliseconds
28
+ end
29
+
30
+ end
@@ -0,0 +1,70 @@
1
+ class Statistician
2
+ def initialize()
3
+ self.count = 0
4
+ self.passes = 0
5
+ self.failures = 0
6
+ self.errors = 0
7
+ self.pending = 0
8
+ end
9
+
10
+ defm inc_count()
11
+ self.count += 1
12
+ end
13
+
14
+ defm inc_passes()
15
+ self.inc_count()
16
+ self.passes += 1
17
+ end
18
+
19
+ defm inc_failures()
20
+ self.inc_count()
21
+ self.failures += 1
22
+ end
23
+
24
+ defm inc_pending()
25
+ self.inc_count()
26
+ self.pending += 1
27
+ end
28
+
29
+ defm inc_errors()
30
+ self.inc_count()
31
+ self.errors += 1
32
+ end
33
+
34
+ defm inc_assertions()
35
+ env = g:speckle_env
36
+ env.assertions += 1
37
+ end
38
+
39
+ defm get_count()
40
+ return self.count
41
+ end
42
+
43
+ defm get_passes()
44
+ return self.passes
45
+ end
46
+
47
+ defm get_failures()
48
+ return self.failures
49
+ end
50
+
51
+ defm get_pending()
52
+ return self.pending
53
+ end
54
+
55
+ defm get_errors()
56
+ return self.errors
57
+ end
58
+
59
+ defm get_assertions()
60
+ return g:speckle_env.assertions
61
+ end
62
+
63
+ defm is_ok()
64
+ return self.get_errors() == 0 && self.get_failures() == 0
65
+ end
66
+
67
+ defm is_not_ok()
68
+ return !self.is_ok()
69
+ end
70
+ end
@@ -0,0 +1,37 @@
1
+ class BufferWriter
2
+ def initialize()
3
+ self.writer = new FileWriter()
4
+ end
5
+
6
+ defm set_output_file(output_file)
7
+ self.writer.set_output_file(output_file)
8
+ end
9
+
10
+ defm strip_colors(line)
11
+ return substitute(line, '\e\[[0-9;]\+[mK]', '', 'g')
12
+ end
13
+
14
+ defm write(line)
15
+ self.writer.write(line)
16
+
17
+ line = self.strip_colors(line)
18
+ append(line('$'), line)
19
+ :normal gJ
20
+ end
21
+
22
+ defm writeln(line)
23
+ self.writer.writeln(line)
24
+
25
+ line = self.strip_colors(line)
26
+ append(line('$'), line)
27
+ :normal G
28
+ end
29
+
30
+ defm flush()
31
+ self.writer.flush()
32
+ end
33
+
34
+ defm flush_line()
35
+ self.writer.flush_line()
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ class ConsoleWriter
2
+ def initialize()
3
+ self.writer = new FileWriter()
4
+ end
5
+
6
+ defm set_output_file(output_file)
7
+ self.writer.set_output_file(output_file)
8
+ end
9
+
10
+ defm write(line)
11
+ self.writer.write(line)
12
+ echon line
13
+ end
14
+
15
+ defm writeln(line)
16
+ self.writer.writeln(line)
17
+ echomsg line
18
+ end
19
+
20
+ defm flush()
21
+ self.writer.flush()
22
+ end
23
+
24
+ defm flush_line()
25
+ self.writer.flush_line()
26
+ end
27
+ end
28
+
@@ -0,0 +1,31 @@
1
+ class FileWriter
2
+ def initialize()
3
+ self.lines = []
4
+ self.current_line = ''
5
+ end
6
+
7
+ defm set_output_file(output_file)
8
+ self.output_file = output_file
9
+ end
10
+
11
+ defm write(line)
12
+ self.current_line = "#{self.current_line}#{line}"
13
+ end
14
+
15
+ defm writeln(line)
16
+ self.flush_line()
17
+ add(self.lines, line)
18
+ end
19
+
20
+ defm flush_line()
21
+ unless self.current_line == ''
22
+ add(self.lines, self.current_line)
23
+ self.current_line = ''
24
+ end
25
+ end
26
+
27
+ defm flush()
28
+ self.flush_line()
29
+ writefile(self.lines, self.output_file)
30
+ end
31
+ end