specdown 0.0.0 → 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.
data/README.markdown ADDED
@@ -0,0 +1 @@
1
+ This library has not yet been implemented. See SPEC.markdown for info about what it might become.
data/SPEC.markdown ADDED
@@ -0,0 +1,122 @@
1
+ # specdown
2
+
3
+ Write your README in markdown, and execute it with specdown. Documentation == Specification == WINNING
4
+
5
+ ## Why?
6
+
7
+ I love README DRIVEN DEVELOPMENT. I love the free-form nature of writing a README. I dislike the process of copying and transforming my README into cucumber. Gherkin works well for many types of requirements, but I dislike turning readable, natural prose into "Given/When/Then" Gherkin. I dislike turning my readable prose into RSpec even more.
8
+
9
+ ## How?
10
+
11
+ Writing your tests with specdown is as simple as writing a README. I'll show you.
12
+
13
+ Let's imagine we're writing a README for a silly little ruby library called "Todo":
14
+
15
+ # Todo
16
+
17
+ A simple library for managing your todo list.
18
+
19
+ ## Usage
20
+
21
+ Go into `irb`, then `require 'todo'`. Type `Todo.List` to see your current to do list:
22
+
23
+ Todo.List #==> []
24
+
25
+ If at any point, you want to completely reset your Todo.List, simply call `Todo!`:
26
+
27
+ Todo!
28
+ Todo.List.should be_empty
29
+
30
+ ### Adding/Removing
31
+
32
+ Now, add an item to your to-do list by calling it as if it were a method on the `Todo` object:
33
+
34
+ Todo.shop_for_groceries
35
+
36
+ This added the item to your `Todo.List`:
37
+
38
+ Todo.List.should == [:shop_for_groceries]
39
+
40
+ You can remove an item from your todo list by adding an exclamation point onto the end of it:
41
+ Todo.shop_for_groceries!
42
+ Todo.List.should be_empty
43
+
44
+
45
+ ### Bulk operations
46
+
47
+ You can also perform bulk operations on your `Todo.List`:
48
+
49
+ Todo.edit! do
50
+ shop
51
+ dry_cleaning!
52
+ shave!
53
+ walk_dogs
54
+ end
55
+
56
+ The items "dry_cleaning" and "shave" were removed from your `Todo.List`, and the items "shop" and "walk_dogs" were added to your Todo.List.
57
+
58
+ Todo.List.should == [
59
+ :shop,
60
+ :walk_dogs
61
+ ]
62
+
63
+ Let's call this file "README.markdown", and place it inside a "specdown/" directory:
64
+
65
+ $ ls -r
66
+ specdown/
67
+ README.markdown
68
+
69
+ We can execute this markdown with specdown by simply the `specdown` command. If you'd like to have some code run before the markdown is executed, put it in a ruby file inside a "specdown" directory:
70
+
71
+ $ cat > specdown/support.rb
72
+
73
+ $LOAD_PATH.unshift './lib'
74
+ require 'rspec/expectations' # for using "should" matchers in the README
75
+ require 'todo'
76
+
77
+ ## Trees and Leafs
78
+
79
+ In the README that we wrote for `Todo`, we actually wrote two tests, or scenarios.
80
+
81
+ `specdown` creates a tree out of our markdown. In our case, the tree for our `Todo` README looks like this:
82
+
83
+
84
+ #Todo
85
+ |
86
+ ##Usage
87
+ / \
88
+ / \
89
+ / \
90
+ / \
91
+ / \
92
+ / \
93
+ / \
94
+ ###Adding/Removing ###Bulk Operations
95
+
96
+ `specdown` will then walk the path from the root to every leaf node in the tree, executing any code it finds along the way.
97
+
98
+ Thus, the first "test" will look like this:
99
+
100
+ Todo.List #==> []
101
+ Todo!
102
+ Todo.List.should be_empty
103
+ Todo.shop_for_groceries
104
+ Todo.List.should == [:shop_for_groceries]
105
+ Todo.shop_for_groceries!
106
+ Todo.List.should be_empty
107
+
108
+ The second "test" looks like this:
109
+
110
+ Todo.List
111
+ Todo!
112
+ Todo.List.should be_empty
113
+ Todo.edit! do
114
+ shop
115
+ dry_cleaning!
116
+ shave!
117
+ walk_dogs
118
+ end
119
+ Todo.List.should == [
120
+ :shop,
121
+ :walk_dogs
122
+ ]
data/bin/specdown ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require 'specdown'
3
+
4
+ Dir["specdown/**/*.rb"].each do |ruby_file|
5
+ require ruby_file
6
+ end
7
+
8
+ Specdown::Command.new.execute
@@ -0,0 +1,93 @@
1
+ Feature: `specdown` command
2
+
3
+ Specdown comes with a `specdown` command that allows you to run your tests from the command line.
4
+
5
+ By default, running `specdown` at a command prompt will cause specdown to look in the current working directory for a "specdown" directory. If it finds a directory called `specdown`, it will eval all code files it finds, then load all "markdown" files and run them, providing you with a report at the end.
6
+
7
+ Scenario: `specdown` with no arguments, and no specdown directory
8
+
9
+ When I run `specdown` from the command line in a directory that contains no 'specdown' directory
10
+ Then I should see the following output:
11
+ """
12
+ 0 markdowns
13
+ 0 tests
14
+ 0 failures
15
+ """
16
+
17
+ Scenario: `specdown` with no arguments, and a specdown directory with a single test
18
+
19
+ Given I have a specdown directory containing a single markdown file:
20
+ """
21
+ # Specdown Example
22
+
23
+ This is an example specdown file.
24
+
25
+ ## Child Node
26
+
27
+ This section is a child node. It contains some ruby code:
28
+
29
+ "simple code".should_not == nil
30
+
31
+ ### First Leaf
32
+
33
+ This section has a failure simulation:
34
+
35
+ raise "specdown error simulation!"
36
+
37
+ ## Last Leaf
38
+
39
+ This section is a leaf node. It contains some ruby code:
40
+
41
+ 1.should == 1
42
+ """
43
+
44
+ When I run `specdown` with no arguments
45
+ Then I should see the following output:
46
+ """
47
+ 1 markdown
48
+ 2 tests
49
+ 2 failures
50
+
51
+ undefined method `should_not' for "simple code":String
52
+ undefined method `should' for 1:Fixnum
53
+ """
54
+
55
+ Scenario: `specdown` with no arguments, and a specdown directory containing a single ruby file and a single markdown file
56
+ Given I have a specdown directory containing a markdown file:
57
+ """
58
+ # Specdown Example
59
+
60
+ This is an example specdown file.
61
+
62
+ ## Child Node
63
+
64
+ This section is a child node. It contains some ruby code:
65
+
66
+ "simple code".should_not == nil
67
+
68
+ ### First Leaf
69
+
70
+ This section has a failure simulation:
71
+
72
+ raise "specdown error simulation!"
73
+
74
+ ## Last Leaf
75
+
76
+ This section is a leaf node. It contains some ruby code:
77
+
78
+ 1.should == 1
79
+ """
80
+ And a single ruby file:
81
+ """
82
+ require 'rubygems'
83
+ require 'rspec/expectations'
84
+ """
85
+ When I run `specdown` with no arguments
86
+ Then I should see the following output:
87
+ """
88
+ 1 markdown
89
+ 2 tests
90
+ 1 failure
91
+
92
+ specdown error simulation!
93
+ """
@@ -0,0 +1,21 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not == nil
10
+
11
+ ### First Leaf
12
+
13
+ This section has a failure simulation:
14
+
15
+ raise "specdown error simulation!"
16
+
17
+ ## Last Leaf
18
+
19
+ This section is a leaf node. It contains some ruby code:
20
+
21
+ 1.should == 1
@@ -0,0 +1,108 @@
1
+ Feature: Specdown Parser
2
+
3
+ The default specdown parser will convert a markdown file into a tree, with the headings inside the markdown forming the nodes of the tree.
4
+
5
+ For example, imagine we are given following simple markdown file:
6
+
7
+ readme = <<-README
8
+
9
+ \# Specdown Example
10
+
11
+ This is an example specdown file.
12
+
13
+ \## Child Node
14
+
15
+ This section is a child node. It contains some ruby code:
16
+
17
+ "simple code".should_not == nil
18
+
19
+ \### First Leaf
20
+
21
+ This section has a failure simulation:
22
+
23
+ raise "specdown error simulation!"
24
+
25
+ \## Last Leaf
26
+
27
+ This section is a leaf node. It contains some ruby code:
28
+
29
+ 1.should == 1
30
+ README
31
+
32
+ As you can see, this forms a tree, with "# Specdown Example" at the root of the tree, and "## Leaf 1" and "## Leaf 2" as the children / leafs.
33
+
34
+ then the Specdown::Parser would turn into the a tree data structure:
35
+
36
+ tree = Specdown::Parser.parse readme
37
+
38
+ You can ask for the root of the tree object via the `root` method:
39
+
40
+ tree.root
41
+
42
+ The root returned is a `Specdown::Parser::Node` object. A `Node` responds to four methods: `name`, `code`, `contents`, and `children`.
43
+
44
+ tree.root.name.should == "Specdown Example"
45
+ tree.root.code.should be(nil)
46
+ tree.root.contents.should == "# Specdown Example\n\nThis is an example specdown file."
47
+
48
+ The `children` method is simply an array of `Specdown::Parser::Node` objects, each corresponding to the children (if any) of the current node.
49
+
50
+ tree.root.children.first.name.should == "Leaf 1"
51
+ tree.root.children.first.code.should == "1.should == 1"
52
+
53
+
54
+ Scenario: Parsing a specdown file
55
+
56
+ Given the following specdown example file:
57
+ """
58
+ # Specdown Example
59
+
60
+ This is an example specdown file.
61
+
62
+ ## Child Node
63
+
64
+ This section is a child node. It contains some ruby code:
65
+
66
+ "simple code".should_not == nil
67
+
68
+ ### First Leaf
69
+
70
+ This section has a failure simulation:
71
+
72
+ raise "specdown error simulation!"
73
+
74
+ ## Last Leaf
75
+
76
+ This section is a leaf node. It contains some ruby code:
77
+
78
+ 1.should == 1
79
+ """
80
+
81
+ When I parse it into a tree:
82
+ """
83
+ @tree = Specdown::Parser.parse @readme
84
+ """
85
+
86
+ Then the root should be the "h1" section:
87
+ """
88
+ @tree.root.name.should == "Specdown Example"
89
+ @tree.root.code.should be_empty
90
+ """
91
+
92
+ And the root should have two children:
93
+ """
94
+ @tree.root.children.length.should == 2
95
+
96
+ child_node = @tree.root.children.first
97
+ first_leaf = child_node.children.first
98
+ last_leaf = @tree.root.children.last
99
+
100
+ child_node.name.should == "Child Node"
101
+ child_node.code.should == '"simple code".should_not == nil'
102
+
103
+ first_leaf.name.should == "First Leaf"
104
+ first_leaf.code.should == 'raise "specdown error simulation!"'
105
+
106
+ last_leaf.name.should == "Last Leaf"
107
+ last_leaf.code.should == "1.should == 1"
108
+ """
@@ -0,0 +1,58 @@
1
+ Feature: Report
2
+
3
+ Specdown comes with a generic reporting class. If you provide it with a runner's Specdown::Stats object (or an array of Specdown::Stats objects), then it will generate a report for you.
4
+
5
+ For example, suppose we have the following Specdown::Stats instance:
6
+
7
+ stats = Specdown::Stats.new
8
+ stats.tests = 3
9
+ stats.exceptions = [StandardError.new("error simulation")]
10
+
11
+ We could then pass it off to our reporter class and receive the following report:
12
+
13
+ Specdown::Report.new(stats).generate.should == %{
14
+ 1 markdown
15
+ 3 tests
16
+ 2 successes
17
+ 1 failure
18
+
19
+ StandardError: error simulation
20
+ %}
21
+
22
+
23
+ Scenario: A Specdown::Report instantiated with a single stats object
24
+
25
+ Given the following Specdown::Stats instance:
26
+ """
27
+ @stats = Specdown::Stats.new
28
+ @stats.tests = 3
29
+ @stats.exceptions << StandardError.new("error simulation")
30
+ """
31
+
32
+ Then `Specdown::Report.new(@stats).generate` should include the following output:
33
+ """
34
+ 1 markdown
35
+ 3 tests
36
+ 1 failure
37
+
38
+ error simulation
39
+ """
40
+
41
+ Scenario: A Specdown::Report instantiated with an array of stats
42
+
43
+ Given the following of Specdown::Stats instances:
44
+ """
45
+ @results = [
46
+ Specdown::Stats.new.tap {|s| s.tests = 3 },
47
+ Specdown::Stats.new.tap {|s| s.tests = 1; s.exceptions << StandardError.new("error simulation") }
48
+ ]
49
+ """
50
+
51
+ Then `Specdown::Report.new(@results).generate` should include the following output:
52
+ """
53
+ 2 markdowns
54
+ 4 tests
55
+ 1 failure
56
+
57
+ error simulation
58
+ """
@@ -0,0 +1,95 @@
1
+ Feature: Runner
2
+
3
+ The `Specdown::Runner` class accepts a markdown parse tree, and runs the tests found within.
4
+
5
+ Imagine we start with this markdown file:
6
+
7
+ \# Specdown Example
8
+
9
+ This is an example specdown file.
10
+
11
+ \## Child Node
12
+
13
+ This section is a child node. It contains some ruby code:
14
+
15
+ "simple code".should_not == nil
16
+
17
+ \### First Leaf
18
+
19
+ This section has a failure simulation:
20
+
21
+ raise "specdown error simulation!"
22
+
23
+ \## Last Leaf
24
+
25
+ This section is a leaf node. It contains some ruby code:
26
+
27
+ 1.should == 1
28
+
29
+ We then parse it into a Specdown::Tree:
30
+
31
+ parse_tree = Specdown::Parser.parse File.read("/path/to/markdown")
32
+
33
+ We can now generate a new `Specdown::Runner` instance and run the tests:
34
+
35
+ runner = Specdown::Runner.new(parse_tree)
36
+ runner.run
37
+
38
+ While running, it will print results to STDOUT like "F."
39
+
40
+ We can access statistics about the run programatically:
41
+
42
+ runner.stats.tests #==> 2
43
+ runner.stats.failures #==> 1
44
+ runner.stats.successes #==> 1
45
+ runner.stats.exceptions.map(&:to_s) #==> ['StandardError: "specdown error simulation"']
46
+
47
+ Scenario: Running tests
48
+
49
+ Given the following specdown example file:
50
+ """
51
+ # Specdown Example
52
+
53
+ This is an example specdown file.
54
+
55
+ ## Child Node
56
+
57
+ This section is a child node. It contains some ruby code:
58
+
59
+ "simple code".should_not == nil
60
+
61
+ ### First Leaf
62
+
63
+ This section has a failure simulation:
64
+
65
+ raise "specdown error simulation!"
66
+
67
+ ## Last Leaf
68
+
69
+ This section is a leaf node. It contains some ruby code:
70
+
71
+ 1.should == 1
72
+ """
73
+
74
+ When I parse it into a tree:
75
+ """
76
+ @tree = Specdown::Parser.parse @readme
77
+ """
78
+
79
+ And I generate a `Specdown::Runner` instance from it:
80
+ """
81
+ @runner = Specdown::Runner.new @tree
82
+ """
83
+
84
+ Then I should be able to run the tests:
85
+ """
86
+ @runner.run
87
+ """
88
+
89
+ And I should be able to access the report data programatically:
90
+ """
91
+ @runner.stats.tests #==> 2
92
+ @runner.stats.failures #==> 1
93
+ @runner.stats.successes #==> 1
94
+ @runner.stats.exceptions.map(&:to_s) #==> ['(eval):3:in `execute_test': specdown error simulation!']
95
+ """
@@ -0,0 +1,21 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not == nil
10
+
11
+ ### First Leaf
12
+
13
+ This section has a failure simulation:
14
+
15
+ raise "specdown error simulation!"
16
+
17
+ ## Last Leaf
18
+
19
+ This section is a leaf node. It contains some ruby code:
20
+
21
+ 1.should == 1
@@ -0,0 +1,2 @@
1
+ require 'rubygems'
2
+ require 'rspec/expectations'
@@ -0,0 +1,21 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not == nil
10
+
11
+ ### First Leaf
12
+
13
+ This section has a failure simulation:
14
+
15
+ raise "specdown error simulation!"
16
+
17
+ ## Last Leaf
18
+
19
+ This section is a leaf node. It contains some ruby code:
20
+
21
+ 1.should == 1
@@ -0,0 +1,21 @@
1
+ When /^I run `specdown` from the command line in a directory that contains no 'specdown' directory$/ do
2
+ @output = `bundle exec ruby -I ./lib ./bin/specdown`
3
+ end
4
+
5
+ Then /^I should see the following output:$/ do |string|
6
+ string.split("\n").each do |line|
7
+ @output.include?(line.strip).should be(true)
8
+ end
9
+ end
10
+
11
+ Given /^I have a specdown directory containing a (?:single )?markdown file:$/ do |string|
12
+ @directory = "features/specdown_examples/no_ruby/"
13
+ end
14
+
15
+ When /^I run `specdown` with no arguments$/ do
16
+ @output = `cd #{@directory} && bundle exec ruby -I ../../../lib ../../../bin/specdown`
17
+ end
18
+
19
+ Given /^a single ruby file:$/ do |string|
20
+ @directory = "features/specdown_examples/with_ruby/"
21
+ end
@@ -0,0 +1,15 @@
1
+ Given /^the following specdown example file:$/ do |string|
2
+ @readme = File.read "features/fixtures/parser_example.markdown"
3
+ end
4
+
5
+ When /^I parse it into a tree:$/ do |string|
6
+ eval string
7
+ end
8
+
9
+ Then /^the root should be the ".*" section:$/ do |string|
10
+ eval string
11
+ end
12
+
13
+ Then /^the root should have two children:$/ do |string|
14
+ eval string
15
+ end
@@ -0,0 +1,14 @@
1
+ Given /^the following Specdown::Stats instance:$/ do |string|
2
+ eval string
3
+ end
4
+
5
+ Then /^`(.*)` should include the following output:$/ do |code, string|
6
+ output = eval code
7
+ string.split("\n").each do |line|
8
+ output.should include(line.strip)
9
+ end
10
+ end
11
+
12
+ Given /^the following of Specdown::Stats instances:$/ do |string|
13
+ eval string
14
+ end
@@ -0,0 +1,15 @@
1
+ When /^I generate a `Specdown::Runner` instance from it:$/ do |string|
2
+ eval string
3
+ end
4
+
5
+ Then /^I should be able to run the tests:$/ do |string|
6
+ eval string
7
+ end
8
+
9
+ Then /^I should be able to print a report:$/ do |string|
10
+ eval string
11
+ end
12
+
13
+ Then /^I should be able to access the report data programatically:$/ do |string|
14
+ eval string
15
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift './lib'
2
+ require 'specdown'
3
+ require 'rspec/expectations'
4
+ require 'rspec/matchers'
@@ -0,0 +1,28 @@
1
+ module Specdown
2
+ class Command
3
+ def initialize
4
+ @markdowns = Dir["specdown/**/*.markdown"]
5
+ end
6
+
7
+ def execute
8
+ run
9
+ report
10
+ end
11
+
12
+ private
13
+ def run
14
+ @results =
15
+ @markdowns.map {|markdown|
16
+ Parser.parse(File.read(markdown))
17
+ }.map {|tree|
18
+ Runner.new(tree)
19
+ }.map {|runner|
20
+ runner.run
21
+ }.collect &:stats
22
+ end
23
+
24
+ def report
25
+ puts Specdown::Report.new(@results).generate
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ module Specdown
2
+ class Node
3
+ attr_accessor :name, :code, :contents, :children, :parent
4
+
5
+ def initialize
6
+ @code = ''
7
+ @contents = ''
8
+ @children = []
9
+ end
10
+
11
+ def code
12
+ @code.strip
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ module Specdown
2
+ module Parser
3
+ extend self
4
+
5
+ def parse(readme)
6
+ kramdown = Kramdown::Document.new readme, :input => :markdown
7
+ build_tree kramdown.root.children
8
+ end
9
+
10
+ private
11
+ def build_tree(parsed_elements)
12
+ tree = Tree.new
13
+ scan_for_root_node parsed_elements
14
+ tree.root = consume_section parsed_elements unless parsed_elements.empty?
15
+ consume_children parsed_elements, tree.root unless parsed_elements.empty?
16
+ tree
17
+ end
18
+
19
+ def consume_children(parsed_elements, current_parent)
20
+ current_level = parsed_elements.first.options[:level]
21
+ raise "Specdown Parse Error: Detected multiple h1 headers in document." if current_level == 1
22
+
23
+ unless parsed_elements.empty?
24
+ current_parent.children << consume_section(parsed_elements, current_parent)
25
+ end
26
+
27
+ unless parsed_elements.empty?
28
+ next_section_level = parsed_elements.first.options[:level]
29
+ if next_section_level < current_level
30
+ consume_children parsed_elements, current_parent.parent
31
+ elsif next_section_level == current_level
32
+ consume_children parsed_elements, current_parent
33
+ else
34
+ consume_children parsed_elements, current_parent.children.last
35
+ end
36
+ end
37
+ end
38
+
39
+ def consume_section(parsed_elements, parent=nil)
40
+ node = Specdown::Node.new
41
+ node.name = parsed_elements.shift.options[:raw_text]
42
+ node.parent = parent
43
+
44
+ while !parsed_elements.empty? && parsed_elements.first.type != :header
45
+ element = parsed_elements.shift
46
+ node.code += element.value if element.type == :codeblock
47
+ node.contents += element.value.to_s + element.children.map(&:value).join
48
+ end
49
+ node
50
+ end
51
+
52
+ def scan_for_root_node(parsed_elements)
53
+ until parsed_elements.empty? || (
54
+ parsed_elements.first.type == :header && parsed_elements.first.options[:level] == 1
55
+ )
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,40 @@
1
+ module Specdown
2
+ class Report
3
+ def initialize(stats)
4
+ if stats.kind_of? Array
5
+ @stats = stats
6
+ else
7
+ @stats = [stats]
8
+ end
9
+ end
10
+
11
+ def generate
12
+ [
13
+ format_stat("markdown", markdowns),
14
+ format_stat("test", tests),
15
+ format_stat("failure", failures)
16
+ ].join("\n") + "\n\n" + exceptions.join("\n\n")
17
+ end
18
+
19
+ private
20
+ def format_stat(word, number)
21
+ "#{number} #{number == 1 ? word : word + "s"}"
22
+ end
23
+
24
+ def tests
25
+ @tests ||= @stats.inject(0) {|sum, stat| sum += stat.tests}
26
+ end
27
+
28
+ def failures
29
+ @failures ||= @stats.inject(0) {|sum, stat| sum += stat.failures}
30
+ end
31
+
32
+ def markdowns
33
+ @stats.count
34
+ end
35
+
36
+ def exceptions
37
+ @stats.collect(&:exceptions).flatten.map {|e| [e.to_s, e.backtrace].join "\n"}
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,18 @@
1
+ module Specdown
2
+ class Stats
3
+ attr_accessor :tests, :exceptions
4
+
5
+ def initialize
6
+ @tests = 0
7
+ @exceptions = []
8
+ end
9
+
10
+ def successes
11
+ @tests - @exceptions.count
12
+ end
13
+
14
+ def failures
15
+ @exceptions.count
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,44 @@
1
+ module Specdown
2
+ class Runner
3
+ attr_reader :stats
4
+
5
+ def initialize(tree)
6
+ @tree = tree
7
+ @stats = Stats.new
8
+ end
9
+
10
+ def run
11
+ depth_first_search @tree.root
12
+ puts "\n\n"
13
+ self
14
+ end
15
+
16
+ private
17
+ def depth_first_search(node, code=[])
18
+ if node.children.empty?
19
+ execute_test(code + [node.code])
20
+ else
21
+ node.children.each do |child|
22
+ depth_first_search(child, (code + [node.code]))
23
+ end
24
+ end
25
+ end
26
+
27
+ def execute_test(code)
28
+ @stats.tests += 1
29
+
30
+ begin
31
+ Sandbox.new.instance_eval do
32
+ eval code.join("\n")
33
+ end
34
+
35
+ print '.'
36
+
37
+ rescue Exception => e
38
+ @stats.exceptions << e
39
+
40
+ print 'F'
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,4 @@
1
+ module Specdown
2
+ class Sandbox
3
+ end
4
+ end
@@ -0,0 +1,8 @@
1
+ module Specdown
2
+ class Tree
3
+ attr_accessor :root
4
+
5
+ def initialize
6
+ end
7
+ end
8
+ end
data/lib/specdown.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'kramdown'
2
+ require 'specdown/parser'
3
+ require 'specdown/node'
4
+ require 'specdown/tree'
5
+ require 'specdown/sandbox'
6
+ require 'specdown/runner'
7
+ require 'specdown/runner/report'
8
+ require 'specdown/runner/stats'
9
+ require 'specdown/command'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: specdown
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 0
10
- version: 0.0.0
9
+ - 1
10
+ version: 0.0.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Parker
@@ -15,19 +15,87 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-12-16 00:00:00 Z
19
- dependencies: []
20
-
18
+ date: 2011-12-30 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: kramdown
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 35
29
+ segments:
30
+ - 0
31
+ - 13
32
+ - 4
33
+ version: 0.13.4
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: cucumber
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :development
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ type: :development
63
+ version_requirements: *id003
21
64
  description:
22
65
  email: moonmaster9000@gmail.com
23
- executables: []
24
-
66
+ executables:
67
+ - specdown
25
68
  extensions: []
26
69
 
27
- extra_rdoc_files: []
28
-
29
- files: []
30
-
70
+ extra_rdoc_files:
71
+ - README.markdown
72
+ - SPEC.markdown
73
+ files:
74
+ - lib/specdown/command.rb
75
+ - lib/specdown/node.rb
76
+ - lib/specdown/parser.rb
77
+ - lib/specdown/runner/report.rb
78
+ - lib/specdown/runner/stats.rb
79
+ - lib/specdown/runner.rb
80
+ - lib/specdown/sandbox.rb
81
+ - lib/specdown/tree.rb
82
+ - lib/specdown.rb
83
+ - bin/specdown
84
+ - README.markdown
85
+ - SPEC.markdown
86
+ - features/command.feature
87
+ - features/fixtures/parser_example.markdown
88
+ - features/parser.feature
89
+ - features/report.feature
90
+ - features/runner.feature
91
+ - features/specdown_examples/no_ruby/specdown/parser_example.markdown
92
+ - features/specdown_examples/with_ruby/specdown/env.rb
93
+ - features/specdown_examples/with_ruby/specdown/parser_example.markdown
94
+ - features/step_definitions/command.rb
95
+ - features/step_definitions/parser.rb
96
+ - features/step_definitions/report.rb
97
+ - features/step_definitions/runner.rb
98
+ - features/support/env.rb
31
99
  homepage: http://github.com/moonmaster9000/specdown
32
100
  licenses: []
33
101
 
@@ -61,5 +129,17 @@ rubygems_version: 1.8.10
61
129
  signing_key:
62
130
  specification_version: 3
63
131
  summary: Write your specs as if they were a README, then EXECUTE them.
64
- test_files: []
65
-
132
+ test_files:
133
+ - features/command.feature
134
+ - features/fixtures/parser_example.markdown
135
+ - features/parser.feature
136
+ - features/report.feature
137
+ - features/runner.feature
138
+ - features/specdown_examples/no_ruby/specdown/parser_example.markdown
139
+ - features/specdown_examples/with_ruby/specdown/env.rb
140
+ - features/specdown_examples/with_ruby/specdown/parser_example.markdown
141
+ - features/step_definitions/command.rb
142
+ - features/step_definitions/parser.rb
143
+ - features/step_definitions/report.rb
144
+ - features/step_definitions/runner.rb
145
+ - features/support/env.rb