docspec 0.0.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/README.md +96 -0
- data/bin/docspec +28 -0
- data/lib/docspec.rb +6 -0
- data/lib/docspec/document.rb +28 -0
- data/lib/docspec/example.rb +52 -0
- data/lib/docspec/output_capturer.rb +16 -0
- data/lib/docspec/tester.rb +39 -0
- data/lib/docspec/version.rb +3 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 285211d9493c575fb886a6e587e6163440017936c9171a015f323ee5b5e75f12
|
4
|
+
data.tar.gz: 8481fd32a94801a88e995c82acee35cbf82f703f59212194e5b8da07d88c1607
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: acee792d5459ed127e6508feb898c3dc37f7cd0a705c3076ac0adbe457470de40b13282a465527a58275cdc7c21785a4e74cd8fd9d692bb3c24d1e026c6e0def
|
7
|
+
data.tar.gz: c5e0e51cef54cf5080914695a1f6292bdd50bfbf113deb10d439e5b093d5265715d02f0172df6f4d551161ea002e5a9416ea00f8b51d30c607ee4f1f1b1a817d
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
Docspec
|
2
|
+
==================================================
|
3
|
+
|
4
|
+
[](https://badge.fury.io/rb/docspec)
|
5
|
+
|
6
|
+
Inline tests in Markdown documents.
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
|
11
|
+
Installation
|
12
|
+
--------------------------------------------------
|
13
|
+
|
14
|
+
$ gem install docspec
|
15
|
+
|
16
|
+
|
17
|
+
Usage
|
18
|
+
--------------------------------------------------
|
19
|
+
|
20
|
+
Add ruby or shell code blocks to your `README.md` document, then run
|
21
|
+
`docspec` to evaluate them.
|
22
|
+
|
23
|
+
|
24
|
+
Rules
|
25
|
+
--------------------------------------------------
|
26
|
+
|
27
|
+
- Anything outside of a code fence is ignored.
|
28
|
+
- Both `ruby` and `shell` code blocks are supported.
|
29
|
+
- Inside a code block, any piece of code that we care about should print
|
30
|
+
something.
|
31
|
+
- Inside a code block, anything starting with `#=>` should define the
|
32
|
+
expected output.
|
33
|
+
- If a piece of code raises an error, the captured output will be the
|
34
|
+
`#inspect` string of that exception.
|
35
|
+
|
36
|
+
To test the `README.md` in the current folder, just run:
|
37
|
+
|
38
|
+
$ docspec
|
39
|
+
|
40
|
+
To test a different file, provide it as the first argument:
|
41
|
+
|
42
|
+
$ docspec TESTS.md
|
43
|
+
|
44
|
+
|
45
|
+
Examples
|
46
|
+
--------------------------------------------------
|
47
|
+
|
48
|
+
These will be tested with `docspec`:
|
49
|
+
|
50
|
+
### Ruby
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# The first line is an optional label
|
54
|
+
puts 'hello world'.upcase
|
55
|
+
#=> HELLO WORLD
|
56
|
+
```
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
# Exceptions are captured
|
60
|
+
raise ArgumentError, "Testing error raising"
|
61
|
+
#=> #<ArgumentError: Testing error raising>
|
62
|
+
```
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
# Multiple lines of code
|
66
|
+
string = "hello"
|
67
|
+
3.times do
|
68
|
+
puts string
|
69
|
+
end
|
70
|
+
#=> hello
|
71
|
+
#=> hello
|
72
|
+
#=> hello
|
73
|
+
```
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# Interleaving code and output
|
77
|
+
puts 2 + 3
|
78
|
+
#=> 5
|
79
|
+
|
80
|
+
puts 2 - 3
|
81
|
+
#=> -1
|
82
|
+
```
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
# This example should fail
|
86
|
+
puts 'hello world'.upcase
|
87
|
+
#=> hello world
|
88
|
+
```
|
89
|
+
|
90
|
+
### Shell
|
91
|
+
|
92
|
+
```shell
|
93
|
+
# Shell commands
|
94
|
+
echo hello world
|
95
|
+
#=> hello world
|
96
|
+
```
|
data/bin/docspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
|
5
|
+
require 'docspec'
|
6
|
+
require 'colsole'
|
7
|
+
include Colsole
|
8
|
+
|
9
|
+
document = ARGV[0] || 'README.md'
|
10
|
+
abort "File not found #{document}" unless File.exist? document
|
11
|
+
tester = Docspec::Tester.new document
|
12
|
+
success = tester.execute
|
13
|
+
|
14
|
+
say ''
|
15
|
+
|
16
|
+
if tester.expected_failures != 0
|
17
|
+
say "!txtblu!Expected failures: #{tester.expected_failures}"
|
18
|
+
end
|
19
|
+
|
20
|
+
if success
|
21
|
+
say "!txtgrn!#{tester.total} tests, #{tester.errors} failed\n"
|
22
|
+
exit 0
|
23
|
+
else
|
24
|
+
say "!txtred!#{tester.total} tests, #{tester.errors} failed\n"
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
|
data/lib/docspec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Docspec
|
2
|
+
class Document
|
3
|
+
attr_reader :filename
|
4
|
+
|
5
|
+
def initialize(filename)
|
6
|
+
@filename = filename
|
7
|
+
end
|
8
|
+
|
9
|
+
def markdown
|
10
|
+
@markdown ||= File.read filename
|
11
|
+
end
|
12
|
+
|
13
|
+
def examples
|
14
|
+
@examples ||= examples!
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def examples!
|
20
|
+
result = []
|
21
|
+
markdown.scan(/```(ruby|shell)\n(.*?)```/m) do |type, code|
|
22
|
+
result << Example.new(code, type)
|
23
|
+
end
|
24
|
+
result
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'diffy'
|
2
|
+
|
3
|
+
module Docspec
|
4
|
+
class Example
|
5
|
+
include OutputCapturer
|
6
|
+
|
7
|
+
attr_reader :code, :type
|
8
|
+
|
9
|
+
def initialize(code, type)
|
10
|
+
@code, @type = code, type
|
11
|
+
end
|
12
|
+
|
13
|
+
def label
|
14
|
+
@label ||= label!
|
15
|
+
end
|
16
|
+
|
17
|
+
def expected
|
18
|
+
@expected ||= code.scan(/#=>\s*(.*)/).map { |match| match.first.strip }.join "\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
def actual
|
22
|
+
@actual ||= actual!
|
23
|
+
end
|
24
|
+
|
25
|
+
def passing?
|
26
|
+
actual == expected
|
27
|
+
end
|
28
|
+
|
29
|
+
def diff
|
30
|
+
Diffy::Diff.new(expected, actual, context: 2).to_s :color
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def label!
|
36
|
+
first_line = code.split("\n").first
|
37
|
+
first_line.gsub(/^#\s*/, '').strip
|
38
|
+
end
|
39
|
+
|
40
|
+
def actual!
|
41
|
+
capture_output do
|
42
|
+
case type
|
43
|
+
when 'ruby'
|
44
|
+
instance_eval(code)
|
45
|
+
when 'shell'
|
46
|
+
puts `#{code}`
|
47
|
+
end
|
48
|
+
end.strip
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Docspec
|
2
|
+
module OutputCapturer
|
3
|
+
def capture_output
|
4
|
+
original_stdout = $stdout
|
5
|
+
$stdout = StringIO.new
|
6
|
+
begin
|
7
|
+
yield
|
8
|
+
$stdout.string
|
9
|
+
rescue => e
|
10
|
+
"#{$stdout.string}#{e.inspect}"
|
11
|
+
ensure
|
12
|
+
$stdout = original_stdout
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'colsole'
|
2
|
+
|
3
|
+
module Docspec
|
4
|
+
class Tester
|
5
|
+
include Colsole
|
6
|
+
attr_reader :document, :errors
|
7
|
+
|
8
|
+
def initialize(document)
|
9
|
+
document = Document.new document unless document.is_a? Document
|
10
|
+
@document = document
|
11
|
+
@errors = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def total
|
15
|
+
@total ||= document.examples.count
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute
|
19
|
+
document.examples.each do |example|
|
20
|
+
if example.passing?
|
21
|
+
say "!txtgrn!PASS: #{example.label}"
|
22
|
+
else
|
23
|
+
@errors += 1
|
24
|
+
say "!txtred!FAIL: #{example.label}"
|
25
|
+
say "---"
|
26
|
+
puts example.diff
|
27
|
+
say "---"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
errors == expected_failures
|
32
|
+
end
|
33
|
+
|
34
|
+
def expected_failures
|
35
|
+
ENV['DOCSPEC_EXPECTED_FAILURES']&.to_i || 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docspec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Danny Ben Shitrit
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colsole
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: diffy
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.3'
|
41
|
+
description: Make your READMEs testable
|
42
|
+
email: db@dannyben.com
|
43
|
+
executables:
|
44
|
+
- docspec
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- bin/docspec
|
50
|
+
- lib/docspec.rb
|
51
|
+
- lib/docspec/document.rb
|
52
|
+
- lib/docspec/example.rb
|
53
|
+
- lib/docspec/output_capturer.rb
|
54
|
+
- lib/docspec/tester.rb
|
55
|
+
- lib/docspec/version.rb
|
56
|
+
homepage: https://github.com/dannyben/docspec
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.5.0
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubygems_version: 3.0.4
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: Embedded tests in Markdown documents
|
79
|
+
test_files: []
|