docspec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,96 @@
1
+ Docspec
2
+ ==================================================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/docspec.svg)](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
+ ```
@@ -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
+
@@ -0,0 +1,6 @@
1
+ require 'byebug' if ENV['BYEBUG']
2
+
3
+ require 'docspec/output_capturer'
4
+ require 'docspec/example'
5
+ require 'docspec/tester'
6
+ require 'docspec/document'
@@ -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
+
@@ -0,0 +1,3 @@
1
+ module Docspec
2
+ VERSION = "0.0.1"
3
+ end
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: []