speckle 0.1.18 → 0.1.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +274 -9
- data/lib/runners/runner.riml +1 -0
- data/lib/runners/spec_runner.riml +7 -1
- data/lib/speckle/cli/environment.rb +19 -2
- data/lib/speckle/version.rb +1 -1
- data/lib/speckle.riml +7 -2
- data/spec/before_hooks_spec.riml +0 -1
- data/spec/with_describe_spec.riml +7 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZDlkY2JlNWI2YzU0Nzk1YWEyOWQ5M2YwZGNkNGIxMjIwZTIwMGI0ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OWNlZjUyYTc2MjdmYTQwMzhiMTg1MzBhNTZmZjdjMmFmYTlkYTdjZg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODllNmEwN2E0ZGEzZDk5ZTNiMDljMmEyOGY5MTE0MjQyMmFiOGY2MDMzNzU3
|
10
|
+
Njk1Mzc4YzY1MmE0YzU1NDA4ZTkzZGI2NjEwNWE5ZGQxMjUxY2JiZTUzYTI5
|
11
|
+
ODRjZTU5ZmY3Y2EzZjU3MjI0ODZjODBiMDI3ODk0MzNiZTc4OGQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTAxMmE2M2MzNmQwOGQ2ZjA4NTFjNTQxMzQxODczMmY5MDNhMDE0MmM1ZjJj
|
14
|
+
OTBjMDY0YTM5ZGFlMTgwYzkyZjQ2ZTUwMzA3Y2QwYTllYWYyNGJmZDFmNWVl
|
15
|
+
ZTFjZDU0YjdlOGJlOWUxNWIzZjcyOTM4MDhmMjg5N2VkMGM5YTg=
|
data/README.md
CHANGED
@@ -1,14 +1,277 @@
|
|
1
|
-
|
1
|
+
## Speckle
|
2
2
|
|
3
|
-
Behaviour driven framework for testing
|
3
|
+
Behaviour driven development framework for testing Vim plugins written in [Riml][1].
|
4
4
|
|
5
5
|
[![Build Status](https://travis-ci.org/dsawardekar/speckle.png)](https://travis-ci.org/dsawardekar/speckle)
|
6
6
|
|
7
|
+
### About Riml
|
8
|
+
For people unfamiliar with `Riml`. [Riml][1] is a programming language that compiles to Vimscript. It's constructs are very similar to languages like `Ruby` and `Coffeescript`. It also provides a layer of abstraction to write OOP code that is converted to Vimscript's Funcref prototype chains.
|
9
|
+
|
10
|
+
### How Speckle works
|
11
|
+
Speckle uses `Riml`s object-oriented constructs to provide
|
12
|
+
a BDD testing framework for Riml. You can use it for both unit testing and functional testing. Using Riml and Speckle you can write Vim plugins using common OOP software idioms and have the same familar tools available in your development workflow.
|
13
|
+
|
14
|
+
Speckle is both a test compiler and test execution engine. It does compilation of the `_spec.riml` specs with [Riml][1] and runs them in a Vim instance, capturing assertions, stacktraces and errors and reports them back after
|
15
|
+
closing the launched vim instance.
|
16
|
+
|
17
|
+
[1]:https://github.com/luke-gru/riml
|
18
|
+
|
7
19
|
## Installation
|
8
20
|
|
9
21
|
$ gem install speckle
|
10
22
|
|
11
|
-
## Usage
|
23
|
+
## Basic Usage
|
24
|
+
|
25
|
+
Here's an example using Speckle.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
riml_include 'dsl.riml'
|
29
|
+
|
30
|
+
class MyFirstSpec
|
31
|
+
defm describe
|
32
|
+
return 'My First Spec'
|
33
|
+
end
|
34
|
+
|
35
|
+
defm it_can_check_equality_of_strings
|
36
|
+
my_string = 'v' . 'i' . 'm'
|
37
|
+
expect(my_string).to_equal(vim)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
A test example is a `Riml` class with a test method that begins with `it`. You can optionally provide a `describe` method to change the displayed name for test in the reporter output.
|
43
|
+
|
44
|
+
Note the `riml_include dsl.riml`. This include provides Speckle's `expect` dsl for use inside the test examples. The path to this include is autoconfigured by Speckle. For including your own classes specify the path like `-I lib`. Where lib is the directory containing your Vim plugin .riml files.
|
45
|
+
|
46
|
+
Speckle looks for tests in the `spec` folder by default. The tests should be named in the form `{name}_spec.riml`. The above example could be saved as
|
47
|
+
`spec/my_first_spec.riml`. To run this test use,
|
48
|
+
|
49
|
+
$ speckle
|
50
|
+
|
51
|
+
If the test succeeded you will get a message like,
|
52
|
+
|
53
|
+
```log
|
54
|
+
✓ 1 tests completed (5ms)
|
55
|
+
Passed: 1, Failures: 0, Errors: 0, Assertions: 1
|
56
|
+
```
|
57
|
+
|
58
|
+
If you change the input string to only `vi` and run it again you will
|
59
|
+
see a message like,
|
60
|
+
|
61
|
+
```log
|
62
|
+
EqualityMatcher #it can check equality of strings
|
63
|
+
AssertionError: expected “vi” to equal “vim”
|
64
|
+
|
65
|
+
|
66
|
+
✖ 1 tests completed (5ms)
|
67
|
+
Passed: 0, Failures: 1, Errors: 0, Assertions: 0
|
68
|
+
```
|
69
|
+
|
70
|
+
## Matchers
|
71
|
+
|
72
|
+
### Equivalence
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
expect(actual).to_equal(expected) # passes if actual == expected
|
76
|
+
expect(actual).to_not_equal(expected) # passes if actual != expected
|
77
|
+
```
|
78
|
+
|
79
|
+
Note: A type mismatch will be thrown when comparing values with
|
80
|
+
different types.
|
81
|
+
|
82
|
+
### Comparisons
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
expect(actual).to_be_gt(expected) # -ve to_not_be_gt
|
86
|
+
expect(actual).to_be_gte(expected) # -ve to_not_be_gte
|
87
|
+
expect(actual).to_be_lte(expected) # -ve to_not_be_lte
|
88
|
+
expect(actual).to_be_lt(expected) # -ve to_not_be_lt
|
89
|
+
expect(actual).to_be_within([delta, expected]) # -ve to_not_be_within
|
90
|
+
expect(actual).to_be_between([min, max]) # -ve to_not_be_between
|
91
|
+
```
|
92
|
+
|
93
|
+
### Regular expressions
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
expect(actual).to_match(pattern) # -ve to_not_match
|
97
|
+
```
|
98
|
+
|
99
|
+
### Boolean
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
expect(actual).to_be_true(expected) # -ve to_be_false
|
103
|
+
expect(actual).to_be_ok(expected) # -ve to_not_be_ok
|
104
|
+
```
|
105
|
+
|
106
|
+
### Existance
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
expect(actual).to_exist() # passes if exists(actual) is not false
|
110
|
+
expect(actual).to_not_exist() # -ve
|
111
|
+
```
|
112
|
+
|
113
|
+
### Dictionary
|
114
|
+
```ruby
|
115
|
+
expect(actual).to_have_key(expected) # passes if actual is a dict with key expected
|
116
|
+
expect(actual).to_not_have_key(expected) # -ve
|
117
|
+
```
|
118
|
+
### Length
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
expect(actual).to_have_length(expected) # passes if len(actual) == expected
|
122
|
+
expect(actual).to_not_have_length(expected) # -ve
|
123
|
+
```
|
124
|
+
|
125
|
+
## Custom Matchers
|
126
|
+
|
127
|
+
In addition to the above default matchers you can create custom
|
128
|
+
matchers easily.
|
129
|
+
|
130
|
+
Consider a Person class in Riml.
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
class Person
|
134
|
+
def initialize(name)
|
135
|
+
self.name = name
|
136
|
+
end
|
137
|
+
|
138
|
+
defm get_name()
|
139
|
+
return self.name
|
140
|
+
end
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
To write matcher to check if a person has the correct name we can
|
145
|
+
write a `PersonNameMatcher`. The class must implement the methods, `match`, `failure_message_for_match` and `failure_message_for_mismatch` as shown below.
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
class PersonNameMatcher
|
149
|
+
defm match(expected, actual)
|
150
|
+
self.result = actual.get_name()
|
151
|
+
return self.result == expected
|
152
|
+
end
|
153
|
+
|
154
|
+
defm failure_message_for_match(expected, actual)
|
155
|
+
return "expected person name to be “#{expected}” but was “#{self.result}”"
|
156
|
+
end
|
157
|
+
|
158
|
+
defm failure_message_for_mismatch(expected, actual)
|
159
|
+
return "expected person name to not be “#{expected}” but was “#{self.result}”"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
```
|
164
|
+
|
165
|
+
Then inside your spec you need to register this matcher using `define_matcher`,
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
matcher = new PersonNameMatcher()
|
169
|
+
define_matcher('to_have_name', 'to_not_have_name', matcher)
|
170
|
+
```
|
171
|
+
|
172
|
+
Now in a test you can use the custom matcher methods, `to_have_name`, and it's negative `to_not_have_name`.
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
defm it_can_check_for_persons_name
|
176
|
+
expect(self.person).to_have_name('john')
|
177
|
+
end
|
178
|
+
|
179
|
+
defm it_can_check_for_negation_of_persons_name
|
180
|
+
expect(self.person).to_not_have_name('foo')
|
181
|
+
end
|
182
|
+
```
|
183
|
+
|
184
|
+
## Hooks
|
185
|
+
|
186
|
+
Speckle supports `before`, `before_each`, `after` and `after_each` hooks
|
187
|
+
that will be run before/after the entire suite or before/after every test.
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
defm before
|
191
|
+
end
|
192
|
+
|
193
|
+
defm before_each
|
194
|
+
end
|
195
|
+
|
196
|
+
defm after
|
197
|
+
end
|
198
|
+
|
199
|
+
defm after_each
|
200
|
+
end
|
201
|
+
```
|
202
|
+
|
203
|
+
## Logging (alternate to echomsg)
|
204
|
+
|
205
|
+
Speckle provides a logger that captures output messages without
|
206
|
+
halting execution of tests. This allows development of vim plugins
|
207
|
+
without needing to use `echomsg` extensively.
|
208
|
+
|
209
|
+
The logger api is,
|
210
|
+
|
211
|
+
```
|
212
|
+
get_logger().log(msg, ...)
|
213
|
+
get_logger().info(msg, ...)
|
214
|
+
get_logger().warn(msg, ...)
|
215
|
+
get_logger().error(msg, ...)
|
216
|
+
get_logger().debug(msg, ...)
|
217
|
+
```
|
218
|
+
|
219
|
+
When running the tests the error messages are shown inline like below.
|
220
|
+
|
221
|
+
```log
|
222
|
+
LoggerSpec
|
223
|
+
✓ it logs a message
|
224
|
+
|
225
|
+
log: Hello World
|
226
|
+
log: A test warning
|
227
|
+
log: An error warning
|
228
|
+
|
229
|
+
```
|
230
|
+
|
231
|
+
## Stacktraces
|
232
|
+
|
233
|
+
Another useful feature of Speckle is it displays stacktraces in a
|
234
|
+
meaningful form to help with debugging.
|
235
|
+
|
236
|
+
The example below has a call to an undefined function.
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
defm it_has_unknown_function
|
240
|
+
CallFooFunction()
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
244
|
+
When this test is run the following stacktrace will be shown.
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
VariousErrorsSpec #it has unknown function
|
248
|
+
Vim(call):E117: Unknown function: <SNR>144_CallFooFunction
|
249
|
+
at <SNR>143_s:Speckle_run
|
250
|
+
at <SNR>143_s:Runner_start
|
251
|
+
at <SNR>143_s:SpecRunner_start
|
252
|
+
at <SNR>144_s:VariousErrorsSpec_it_has_unknown_function, line 2
|
253
|
+
```
|
254
|
+
|
255
|
+
## Isolated Testing
|
256
|
+
|
257
|
+
Speckle can be made to run only specific tests using the `--grep` option. For example, to only run tests in the `spec/models` folder use
|
258
|
+
|
259
|
+
$ speckle --grep spec/models
|
260
|
+
|
261
|
+
Further to only run specific tests we can tag the test with a keyword, and then use `--tag keyword` to run only those tests. Tagging is done by adding a `_tagname` suffix to the test method name. For example to tag a spec with the tag `perf`, you would use,
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
defm it_will_work_perf
|
265
|
+
end
|
266
|
+
```
|
267
|
+
|
268
|
+
And run the test with,
|
269
|
+
|
270
|
+
$ speckle --tag perf
|
271
|
+
|
272
|
+
Both these flags can be combined to limit the tests run.
|
273
|
+
|
274
|
+
## Complete Usage
|
12
275
|
|
13
276
|
$ speckle [options] [file(s) OR directory]
|
14
277
|
-a, --all Compile and run tests (default)
|
@@ -20,7 +283,7 @@ Options:
|
|
20
283
|
-I, --libs <libs> Specify additional riml library path(s)
|
21
284
|
-g, --grep <pattern> Only run tests matching the pattern
|
22
285
|
-i, --invert Inverts --grep matches
|
23
|
-
-r, --reporter <reporter> Specify the reporter to use (spec, min, dot, tap)
|
286
|
+
-r, --reporter <reporter> Specify the reporter to use (spec, min, dot, tap, fivemat)
|
24
287
|
-b, --bail Bail on first test failure
|
25
288
|
-w, --watch Watch tests for changes
|
26
289
|
-m, --vim <vim> Vim program used to test, default(vim)
|
@@ -34,8 +297,10 @@ Options:
|
|
34
297
|
|
35
298
|
## Contributing
|
36
299
|
|
37
|
-
1.
|
38
|
-
2.
|
39
|
-
3.
|
40
|
-
|
41
|
-
|
300
|
+
1. Speckle uses [git flow](https://github.com/nvie/gitflow) based branching model.
|
301
|
+
2. Pull requests should go against the `develop` branch.
|
302
|
+
3. Try to include failing tests if possible.
|
303
|
+
|
304
|
+
## License
|
305
|
+
|
306
|
+
MIT License. Copyright (c) 2013 Darshan Sawardekar.
|
data/lib/runners/runner.riml
CHANGED
@@ -23,7 +23,13 @@ class SpecRunner
|
|
23
23
|
defm start(reporter, stats)
|
24
24
|
spec = self.spec
|
25
25
|
did_fail = false
|
26
|
-
|
26
|
+
if has_key(spec, 'describe')
|
27
|
+
context = self.call_hook('describe')
|
28
|
+
elseif has_key(spec, 'spec_name')
|
29
|
+
context = spec.spec_name
|
30
|
+
else
|
31
|
+
context = 'Unknown Spec'
|
32
|
+
end
|
27
33
|
reporter.on_context_start(context, stats)
|
28
34
|
|
29
35
|
try
|
@@ -4,6 +4,7 @@ module Speckle
|
|
4
4
|
|
5
5
|
require 'optparse'
|
6
6
|
require 'ostruct'
|
7
|
+
require 'find'
|
7
8
|
|
8
9
|
class Environment
|
9
10
|
include Loader
|
@@ -94,7 +95,7 @@ module Speckle
|
|
94
95
|
opts.on('-v', '--verbose', 'Display verbose output') do
|
95
96
|
options.verbose = true
|
96
97
|
end
|
97
|
-
|
98
|
+
|
98
99
|
opts.on('-D', '--debug', 'Display debug output') do
|
99
100
|
options.verbose = true
|
100
101
|
options.debug = true
|
@@ -140,14 +141,30 @@ module Speckle
|
|
140
141
|
options.action = :show_parser_error
|
141
142
|
end
|
142
143
|
|
144
|
+
if action_needs_args?(options.action) and options.libs.nil?
|
145
|
+
options.libs = build_riml_path(['lib', 'spec'])
|
146
|
+
end
|
147
|
+
|
143
148
|
options
|
144
149
|
end
|
145
150
|
|
146
151
|
def action_needs_args?(action)
|
147
152
|
[:compile_and_test, :compile, :test].include? action
|
148
153
|
end
|
149
|
-
end
|
150
154
|
|
155
|
+
def build_riml_path(dirs, pattern = /.*\.riml$/, spec_pattern = /.*_spec\.riml$/)
|
156
|
+
libs = []
|
157
|
+
dirs.each do |dir|
|
158
|
+
Find.find(dir) do |path|
|
159
|
+
if path =~ pattern && path !~ spec_pattern
|
160
|
+
libs << File.dirname(path)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
libs.uniq.join(':')
|
166
|
+
end
|
167
|
+
end
|
151
168
|
|
152
169
|
end
|
153
170
|
end
|
data/lib/speckle/version.rb
CHANGED
data/lib/speckle.riml
CHANGED
@@ -120,7 +120,7 @@ class g:Speckle
|
|
120
120
|
defm get_bail
|
121
121
|
return g:speckle_bail
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
defm get_tag
|
125
125
|
return g:speckle_tag
|
126
126
|
end
|
@@ -156,7 +156,12 @@ class g:Speckle
|
|
156
156
|
map(classes, "substitute(v:val, 'function ', '', '')")
|
157
157
|
|
158
158
|
for klass in classes
|
159
|
-
eval("a:runner.add(#{klass})")
|
159
|
+
klass_instance = eval("a:runner.add(#{klass})")
|
160
|
+
res = matchlist(klass, '\v%(\<SNR\>\d+_)?(.*)SpecConstructor\(\)$')
|
161
|
+
if len(res) >= 2
|
162
|
+
spec_name = res[1]
|
163
|
+
klass_instance.spec_name = spec_name
|
164
|
+
end
|
160
165
|
end
|
161
166
|
end
|
162
167
|
end
|
data/spec/before_hooks_spec.riml
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: speckle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darshan Sawardekar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: riml
|
@@ -186,6 +186,7 @@ files:
|
|
186
186
|
- spec/speckle_mode_spec.riml
|
187
187
|
- spec/stacktrace_spec.riml
|
188
188
|
- spec/tagged_spec.riml
|
189
|
+
- spec/with_describe_spec.riml
|
189
190
|
- spec_errors/hook_errors_spec.riml
|
190
191
|
- spec_errors/various_errors_spec.riml
|
191
192
|
- speckle.gemspec
|
@@ -241,3 +242,4 @@ test_files:
|
|
241
242
|
- spec/speckle_mode_spec.riml
|
242
243
|
- spec/stacktrace_spec.riml
|
243
244
|
- spec/tagged_spec.riml
|
245
|
+
- spec/with_describe_spec.riml
|