lab42_literate 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 719c356f00f0141fa7a9c0bfec1b25792f067927
4
- data.tar.gz: ab1de21e75855dcf24996a447d08479734a54901
3
+ metadata.gz: 5dc4434c53fc4b7ae709911bed4ea867eee642b4
4
+ data.tar.gz: 3a68fe614d6f32e3b5e13d8bb46a02ca28347ffc
5
5
  SHA512:
6
- metadata.gz: eb38c90f79ff71b04b4d6252fe0f5ce7ba6d4bc9564ce279ee8ea2f198f107568d7e609eccf3952af8680a389c13b0654086cc0edd784d631af86c4db4fbd8f4
7
- data.tar.gz: fadeeeee4eb23c14de66a2d1788a7d01aa2ffb620c7a6f65b3c5b82c01c9d5def3e517bb607bdfe3ea7be8e6ce5f643d0dfd12943f6e9c8fae498b58348813d3
6
+ metadata.gz: d9e5a3cab528ecc1e3c8b4aec44068506e69dfc0445e121ddaef0e6fb350b8c379e6ec1141f48222cb775d7a66925d988d6e65cc23e9b7c21358066a0ddc5184
7
+ data.tar.gz: 128ced3230f2486533283039ed0ae96d1c278826d4dcc557b5329b52d664ac0f6f4067f75ad3f9dd5e77b547ee64f3982358bb87ecc9c83fbdab4342045ea766
data/README.md CHANGED
@@ -7,7 +7,17 @@
7
7
  [![Issue Count](https://codeclimate.com/github/RobertDober/lab42_literate/badges/issue_count.svg)](https://codeclimate.com/github/RobertDober/lab42_literate)
8
8
  [![Test Coverage](https://codeclimate.com/github/RobertDober/lab42_literate/badges/coverage.svg)](https://codeclimate.com/github/RobertDober/lab42_literate)
9
9
 
10
- ## Literate Programming à la doctest.
10
+ ## Literate Programming à la doctest in Elxir.
11
+
12
+ [Elixir Doctest](https://elixir-lang.org/getting-started/mix-otp/docs-tests-and-with.html#doctests) has inspired this gem.
13
+
14
+ Of course Elixir doctests from the metadata of a compiled elixir source (beam).
15
+
16
+ As in Ruby we do not have any metadata this works with simple text extraction and evalutaion.
17
+
18
+ This gives us however the possibility to write our doctests in **any** file and allows you
19
+ to assure that your `README.md` code examples are **all correct**.
20
+
11
21
 
12
22
  Just extract code blocks from any file, and run them as specs with a simple `doctest file` in an RSpec example group.
13
23
 
@@ -49,14 +59,76 @@ with
49
59
 
50
60
  ### How does it work?
51
61
 
52
- Each block ` ```ruby literate` creates an example with title `"literate block in #{file}:#{start_lnb}..#{end_lnb}"`
53
- and instance_evals the lines from the block in the example's context.
62
+ Each block ` ```ruby literate` creates an example group with title `"literate block in #{file}:#{start_lnb}..#{end_lnb}"`.
63
+
64
+ Then an anonymous example `it do ...`
65
+ and instance_evals the lines from the block in this example's context.
54
66
 
55
67
 
56
68
  ### Setup?
57
69
 
58
- Not yet.
59
70
 
60
- ### Explicit Title of the generated example
71
+ #### Inside the spec calling `doctest`
72
+
73
+
74
+ Given this literate file
75
+
76
+ ```ruby literate
77
+ foo.reverse #=> 'oof'
78
+ ```
79
+
80
+ will perfectly work if you setup your spec as follows
81
+
82
+ ```ruby
83
+ RSpec.describe 'FOO', type: :literate do
84
+ let(:foo){ 'foo' }
85
+ doctest('literate_file.md')
86
+ end
87
+ ```
88
+
89
+
90
+ #### Inside the literal file itself
91
+
92
+ All literate blocks containing a `Given` block inside the document will be
93
+ executed in the context in which `doctest` has been called, **before** the
94
+ example blocks will be generated, thusly the following literate file will
95
+ succeed
96
+
97
+ ```ruby literate
98
+ Given do
99
+ let(:a){ 1 }
100
+ end
101
+ ```
102
+
103
+ ```ruby literate
104
+ a + b #=> 42
105
+ ```
106
+
107
+ ```ruby literate
108
+ Given do
109
+ let(:b){ 41 }
110
+ end
111
+ ```
112
+
113
+
114
+
115
+ ### Explicit Title of the generated Example Group
61
116
 
62
117
  Just add text after ` ```ruby literate`
118
+
119
+ E.g.
120
+
121
+ ```ruby literate Assure errors are empty
122
+
123
+ ...
124
+ expect(errors).to be_empty
125
+
126
+ ```
127
+
128
+ ### Calling `doctest` inside an Example
129
+
130
+ Will be deprecated.
131
+
132
+ Does not support all features.
133
+
134
+ Use at own risk.
@@ -2,10 +2,18 @@ module Lab42
2
2
  module Literate
3
3
  require_relative 'literate/example_doctest'
4
4
  require_relative 'literate/group_doctest'
5
+
6
+ module Given
7
+ def Given &blk
8
+ instance_exec(&blk)
9
+ end
10
+ end
5
11
  end
6
12
  end
7
13
 
8
14
  RSpec.configure do | conf |
9
15
  conf.extend Lab42::Literate::GroupDoctest, type: :literate
16
+ conf.extend Lab42::Literate::Given, type: :literate
17
+
10
18
  conf.include Lab42::Literate::ExampleDoctest, type: :literate
11
19
  end
@@ -1,3 +1,7 @@
1
+ require 'parser/current'
2
+ Parser::Builders::Default.emit_lambda = true
3
+ Parser::Builders::Default.emit_procarg0 = true
4
+
1
5
  class Lab42::Literate::Extractor::Block
2
6
  attr_reader :lines, :start_lnb, :title
3
7
 
@@ -5,14 +9,23 @@ class Lab42::Literate::Extractor::Block
5
9
  lines << line
6
10
  end
7
11
 
12
+
8
13
  def get_title alternative
9
14
  title.empty? ? alternative : title
10
15
  end
11
16
 
17
+
18
+ def given?
19
+ parsed.children.first.children == [nil, :Given]
20
+ rescue
21
+ false
22
+ end
23
+
12
24
  def range
13
25
  start_lnb..(start_lnb.pred + lines.size)
14
26
  end
15
27
 
28
+
16
29
  private
17
30
 
18
31
  def initialize start_lnb, title: ''
@@ -21,4 +34,7 @@ class Lab42::Literate::Extractor::Block
21
34
  @title = title
22
35
  end
23
36
 
37
+ def parsed
38
+ @__parsed__ ||= Parser::CurrentRuby.parse(lines.join("\n"))
39
+ end
24
40
  end
@@ -3,20 +3,27 @@ module Lab42::Literate::GroupDoctest
3
3
  Ex = Lab42::Literate::Extractor
4
4
 
5
5
  def doctest filename
6
- doc_blocks = Ex.extract(File.readlines(filename))
7
- doc_blocks.each{ |block| make_context filename, block }
6
+ blocks = Ex
7
+ .extract(File.readlines(filename))
8
+
9
+ setups, examples = blocks.partition(&:given?)
10
+ setups.each{ |setup| make_setup filename, setup }
11
+ examples.each{ |example| make_context filename, example }
8
12
  end
9
13
 
10
14
  private
11
15
 
12
- def make_context filename, block
13
- return if block.lines.empty?
14
- title = block.get_title "literate block in #{filename}:#{block.range.inspect}"
16
+ def make_context filename, example
17
+ return if example.lines.empty?
18
+ title = example.get_title "literate block in #{filename}:#{example.range.inspect}"
15
19
  context title do
16
20
  it do
17
- eval(block.lines.join("\n"))
21
+ eval(example.lines.join("\n"))
18
22
  end
19
23
  end
20
24
  end
21
25
 
26
+ def make_setup filename, setup
27
+ eval(setup.lines.join("\n"))
28
+ end
22
29
  end
@@ -1,5 +1,5 @@
1
1
  module Lab42
2
2
  module Literate
3
- VERSION = '0.1.2'
3
+ VERSION = '0.1.3'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lab42_literate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Dober
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-19 00:00:00.000000000 Z
11
+ date: 2017-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: parser
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.4'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: cucumber
29
43
  requirement: !ruby/object:Gem::Requirement