cukable 0.1.1 → 0.1.2

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