docspec 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50f8d84c839b9b2c42002526d2a71b7ba77c3e4593e3bd11707b15437b8ff8fd
4
- data.tar.gz: 03b17f9c88a24ac31c405954aadd080b65b8c288ccb3f8b92d25b3ec45d03017
3
+ metadata.gz: ad249396cfc15361e8f19e3932b5c75ab565b5042ce3431204daf0a39d4f0a14
4
+ data.tar.gz: a0772e8fd3692466756215f0786709fae4c0772248d1715a0503810a7e0af719
5
5
  SHA512:
6
- metadata.gz: ad12b1aa05ab33e0fa3d506375c7f5de01edd4da59c3423d995af02b642ce56b6d08820fa0ea602998b6f895e4be8e2b0b2b5cbb4774f46cec4a1e19e7fb26ed
7
- data.tar.gz: ed148aa6718aaa0b9c624e9af55b0029a115a6cb48e710d55acb1029ebce895001e5ff77ae9af8c0ee3cdac39cb4972a994a94a2490040dcf1322dce59fab18f
6
+ metadata.gz: 4985a1fcb629b102bd560fc4a33bb24d18b0ef91368619cfbcc1f053ac2ac3fffa15426e81f1826de87bebeb5233ad4d416551f8eaad9c52f2513cd273d0b04f
7
+ data.tar.gz: cae6a31e132105853a6015d53d39a3d0ad13bbd99b94fd03e10bedada81e635d7409a2495940d98d9447ff51e9f8249de719e5bd8dfa1aec8a1c4af8dd2a52cc
data/README.md CHANGED
@@ -20,40 +20,49 @@ Installation
20
20
  Usage
21
21
  --------------------------------------------------
22
22
 
23
- Add ruby or shell code blocks to your `README.md` document, then run
24
- `docspec` to evaluate them.
23
+ Docspec expects one or more Markdown files with embedded code snippets to
24
+ test.
25
25
 
26
+ Code snippets should be enclosed in a `ruby` or `shell` code fence:
26
27
 
27
- Rules
28
- --------------------------------------------------
28
+ ```ruby
29
+ code_to_test = 'here'
30
+ #=> expected output
31
+ ```
32
+
33
+ This document itself serves as the test suite for this gem, so you can take a
34
+ look at its source.
29
35
 
30
- - Anything outside of a code fence is ignored.
31
- - Both `ruby` and `shell` code blocks are supported.
32
- - Inside a code block, any piece of code that we care about should print
33
- something.
34
- - Inside a code block, anything starting with `#=>` should define the
35
- expected output.
36
- - If a piece of code raises an error, the captured output will be the
37
- `#inspect` string of that exception.
38
- - If the first line of a code block includes the string `[:ignore_failure]`,
39
- the example will not be considered an error if it fails.
40
36
 
37
+ ### Testing with the `docspec` command line
41
38
 
42
- To test the `README.md` in the current folder, just run:
39
+ Test the examples in `./README.md`:
43
40
 
44
41
  $ docspec
45
42
 
46
- To test a different file, provide it as the first argument:
43
+ Test a different file:
47
44
 
48
45
  $ docspec TESTS.md
49
46
 
50
47
 
48
+ ### Testing from Ruby code
49
+
50
+ ```ruby
51
+ # Running from Ruby code
52
+ document = Docspec::Document.from_file 'sample.md'
53
+ document.test
54
+ #=> pass : Sample Test
55
+
56
+ puts document.success?
57
+ #=> true
58
+ ```
59
+
60
+
51
61
  Examples
52
62
  --------------------------------------------------
53
63
 
54
- These will be tested with `docspec`:
55
-
56
- ### Ruby
64
+ Code examples that you want to test, should output something to stdout.
65
+ Specify the expected output by prefixing it with `#=>`:
57
66
 
58
67
  ```ruby
59
68
  # The first line is an optional label
@@ -61,12 +70,17 @@ puts 'hello world'.upcase
61
70
  #=> HELLO WORLD
62
71
  ```
63
72
 
73
+ If an example raises an exception, the captured output will be the `#inspect`
74
+ string of that exception:
75
+
64
76
  ```ruby
65
77
  # Exceptions are captured
66
78
  raise ArgumentError, "Testing error raising"
67
79
  #=> #<ArgumentError: Testing error raising>
68
80
  ```
69
81
 
82
+ Your code and expected output can contain multiple lines of code:
83
+
70
84
  ```ruby
71
85
  # Multiple lines of code
72
86
  string = "hello"
@@ -78,6 +92,8 @@ end
78
92
  #=> hello
79
93
  ```
80
94
 
95
+ and you can alternate between code and expected output:
96
+
81
97
  ```ruby
82
98
  # Interleaving code and output
83
99
  puts 2 + 3
@@ -87,6 +103,13 @@ puts 2 - 3
87
103
  #=> -1
88
104
  ```
89
105
 
106
+ The first line of the example may contain specially formatted flags. Flags
107
+ are always formatted like this: `[:flag_name]`.
108
+
109
+ The `[:ignore_failure]` flag allows the example to fail. It will show the
110
+ failure in the output, but will not elevate the exit status to a failure
111
+ state:
112
+
90
113
  ```ruby
91
114
  # This example may fail [:ignore_failure]
92
115
  # Due to the :ignore_failure flag, it will show the failure diff, but will
@@ -95,26 +118,43 @@ puts 'hello world'.upcase
95
118
  #=> hello world
96
119
  ```
97
120
 
121
+ Another available flag, is the `[:skip]` flag, which will omit the example
122
+ from the test run:
123
+
98
124
  ```ruby
99
- # Code that does not generate any output will be executed before each
100
- # of the subsequent examples.
125
+ # [:skip]
126
+ this will not be executed
127
+ ```
128
+
129
+ Sometimes it is useful to build the example over several different code
130
+ blocks. To help achieve this, docspec will treat any example that does not
131
+ output anything as a code that needs to be executed before all subsequent
132
+ examples:
133
+
134
+ ```ruby
135
+ # Define a function for later use
101
136
  def create_caption(text)
102
137
  [text.upcase, ("=" * text.length)].join "\n"
103
138
  end
104
139
  ```
105
140
 
141
+ All the examples below this line, will have the above function available:
142
+
106
143
  ```ruby
107
- # Example that builds upon code that was defined earlier
144
+ # Use a previously defined function
108
145
  puts create_caption "tada!"
109
146
  #=> TADA!
110
147
  #=> =====
111
148
  ```
112
149
 
113
150
 
114
- ### Shell
151
+ Finally, examples marked with a `shell` code fence will be executed by the
152
+ shell, and not by ruby:
115
153
 
116
154
  ```shell
117
155
  # Shell commands
118
156
  echo hello world
119
157
  #=> hello world
120
158
  ```
159
+
160
+
data/bin/docspec CHANGED
@@ -8,16 +8,16 @@ include Colsole
8
8
 
9
9
  document = ARGV[0] || 'README.md'
10
10
  abort "File not found #{document}" unless File.exist? document
11
- tester = Docspec::Tester.new document
12
- success = tester.execute
11
+ document = Docspec::Document.from_file document
12
+ document.test
13
13
 
14
14
  say ''
15
15
 
16
- if success
17
- say "!txtgrn!#{tester.total} tests, #{tester.errors} failed\n"
16
+ if document.success?
17
+ say "!txtgrn!#{document.total_examples} tests, #{document.failed_examples} failed\n"
18
18
  exit 0
19
19
  else
20
- say "!txtred!#{tester.total} tests, #{tester.errors} failed\n"
20
+ say "!txtred!#{document.total_examples} tests, #{document.failed_examples} failed\n"
21
21
  exit 1
22
22
  end
23
23
 
@@ -1,13 +1,14 @@
1
1
  module Docspec
2
2
  class Document
3
- attr_reader :filename
3
+ include Testable
4
+ attr_reader :filename, :markdown
4
5
 
5
- def initialize(filename)
6
- @filename = filename
6
+ def self.from_file(filename)
7
+ new File.read(filename)
7
8
  end
8
9
 
9
- def markdown
10
- @markdown ||= File.read filename
10
+ def initialize(markdown)
11
+ @markdown = markdown
11
12
  end
12
13
 
13
14
  def examples
@@ -19,7 +20,8 @@ module Docspec
19
20
  def examples!
20
21
  result = []
21
22
  markdown.scan(/```(ruby|shell)\s*\n(.*?)```/m) do |type, code|
22
- result << Example.new(code, type)
23
+ example = Example.new(code, type)
24
+ result << example unless example.skip?
23
25
  end
24
26
  result
25
27
  end
@@ -48,6 +48,10 @@ module Docspec
48
48
  @full_code = "#{codes}\n#{@full_code}"
49
49
  end
50
50
 
51
+ def skip?
52
+ flags.include? :skip
53
+ end
54
+
51
55
  def success?
52
56
  actual == expected
53
57
  end
@@ -0,0 +1,57 @@
1
+ require 'colsole'
2
+
3
+ module Docspec
4
+ module Testable
5
+ include Colsole
6
+ attr_reader :failed_examples, :total_examples
7
+
8
+ def before_codes
9
+ @before_codes ||= []
10
+ end
11
+
12
+ def success?
13
+ failed_examples == 0
14
+ end
15
+
16
+ def each_example
17
+ reset_counters
18
+
19
+ examples.each do |example|
20
+ if example.empty?
21
+ before_codes << example.code
22
+ else
23
+ @total_examples += 1
24
+ example.prepend before_codes
25
+ @failed_examples += 1 unless example.success? or example.ignore_failure?
26
+ end
27
+
28
+ yield example
29
+ end
30
+ end
31
+
32
+ def test
33
+ each_example do |example|
34
+ if example.empty?
35
+ say "!txtpur!void :!txtrst! #{example.label}"
36
+ elsif example.success?
37
+ say "!txtgrn!pass :!txtrst! #{example.label}"
38
+ else
39
+ say "!txtred!FAIL : #{example.label}"
40
+ say "---"
41
+ puts example.diff
42
+ say "---"
43
+ end
44
+ end
45
+ end
46
+
47
+ protected
48
+
49
+ def reset_counters
50
+ @before_codes = nil
51
+ @failed_examples = 0
52
+ @total_examples = 0
53
+ end
54
+
55
+ end
56
+ end
57
+
@@ -1,3 +1,3 @@
1
1
  module Docspec
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/docspec.rb CHANGED
@@ -2,5 +2,5 @@ require 'byebug' if ENV['BYEBUG']
2
2
 
3
3
  require 'docspec/output_capturer'
4
4
  require 'docspec/example'
5
- require 'docspec/tester'
5
+ require 'docspec/testable'
6
6
  require 'docspec/document'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
@@ -65,7 +65,7 @@ files:
65
65
  - lib/docspec/document.rb
66
66
  - lib/docspec/example.rb
67
67
  - lib/docspec/output_capturer.rb
68
- - lib/docspec/tester.rb
68
+ - lib/docspec/testable.rb
69
69
  - lib/docspec/version.rb
70
70
  homepage: https://github.com/dannyben/docspec
71
71
  licenses:
@@ -1,45 +0,0 @@
1
- require 'colsole'
2
-
3
- module Docspec
4
- class Tester
5
- include Colsole
6
- attr_reader :document, :errors, :total
7
-
8
- def initialize(document)
9
- document = Document.new document unless document.is_a? Document
10
- @document = document
11
- @errors = 0
12
- @total = 0
13
- end
14
-
15
- def before_codes
16
- @before_codes ||= []
17
- end
18
-
19
- def execute
20
- document.examples.each do |example|
21
- if example.empty?
22
- before_codes << example.code
23
- next
24
- end
25
-
26
- @total += 1
27
-
28
- example.prepend before_codes
29
-
30
- if example.success?
31
- say "!txtgrn!PASS: #{example.label}"
32
- else
33
- @errors += 1 unless example.ignore_failure?
34
- say "!txtred!FAIL: #{example.label}"
35
- say "---"
36
- puts example.diff
37
- say "---"
38
- end
39
- end
40
-
41
- errors == 0
42
- end
43
- end
44
- end
45
-