cukable 0.1.1 → 0.1.2

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.
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,17 @@
1
+ Cukable History
2
+ ===============
3
+
4
+ 0.1.2
5
+ -----
6
+
7
+ - Multiple-project capability
8
+ - Support for RVM and bundler
9
+
10
+
11
+ 0.1.1
12
+ -----
13
+
14
+ - SlimJSON output formatter for Cucumber
15
+ - Cuke fixture for running tests from FitNesse
16
+ - Basic single-project support (one FitNesse instance per project)
17
+
data/README.md CHANGED
@@ -32,8 +32,10 @@ To install Cukable, do:
32
32
  Cukable requires [rubyslim](http://github.com/unclebob/rubyslim) in order to
33
33
  work; as of this writing, rubyslim is not officially packaged as a gem, making
34
34
  it slightly more difficult to get Cukable working. For this reason, a makeshift
35
- rubyslim gem is provided in the `vendor/cache` directory of Cukable. Install
36
- this into whatever environment you plan to run Cukable under, like so:
35
+ rubyslim gem is provided in the `vendor/cache` directory of Cukable. Use `gem
36
+ list cukable -d` to find out the full installation path for cukable, then
37
+ append `/vendor/cache/rubyslim-0.1.1.gem` on the end of that,a nd install like
38
+ so:
37
39
 
38
40
  $ gem install /path/to/cukable/vendor/cache/rubyslim-0.1.1.gem
39
41
 
@@ -43,6 +45,19 @@ please report any issues with it to the
43
45
  [Cukable issue tracker](http://github.com/wapcaplet/cukable/issues).
44
46
 
45
47
 
48
+ Configuration
49
+ -------------
50
+
51
+ FitNesse uses a JSON format for its test reporting, so you must enable the SLIM
52
+ JSON output formatter provided by Cukable. To make Cucumber aware of this
53
+ formatter, add this line:
54
+
55
+ require 'cukable/slim_json_formatter'
56
+
57
+ to your `features/support/env.rb`, `features/support/custom_env.rb`, or
58
+ wherever you're keeping custom initialization for your Cucumber environment.
59
+
60
+
46
61
  Converting existing features
47
62
  ----------------------------
48
63
 
@@ -291,6 +306,44 @@ any arguments passed to individual tables, because Cucumber is only executed
291
306
  once for the entire suite.
292
307
 
293
308
 
309
+ Multiple projects
310
+ -----------------
311
+
312
+ As of Cukable version 0.1.2, you can run tests in multiple project directories.
313
+ For example, you may have two applications that you want to test with Cukable:
314
+
315
+ - `/home/eric/projects/A`: First application you want to test
316
+ - `/home/eric/projects/B`: Second application you want to test
317
+ - `/home/eric/projects/FitNesseRoot`: Where your wiki is stored
318
+
319
+ Projects `A` and `B` may have different dependencies, and you want Cukable to
320
+ mimic the process of running `cucumber` within each of those directories. If
321
+ `A` and `B` are Rails applications, and you know what's good for you, you're
322
+ already using [bundler](http://gembundler.com/) to manage each application's
323
+ gem dependencies, and [RVM](http://rvm.beginrescueend.com/) with two distinct
324
+ gemsets to keep the projects' dependencies from interfering with one another.
325
+ This is what Cukable expects that you are doing.
326
+
327
+ In your wiki pages (either in a `Cuke` table, or in the `accelerate` function
328
+ call), you can pass a third argument (after `CUCUMBER_ARGS`) that indicates the
329
+ directory where that test should be executed. For instance, you could have a
330
+ wiki page with two tests--one for each project:
331
+
332
+ !| Table: Cuke | | /home/eric/projects/A |
333
+ | When I run a test on project A |
334
+ | Then the test should pass |
335
+
336
+ !| Table: Cuke | | /home/eric/projects/B |
337
+ | When I run a different test on project B |
338
+ | Then the test should pass |
339
+
340
+ These two tests will be executed in their respective directories. If the two
341
+ applications have differing gem dependencies, you should put an `.rvmrc` file
342
+ in both the `A` and `B` directories, containing the correct `rvm` command to
343
+ switch gemsets; if Cukable finds an `.rvmrc` in a project directory, it will be
344
+ sourced so that Cucumber runs within the context of that gemset.
345
+
346
+
294
347
  Support
295
348
  -------
296
349
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cukable"
3
- s.version = "0.1.1"
3
+ s.version = "0.1.2"
4
4
  s.summary = "Runs Cucumber tests from FitNesse"
5
5
  s.description = <<-EOS
6
6
  Cukable allows running Cucumber test scenarios from FitNesse
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.add_dependency 'cucumber'
15
15
  s.add_dependency 'diff-lcs'
16
16
 
17
+ s.add_development_dependency 'rake', '~> 0.8.7'
17
18
  s.add_development_dependency 'rspec', '>= 2.2.0'
18
19
  s.add_development_dependency 'rcov'
19
20
  s.add_development_dependency 'yard'
@@ -4,7 +4,7 @@ Feature: Cuke fixture
4
4
  Given a standard Cucumber project directory structure
5
5
 
6
6
  Scenario: Do table
7
- Given a Cuke fixture
7
+ Given a default Cuke fixture
8
8
  When I do this table:
9
9
  | Feature: Table |
10
10
  | Scenario: Table |
@@ -18,19 +18,19 @@ Feature: Cuke fixture
18
18
  """
19
19
 
20
20
  Scenario: Write features
21
- Given a Cuke fixture
21
+ Given a default Cuke fixture
22
22
  And a FitNesse wiki
23
- And a FitNesse suite "TestSuite" with:
23
+ And a Suite "TestSuite" containing:
24
24
  """
25
25
  !contents
26
26
  """
27
- And a FitNesse test "TestSuite/HelloWorld" with:
27
+ And a Test "TestSuite/HelloWorld" containing:
28
28
  """
29
29
  | Table: Cuke |
30
30
  | Feature: Hello |
31
31
  | Scenario: Hello |
32
32
  """
33
- And a FitNesse test "TestSuite/GoodbyeWorld" with:
33
+ And a Test "TestSuite/GoodbyeWorld" containing:
34
34
  """
35
35
  | Table: Cuke |
36
36
  | Feature: Goodbye |
@@ -50,9 +50,60 @@ Feature: Cuke fixture
50
50
  """
51
51
 
52
52
 
53
+ Scenario: Write features for multiple projects
54
+ Given a FitNesse wiki
55
+ And a Suite "TestSuite" containing:
56
+ """
57
+ !define TEST_SYSTEM {slim}
58
+ !define TEST_RUNNER {rubyslim}
59
+ !define COMMAND_PATTERN {rubyslim}
60
+ !contents
61
+ """
62
+
63
+ And a Suite "TestSuite/ProjectA" containing:
64
+ """
65
+ !contents
66
+ """
67
+ And a Test "TestSuite/ProjectA/HelloWorld" containing:
68
+ """
69
+ | Table: Cuke |
70
+ | Feature: Hello |
71
+ | Scenario: Hello |
72
+ """
73
+ And a Cuke fixture with arguments:
74
+ | project_dir | project_a |
75
+
76
+ When I write features for suite "TestSuite/ProjectA"
77
+ Then "project_a/features/fitnesse/HelloWorld_0.feature" should contain:
78
+ """
79
+ Feature: Hello
80
+ Scenario: Hello
81
+ """
82
+
83
+ Given a Suite "TestSuite/ProjectB" containing:
84
+ """
85
+ !contents
86
+ """
87
+ And a Test "TestSuite/ProjectB/GoodbyeWorld" containing:
88
+ """
89
+ | Table: Cuke |
90
+ | Feature: Goodbye |
91
+ | Scenario: Goodbye |
92
+ """
93
+ And a Cuke fixture with arguments:
94
+ | project_dir | project_b |
95
+
96
+ When I write features for suite "TestSuite/ProjectB"
97
+ Then "project_b/features/fitnesse/GoodbyeWorld_0.feature" should contain:
98
+ """
99
+ Feature: Goodbye
100
+ Scenario: Goodbye
101
+ """
102
+
103
+
53
104
  Scenario: Accelerate suite
54
105
  Given a FitNesse wiki
55
- And a Cuke fixture
106
+ And a default Cuke fixture
56
107
  And a Suite "FeatureS" containing:
57
108
  """
58
109
  !define TEST_SYSTEM {slim}
@@ -88,7 +139,7 @@ Feature: Cuke fixture
88
139
  [
89
140
  ["report:Feature: Passing"],
90
141
  ["report:Scenario: Passing"],
91
- ["error:Given a step passes"]
142
+ ["pass:Given a step passes"]
92
143
  ]
93
144
  """
94
145
 
@@ -97,16 +148,18 @@ Feature: Cuke fixture
97
148
  [
98
149
  ["report:Feature: Failing"],
99
150
  ["report:Scenario: Failing"],
100
- ["error:Given a step fails"]
151
+ ["fail:Given a step fails"]
101
152
  ]
102
153
  """
103
154
 
104
155
 
105
156
  @wip
157
+ @focus
106
158
  Scenario: Accelerate suite with skipped tags
107
159
  # FIXME: Fails when run with other scenarios. Lack of init/cleanup in self_test dir?
108
160
  Given a FitNesse wiki
109
- And a Cuke fixture
161
+ And a Cuke fixture with arguments:
162
+ | cucumber_args | --tags ~@skip |
110
163
 
111
164
  And a Test "FeatureS/SkippedScenariosFeature" containing:
112
165
  """
@@ -131,7 +184,6 @@ Feature: Cuke fixture
131
184
  | Given a step fails |
132
185
  """
133
186
 
134
- When I set CUCUMBER_ARGS to "--tags ~@skip"
135
187
  And I run the accelerator for suite "FeatureS"
136
188
 
137
189
  Then "slim_results/features/fitnesse/SkippedScenariosFeature_0.feature.json" should contain JSON:
@@ -1,4 +1,3 @@
1
- @wip
2
1
  Feature: Slim JSON Formatter
3
2
 
4
3
  Background:
@@ -146,8 +145,7 @@ Feature: Slim JSON Formatter
146
145
  ["report:Examples: "],
147
146
  ["report: ", "pass:result"],
148
147
  ["report: ", "pass:passes"],
149
- ["report: ", "fail:fails"],
150
- ["fail:<br/>"]
148
+ ["fail:", "fail:fails"]
151
149
  ]
152
150
  """
153
151
 
@@ -12,17 +12,6 @@ end
12
12
 
13
13
  Given /^a FitNesse wiki$/ do
14
14
  create_standard_fitnesse_dir
15
- @fitnesse_root = 'FitNesseRoot'
16
- end
17
-
18
-
19
- Given /^a FitNesse suite "(.+)" with:$/ do |page_name, content|
20
- create_fitnesse_page(page_name, content)
21
- end
22
-
23
-
24
- Given /^a FitNesse test "(.+)" with:$/ do |page_name, content|
25
- create_fitnesse_page(page_name, content)
26
15
  end
27
16
 
28
17
 
@@ -38,12 +27,16 @@ end
38
27
 
39
28
 
40
29
  Then /^"(.+)" should contain:$/ do |filename, text|
41
- file_should_contain(filename, text)
30
+ in_test_dir do
31
+ file_should_contain(filename, text)
32
+ end
42
33
  end
43
34
 
44
35
 
45
36
  Then /^"(.+)" should contain JSON:$/ do |filename, json_text|
46
- file_should_contain_json(filename, json_text)
37
+ in_test_dir do
38
+ file_should_contain_json(filename, json_text)
39
+ end
47
40
  end
48
41
 
49
42
 
@@ -57,25 +50,34 @@ end
57
50
 
58
51
 
59
52
  Given /^a (Test|Suite) "(.+)" containing:$/ do |type, filename, content|
60
- content_file = File.join(@fitnesse_root, filename, 'content.txt')
61
- properties_file = File.join(@fitnesse_root, filename, 'properties.xml')
53
+ content_file = File.join(fitnesse_dir, filename, 'content.txt')
54
+ properties_file = File.join(fitnesse_dir, filename, 'properties.xml')
62
55
  create_file(content_file, content)
63
56
  create_file(properties_file, xml_content(type))
64
57
  end
65
58
 
66
59
 
67
60
  Then /^I should have a (Test|Suite) "(.+)" containing:$/ do |type, filename, content|
68
- content_file = File.join(@fitnesse_root, filename, 'content.txt')
69
- properties_file = File.join(@fitnesse_root, filename, 'properties.xml')
61
+ content_file = File.join(fitnesse_dir, filename, 'content.txt')
62
+ properties_file = File.join(fitnesse_dir, filename, 'properties.xml')
70
63
  file_should_contain(content_file, content)
71
64
  file_should_contain(properties_file, xml_content(type))
72
65
  end
73
66
 
74
67
 
75
- Given /^a Cuke fixture$/ do
68
+ Given /^a default Cuke fixture$/ do
76
69
  in_test_dir do
77
70
  @cuke = Cukable::Cuke.new
78
- @cucumber_args = ''
71
+ end
72
+ end
73
+
74
+
75
+ Given /^a Cuke fixture with arguments:$/ do |arg_table|
76
+ args = arg_table.rows_hash
77
+ cucumber_args = args['cucumber_args'] or ''
78
+ project_dir = args['project_dir'] or ''
79
+ in_test_dir do
80
+ @cuke = Cukable::Cuke.new(cucumber_args, project_dir)
79
81
  end
80
82
  end
81
83
 
@@ -89,7 +91,7 @@ end
89
91
 
90
92
  When /^I write features for suite "(.+)"$/ do |suite_name|
91
93
  in_test_dir do
92
- @cuke.write_suite_features("FitNesseRoot/#{suite_name}")
94
+ @cuke.write_suite_features(File.join(fitnesse_dir, suite_name))
93
95
  end
94
96
  end
95
97
 
@@ -97,16 +99,11 @@ end
97
99
  When /^I convert features to FitNesse$/ do
98
100
  in_test_dir do
99
101
  @converter = Cukable::Converter.new
100
- @converter.features_to_fitnesse('features', @fitnesse_root)
102
+ @converter.features_to_fitnesse('features', fitnesse_dir)
101
103
  end
102
104
  end
103
105
 
104
106
 
105
- When /^I set CUCUMBER_ARGS to "(.+)"$/ do |args|
106
- @cucumber_args = args
107
- end
108
-
109
-
110
107
  When /^I run the accelerator for suite "(.+)"$/ do |suite_name|
111
108
  in_test_dir do
112
109
  @cuke.accelerate("#{suite_name}.AaaAccelerator", @cucumber_args)
@@ -16,12 +16,23 @@ class CukableHelper
16
16
  end
17
17
 
18
18
 
19
+ def fitnesse_dir
20
+ @fitnesse_dir ||= File.join(test_dir, "FitNesseRoot")
21
+ end
22
+
23
+
19
24
  # Execute `block` within `test_dir`
20
25
  def in_test_dir(&block)
21
26
  Dir.chdir(test_dir, &block)
22
27
  end
23
28
 
24
29
 
30
+ # Execute `block` within `fitnesse_dir`
31
+ def in_fitnesse_dir(&block)
32
+ Dir.chdir(fitnesse_dir, &block)
33
+ end
34
+
35
+
25
36
  # Create a standard cucumber features/ directory in `test_dir`
26
37
  def create_standard_cucumber_dir
27
38
  in_test_dir do
@@ -35,7 +46,7 @@ class CukableHelper
35
46
 
36
47
  def create_standard_fitnesse_dir
37
48
  in_test_dir do
38
- FileUtils.mkdir_p 'FitNesseRoot'
49
+ FileUtils.mkdir_p fitnesse_dir
39
50
  end
40
51
  end
41
52
 
@@ -50,18 +61,6 @@ class CukableHelper
50
61
  end
51
62
 
52
63
 
53
- def create_fitnesse_page(page_name, content)
54
- in_test_dir do
55
- page_dir = File.join('FitNesseRoot', page_name)
56
- page_file = File.join(page_dir, 'content.txt')
57
- FileUtils.mkdir_p page_dir
58
- File.open(page_file, 'w') do |file|
59
- file.puts(content)
60
- end
61
- end
62
- end
63
-
64
-
65
64
  # Create features/support/env.rb with necessary configuration for running
66
65
  # cucumber there
67
66
  def create_env_rb
@@ -75,27 +74,25 @@ class CukableHelper
75
74
 
76
75
 
77
76
  def create_stepdefs
78
- in_test_dir do
79
- File.open('features/step_definitions/simple_steps.rb', 'w') do |file|
80
- file.puts <<-EOF
81
- Given /^a step passes$/ do
82
- true.should == true
83
- end
84
- Given /^a step fails$/ do
85
- true.should == false
86
- end
87
- Given /^a step is skipped$/ do
88
- true.should == true
89
- end
90
- Given /^I have a table:$/ do |table|
91
- table.raw.each do |row|
92
- row.each do |cell|
93
- cell.should == 'OK'
94
- end
77
+ File.open('features/step_definitions/simple_steps.rb', 'w') do |file|
78
+ file.puts <<-EOF
79
+ Given /^a step passes$/ do
80
+ true.should == true
81
+ end
82
+ Given /^a step fails$/ do
83
+ true.should == false
84
+ end
85
+ Given /^a step is skipped$/ do
86
+ true.should == true
87
+ end
88
+ Given /^I have a table:$/ do |table|
89
+ table.raw.each do |row|
90
+ row.each do |cell|
91
+ cell.should == 'OK'
95
92
  end
96
93
  end
97
- EOF
98
- end
94
+ end
95
+ EOF
99
96
  end
100
97
  end
101
98
 
@@ -129,26 +126,23 @@ class CukableHelper
129
126
  # Ensure that the given file contains exactly the given text
130
127
  # (extra newlines/whitespace at beginning or end don't count)
131
128
  def file_should_contain(filename, text)
132
- in_test_dir do
133
- IO.read(filename).strip.should == text.strip
134
- end
129
+ IO.read(filename).strip.should == text.strip
135
130
  end
136
131
 
137
132
 
138
133
  # Ensure that the given filename contains JSON text.
139
134
  #
140
- # JSON does not need to match exactly; the output of each line
141
- # should *start* with the expected JSON text, but could contain
142
- # additional stuff afterwards.
135
+ # JSON does not need to match exactly; the output of each line should *start*
136
+ # with the expected JSON text, but could contain additional stuff afterwards.
137
+ # (This is done so that a <span> with the source filename can appear after
138
+ # the line, and that kind of thing is too volatile to test for.)
143
139
  def file_should_contain_json(filename, json_text)
144
- in_test_dir do
145
- got_json = JSON.load(File.open(filename))
146
- want_json = JSON.parse(json_text)
140
+ got_json = JSON.load(File.open(filename))
141
+ want_json = JSON.parse(json_text)
147
142
 
148
- got_json.zip(want_json).each do |got_row, want_row|
149
- got_row.zip(want_row).each do |got, want|
150
- got.should =~ /^#{want}/
151
- end
143
+ got_json.zip(want_json).each do |got_row, want_row|
144
+ got_row.zip(want_row).each do |got, want|
145
+ got.should =~ /^#{want}/
152
146
  end
153
147
  end
154
148
  end
@@ -181,3 +175,8 @@ After do
181
175
  #remove_test_dir
182
176
  end
183
177
 
178
+ Before do
179
+ remove_test_dir
180
+ create_test_dir
181
+ end
182
+
@@ -165,6 +165,9 @@ module Cukable
165
165
  # Status messages to return
166
166
  messages = []
167
167
 
168
+ # Strip trailing slash
169
+ fitnesse_path = fitnesse_path.gsub(/\/$/, '')
170
+
168
171
  # Ensure FitNesse directory already exists
169
172
  if !File.directory?(fitnesse_path)
170
173
  raise ArgumentError, "FitNesse path must be an existing directory."
@@ -183,7 +186,7 @@ module Cukable
183
186
  # Determine the appropriate wiki path name
184
187
  wiki_path = File.join(fitnesse_path, wikify_path(feature_path))
185
188
  # Fill ancestors of the wiki path with stubs for suites
186
- create_suite_stubs(File.dirname(wiki_path))
189
+ create_suite_stubs(File.dirname(wiki_path), fitnesse_path)
187
190
  # Convert the .feature to wikitext
188
191
  content = feature_to_fitnesse(File.open(feature_path)).join("\n")
189
192
  # Write the wikitext to a wiki page
@@ -243,17 +246,20 @@ module Cukable
243
246
  # # FitNesseRoot/PageOne/PageTwo/content.txt
244
247
  # # FitNesseRoot/PageOne/PageTwo/PageThree/content.txt
245
248
  #
246
- # @param [String] fitnesse_path
249
+ # @param [String] wiki_path
247
250
  # Directory name of deepest level in the wiki hierarchy where
248
251
  # you want content stubs to be created
252
+ # @param [String] root_path
253
+ # FitNesseRoot directory--the stopping point in `wiki_path`'s
254
+ # ancestry, where no more content stubs will be created.
249
255
  #
250
- def create_suite_stubs(fitnesse_path)
256
+ def create_suite_stubs(wiki_path, root_path)
251
257
  # Content string to put in each stub file
252
258
  content = '!contents -R9 -p -f -h'
253
- # Starting with `fitnesse_path`
254
- path = fitnesse_path
255
- # Until there are no more ancestor directories
256
- while path != '.'
259
+ # Starting with `wiki_path`
260
+ path = wiki_path
261
+ # Until the root level is reached
262
+ until path == root_path || path == '.'
257
263
  # If there is no content.txt file, create one
258
264
  if !File.exists?(File.join(path, 'content.txt'))
259
265
  create_wiki_page(path, content, 'suite')
@@ -35,6 +35,12 @@ module Cukable
35
35
  @@last_suite_name = nil
36
36
 
37
37
 
38
+ # Execute a block inside `@project_dir`.
39
+ def in_project_dir(&block)
40
+ Dir.chdir(@project_dir, &block)
41
+ end
42
+
43
+
38
44
  # Create the fixture, with optional Cucumber command-line arguments.
39
45
  #
40
46
  # @param [String] cucumber_args
@@ -43,13 +49,17 @@ module Cukable
43
49
  # test. Otherwise, the `cucumber_args` passed to `accelerate`
44
50
  # take precedence.
45
51
  #
46
- def initialize(cucumber_args='')
47
- # Directory where temporary .feature files will be written
52
+ def initialize(cucumber_args='', project_dir='')
53
+ # Path to where temporary .feature files will be written
54
+ # (relative to @project_dir)
48
55
  @features_dir = File.join('features', 'fitnesse')
49
- # Directory where JSON output files will be written by Cucumber
56
+ # Where JSON output files will be written by Cucumber
57
+ # (relative to @project_dir)
50
58
  @output_dir = 'slim_results'
51
59
  # Cucumber command-line arguments
52
- @cucumber_args = cucumber_args
60
+ @cucumber_args = cucumber_args or ''
61
+ @project_dir = File.expand_path((project_dir or '.'))
62
+ ensure_directory(@project_dir)
53
63
  end
54
64
 
55
65
 
@@ -67,10 +77,12 @@ module Cukable
67
77
  # Command-line arguments to pass to Cucumber for this run.
68
78
  # Affects all tests in the suite.
69
79
  #
70
- def accelerate(test_name, cucumber_args='')
80
+ def accelerate(test_name, cucumber_args='', project_dir='')
71
81
  # Remove wiki cruft from the test_path
72
82
  test_name = remove_cruft(test_name)
73
83
  @cucumber_args = cucumber_args
84
+ @project_dir = File.expand_path((project_dir or '.'))
85
+ ensure_directory(@project_dir)
74
86
 
75
87
  # Don't run the accelerator unless we're on a page called AaaAccelerator
76
88
  if !(test_name =~ /^.*AaaAccelerator$/)
@@ -97,8 +109,10 @@ module Cukable
97
109
  # two people are running different suites at the same time?
98
110
  # The same suite at the same time?
99
111
  [@features_dir, @output_dir].each do |dir|
100
- FileUtils.rm_rf(dir)
101
- FileUtils.mkdir(dir)
112
+ in_project_dir do
113
+ FileUtils.rm_rf(dir)
114
+ FileUtils.mkdir(dir)
115
+ end
102
116
  end
103
117
 
104
118
  # Reset the digest-to-json map, then fill it in with the
@@ -106,8 +120,10 @@ module Cukable
106
120
  @@output_files = Hash.new
107
121
 
108
122
  # Write all .feature files and run Cucumber on them
109
- feature_filenames = write_suite_features(suite)
110
- run_cucumber(feature_filenames, @output_dir)
123
+ in_project_dir do
124
+ feature_filenames = write_suite_features(suite)
125
+ run_cucumber(feature_filenames)
126
+ end
111
127
 
112
128
  # Parse the results out over their sources.
113
129
  return true # Wait for someone to test one of the same tables.
@@ -130,7 +146,9 @@ module Cukable
130
146
  @features_dir, "#{feature}_#{number}.feature")
131
147
  feature_filenames << feature_filename
132
148
  begin
133
- write_feature(table, feature_filename)
149
+ in_project_dir do
150
+ write_feature(table, feature_filename)
151
+ end
134
152
  rescue FormatError => err
135
153
  puts "!!!! Error writing #{feature_filename}:"
136
154
  puts err.message
@@ -140,7 +158,7 @@ module Cukable
140
158
 
141
159
  # Store the JSON filename in the digest hash
142
160
  digest = table_digest(table)
143
- json_filename = File.join(@output_dir, "#{feature_filename}.json")
161
+ json_filename = File.join(@project_dir, @output_dir, "#{feature_filename}.json")
144
162
  @@output_files[digest] = json_filename
145
163
  end
146
164
  end
@@ -168,14 +186,14 @@ module Cukable
168
186
  # Otherwise, run Cucumber from scratch on this table,
169
187
  # and return the results
170
188
  else
171
- # FIXME: Move this to a separate method?
172
- # Create @features_dir if it doesn't exist
173
- FileUtils.mkdir(@features_dir) unless File.directory?(@features_dir)
174
189
  feature_filename = File.join(@features_dir, 'fitnesse_test.feature')
175
190
  # Create the feature file, run cucumber, return results
176
- write_feature(table, feature_filename)
177
- run_cucumber([feature_filename], @output_dir)
178
- results = File.join(@output_dir, "#{feature_filename}.json")
191
+ in_project_dir do
192
+ ensure_directory(@features_dir)
193
+ write_feature(table, feature_filename)
194
+ run_cucumber([feature_filename])
195
+ end
196
+ results = File.join(@project_dir, @output_dir, "#{feature_filename}.json")
179
197
  end
180
198
 
181
199
  # If the results file exists, parse it, merge with the original table,
@@ -243,7 +261,7 @@ module Cukable
243
261
  got_feature = false
244
262
  got_scenario = false
245
263
 
246
- FileUtils.mkdir(@features_dir) unless File.directory?(@features_dir)
264
+ ensure_directory(@features_dir)
247
265
  file = File.open(feature_filename, 'w')
248
266
 
249
267
  # Error if there is not exactly one "Feature" row
@@ -277,22 +295,32 @@ module Cukable
277
295
 
278
296
 
279
297
  # Run cucumber on `feature_filenames`, and output
280
- # results in FitNesse table format to `output_dir`.
298
+ # results in FitNesse table format to `@output_dir`.
281
299
  #
282
300
  # @param [Array] feature_filenames
283
301
  # All `.feature` files to execute
284
- # @param [String] output_dir
285
- # Where to save the SlimJSON-formatted results
286
302
  #
287
- def run_cucumber(feature_filenames, output_dir)
288
- req = "--require /home/eric/git/cukable/lib/"
303
+ def run_cucumber(feature_filenames)
304
+ # Tell cucumber to require the directory where this file lives,
305
+ # so it can find the SlimJSON formatter
306
+ lib = File.expand_path(File.dirname(__FILE__))
307
+ req = "--require #{lib} --require features"
289
308
  format = "--format Cucumber::Formatter::SlimJSON"
290
- output = "--out #{output_dir}"
309
+ output = "--out #{@output_dir}"
291
310
  args = @cucumber_args
292
311
  features = feature_filenames.join(" ")
312
+ cucumber_cmd = "#{cucumber_executable} #{req} #{format} #{output} #{args} #{features}"
293
313
 
294
- #puts "cucumber #{req} #{format} #{output} #{args} #{features}"
295
- system "cucumber #{req} #{format} #{output} #{args} #{features}"
314
+
315
+ in_project_dir do
316
+ # If project_dir contains an .rvmrc, wrap the command in a bash
317
+ # session that will use the correct environment
318
+ if File.exist?('.rvmrc')
319
+ cucumber_cmd = "bash -l -c 'source .rvmrc ; #{cucumber_cmd}' "
320
+ end
321
+ puts "Running: #{cucumber_cmd}"
322
+ system cucumber_cmd
323
+ end
296
324
 
297
325
  # TODO: Ensure that the correct number of output files were written
298
326
  #if !File.exist?(@results_filename)
@@ -300,6 +328,23 @@ module Cukable
300
328
  #end
301
329
  end
302
330
 
331
+
332
+ # Return the name of the cucumber executable. If `project_dir` contains a
333
+ # `Gemfile`, use `bundle exec cucumber`; otherwise, use `cucumber`.
334
+ def cucumber_executable
335
+ if File.exist?(File.join(@project_dir, 'Gemfile'))
336
+ return "bundle exec cucumber"
337
+ else
338
+ return "cucumber"
339
+ end
340
+ end
341
+
342
+
343
+ # Ensure that a directory `path` exists
344
+ def ensure_directory(path)
345
+ FileUtils.mkdir_p(path) unless File.directory?(path)
346
+ end
347
+
303
348
  end
304
349
  end
305
350
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cukable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Eric Pierce
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-03-23 00:00:00 -06:00
19
+ date: 2011-07-09 00:00:00 -06:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -62,9 +62,25 @@ dependencies:
62
62
  type: :runtime
63
63
  version_requirements: *id003
64
64
  - !ruby/object:Gem::Dependency
65
- name: rspec
65
+ name: rake
66
66
  prerelease: false
67
67
  requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ hash: 49
73
+ segments:
74
+ - 0
75
+ - 8
76
+ - 7
77
+ version: 0.8.7
78
+ type: :development
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: rspec
82
+ prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
68
84
  none: false
69
85
  requirements:
70
86
  - - ">="
@@ -76,11 +92,11 @@ dependencies:
76
92
  - 0
77
93
  version: 2.2.0
78
94
  type: :development
79
- version_requirements: *id004
95
+ version_requirements: *id005
80
96
  - !ruby/object:Gem::Dependency
81
97
  name: rcov
82
98
  prerelease: false
83
- requirement: &id005 !ruby/object:Gem::Requirement
99
+ requirement: &id006 !ruby/object:Gem::Requirement
84
100
  none: false
85
101
  requirements:
86
102
  - - ">="
@@ -90,11 +106,11 @@ dependencies:
90
106
  - 0
91
107
  version: "0"
92
108
  type: :development
93
- version_requirements: *id005
109
+ version_requirements: *id006
94
110
  - !ruby/object:Gem::Dependency
95
111
  name: yard
96
112
  prerelease: false
97
- requirement: &id006 !ruby/object:Gem::Requirement
113
+ requirement: &id007 !ruby/object:Gem::Requirement
98
114
  none: false
99
115
  requirements:
100
116
  - - ">="
@@ -104,11 +120,11 @@ dependencies:
104
120
  - 0
105
121
  version: "0"
106
122
  type: :development
107
- version_requirements: *id006
123
+ version_requirements: *id007
108
124
  - !ruby/object:Gem::Dependency
109
125
  name: bluecloth
110
126
  prerelease: false
111
- requirement: &id007 !ruby/object:Gem::Requirement
127
+ requirement: &id008 !ruby/object:Gem::Requirement
112
128
  none: false
113
129
  requirements:
114
130
  - - ">="
@@ -118,7 +134,7 @@ dependencies:
118
134
  - 0
119
135
  version: "0"
120
136
  type: :development
121
- version_requirements: *id007
137
+ version_requirements: *id008
122
138
  description: " Cukable allows running Cucumber test scenarios from FitNesse\n"
123
139
  email: wapcaplet88@gmail.com
124
140
  executables:
@@ -128,9 +144,10 @@ extensions: []
128
144
  extra_rdoc_files: []
129
145
 
130
146
  files:
147
+ - .gitignore
131
148
  - .yardopts
132
149
  - Gemfile
133
- - Gemfile.lock
150
+ - History.md
134
151
  - README.md
135
152
  - Rakefile
136
153
  - bin/cuke2fit
@@ -1,47 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- cukable (0.1.1)
5
- cucumber
6
- diff-lcs
7
- json
8
-
9
- GEM
10
- remote: http://rubygems.org/
11
- specs:
12
- bluecloth (2.0.11)
13
- builder (2.1.2)
14
- cucumber (0.8.5)
15
- builder (~> 2.1.2)
16
- diff-lcs (~> 1.1.2)
17
- gherkin (~> 2.1.4)
18
- json_pure (~> 1.4.3)
19
- term-ansicolor (~> 1.0.4)
20
- diff-lcs (1.1.2)
21
- gherkin (2.1.5)
22
- trollop (~> 1.16.2)
23
- json (1.5.1)
24
- json_pure (1.4.6)
25
- rcov (0.9.9)
26
- rspec (2.5.0)
27
- rspec-core (~> 2.5.0)
28
- rspec-expectations (~> 2.5.0)
29
- rspec-mocks (~> 2.5.0)
30
- rspec-core (2.5.1)
31
- rspec-expectations (2.5.0)
32
- diff-lcs (~> 1.1.2)
33
- rspec-mocks (2.5.0)
34
- term-ansicolor (1.0.5)
35
- trollop (1.16.2)
36
- yard (0.6.4)
37
-
38
- PLATFORMS
39
- ruby
40
-
41
- DEPENDENCIES
42
- bluecloth
43
- bundler (~> 1.0)
44
- cukable!
45
- rcov
46
- rspec (>= 2.2.0)
47
- yard