specdown 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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