diff --git a/.gitignore b/.gitignore index 99bfed25ac..3d135bac25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .bundle -Gemfile.lock nbproject coverage pkg @@ -23,3 +22,6 @@ rerun.txt ._* .rvmrc .sass-cache +doc/ +*.tgz +Gemfile.lock diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..524ad543d5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "features/cucumber-features"] + path = features/cucumber-features + url = https://github.com/cucumber/cucumber-features diff --git a/.rspec b/.rspec index 4e1e0d2f72..cce76064ce 100644 --- a/.rspec +++ b/.rspec @@ -1 +1 @@ ---color +--color --backtrace diff --git a/.rvmrc b/.rvmrc index 92a100e317..1cd239632a 100644 --- a/.rvmrc +++ b/.rvmrc @@ -1 +1 @@ -rvm @cucumber --create +rvm gemset use cucumber diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..47d09d1b9c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +rvm: + - 1.9.3 + - 1.9.2 +# whitelist +branches: + only: + - master + +notifications: + email: + - cukes-devs@googlegroups.com + irc: + - "irc.freenode.org#cucumber" diff --git a/Gemfile b/Gemfile index 004c184b38..c7d14233ed 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,4 @@ source "http://rubygems.org" - -group :development do - # gem 'gherkin', :path => '../gherkin' -end - gemspec + +# gem 'gherkin', :path => '../gherkin' diff --git a/History.txt b/History.md similarity index 75% rename from History.txt rename to History.md index 059f354fa6..27c13e85f9 100644 --- a/History.txt +++ b/History.md @@ -1,11 +1,197 @@ -== 0.10.2 (2011-03-21) +## [v1.2.0](https://github.com/cucumber/cucumber/compare/v1.1.9...v1.2.0) -=== Bugfixes +## New Features +* Extracted the PDF formatter into a separate gem. (#241 Matt Wynne) + +## [v1.1.9](https://github.com/cucumber/cucumber/compare/v1.1.8...v1.1.9) + +## Bugfixes +* Removed deprecation warning for `source_tag_names`. It's not deprecated anymore. (Aslak Hellesøy) + +## [v1.1.8](https://github.com/cucumber/cucumber/compare/v1.1.7...v1.1.8) + +## Bugfixes +* Column mapping dangerously applied twice to the same cell! ([#202](https://github.com/cucumber/cucumber/issues/202), [#208](https://github.com/cucumber/cucumber/pull/208) Brian Dunn) + +## New Features +* Don't pollute RbWorld with the AnsiEscapes methods ([#219](https://github.com/cucumber/cucumber/issues/219), [#221](https://github.com/cucumber/cucumber/pull/221) Ben Woosley) + +## [v1.1.7](https://github.com/cucumber/cucumber/compare/v1.1.6...v1.1.7) + +### Bugfixes + +* Finish off backwards compatability fix for Capybara ([#229](https://github.com/cucumber/cucumber/pull/229) Cezary Baginski) + +## [v1.1.6](https://github.com/cucumber/cucumber/compare/v1.1.5...v1.1.6) + +### New features + +* Added `file_colon_line` to `stepdefs.json` (outputted by `--dotcucumber`). ([#214](https://github.com/cucumber/cucumber/pull/214) MOROHASHI Kyosuke) + +### Bugfixes + +* Release 1.1.5 unintentionally broke backwards compatibility in some APIs we hadn't considered were used outside of cucumber. + Well, it was, in the popular Capybara browser automation tool, so we added back the API we removed. See the history for details. (Aslak Hellesøy) +* After some infantile bickering about a trivial bug that any hipster startup ruby programmer could have circumvented by using a fork with a fix, + I finally sucked up to a horde of people and made HTML reports work again (I'm gonna rename them TPS reports). ([#203](https://github.com/cucumber/cucumber/pull/203) Jon Merrifield) + +## [v1.1.5](https://github.com/cucumber/cucumber/compare/v1.1.4...v1.1.5) + +### New Features + +* Upgraded to gherkin 2.8.0 (Aslak Hellesøy) + +### Bugfixes + +* Background fails, but build succeeds ([#205](https://github.com/cucumber/cucumber/issues/205) tcwitte) + +## [v1.1.4](https://github.com/cucumber/cucumber/compare/v1.1.3...v1.1.4) + +### New Features + +* Upgrade to Gherkin 2.7.1 (Aslak Hellesøy) + +## [v1.1.3](https://github.com/cucumber/cucumber/compare/v1.1.2...v1.1.3) + +### New Features + +* Generate stepdef metadata with --dotcucumber. Useful for Cukepatch. (Aslak Hellesøy) +* Show class name of exceptions in the HTML formatter ([#159](https://github.com/cucumber/cucumber/pull/159) Jari Bakken) +* Deferred table header and column mappings ([#163](https://github.com/cucumber/cucumber/pull/163) Richard Lawrence) + +### Bugfixes + +* Escape exceptions in HTML formatter ([#178](https://github.com/cucumber/cucumber/pull/178) leachdaniel) +* Retry when feature_element returns failed ([#172](https://github.com/cucumber/cucumber/pull/172) Charles Finkel) +* Rerun formatter output does not include failing scenario outline examples ([#57](https://github.com/cucumber/cucumber/issues/57) Jan Brauer) + +## [v1.1.2](https://github.com/cucumber/cucumber/compare/v1.1.1...v1.1.2) + +### Changed features + +* Break long lines in output. Only needed for better output formatting in the Cucumber Book! (Aslak Hellesøy) + +### Changed features + +* Deprecated i18n methods in World, and added a new #step method to use instead. ([#68](https://github.com/cucumber/cucumber/issues/68) Matt Wynne) +* The JSON formatter output has changed slightly. Old format: + + { + features: [feature here] + } + +New format: + + [feature here] + +Also see [Gherkin 2.6.0 History](https://github.com/cucumber/gherkin/blob/master/History.md) for info about new `id` and `uri` elements in the JSON. + +## [v1.1.0](https://github.com/cucumber/cucumber/compare/v1.0.6...v1.1.0) + +### Changed features +* The JSON formatter output has changed. See [Gherkin 2.5.0 History](https://github.com/cucumber/gherkin/blob/master/History.md) (Aslak Hellesøy) + +## [v1.0.6](https://github.com/cucumber/cucumber/compare/v1.0.5...v1.0.6) + +### Bugfixes +* Work around rubygems/yaml utter retardedness ([#136](https://github.com/cucumber/cucumber/issues/136) Aslak Hellesøy) + +## [v1.0.5](https://github.com/cucumber/cucumber/compare/v1.0.4...v1.0.5) + +### Bugfixes + +* Gemspec corrupted in 1.0.4 (I had to upgrade my rubygems to 1.8.10 to fix it). ([#136](https://github.com/cucumber/cucumber/issues/136) Aslak Hellesøy) + +## [v1.0.4](https://github.com/cucumber/cucumber/compare/v1.0.3...v1.0.4) + +### Bugfixes + +* Guard against the require succeeding, but not properly loading a module. ([#93](https://github.com/cucumber/cucumber/pull/93) Christopher Meiklejohn) +* Cmdline arguments parsing error if --drb is enabled. ([#117](https://github.com/cucumber/cucumber/issues/117) Roman Chernyatchik) +* Replace capturing groups with non-capturing in RbTransform#to_s ([#106](https://github.com/cucumber/cucumber/pull/106) Thomas Walpole) +* Patched unmatched message in HTML formatter. (Nikita) +* Overriding a method that causes a NoMethodError when a Before hook is called on a feature run that has no scenarios. (ccthiel) + +## [v1.0.3](https://github.com/cucumber/cucumber/compare/v1.0.2...v1.0.3) + +### Bugfixes +* Do not escape the replaced entity ([#126](https://github.com/cucumber/cucumber/pull/126) Jonathan Tron) + +### New Features +* DocStrings now have a content_type ([#132](https://github.com/cucumber/cucumber/issues/132) Matt Wynne) + +## [v1.0.2](https://github.com/cucumber/cucumber/compare/v1.0.1...v1.0.2) + +### Bugfixes +* Cucumber 1.0.1 breaks cuke4duke ([#104](https://github.com/cucumber/cucumber/issues/104) Aslak Hellesøy) + +### New Features +* Better line truncation if $CUCUMBER_TRUNCATE_OUTPUT has a max line length value. (Aslak Hellesøy) + +### Changes Features +* --no-source also excludes location from the summary. (Aslak Hellesøy) + +## [v1.0.1](https://github.com/cucumber/cucumber/compare/v1.0.0...v1.0.1) + +### Bugfixes +* Removed extra colons emitted by rerun formatter ([#99](https://github.com/cucumber/cucumber/pull/99) Juan Manuel Barreneche) +* cucumber 1.0.0 wrong number of arguments error when generating json format on jruby for windows ([#97](https://github.com/cucumber/cucumber/issues/97) (Aslak Hellesøy) +* Recent change to junit.rb breaks on Windows ([#81](https://github.com/cucumber/cucumber/issues/81), [#86](https://github.com/cucumber/cucumber/pull/86) Johnlon, Aslak Hellesøy) +* Cucumber fails on nil and does not print out failed tests ([#95](https://github.com/cucumber/cucumber/pull/95) Nikita) +* Javascript code is not being displayed in HTML output ([#58](https://github.com/cucumber/cucumber/issues/58) Aslak Hellesøy) + +### New Features +* If the CUCUMBER_TRUNCATE_OUTPUT environment variable is set, lines will be truncated. Used by the Cucumber book. (Aslak Hellesøy) + +## [v1.0.0](https://github.com/cucumber/cucumber/compare/v0.10.6...v1.0.0) + +Yipeeeeeeeee! + +### New Features +* Use Rake 1.9.2 for development (Aslak Hellesøy) +* Rake task exits with an error if rcov is true and we're on Ruby 1.9.x (Aslak Hellesøy) +* Started implementation of cucumber-features (Mike Sassak, Julien Biezemans, Aslak Hellesøy) + +## [v0.10.6](https://github.com/cucumber/cucumber/compare/v0.10.5...v0.10.6) + +### New Features +* API docs at http://cukes.info/cucumber/api/ruby/latest/ + +### Bugfixes +* Fixed a regression in the HTML formatter's #embed implementation (#77 Aslak Hellesøy) + +## [v0.10.5](https://github.com/cucumber/cucumber/compare/v0.10.3...v0.10.5) + +(0.10.4 was forgotten!) + +### Changed features +* The announce method is deprecated. Use puts instead (#67 Aslak Hellesøy) +* The announce_world method is gone. Use puts(self) instead (#67 Aslak Hellesøy) + +### New Features +* Better JUnit formatter support for sub directories and scenario outlines (#59, #61, #62 Matt Simpson, Kenny Ortmann) + +### Bugfixes +* Fix for Gem.available? deprecation warning (#75 Jake Benilov) +* Update URLs to reflect Cucumber's new location on Github (Jake Benilov) + +## [v0.10.3](https://github.com/cucumber/cucumber/compare/v0.10.2...v0.10.3) + +### New Features +* Better JUnit formatter support for sub directories and scenario outlines (#59 Matt Simpson) +* Coloured output that spans several lines sets colours for each line. (Aslak Hellesøy) +* New bundler attribute on the Rake task, allowing faster execution. (Aslak Hellesøy) +* Fix Table#rows cell ordering in ruby 1.8. (#47_github Brian Dunn) +* JUnit Formatter: record skipped/pending/undefined scenario results (#655 meeee) + +## [v0.10.2](https://github.com/cucumber/cucumber/compare/v0.10.1...v0.10.2) + +### Bugfixes * Neuter both MiniTest::Unit and Test::Unit's overzealous test runners. (Aslak Hellesøy) -== 0.10.1 (2011-03-20) +## [v0.10.1](https://github.com/cucumber/cucumber/compare/v0.10.0...v0.10.1) -=== New Features +### New Features * The #embed method can take a 3rd optional label argument. In the HTML report that's used for the link title. (Pat Leamon) * Render .wire files through ERB (Kevin Olbrich) * Happy coexistence with Rake 0.9 (Cezary Baginski) @@ -18,236 +204,236 @@ * Include scenario file reference in html formatter output (Brandon Faloona) * Relax gem dependencies to use >= instead of ~> (Rob Slifka, Aslak Hellesøy) -=== Bugfixes +### Bugfixes * Missing methods in Runtime::ForProgrammingLanguages - make v8 example run again (Chris Mytton) -* Features files are sorted before they are executed, giving consistent results accross different OSes (Guewen Baconnier) +* Features files are sorted before they are executed, giving consistent results across different OSes (Guewen Baconnier) * Remove duplicate lines in backtraces in the HTML report (Jari Bakken) -== 0.10.0 (2010-12-07) +## [v0.10.0](https://github.com/cucumber/cucumber/compare/v0.9.4...v0.10.0) We're bumping the minor number in this release because there are some incompatible changes in the JSON support. This should not affect users. The major new feature in this release is ANSICON support for Windows users. -=== New Features -* #map_column! should allow a string or symbol as the column name passed in (Ed Schmalzle) +### New Features +* map_column! should allow a string or symbol as the column name passed in (Ed Schmalzle) * Deprecate win32console and use ANSICON instead (Boško Ivanišević) * Set builder dependency to >= 2.1.2, which will work with both Rails 2 and 3. (bUg., David Trasbo, Matt Wynne) -=== Bugfixes +### Bugfixes * Changed the HTML formatter to show Scenarios with 'Pending' steps to be yellow rather than green (Arti) -=== Changed Features +### Changed Features * JSON output now contains optional "match", "result" and "embeddings" elements underneath each step. (Aslak Hellesøy) -== 0.9.4 (2010-11-07) +## [v0.9.4](https://github.com/cucumber/cucumber/compare/v0.9.3...v0.9.4) -=== Bugfixes +### Bugfixes * Superfluous space after step_keyword value in snippet_text message (#679 Aslak Hellesøy) -* Better Handling for "announce" in HTML formatter (#676 Stephen Kennedy) +* Better Handling for "puts" in HTML formatter (#676 Stephen Kennedy) * Too many open files - getcwd (#666 Aslak Hellesøy) * Cucumber 0.9.3 prevents Test::Unit from running (#677 Aslak Hellesøy) * Performance degradation when running feature files with over 1000 steps (#675 Dimitri Geshef) -== 0.9.3 (2010-10-24) +## [v0.9.3](https://github.com/cucumber/cucumber/compare/v0.9.2...v0.9.3) -=== Bugfixes +### Bugfixes * Better JSON representation of Regexps (Aslak Hellesøy) * Update to work with latest spork (Matt Wynne) * Prevent MiniTest::Unit#autorun from running in at_exit hook. (Aslak Hellesøy) * Fixed incorect --help for --strict. It fails on both pending and undefined. (Aslak Hellesøy) -== 0.9.2 (2010-10-04) +## [v0.9.2](https://github.com/cucumber/cucumber/compare/v0.9.1...v0.9.2) -=== Bugfixes +### Bugfixes * Too many open files - getcwd (#666 Aslak Hellesøy) -== 0.9.1 (2010-10-02) +## [v0.9.1](https://github.com/cucumber/cucumber/compare/v0.9.0...v0.9.1) -=== Bugfixes +### Bugfixes * Just a minor internal change to make Cuke4Duke happy. (Aslak Hellesøy) -== 0.9.0 (2010-09-21) +## [v0.9.0](https://github.com/cucumber/cucumber/compare/v0.8.5...v0.9.0) Maintenance release for the new release of Gherkin 2.2.3. -=== Bugfixes +### Bugfixes * Compatibility with rspec-2.0.0.beta.19 mocks (Aslak Hellesøy) * JUnit formatter now puts output in CDATA sections. (Dmitry Amelchenko) -=== New features +### New features * --dry-run now shows snippets (Ben Hall) * Use Bundler for dependency management. (Aslak Hellesøy, Rob Hunter) -=== Removed features +### Removed features * No more Jeweler -=== Internal changes +### Internal changes * Big refactoring of StepMother (Matt Wynne) -== 0.8.5 (2010-07-14) +## [v0.8.5](https://github.com/cucumber/cucumber/compare/v0.8.4...v0.8.5) -=== Bugfixes +### Bugfixes * Location of stepdefs outside the project (in gems) are reported incorrectly. (#583 Aslak Hellesøy) * Cucumber::Rake::Task uses 'bundle exec' when using bundler (#626 John Firebaugh) -== 0.8.4 (2010-07-12) +## [v0.8.4](https://github.com/cucumber/cucumber/compare/v0.8.3...v0.8.4) -=== Bugfixes +### Bugfixes * Fix "Errno::EADDRNOTAVAIL" errors that may be received with spork on Snow Leopard. (Lucas Mundim) -=== New features +### New features * Detect limit for negative tags (#636 Aslak Hellesøy) * Support for RSpec 2 doubles (mocks and stubs) (Aslak Hellesøy) -== 0.8.3 (2010-06-16) +## [v0.8.3](https://github.com/cucumber/cucumber/compare/v0.8.2...v0.8.3) Just a quick bugfix release. -=== Bugfixes +### Bugfixes * Scenario outlines that fail with exception exit process (Aslak Hellesøy) -== 0.8.2 (2010-06-16) +## [v0.8.2](https://github.com/cucumber/cucumber/compare/v0.8.1...v0.8.2) Bugfix release which most importantly fixes an issue with the gem's gemspec. -=== Bufixes +### Bufixes * Fix v8 support which broke in 0.8.1 because of new gherkin API (Aslak Hellesøy) * Call Around hooks for each example in scenario outlines. (John Firebaugh) * Remove extraneous tmp file from the gemspec, which broke installation in some environments. (Fernando Brito, Aslak Hellesøy) * 0.8.1 fails on JRuby (#627 Aslak Hellesøy) -=== New Features +### New Features * JavaScript to Hide/Expand Scenarios in HTML report (#621 stkenned) -== 0.8.1 (2010-06-15) +## [v0.8.1](https://github.com/cucumber/cucumber/compare/v0.8.0...v0.8.1) -=== Bufixes +### Bufixes * generate test report fails: ast/outline_table.rb fails in status() (#615 Aslak Hellesøy) -=== New Features +### New Features * Undefined steps with integers (Given 3 cukes) will generate snippets like (Given /(\d+) cukes/). (Aslak Hellesøy) -== 0.8.0 (2010-06-06) +## [v0.8.0](https://github.com/cucumber/cucumber/compare/v0.7.3...v0.8.0) -=== Bugfixes +### Bugfixes * Require profile option causes a NoMethodError for Cucumber with JRuby (#601 John Firebaugh) * Deprecations warnings with Spork + Cucumber + RSpec 2.0. (#619 Brian Cardarella) * Fixed edge case compatibility problem with Gherkin 1.0.30. (#618 Aslak Hellesøy) -=== New features +### New features * Better table support in the V8 Javascript support (Joseph Wilk) * JSON formatters (json and json_pretty). (Jari Bakken) -=== Removed features +### Removed features * The --no-diff option is removed. If you're using RSpec you will *always* get diffs. (Aslak Hellesøy) -=== Changed Features +### Changed Features * Upgraded to be compatible with rspec 2.0.0.beta.10 (Aslak Hellesøy) * Ruby snippets will use "([^"]*)" instead of "([^\"]*)"$/ - wasn't properly fixed in 0.7.1. (Aslak Hellesøy) * Preserve the order features files are passed and use this for execution order (#617 Joseph Wilk) -== 0.7.3 (2010-05-17) +## [v0.7.3](https://github.com/cucumber/cucumber/compare/v0.7.2...v0.7.3) -=== New Features +### New Features * Table cells can now contain escaped bars - \| and escaped backslashes - \\. (Gregory Hnatiuk, Aslak Hellesøy) * Added support for Around hooks. (#605 John Firebaugh) -== 0.7.2 (2010-05-03) +## [v0.7.2](https://github.com/cucumber/cucumber/compare/v0.7.1...v0.7.2) -=== Bugfixes +### Bugfixes * REALLY add backwards compatibility fix (with deprecation warning) for legacy 0.6.4 formatters. (Aslak Hellesøy) -== 0.7.1 (2010-05-03) +## [v0.7.1](https://github.com/cucumber/cucumber/compare/v0.7.0...v0.7.1) -=== Bugfixes +### Bugfixes * Add backwards compatibility fix (with deprecation warning) for legacy 0.6.4 formatters. (Aslak Hellesøy) -=== Changed Features +### Changed Features * Ruby and Javascript snippets will use "([^"]*)" instead of "([^\"]*)"$/ (Aslak Hellesøy) -== 0.7.0 (2010-05-02) +## [v0.7.0](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.8...v0.7.0) This release is an important milestone for Cucumber. A new parser (the gherkin gem) parses feature files 50-100 times faster than with 0.6.x and previous releases. Make sure you read the upgrade instructions! http://wiki.github.com/aslakhellesoy/cucumber/upgrading -== 0.7.0.beta.8 (2010-04-29) +## [v0.7.0.beta.8](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.7...v0.7.0.beta.8) -=== Bugfixes +### Bugfixes * Inconsistent order of execution Background and Before in 0.7.0.beta.2 (#600 Mike Sassak) * Make sure both lexing and parsing errors are captured and reported with line number (Gregory Hnatiuk) -== 0.7.0.beta.7 (2010-04-28) +## [v0.7.0.beta.7](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.6...v0.7.0.beta.7) -=== Bugfixes +### Bugfixes * Depend on gherkin-1.0.22, which should now make things work on Windows and Ruby 1.8.x-1.9.x. (Aslak Hellesøy) -== 0.7.0.beta.6 (2010-04-28) +## [v0.7.0.beta.6](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.5...v0.7.0.beta.6) -=== Bugfixes +### Bugfixes * Fixed a small regression with pystrings and calling steps from stepdefs, introduced in a previous beta. (Aslak Hellesøy) -== 0.7.0.beta.5 (2010-04-27) +## [v0.7.0.beta.5](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.4...v0.7.0.beta.5) -=== New Features +### New Features * Support RSpec 2. (RSpec >= 1.2.4 is still supported). (Aslak Hellesøy, Ryan Bigg) -=== Removed features +### Removed features * No more support for RSpec <= 1.2.3. (Aslak Hellesøy) -== 0.7.0.beta.4 (2010-04-24) +## [v0.7.0.beta.4](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.3...v0.7.0.beta.4) -=== New Features +### New Features * New, experimental V8 javascript support - step definitions in Javascript! (Joseph Wilk) -=== Bugfixes +### Bugfixes * Gherkin is loaded via rubygems if it can't be found on the $LOAD_PATH. (Aslak Hellesøy) -== 0.7.0.beta.3 (2010-04-23) +## [v0.7.0.beta.3](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.2...v0.7.0.beta.3) -=== Changed Features +### Changed Features * Step Definitions and calling steps from step definitions can again use And and But (was removed in 0.7.0.beta.2) (Aslak Hellesøy) -== 0.7.0.beta.2 (2010-04-21) +## [v0.7.0.beta.2](https://github.com/cucumber/cucumber/compare/v0.7.0.beta.1...v0.7.0.beta.2) -=== New Features +### New Features * Depend on Gherkin 1.0.18, which has some bugfixes. (Aslak Hellesøy) -== 0.7.0.beta.1 (2010-04-20) +## [v0.7.0.beta.1](https://github.com/cucumber/cucumber/compare/v0.6.4...v0.7.0.beta.1) Treetop is gone and replaced with Ragel. The new Ragel parser lives in the gherkin gem. Parse times are up to 100 times faster. -=== New Features +### New Features * Upgraded Sinatra example to use Sinatra 1.0 and Capybara. (Aslak Hellesøy) -=== Changed Features +### Changed Features * New i18n translations now have to be contributed to the gherkin project. -== 0.6.4 2010-03-30 +## [v0.6.4](https://github.com/cucumber/cucumber/compare/v0.6.3...v0.6.4) -=== Bugfixes +### Bugfixes * Better handling of --guess with optional capture groups (Tim Felgentreff) * Parsing of rerun.txt can't use Shellwords on Windows (#581 David Esposito) -* #announce can now take non-String arguments just like Kernel#puts - #to_s is done implicitly. (Aslak Hellesøy) +* \#puts can now take non-String arguments just like Kernel#puts - #to_s is done implicitly. (Aslak Hellesøy) * Attempt to fix Cucumber::CODEPAGE error again for Windows (#561 Aslak Hellesøy) * Tab indentation causes multiline step arguments to fail (#585 Aslak Hellesøy) * Properly pass tags over the wire protocol (Matt Wynne) * Profile loading should honour the --strict option (#580 Rob Holland) * Snippets are properly printed when using '*' as step keyword. (Used to cause infinite recursion). (Aslak Hellesøy) -=== New features -* Added #announce_world method, printing the World class and all included modules (Ruby only). (Aslak Hellesøy) -* Added #announce to the PDF formatter (Nicolas Bessi) +### New features +* Added #puts_world method, printing the World class and all included modules (Ruby only). (Aslak Hellesøy) +* Added #puts to the PDF formatter (Nicolas Bessi) * Show fails for After/Before hooks in the progress formatter (#584 Joseph Wilk) -== Changed features +### Changed features * Switced to ISO 639-1 (language) and ISO 3166 alpha-2 (region - if applicable). Applies to Catalan, Swedish, Welsh, Romanian and Serbian. (Aslak Hellesøy) -== 0.6.3 2010-03-02 +## [v0.6.3](https://github.com/cucumber/cucumber/compare/v0.6.2...v0.6.3) -=== Bugfixes +### Bugfixes * Split arguments in cucumber.yml with shellwords. Example: myprofile: --out="Features report.html" (Nathaniel Haas) * Breakage in Rails 2-3-stable after html_safe is added to the repo. (#577 Aslak Hellesøy) * uninitialized constant Cucumber::CODEPAGE (NameError) (#561 Aslak Hellesøy) @@ -256,17 +442,17 @@ Parse times are up to 100 times faster. * Fix various places in PDF formatter where HTML entities could break prawn (Matt Wynne) * The rerun formatter outputs failed, pending and undefined scenarios (before: only failing) (Aslak Hellesøy) -=== New features +### New features * Added "Angenommen" as German synonym for Given (Sven Fuchs, Aslak Hellesøy) -* New #ask(question, timeout_seconds=60) method available to stepdefs. Asks for input and #announce-s question and answer. (Aslak Hellesøy) +* New #ask(question, timeout_seconds=60) method available to stepdefs. Asks for input and #puts-s question and answer. (Aslak Hellesøy) * Links to step definitions are now clickable in TextMate's HTML report (Rob Aldred) * Add diff! message to wire protocol to allow for immediate diff response to invokes (Matt Wynne) * Add tags to begin/end scenario messages on wire protocol to support tagged hooks (#571 Matt Wynne) * Default timeouts to 120s for invoke, begin_scenario and end_scenario messages in wire protocol (#572 Matt Wynne) -== 0.6.2 2010-01-18 +## [v0.6.2](https://github.com/cucumber/cucumber/compare/v0.6.1...v0.6.2) -=== Bugfixes +### Bugfixes * Update --help for --tags which was out of date. (Aslak Hellesøy) * Explicitly use Prawn 0.6.3 for pdf formatter since 0.7.1 is broken (Aslak Hellesøy) * PDF formatter renders tables incorrectly (#553 Andy Waite) @@ -275,72 +461,72 @@ Parse times are up to 100 times faster. * Added option to override output encoding on Windows with an CUCUMBER_OUTPUT_ENCODING env var (Aslak Hellesøy) * PDF generation requires 'prawn-format' (#558 Aslak Hellesøy) -=== New features +### New features * Show profiles in error scenario summary. (#550 Joseph Wilk) -=== Removed features +### Removed features * element_at and table_at have been removed. Use tableish in cucumber-rails instead. (Aslak Hellesœy) -== 0.6.1 2010-01-03 +## [v0.6.1](https://github.com/cucumber/cucumber/compare/v0.6.0...v0.6.1) -=== Bugfixes +### Bugfixes * Fixed broken console handling on Windows/JRuby that was introduced in 0.6.0. (Aslak Hellesøy) -== 0.6.0 2010-01-03 +## [v0.6.0](https://github.com/cucumber/cucumber/compare/v0.5.3...v0.6.0) Bumping to 0.6.0 for this release since we're breaking backwards compatibility with tags. -=== Changed Features +### Changed Features * Tag boolean logic is inverted. What was ORed before is now ANDed and vice versa. (#504 Aslak Hellesøy) This makes it more practical in most cases to mix tags from profiles and the command line In previous versions the following command line: - --tags @foo,~@bar --tags @zap (on the command line) + `--tags @foo,~@bar --tags @zap (on the command line)` or the following Hook: - Before("@foo,~@bar", "@zap") (for Hooks) + `Before("@foo,~@bar", "@zap") (for Hooks)` would be equivalent to the boolean expression: (@foo && !@bar) || @zap Starting with this release it will be equivalent to: (@foo || !@bar) && @zap -=== Bugfixes +### Bugfixes * Cucumber not loading the correct settings using autospec (#496, #523 Aslak Hellesøy, Andrzej Śliwa) * Ruby 1.9.2 fails to load features/support/env.rb (#549 Aslak Hellesøy) * All features (except 4) pass on 1.9.2 (but not on 1.9.1) (Aslak Hellesøy) * Add missing require statement in rerun formatter which broke RubyMine (Noah Sussman) -== 0.5.3 2009-12-22 +## [v0.5.3](https://github.com/cucumber/cucumber/compare/v0.5.2...v0.5.3) Another small release today to please a sister project. This time Cuke4Nuke. -=== New Features +### New Features * Simplified wire protocol to mostly use success / fail responses (Matt Wynne) -== 0.5.2 2009-12-22 +## [v0.5.2](https://github.com/cucumber/cucumber/compare/v0.5.1...v0.5.2) -=== New Features +### New Features * On JRuby/Cuke4Duke, --require DIR will put DIR on the $CLASSPATH, making it easier to load step def classes (Aslak Hellesøy) * New --jars option that will load jar files. Only available on JRuby. Practical for Cuke4Duke. (Aslak Hellesøy) -=== Bugfixes +### Bugfixes * Add #embed back to html formatter (#547 Brandon Faloona) * Refactored wire protocol code and added configurable timeout to allow for long running step definitions. (#546 Matt Wynne) -== 0.5.1 2009-12-16 +## [v0.5.1](https://github.com/cucumber/cucumber/compare/v0.5.0...v0.5.1) Small bugfix release. -=== Bugfixes +### Bugfixes * Replaced dependency on json gem with an error message, so that the cucumber gem installs on JRuby. (Aslak Hellesøy) -== 0.5.0 2009-12-15 +## [v0.5.0](https://github.com/cucumber/cucumber/compare/v0.4.4...v0.5.0) We're bumping to 0.5.0 for this release since all of the Rails code has now moved to a new gem - cucumber-rails. Please see History.txt in cucumber-rails for details about what's new on the Rails side. -=== New features +### New features * "Given" in Dutch is now aliased to "Gegeven" or "Stel". (Iain Hecker) * New --i18n option to list keywords in various languages. (Aslak Hellesøy) * Added a Tcl example using Sam Stephenson's ruby-tcl (Aslak Hellesøy) @@ -348,11 +534,11 @@ Please see History.txt in cucumber-rails for details about what's new on the Rai * The HTML formatter produces a much nicer report, with TextMate link integration. (Rob Aldred) * Wire protocol now supports table arguments, step definition source & regexp, snippets, pending, table diffing (Matt Wynne) -=== Changed Features +### Changed Features * Per-word trailing-space setting for step keywords using '<'. See 'fr' in languages.yml for example. (#525 Gregory Hnatiuk) * Formatters will no longer be passed File objects. They must use ensure_io, ensure_file or ensure_dir. (Aslak Hellesøy) -=== Bugfixes +### Bugfixes * Exception messages are properly escaped in the HTML report. (Aslak Hellesøy) * Improved UTF-8 support for Windows. (Aslak Hellesøy) * Make #element_at / #table_at work on Webrat 0.6.0. This is now deprecated it in favour of #tableish from the cucumber-rails gem. (Aslak Hellesøy) @@ -362,22 +548,22 @@ Please see History.txt in cucumber-rails for details about what's new on the Rai * Regex escape the path when filtering the backtrace (Corey Donohoe & Simon Rozet) * Add gem dependency on JSON gem, required by wire protocol (#533 Matt Wynne) -=== Removed Features +### Removed Features * All Rails-related code is in a separate gem: cucumber-rails. Install that if you're working with Rails. (#483 Aslak Hellesøy) * --language is removed: http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages (Aslak Hellesøy) -== 0.4.4 2009-11-13 +## [v0.4.4](https://github.com/cucumber/cucumber/compare/v0.4.3...v0.4.4) What a bad day to make a release, but here goes. -=== New features +### New features * Cucumber should use ActiveSupport::Callbacks for fixtures (#516 Adam Salter) * Make 'I' optional in all webrat steps. (Gavin Hughes) * Make generated cucumber.rake work with a vendored gem (Alex Rothenberg) * Native support for ANSIColor on IronRuby via the iron-term-ansicolor gem (Will Green) * Call a bunch of steps from step definitions - also with tables or pystrings. Copy-paste friendly (Bodaniel Jeanes, Jack Chen, Aslak Hellesøy) -=== Bugfixes +### Bugfixes * Pretty printer fails when expanding scenario outlines with -x when the background includes a table (#515 Mike Sassak) * Ensure tags used with Before/After hooks always get parsed (#520 Joseph Wilk) * Define IRONRUBY correctly on Ruby 1.9 (Joe Van Dyk) @@ -385,13 +571,13 @@ What a bad day to make a release, but here goes. * Avoid duplicate cucumber entries in database.yml (Daniel Hofstetter) * Added respond_to? when checking config.cache_classes for older Rails versions (Jeremy Durham) -=== Changed Features +### Changed Features * Rails support has been moved to the cucumber-rails gem (Dennis Blöte, Aslak Hellesøy) TODO - WIKI DOCUMENTATION BEFORE RELEASE * The code for Czech has changed from cz to cs. (deepj) * $cucumber_interrupted is now Cucumber.wants_to_quit - avoid global variable, which gives warnings. (Aslak Hellesøy) * Examples keyword without a colon is deprecated loudly. Gherkin will not recognize it at all. (Gherkin #30 Mike Sassak) -== 0.4.3 2009-10-28 +## [v0.4.3](https://github.com/cucumber/cucumber/compare/v0.4.2...v0.4.3) The exciting thing about this release is that the wire protocol is starting to take shape. This means you can now use Cucumber with .NET - writing step definitions in C#. And this is without having to use IronRuby at all! @@ -399,20 +585,20 @@ See Cuke4Nuke (http://wiki.github.com/richardlawrence/Cuke4Nuke) for more inform As usual there are several small features and bug fixes. -=== New Features +### New Features * Add support for ORing tags which are passed in with seperate --tag arguments. Make comma seperated tags use AND (#368 Joseph Wilk) * New Wire Protocol - allowing out of process execution of Cucumber scenarios. (#428 Matt Wynne) * Added an example illustrating how to get screenshots in HTML reports (examples/watir) (Aslak Hellesøy) * Added new #embed(file, mime_type) method to visitors and Ruby Worlds to make it easier to embed screenshots (Aslak Hellesøy) -* The #announce method available from Ruby Step Definitions will print *after* the step is executed. (#487 Zoltan Penzeli) +* The #puts method available from Ruby Step Definitions will print *after* the step is executed. (#487 Zoltan Penzeli) * Add support for rolling back transaction for all open database connections. (John Ferlito) * Show scenario and step summary in HTML formatter (#285 Joseph Wilk) * Ast::Table can now be constructed with an Array of Hash. (Aslak Hellesøy) -=== Changed features -* The #announce method will no longer escape HTML if the html formatter is used. Escaping must be done manually. (Aslak Hellesøy) +### Changed features +* The #puts method will no longer escape HTML if the html formatter is used. Escaping must be done manually. (Aslak Hellesøy) -=== Bugfixes +### Bugfixes * Fixed incorrect rendering of step arguments with UTF8 characters (Aslak Hellesøy) * "--format rerun", with a Scenario Outline, kills cucumber (#492 Aslak Hellesøy) * Usage formatter is not reporting time correctly. (Elliot Crosby-McCullough) @@ -420,38 +606,38 @@ As usual there are several small features and bug fixes. * Better Danish translation (Thorbjørn Ravn Andersen) -== 0.4.2 2009-10-14 +## [v0.4.2](https://github.com/cucumber/cucumber/compare/v0.4.1...v0.4.2) Bugfix release. The 0.4.1 release was hosed when switching from Hoe to Jeweler. -== 0.4.1 2009-10-14 +## [v0.4.1](https://github.com/cucumber/cucumber/compare/v0.4.0...v0.4.1) This is mostly a bugfix release. Some of Cucumber's own features have been fixed so they pass on more platforms, making it easier for people to contribute. The README.txt also describes how to get up and running with the development environment. -=== Bugfixes +### Bugfixes * Cucumber's features verified passing on MRI 1.8.6 (OSX), 1.8.7 (OSX), 1.9.1 (OSX/Win) and JRuby 1.4.0RC1 (OSX). (Aslak Hellesøy) * Ensure no errors are raised when limiting with tags which are not in the feature set (#464 Joseph Wilk) * Missing Romanian keywords added for Examples, Scenario Outline and Background (to my best google translate knowledge) (Aslak Hellesøy) * Make rerun and --drb work together again after formatter API changes (#485 Erik Hansson, John Ferlito) -=== New Features +### New Features * The Rails cucumber generator will only default to RSpec if installed. And print better help. (Aslak Hellesøy) * Added 'but' variants to Japanese. (Kakutani Shintaro) * README.txt explains people how to run all tests. Install gems with geminstaller. (Aslak Hellesøy) * Added support for Serbian language, both Cyrillic and Latin with usage examples. (Dejan Dimic) * Add new 'debug' formatter for debugging and visualising the calls to listeners. (Matt Wynne) -=== Changed features +### Changed features * Use http://github.com/aslakhellesoy/wac instead of http://github.com/aslakhellesoy/ansicolor on Windows/JRuby (#456 Aslak Hellesøy) -=== Internal changes +### Internal changes * Ditched Hoe for Jeweler (Aslak Hellesøy) * Added StepMother#invoke(step_name, multiline_argument=nil) - needed by cuke4duke ticket #26 (Aslak Hellesøy) * StepDefinitionMethods is gone. -== 0.4.0 2009-10-09 +## [v0.4.0](https://github.com/cucumber/cucumber/compare/v0.3.104...v0.4.0) The back to stable release. When we went from 0.3.11 to 0.3.90 we thought we were close to a 0.4.0 release. Then the community went nuts and a lot of great contributions came in. Some of those broke backwards compatibility, and we decided it would be @@ -462,7 +648,7 @@ Rails users: you *must* run script/generate cucumber after installing this versi If something breaks for you, please please please read this file carefully. It's most likely something referenced here, and that will give you more information so you can solve any problems. If not, just get in touch on IRC or the Google Group. -=== New Features +### New Features * Total feature parsing time is shown when run with --verbose. Useful for benchmarking with future Ragel parser (Aslak Hellesøy) * Tables yielded to step definitions are no longer frozen, so you can edit their data without #dup'ing (Aslak Hellesøy) * Transform can now transform tables, using /table:col1,col2,col3/ (#478 Corey Haines) @@ -475,14 +661,14 @@ that will give you more information so you can solve any problems. If not, just * Stop the confusion between "homepage" and "home page" by allowing both (Ryan Bigg & Bodaniel Jeanes) * Make script/cucumber file generated by the Rails cucumber generator look for cucumber in vendored gems as well. (Tom ten Thij) -=== Changed Features +### Changed Features * Step tables now default empty table cells to empty strings and not nil (#470 Joseph Wilk) -=== Removed Features +### Removed Features * The feature_list, feature_pattern, step_list and step_pattern properties are removed from the Rake task. Use profiles instead. (Aslak Hellesøy) * The FeatureTask is removed. Use profiles instead. -=== Bugfixes +### Bugfixes * instance_exec get declared private (#477 Tim Galeckas) * Transforms can return nil. (Thomas Marek) * Generated rails rake tasks doesn't use the vendored version cucumber binary (#468 Josh Nichols) @@ -498,55 +684,55 @@ that will give you more information so you can solve any problems. If not, just * Better backtraces for Ruby 1.8.7. (Jakob Skov-Pedersen) * String step definitions ( Given 'I have $number cucumbers' ) are escaped before being turned into regular expressions. (David Waite) -== 0.3.104 2009-09-27 +## [v0.3.104](https://github.com/cucumber/cucumber/compare/v0.3.103...v0.3.104) This release has some minor changes to the command line and formatters. The biggest change is internally, paving the way for more programming language support in Cuke4Duke, which now supports step definitions written in Java, Scala, Groovy, Clojure and Javascript! -=== New Features +### New Features * "usage" formatter should display progress (#437 Aslak Hellesøy) * Added example for Ramaze. (Yutaka HARA) -=== Bugfixes +### Bugfixes * Fixed regression in profile formatter from 0.3.102. (Aslak Hellesøy) * Raise a proper error message if someone forgets @ for tags, example: --tags ~foo or --tags bar. (Aslak Hellesøy) * lib/cucumber/formatter/html.rb requires xml (#458 Brent Snook) * lib/cucumber/formatter/html.rb requires ruby-debug (#455 Assaf Arkin) * Allow for STDOUT formatters to be defined in profiles. Addresses an Autotest plugin issue. (#375 Gabriel Medina) -=== Removed features +### Removed features * The --dry-run option no longer implies --no-source and --no-snippets. It only implies --no-snippets. (Aslak Hellesøy) -=== Changed features +### Changed features * The profile and usage formatters have been combined to the usage formatter. Use it eith or without --dry-run. See --help for more. (Aslak Hellesøy) * The steps formatter has been renamed to stepdefs formatter. (Aslak Hellesøy) * The internal programming language API has changed, giving more power to the implementation. See #428. (Aslak Hellesøy) -== 0.3.103 2009-09-24 +## [v0.3.103](https://github.com/cucumber/cucumber/compare/v0.3.102...v0.3.103) This release gives you back some of the control over the Rails environment that was accidentally taken away from you in the previous release. Using this release on a Rails project requires a rerun of script/generate cucumber. -=== New Features +### New Features * Added a new @no-txn tag to selectively turn off transactions for a particlular scenario. * Added back a way to globally turn off transactions. * Renamed @allow_rescue tag to @allow-rescue. -=== Bugfixes +### Bugfixes * Gracefully handle cases when optional regexp groups are not matched. Ex: /should( not)? be flashed '([^']*?)'$/ (Aslak Hellesøy) -=== Changed Features +### Changed Features * The Formatter API has completely changed. Formatters are no longer a double-dispacth visitor - just a single-dispatch listener (#438 Matt Wynne) -== 0.3.102 2009-09-22 +## [v0.3.102](https://github.com/cucumber/cucumber/compare/v0.3.101...v0.3.102) This release has some changes in the Rails support, so make sure you run "script/generate cucumber" after you upgrade. Other noteworthy new features are improved Hook, tags and Transform support, and as always - several smaller bug fixes. -=== New Features +### New Features * Added new internal API for Regexp and groups, allowing other programming languages to leverage native regexps. (Aslak Hellesøy) * New @allow_rescue tag for Rails scenarios. Causes exceptions raised in actions to be caught by rails and not bubble up to Cucumber (Aslak Hellesøy) * Negative tags can now be used in hooks, just like the command line's --tags option: Before('~@yarr') - will run for all scenarios that *don't* have the @yarr tag. (Aslak Hellesøy) @@ -554,7 +740,7 @@ Other noteworthy new features are improved Hook, tags and Transform support, and * Other Transforms can be reused by calling Transform with a string inside of another Transform definition (Larry Diehl) * Execute "After" hooks in reverse order of declaration for better behavior with dependent blocks and to mimic the behavior of at_exit (David Waite) -=== Bugfixes +### Bugfixes * features/support/env.rb runs commands twice (bugfix cuts total time by almost 50% w00t) (#452 Jim Meyer) * Problems adding custom formatters to features/support. (features/support is added to $LOAD_PATH) (#449 Aslak Hellesøy) * Some options set in cucumber.yml profiles are ignored (#446 Leonard CHIN) @@ -562,19 +748,19 @@ Other noteworthy new features are improved Hook, tags and Transform support, and * rspec-rails, :lib => false (#447 David Chelimsky) * Cucumber with Spork breaks on OS X Snow Leopard (#431 David Chelimsky) -=== Changed Features +### Changed Features * Tag names passed on the command line *always* have to use the @ sign. --tags foo or --tags ~bar won't work. Use --tags @foo or --tags ~@bar (Aslak Hellesøy) -=== Removed features +### Removed features * The Cucumber::Rails.bypass_rescue no longer exists. Errors will always bubble up, unless you use the new @allow_rescue tag. (Aslak Hellesøy) * The Cucumber::Rails.use_transactional_fixtures no longer exists. Transactional fixtures are always enabled for the cucumber environment. (Aslak Hellesøy) -== 0.3.101 2009-09-15 +## [v0.3.101](https://github.com/cucumber/cucumber/compare/v0.3.100...v0.3.101) Two exciting things in this release. Step Argument Transforms and a PDF formatter you can use to send your features to your customer for review! -=== New Features +### New Features * New pdf formatter (#425 Mads Buus) * Step Argument Transforms: These let you use the Transform method to register regular expressions to catch and transform/coerce arguments before they are yielded to step definitions: @@ -582,56 +768,56 @@ your features to your customer for review! * Adding webrat steps for asserting content does or does not exist within a particular element (using webrat's within method) (Kieran Pilkington) -== 0.3.100 2009-09-09 +## [v0.3.100](https://github.com/cucumber/cucumber/compare/v0.3.99...v0.3.100) The JavaZone release! -=== New Features +### New Features * Added support for Uzbek (msarvar) * The file argument on the cucumber command line will replace contents of file on cli if file is prefixed with @ (Tero Tilus) -=== Bugfixes +### Bugfixes * Backtraces on JRuby are handled in a cleaner way when the exception comes from Java (NativeException). (Aslak Hellesøy) * When exceptions occur in a Before block the rest of the scenario is now skipped (#331 Matt Wynne) -== 0.3.99 2009-09-03 +## [v0.3.99](https://github.com/cucumber/cucumber/compare/v0.3.98...v0.3.99) -=== New Features +### New Features * Support for Croatian (Bkrsta) * Make #feature available from scenario so you can do: Before{|scenario| scenario.feature}. (Aslak Hellesøy) * cucumber.yml parsing supports ERB syntax (#427 Gregory Hnatiuk) * New AfterConfiguration hook added; a block can be specified that takes Cucumber::Cli::Configuration (#423 Brent Snook) * Cucumber::Cli::Configuration#feature_dirs and #out_stream exposed as public attributes so that they may be used in AfterConfiguration hook (#423 Brent Snook) -== 0.3.98 2009-08-25 +## [v0.3.98](https://github.com/cucumber/cucumber/compare/v0.3.97...v0.3.98) Just a small release to help Cuke4Duke, which will be presented at Agile2009 in 2 days. -=== New Features +### New Features * Backtrace filtering now happens in StepInvocation class, meaning other languages (Cuke4Duke) can get backtraces stripped. (Aslak Hellesøy) * Cucumber::Ast::Table#map_headers now allows for a block that will convert all the headers. See docs for details. (Ben Mabey) -== 0.3.97 2009-08-23 +## [v0.3.97](https://github.com/cucumber/cucumber/compare/v0.3.96...v0.3.97) The AA-FTT release. Creating a release for the AA-FTT meeting in Chicago so that we can play with the new language API and maybe knock out some better .NET support. -=== Bugfixes +### Bugfixes * Allow comments on examples sections underneath scenario outlines (#420 Mike Sassak) * Table.map_headers! will fail with a decent error message when 0 or 2+ headers are matched. (Aslak Hellesøy) * Fixed an issue with comments with preceding spaces after a background causing a parse error (#401 Joseph Wilk) -=== New Features +### New Features * The public API is documented and there is a new :sdoc task to generate nice searchable API docs. * Add :default => :cucumber when setting up Rake tasks for Cucumber in Rails (Aslak Hellesøy) * New When /^I fill in "([^\"]*)" for "([^\"]*)"$/ Webrat step for Rails (Aslak Hellesøy) -=== Changed Features +### Changed Features * Changed the Programming Language API to support languages without "bleed through" (e.g. rubypython can't invoke ruby objs) (Aslak Hellesøy) * The Programming Language API manages hooks on the language level instead of on the step mother level (Aslak Hellesøy) -== 0.3.96 2009-08-15 +## [v0.3.96](https://github.com/cucumber/cucumber/compare/v0.3.95...v0.3.96) This release doesn't have any significant new features or bug fixes, but there are big internal changes. This release has a new API for plugging in other programming languages. @@ -640,17 +826,17 @@ You can read more about that here: http://groups.google.com/group/cukes/browse_t This might break other tools that are using Cucumber's internal APIs. For example Spork broke and had to be patched. Please upgrade to Spork 0.5.9 if you are using Spork. -=== New Features +### New Features * Ability to preload natural language in Spork's prefork. Rerun script/generate cucumber --spork to see how. (Aslak Hellesøy) * Ability to control which DRb port is used via the --port flag or by setting CUCUMBER_DRB environment variable. (Chris Flipse) * Upgrade Rails generator to use webrat 0.5.0. (Aslak Hellesøy) * Upgrade Sinatra example to work with rack-test 0.4.1 and webrat 0.5.0. (Aslak Hellesøy) -=== Changed Features +### Changed Features * --strict will cause an exit code 1 for missing and pending (used to be for missing only). (Mads Buus) * junit formatter doesn't report pending steps unless --strict is used. (Mads Buus) -== 0.3.95 2009-08-13 +## [v0.3.95](https://github.com/cucumber/cucumber/compare/v0.3.94...v0.3.95) This release improves Webrat support for table-like HTML markup. Now you can easily turn the HTML elements table, dl, ol and ul elements into a 2D array. This is particularly useful for comparing @@ -658,7 +844,7 @@ data in your HTML with a Cucumber table using Cucumber::Ast::Table#diff! This release also fixes several bugs related to --drb (Spork) and profiles (cucumber.yml) -=== Bug Fixes +### Bug Fixes * --guess will always prefer the longest regexp with no groups if they exist. * Prevent delays if a NoMethodError is raise in a step definition. Define a light #inspect in World. (#374 Aslak Hellesøy) * Restore 'features' as the default feature running path. (#412 Ben Mabey) @@ -666,18 +852,18 @@ This release also fixes several bugs related to --drb (Spork) and profiles (cucu * --language picked up from profiles again. (#409 Ben Mabey) * Resolved infinite loop problem when --drb was defined in a profile. (#408 Ben Mabey) -=== New Features +### New Features * Cucumber::World#table has been overloaded to work with 2D Array in addition to a table String to be parsed. * New When /^I fill in the following:$/ step definition for Webrat. Useful for filling out a form with a Table. (Aslak Hellesøy) * The object returned by element_at (Webrat::Element) has a #to_table that works for table, dl, ol and ul. (Aslak Hellesøy) * An explanation of why failures are ok is printed when --wip is used. (Aslak Hellesøy) * Added cucumber alias for cucumber:ok in Rails Rake tasks. (Aslak Hellesøy) -=== Changed features +### Changed features * element_at('table').to_table should be used instead of table_at('table').to_a. The old way is deprecated but still works. (Aslak Hellesøy) * element_at (and the depracated table_at) no longer takes a DOM id, only CSS selectors. Change "my_id" to "#my_id". (Aslak Hellesøy) -== 0.3.94 2009-08-06 +## [v0.3.94](https://github.com/cucumber/cucumber/compare/v0.3.93...v0.3.94) Kanban take II. @@ -688,13 +874,13 @@ However, this feature went mostly unnoticed, and because we think it's so great to make it the default for Rails projects. When you bootstrap your Rails project for Cucumber you will now get 2 Cucumber Rake tasks for Kanban development: - cucumber:ok : Run features that should pass. This runs your "good,old" features - cucumber:wip : Run the features you're working on that don't pass yet. Tag them with @wip. Max 2! + cucumber:ok : Run features that should pass. This runs your "good,old" features + cucumber:wip : Run the features you're working on that don't pass yet. Tag them with @wip. Max 2! So upgrade today and get into the habit of tagging new features with @wip (or invent your own tags). You'll achieve better flow this way. -=== New features +### New features * Support limiting the number of feature elements with certain tags (#353 Joseph Wilk) * script/generate cucumber sets up 'cucumber:ok' and 'cucumber:wip' tasks and deprecates 'features'. More Kanban love. (#344 Aslak Hellesøy) * Better JUnit formatter: feature->testsuite, scenario->testcase. Better timing and support for background and scenario outline. (Mads Buus Westmark) @@ -706,51 +892,51 @@ You'll achieve better flow this way. * Document builtin formatters with --help. (#406 Aslak Hellesøy) * Added support for using regular expressions when mapping table headers. (Peter Williams) -== 0.3.93 2009-08-03 +## [v0.3.93](https://github.com/cucumber/cucumber/compare/v0.3.92...v0.3.93) Highlights in this release: Improved profile handling (cucumber.yml) and a fix for cucumber hanging. -=== New features +### New features * script/generate cucumber --spork now sets up a spork gem dependency in the cucumber.rb environment. (Aslak Hellesøy) * Feature files defined on the command line override any that are present in profiles. (#344 Ben Mabey) * Default (STDOUT) formatter defined in profile can be overridden from the command line. (#344 Ben Mabey) * Displays which profile, if any, is being used. (Ben Mabey) * click_link_within(parent, link) webrat step (Joakim Kolsjö) -=== Bugfixes +### Bugfixes * script/cucumber correctly loads the gem's binary if the plugin isn't installed. * Cucumber hangs waiting for Ctrl+C if an Error is raised. (#374 Aslak Hellesøy) -== 0.3.92 2009-07-29 +## [v0.3.92](https://github.com/cucumber/cucumber/compare/v0.3.91...v0.3.92) This release has some minor improvements to the new Table.diff! functionality. For example, if you're using Webrat and you want to compare a feature table with a HTML table containing links in one of the columns, you can do: - actual = Cucumber::Ast::Table.new(table_at('table').to_a) - actual.map_column!('Name') { |text| text.strip.match(/>(.*)(.*) steps called from steps (#65 Aslak Hellesøy) -=== New features +### New features * Australian translation (Josh Graham) -* Added World#announce(announcment) which lets you output text to the formatted output (#222 Rob Kaufmann) +* Added World#puts(announcment) which lets you output text to the formatted output (#222 Rob Kaufmann) * Added Table#transpose to to allow use of vertically aligned table keys (Torbjørn Vatn, Aslak Hellesøy) * Added Table#map_headers to to allow use of more readable headers (Rob Holland) * New -S/--step-definitions option. Useful (among other things) for tools that implement automcompletion. (#208 Aslak Hellesøy). @@ -1243,13 +1429,13 @@ for multiline arguments are some of the highlights. * It's no longer necessary to compile the Treetop grammar when adding a new language. Localised parser is generated at runtime. (Aslak Hellesøy) * New --guess option tries to guess the best step definition match instead of raising Cucumber::Multiple. (Jake Howerton) -=== Removed features +### Removed features * "GivenScenario" is gone. Instead you can call Steps from Step Definitions, or use the new Background feature (#153) * "More Examples" is gone. "Scenario" + "More Examples" is no longer supported. Use "Scenario Outline" + "Examples" instead. * Pure Ruby features are no longer supported. * Remove --color option in autotest. Can be added manually in cucumber.yml (#215 Jean-Michel Garnier) -== (0.1.16.4 aslakhellesoy-cucumber gem on GitHub) +## 0.1.16.4 Bugfix release. @@ -1257,13 +1443,13 @@ IMPORTANT NOTE FOR RAILS USERS. The template used to generate your features/support/env.rb has changed. You have to apply a minor change manually for existing Rails projects when you upgrade to this version. Change this: - require 'webrat/rspec-rails' + require 'webrat/rspec-rails' to this: - require 'webrat/core/matchers' + require 'webrat/core/matchers' -=== New features +### New features * Finnish translation (Tero Tilus) * Use Webrat's #contain matcher in generated "I should (not) see" step definitions (Bryan Helmkamp) @@ -1273,53 +1459,53 @@ to this: * Better handling of ARGV (#169 David Chelimsky, Ben Mabey) * Compatibility with ruby-debug (do ARGV.dup in bin/cucumber so it can restart ruby with same args) (Aslak Hellesøy) -== 0.1.16 2009-01-19 +## [v0.1.16](https://github.com/cucumber/cucumber/compare/v0.1.15...v0.1.16) This is a small bugfix release. The most notable improvement is compatibility with Webrat 0.4. Rails/Webrat users should upgrade both Cucumber and Webrat gems. -=== New features +### New features * Allow argument placeholders in step tables and multiline comments (#121 Joseph Wilk) * Scenario Outline can be followed by several named Examples sections (#123 Aslak Hellesøy) * Add the #binary= method back to the Rake task. It is needed by merb_cucumber for running the features of a merb app with it's bundled gems. (Thomas Marek) * Added a /^When I go to (.+)$/ step definition to webrat_steps.rb and a simple page name to path mapping method (Bryan Helmkamp) -=== Bugfixes +### Bugfixes * Fix to run single scenarios when the line number specified doesn't correspond to a step (i.e. blank lines or rows) (#160 Luismi Cavallé) -=== Removed features +### Removed features -== 0.1.15 2009-01-08 +## [v0.1.15](https://github.com/cucumber/cucumber/compare/v0.1.14...v0.1.15) Bugfix release -=== New features +### New features * 한국어! (Korean!) (John Hwang) -=== Bugfixes +### Bugfixes * --dry-run skips running before/after/steps (#147 Ian Dees) * Fix a minor bug in the console formatter's summary (David Chelimsky) * Better quoting of Scenario names in Autotest (Peter Jaros) * Added some small workarounds for unicode handling on Windows (Aslak Hellesøy) -== 0.1.14 2009-01-04 +## [v0.1.14](https://github.com/cucumber/cucumber/compare/v0.1.13...v0.1.14) This is the first release of Cucumber that runs on Ruby 1.9. There are still some encoding-related issues with Arabic (ar), Japanese (ja) and Simplified Chinese (zh-CN). Patches are welcome. Other than that - a couple of minor bug fixes and polishing. -=== New features +### New features * Pretty formatter shows number of scenarios (#139 Joseph Wilk) * Rudimentary support for Ruby 1.9. Now it's ok to file Ruby 1.9-related bugs. -=== Bugfixes +### Bugfixes * Fixed "No such file or directory -- cucumber (LoadError)" bug with AutoTest (Aslak Hellesøy) * Fixed `load_missing_constant': uninitialized constant Dispatcher error with Rails (Aslak Hellesøy) -=== Removed features +### Removed features * The #binary= method is gone from the Rake task. It will always point to the binary in the current gem. (Aslak Hellesøy) -== 0.1.13 2008-12-20 +## [v0.1.13](https://github.com/cucumber/cucumber/compare/v0.1.12...v0.1.13) It's time for some new features again. Output is now much better since you can use diffing, tweak the output colours and get the full --backtrace if you want. Managing your support/* files became @@ -1329,7 +1515,7 @@ bug fixes. Enjoy! -=== New features +### New features * Console output is no longer bold, but regular. Step arguments are bold instead of blold+underlined. (Aslak Hellesøy) * Console output can be configured with CUCUMBER_COLORS in your shell. (Aslak Hellesøy) * Added new --backtrace option to show full backtrace (Aslak Hellesøy) @@ -1341,7 +1527,7 @@ Enjoy! * Scenario Outlines are now usable in pure ruby (Joseph Wilk) * Add support for calling 'pending' from step definitions. (#112 Joseph Wilk) -=== Bugfixes +### Bugfixes * Make rails before filters work correctly (#122, #129 Guillermo Álvarez Fernández) * Proper Unicode support for Windows command shells: Just require cucumber/formatter/unicode in env.rb (Aslak Hellesøy) * Fixed disappearing "a" on Windows (#81 Aslak Hellesøy) @@ -1352,51 +1538,51 @@ Enjoy! * document :x run option in command line help (#114, Aslak Hellesøy) * Change 'visits' to 'visit' in features generator to comply with new Webrat API (Darius Roberts) -=== Removed features +### Removed features -== 0.1.12 2008-12-04 +## [v0.1.12](https://github.com/cucumber/cucumber/compare/v0.1.11...v0.1.12) This is the "getting serious with IronRuby release" - largely based on "Patrick Gannon":http://www.patrickgannon.net/archive/2008/10/23/bdd-style-feature-tests-using-ironruby-and-rspeccucumber.aspx's blog entry. -== New features +### New features * Cucumber works with IronRuby/.NET - http://github.com/aslakhellesoy/cucumber/wikis/ironruby-and-net (Aslak Hellesøy) -== Bugfixes +### Bugfixes * Fixed bug which was preventing coloring under Autotest (#111, Alan Larkin) -== Removed features +### Removed features None -== 0.1.11 2008-12-02 +## [v0.1.11](https://github.com/cucumber/cucumber/compare/v0.1.10...v0.1.11) Bugfix release with a couple of minor additional features to the command line options. -=== New features +### New features * Capture output from cucumber in Autotest (Alan Larkin) * Update cucumber generator to work with latest Webrat (Bryan Helkamp) * CUCUMBR LIKEZ 2 SPEEK WIF KATS. KTHXBAI (Aimee Daniells) * Support for dynamically pluggable formatters (#99 Joseph Wilk) * --verbose mode to see ruby files and feature files loaded by Cucumber (#106 Joseph Wilk) -=== Bugfixes +### Bugfixes * The jcode library is not loaded on JRuby/Rails. Workaround for http://tinyurl.com/55uu3u. (Aslak Hellesøy) * Support including modules for class passed to --format (#109 Joseph Wilk) -=== Removed features +### Removed features * The cucumber gem no longer depends on the rspec gem. It must be downloaded manually if RSpec is used. (Jeff Rafter) -== 0.1.10 2008-11-25 +## [v0.1.10](https://github.com/cucumber/cucumber/compare/v0.1.9...v0.1.10) This release mostly has smaller bugfixes. The most significant new feature is how line numbers are specified. You can now run multiple features at specific lines numbers like this: - cucumber foo.feature:15 bar.feature:6:45:111 + cucumber foo.feature:15 bar.feature:6:45:111 This will run foo.feature at line 15 and bar.feature at line 6, 45 and 111. -=== New features +### New features * Added example showing how to use Cucumber with Test::Unit + Matchy instead of RSpec (Aslak Hellesøy) * Yield existing world object to World block (#87 Aslak Hellesøy) * AUTOFEATURE=tRue works (case insensitive) (Aslak Hellesøy) @@ -1406,18 +1592,18 @@ This will run foo.feature at line 15 and bar.feature at line 6, 45 and 111. * Try to load webrat gem if it's not installed as a plugin (Aslak Hellesøy) * Support example.feature:20 or example.feature:10:20:30 syntax for running features at specific line number(s). (#88 Joseph Wilk) -=== Bugfixes +### Bugfixes * Windows - all the 'a' characters in the output have gone on strike (#81 Luis Lavena, Joseph Wilk, Aslak Hellesøy) * Raise a nice error when encountering step definition without block (#95 Aslak Hellesøy) * Features written using Ruby where breaking due to missing a line number (#91 Joseph Wilk) * Directly creating a Table meant the scenario table header was never set which was causing a formatter error (#91 Joseph Wilk) -=== Removed features +### Removed features * $KCODE='u' is no longer done automatically. Developers should do that explicitly when needed in step definitions or env.rb. * Step definition without a block being treated as pending (#64 Joseph Wilk) * The --line option has been removed. Use the new file.feature:line format instead. -== 0.1.9 2008-11-12 +## [v0.1.9](https://github.com/cucumber/cucumber/compare/v0.1.8...v0.1.9) With this release Cucumber supports 19 (!) natural languages: @@ -1447,26 +1633,26 @@ add it: http://github.com/aslakhellesoy/cucumber/wikis/spoken-languages Main functional changes in this release is "Autotest":http://github.com/aslakhellesoy/cucumber/wikis/autotest-integration support and how multiline strings work in feature files: - # In your .feature file - Then I should see - """ - A string - that "indents" - and spans - several lines + # In your .feature file + Then I should see + """ + A string + that "indents" + and spans + several lines - """ + """ - # In your steps.rb file - Then 'I should see' do |text| - text.should == "A string\n that \"indents\"\nand spans\nseveral lines\n" - end + # In your steps.rb file + Then 'I should see' do |text| + text.should == "A string\n that \"indents\"\nand spans\nseveral lines\n" + end The triple quotes are used to define the start and end of a string, and it also defines what gets stripped away in the inside string. If the triple quotes are indented 4 spaces, then the text within will have the 4 first spaces removed too. -=== New features +### New features * Added --[no-]color option to force color on or off (Peter Jaros) * Step definition without a block will be treated as pending (#64 Joseph Wilk) * Added support for Welsh (improvements welcome) (Joseph Wilk) @@ -1483,7 +1669,7 @@ spaces removed too. * Added support for Japanese. (Kakutani Shintaro) * Added support for Texan (improvements welcome). (Aslak Hellesøy) -=== Bugfixes +### Bugfixes * Pending step snippets should escape special Regexp characters (#82 Joseph Wilk) * Scenario without a body shouldn't show up as complete (#63 Josh Knowles) * Fixed bug where utf-8 strings where breaking comment alighments. (#79 Joseph Wilk) @@ -1497,10 +1683,10 @@ spaces removed too. * Don't load cucumber.yml unless it exists (Aslak Hellesøy) * Fixing bug where specifying line number 1 in a feature which starts with a scenario with a scenario table was raising an error (#56 Joseph Wilk) -=== Removed features +### Removed features -== 0.1.8 2008-10-18 +## [v0.1.8](https://github.com/cucumber/cucumber/compare/v0.1.7...v0.1.8) This release extends the support for tables. PLEASE NOTE THAT TABLES ARE STILL EXPERIMENTAL. In previous releases it has been possible to use tables to define "more examples" of a scenario in @@ -1508,22 +1694,22 @@ a FIT-style column fixture kind of way. Now you can also use tables as arguments Tables used to define more examples after a scenario must now be prefixed. In English it looks like this: - Feature: Addition - In order to avoid silly mistakes - As a math idiot - I want to be told the sum of two numbers + Feature: Addition + In order to avoid silly mistakes + As a math idiot + I want to be told the sum of two numbers - Scenario: Add two numbers - Given I have entered 50 into the calculator - And I have entered 70 into the calculator - When I press add - Then the result should be 120 on the screen + Scenario: Add two numbers + Given I have entered 50 into the calculator + And I have entered 70 into the calculator + When I press add + Then the result should be 120 on the screen - More Examples: - | input_1 | input_2 | button | output | - | 20 | 30 | add | 50 | - | 2 | 5 | add | 7 | - | 0 | 40 | add | 40 | + More Examples: + | input_1 | input_2 | button | output | + | 20 | 30 | add | 50 | + | 2 | 5 | add | 7 | + | 0 | 40 | add | 40 | Languages that are not updated yet will have to use "More Examples" until we get the translations. @@ -1532,32 +1718,32 @@ that can span several lines. This can be a table or a string. Example: - Given the following people exist: - | name | email | phone | - | Aslak | aslak@email.com | 123 | - | Joe | joe@email.com | 234 | - | Bryan | bryan@email.org | 456 | - When I search for email.com - Then I should see: - | name | email | phone | - | Aslak | aslak@email.com | 123 | - | Joe | joe@email.com | 234 | - And I should see: - "Some text - on several lines" + Given the following people exist: + | name | email | phone | + | Aslak | aslak@email.com | 123 | + | Joe | joe@email.com | 234 | + | Bryan | bryan@email.org | 456 | + When I search for email.com + Then I should see: + | name | email | phone | + | Aslak | aslak@email.com | 123 | + | Joe | joe@email.com | 234 | + And I should see: + "Some text + on several lines" The step definitions for such multiline steps must define an extra block argument for the argument: - Given /the following people exist:/ do |people_table| - # people_table is of type Cucumber::Model::Table - # See RDoc for more info - end + Given /the following people exist:/ do |people_table| + # people_table is of type Cucumber::Model::Table + # See RDoc for more info + end - Then /I should see:/ do |string| - # string is a plain old ruby String with leading spaces on each line removed - end + Then /I should see:/ do |string| + # string is a plain old ruby String with leading spaces on each line removed + end -=== New features +### New features * Added profile formatter. (#35, Joseph Wilk) * Added support for Chinese Simplified. (Liming Lian) * Added support for Dutch. (Sjoerd Tieleman) @@ -1567,41 +1753,41 @@ The step definitions for such multiline steps must define an extra block argumen * Show the file for the feature as a comment when displaying with the pretty formatter. (#40, Joseph Wilk) * Show the feature file and line for pending steps as a comment when displaying with the pretty formatter. (#40, Joseph Wilk) -=== Bugfixes +### Bugfixes * Fixed speling errors in Spanish (Daniel Cadenas) * ActionMailer delivery_method should not be set to test (#41, Luke Melia) * Reverse incorrectly ordered args in webrat select step (#43, David Chelimsky) * Support comments above the first scenario (#31, Aslak Hellesøy) * Fixed the HTML Formatter to use actual values for FIT table headers (#30, Joseph Wilk) -=== Removed features +### Removed features * Removed the /^I go to (.*)$/ step from common_webrat.rb - it's not language agnostic and provides little value. -=== New features +### New features * Added new --out option to make it easier to specify output from Rake and cucumber.yml -== 0.1.7 2008-10-05 +## [v0.1.7](https://github.com/cucumber/cucumber/compare/v0.1.6...v0.1.7) This release fixes a few bugs and adds some new features. The most notable features are: -=== Calling steps from steps +### Calling steps from steps Step definitions are a little bit closer to having regular method semantics. You define them, but now you can also call them from other steps. Here is an example: - Given /I am logged in as an (.*) named (.*)$/ do |role, name| - Given "I am registered as #{role}, #{name}, secret" - When "I log in with #{name}, secret" - end + Given /I am logged in as an (.*) named (.*)$/ do |role, name| + Given "I am registered as #{role}, #{name}, secret" + When "I log in with #{name}, secret" + end - Given /I am registered as (.*), (.*), (.*)/ do |role, name, password| - # (Code removed for brevity) - end + Given /I am registered as (.*), (.*), (.*)/ do |role, name, password| + # (Code removed for brevity) + end - When /I log in with (.*), (.*)/ do |name, password| - # (Code removed for brevity) - end + When /I log in with (.*), (.*)/ do |name, password| + # (Code removed for brevity) + end This means that steps can be reused in other steps. The GivenScenario feature achieves a similar effect (on the scenario level), but this feature is something we're not very happy with, mostly @@ -1610,29 +1796,29 @@ because it's not parameterisable. Calling steps from steps is. GivenScenario will still be working several releases, but the plan is to remove it completely in the 0.3.0 release. -=== Seeing where a step is defined +### Seeing where a step is defined Prior to this release it could be hard to find out where the ruby step definition matching a plain text step is defined. Not anymore! Cucumber will now output this: - Scenario: Regular numbers - Given I have entered 3 into the calculator # features/steps/calculator_steps.rb:12 - And I have entered 2 into the calculator # features/steps/calculator_steps.rb:12 - When I press divide # features/steps/calculator_steps.rb:16 - Then the result should be 1.5 on the screen # features/steps/calculator_steps.rb:20 - And the result class should be Float # features/steps/calculator_steps.rb:24 + Scenario: Regular numbers + Given I have entered 3 into the calculator # features/steps/calculator_steps.rb:12 + And I have entered 2 into the calculator # features/steps/calculator_steps.rb:12 + When I press divide # features/steps/calculator_steps.rb:16 + Then the result should be 1.5 on the screen # features/steps/calculator_steps.rb:20 + And the result class should be Float # features/steps/calculator_steps.rb:24 -=== Bugfixes +### Bugfixes * Fixed a bug in the command line args being lost when using --profile (#27, Joseph Wilk) * Fixed a bug in Webrat selects (Tim Glen) * Fixed parsing of DOS line endings (#2, #28, Aslak Hellesøy) -=== New features +### New features * Steps can be called from other steps (#3, Bryan Helmkamp, Aslak Hellesøy) * Added But keyword to all languages (#21, Aslak Hellesøy) * Added --no-source option to display step definition location next to step text (#26, Joseph Wilk, Aslak Hellesøy) * Added more Webrat steps (#25, Tim Glen) -== 0.1.6 2008-10-01 +## [v0.1.6](https://github.com/cucumber/cucumber/compare/f3292f4023a707099d02602b2bd6c4ca3cec6820...v0.1.6) First gem release! diff --git a/LICENSE b/LICENSE index 621d6e6572..1dfd03201b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2008,2009 Aslak Hellesøy +Copyright (c) 2008,2009,2010,2011 Aslak Hellesøy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md new file mode 100644 index 0000000000..acbf95cf38 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +[![Build Status](https://secure.travis-ci.org/cucumber/cucumber.png)](http://travis-ci.org/cucumber/cucumber) [![Dependency Status](https://gemnasium.com/cucumber/cucumber.png)](https://gemnasium.com/cucumber/cucumber) + +The main website is at http://cukes.info/ +The documentation is at https://wiki.github.com/cucumber/cucumber/ + +## Note on Patches/Pull Requests + +* Fork the project. +* Make your feature addition or bug fix. +* Add tests for it. This is important so I don't break it in a + future version unintentionally. +* Commit, do not mess with Rakefile, version, or history. + (if you want to have your own version, that is fine but + bump version in a commit by itself I can ignore when I pull) +* Send me a pull request. Bonus points for topic branches. + +## Running tests + + gem install bundler + bundle install + git submodule update --init --recursive + rake + +## Release Process + +Before you even attempt to do a release, make sure you can log into cukes.info and touch a file in /var/www/cucumber/api/ruby (see gem_tasks/yard.rake). You need to be able to do this in order to upload YARD docs as part of the release. + +* Bump the version number in `lib/cucumber/platform.rb`. +* Make sure `History.md` is updated with the upcoming version number, and has entries for all fixes. +* No need to add a `History.md` header at this point - this should be done when a new change is made, later. + +Now release it + + bundle update + rake + git commit -m "Release X.Y.Z" + rake release + +## Copyright + +Copyright (c) 2008,2009,2010,2011 Aslak Hellesøy and Contributors. See LICENSE for details. + diff --git a/README.rdoc b/README.rdoc deleted file mode 100644 index 796c1965dc..0000000000 --- a/README.rdoc +++ /dev/null @@ -1,26 +0,0 @@ -= Cucumber - -The main website is at http://cukes.info/ -The documentation is at http://wiki.github.com/aslakhellesoy/cucumber/ - -== Note on Patches/Pull Requests - -* Fork the project. -* Make your feature addition or bug fix. -* Add tests for it. This is important so I don't break it in a - future version unintentionally. -* Commit, do not mess with Rakefile, version, or history. - (if you want to have your own version, that is fine but - bump version in a commit by itself I can ignore when I pull) -* Send me a pull request. Bonus points for topic branches. - -== Running tests - - rake - -If you get errors about missing gems - just install them. - -== Copyright - -Copyright (c) 2008,2009 Aslak Hellesøy. See LICENSE for details. - diff --git a/Rakefile b/Rakefile index efa0f78bd7..0190bee262 100644 --- a/Rakefile +++ b/Rakefile @@ -1,12 +1,12 @@ # encoding: utf-8 require 'rubygems' require 'bundler' -Bundler.setup Bundler::GemHelper.install_tasks +$:.unshift(File.dirname(__FILE__) + '/lib') Dir['gem_tasks/**/*.rake'].each { |rake| load rake } task :default => [:spec, :cucumber] require 'rake/clean' -CLEAN.include %w(**/*.{log,pyc,rbc}) +CLEAN.include %w(**/*.{log,pyc,rbc,tgz} doc) diff --git a/cucumber.gemspec b/cucumber.gemspec index 531273cb9f..36da80ac23 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -12,45 +12,46 @@ Gem::Specification.new do |s| s.homepage = "http://cukes.info" s.platform = Gem::Platform::RUBY - s.default_executable = "cucumber" s.post_install_message = %{ (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) Thank you for installing cucumber-#{Cucumber::VERSION}. -Please be sure to read http://wiki.github.com/aslakhellesoy/cucumber/upgrading +Please be sure to read http://wiki.github.com/cucumber/cucumber/upgrading for important information about this release. Happy cuking! (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) } - s.add_dependency 'gherkin', '>= 2.3.5' - s.add_dependency 'builder', '>= 2.1.2' - s.add_dependency 'diff-lcs', '>= 1.1.2' - s.add_dependency 'json', '>= 1.4.6' + s.add_runtime_dependency 'gherkin', '~> 2.9.0' + s.add_runtime_dependency 'builder', '>= 2.1.2' + s.add_runtime_dependency 'diff-lcs', '>= 1.1.2' + s.add_runtime_dependency 'json', '>= 1.4.6' - s.add_development_dependency 'aruba', '>= 0.3.4' - s.add_development_dependency 'rake', '>= 0.8.7' - s.add_development_dependency 'rspec', '>= 2.5.0' - s.add_development_dependency 'nokogiri', '>= 1.4.4' - s.add_development_dependency 'prawn', '= 0.8.4' - s.add_development_dependency 'prawn-layout', '= 0.8.4' + s.add_development_dependency 'aruba', '~> 0.4.11' + s.add_development_dependency 'rake', '>= 0.9.2' + s.add_development_dependency 'rspec', '~> 2.7.0' # We'll bump when gherkin is ready to bump + s.add_development_dependency 'nokogiri', '>= 1.5.0' s.add_development_dependency 'syntax', '>= 1.0.0' - s.add_development_dependency 'spork', '>= 0.8.4' - s.add_development_dependency 'simplecov', '>= 0.4.1' - + s.add_development_dependency 'spork', '>= 0.9.0.rc9' + s.add_development_dependency 'simplecov', '>= 0.5.4' + + # For Documentation: + s.add_development_dependency('yard', '~> 0.7.4') + s.add_development_dependency('rdiscount', '~> 1.6.8') + s.add_development_dependency('bcat', '~> 0.6.2') + # Needed for examples (rake examples) s.add_development_dependency 'ramaze' - s.add_development_dependency 'rack-test', '>= 0.5.7' + s.add_development_dependency 'rack-test', '>= 0.6.1' s.add_development_dependency 'webrat', '>= 0.7.3' - s.add_development_dependency 'sinatra', '>= 1.2.0' - s.add_development_dependency 'capybara', '>= 0.4.1' + s.add_development_dependency 'sinatra', '>= 1.3.1' + s.add_development_dependency 'capybara', '>= 1.1.1' s.rubygems_version = ">= 1.6.1" - s.files = `git ls-files`.split("\n") + s.files = `git ls-files`.split("\n").reject {|path| path =~ /\.gitignore$/ } s.test_files = `git ls-files -- {spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } - s.extra_rdoc_files = ["LICENSE", "README.rdoc", "History.txt"] s.rdoc_options = ["--charset=UTF-8"] s.require_path = "lib" end diff --git a/cucumber.yml b/cucumber.yml index c5679f401f..0287c10655 100644 --- a/cucumber.yml +++ b/cucumber.yml @@ -1,7 +1,7 @@ <% rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" rerun_opts = rerun.to_s.strip.empty? ? "--format progress features" : "--format pretty #{rerun}" -std_opts = "--format pretty features --strict --tags ~@wip" +std_opts = "--format progress features --tags ~@wip" begin require 'rspec/expectations' std_opts << ' --tags ~@rspec1' @@ -10,7 +10,7 @@ rescue LoadError std_opts << ' --tags ~@rspec2' end %> -default: <%= std_opts %> +default: <%= std_opts %> --dotcucumber features/.cucumber jruby: <%= std_opts %> --tags ~@spork --tags ~@wire jruby_win: <%= std_opts %> --tags ~@spork --tags ~@wire CUCUMBER_FORWARD_SLASH_PATHS=true windows_mri: <%= std_opts %> --tags ~@spork --tags ~@wire --tags ~@needs-many-fonts CUCUMBER_FORWARD_SLASH_PATHS=true diff --git a/examples/i18n/ru/features/division.feature b/examples/i18n/ru/features/division.feature index e61c2fdb91..736d029a14 100644 --- a/examples/i18n/ru/features/division.feature +++ b/examples/i18n/ru/features/division.feature @@ -1,5 +1,5 @@ # language: ru -Фича: Деление чисел +Функция: Деление чисел Поскольку деление сложный процесс и люди часто допускают ошибки Нужно дать им возможность делить на калькуляторе @@ -9,7 +9,7 @@ Если я нажимаю "/" То результатом должно быть число <частное> - Значения: + Примеры: | делимое | делитель | частное | | 100 | 2 | 50 | | 28 | 7 | 4 | diff --git a/examples/sinatra/features/support/env.rb b/examples/sinatra/features/support/env.rb index 7107e88a72..a0ec2f6981 100644 --- a/examples/sinatra/features/support/env.rb +++ b/examples/sinatra/features/support/env.rb @@ -1,4 +1,4 @@ -# See http://wiki.github.com/aslakhellesoy/cucumber/sinatra +# See http://wiki.github.com/cucumber/cucumber/sinatra # for more details about Sinatra with Cucumber require File.dirname(__FILE__) + '/../../app' diff --git a/examples/v8/features/fibonacci.feature b/examples/v8/features/fibonacci.feature index 25dd44a7bb..7f0c43a36c 100644 --- a/examples/v8/features/fibonacci.feature +++ b/examples/v8/features/fibonacci.feature @@ -17,7 +17,7 @@ Feature: Fibonacci | 9 | [1, 1, 2, 3, 5, 8] | | 100 | [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] | - Scenario: Single series tested via a PyString + Scenario: Single series tested via a DocString When I ask Javascript to calculate fibonacci up to 2 with formatting Then it should give me: """ diff --git a/examples/watir/features/step_definitions/search_steps.rb b/examples/watir/features/step_definitions/search_steps.rb index 84211519a2..0face53c34 100644 --- a/examples/watir/features/step_definitions/search_steps.rb +++ b/examples/watir/features/step_definitions/search_steps.rb @@ -16,7 +16,7 @@ # To avoid step definitions that are tightly coupled to your user interface, # consider creating classes for your pages - such as this: -# http://github.com/aslakhellesoy/cucumber/tree/v0.1.15/examples/watir/features/step_definitons/search_steps.rb +# http://github.com/cucumber/cucumber/tree/v0.1.15/examples/watir/features/step_definitons/search_steps.rb # # You may keep the page classes along your steps, or even better, put them in separate files, e.g. # support/pages/google_search.rb diff --git a/features/.cucumber/stepdefs.json b/features/.cucumber/stepdefs.json new file mode 100644 index 0000000000..edfba92c2f --- /dev/null +++ b/features/.cucumber/stepdefs.json @@ -0,0 +1,990 @@ +[ + { + "source": "^I'm using a clean gemset \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:7", + "steps": [ + + ] + }, + { + "source": "^a directory named \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:11", + "steps": [ + + ] + }, + { + "source": "^a file named \"([^\"]*)\" with:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:15", + "steps": [ + { + "name": "a file named \"features/doc_string.feature\" with:", + "args": [ + { + "offset": 14, + "val": "features/doc_string.feature" + } + ] + }, + { + "name": "a file named \"features/f.feature\" with:", + "args": [ + { + "offset": 14, + "val": "features/f.feature" + } + ] + }, + { + "name": "a file named \"features/only_background_and_hooks.feature\" with:", + "args": [ + { + "offset": 14, + "val": "features/only_background_and_hooks.feature" + } + ] + }, + { + "name": "a file named \"features/only_background_and_hooks_steps.rb\" with:", + "args": [ + { + "offset": 14, + "val": "features/only_background_and_hooks_steps.rb" + } + ] + }, + { + "name": "a file named \"features/step_definitions/doc_string_steps.rb\" with:", + "args": [ + { + "offset": 14, + "val": "features/step_definitions/doc_string_steps.rb" + } + ] + }, + { + "name": "a file named \"features/step_definitions/multiline_steps.rb\" with:", + "args": [ + { + "offset": 14, + "val": "features/step_definitions/multiline_steps.rb" + } + ] + }, + { + "name": "a file named \"features/step_definitions/steps.rb\" with:", + "args": [ + { + "offset": 14, + "val": "features/step_definitions/steps.rb" + } + ] + }, + { + "name": "a file named \"features/support/hooks.rb\" with:", + "args": [ + { + "offset": 14, + "val": "features/support/hooks.rb" + } + ] + }, + { + "name": "a file named \"features/support/ze/formator.rb\" with:", + "args": [ + { + "offset": 14, + "val": "features/support/ze/formator.rb" + } + ] + } + ] + }, + { + "source": "^a (\\d+) byte file named \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:19", + "steps": [ + + ] + }, + { + "source": "^an empty file named \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:23", + "steps": [ + + ] + }, + { + "source": "^I write to \"([^\"]*)\" with:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:27", + "steps": [ + + ] + }, + { + "source": "^I overwrite \"([^\"]*)\" with:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:31", + "steps": [ + + ] + }, + { + "source": "^I append to \"([^\"]*)\" with:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:35", + "steps": [ + + ] + }, + { + "source": "^I append to \"([^\"]*)\" with \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:39", + "steps": [ + + ] + }, + { + "source": "^I remove the file \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:43", + "steps": [ + + ] + }, + { + "source": "^I cd to \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:47", + "steps": [ + + ] + }, + { + "source": "^I run \"(.*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:51", + "steps": [ + + ] + }, + { + "source": "^I run `([^`]*)`$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:56", + "steps": [ + { + "name": "I run `cucumber -f stepdefs --dry-run`", + "args": [ + { + "offset": 7, + "val": "cucumber -f stepdefs --dry-run" + } + ] + }, + { + "name": "I run `cucumber -f usage --dry-run`", + "args": [ + { + "offset": 7, + "val": "cucumber -f usage --dry-run" + } + ] + }, + { + "name": "I run `cucumber -q -t @one -t @three features/tagulicious.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q -t @one -t @three features/tagulicious.feature" + } + ] + }, + { + "name": "I run `cucumber -q -t @one,@three features/tagulicious.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q -t @one,@three features/tagulicious.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/background_tagged_before_on_outline.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/background_tagged_before_on_outline.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/failing_background.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/failing_background.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/failing_background_after_success.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/failing_background_after_success.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/multiline_args_background.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/multiline_args_background.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/passing_background.feature:9`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/passing_background.feature:9" + } + ] + }, + { + "name": "I run `cucumber -q features/passing_background.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/passing_background.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/pending_background.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/pending_background.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/scenario_outline_failing_background.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/scenario_outline_failing_background.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/scenario_outline_passing_background.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/scenario_outline_passing_background.feature" + } + ] + }, + { + "name": "I run `cucumber -q features/tagulicious.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber -q features/tagulicious.feature" + } + ] + }, + { + "name": "I run `cucumber features/f.feature:2`", + "args": [ + { + "offset": 7, + "val": "cucumber features/f.feature:2" + } + ] + }, + { + "name": "I run `cucumber features/f.feature:6`", + "args": [ + { + "offset": 7, + "val": "cucumber features/f.feature:6" + } + ] + }, + { + "name": "I run `cucumber features/only_background_and_hooks.feature`", + "args": [ + { + "offset": 7, + "val": "cucumber features/only_background_and_hooks.feature" + } + ] + }, + { + "name": "I run `cucumber`", + "args": [ + { + "offset": 7, + "val": "cucumber" + } + ] + } + ] + }, + { + "source": "^I successfully run \"(.*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:60", + "steps": [ + + ] + }, + { + "source": "^I successfully run `([^`]*)`$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:65", + "steps": [ + + ] + }, + { + "source": "^I run \"([^\"]*)\" interactively$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:69", + "steps": [ + + ] + }, + { + "source": "^I run `([^`]*)` interactively$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:74", + "steps": [ + + ] + }, + { + "source": "^I type \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:78", + "steps": [ + + ] + }, + { + "source": "^the output should contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:82", + "steps": [ + { + "name": "the output should contain \"WARNING\"", + "args": [ + { + "offset": 27, + "val": "WARNING" + } + ] + } + ] + }, + { + "source": "^the output from \"([^\"]*)\" should contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:86", + "steps": [ + + ] + }, + { + "source": "^the output from \"([^\"]*)\" should not contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:90", + "steps": [ + + ] + }, + { + "source": "^the output should not contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:94", + "steps": [ + + ] + }, + { + "source": "^the output should contain:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:98", + "steps": [ + { + "name": "the output should contain:", + "args": [ + + ] + } + ] + }, + { + "source": "^the output should not contain:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:102", + "steps": [ + + ] + }, + { + "source": "^the output should contain exactly \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:106", + "steps": [ + + ] + }, + { + "source": "^the output should contain exactly:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:110", + "steps": [ + + ] + }, + { + "source": "^the output should match \\/([^\\/]*)\\/$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:118", + "steps": [ + + ] + }, + { + "source": "^the output should match:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:122", + "steps": [ + + ] + }, + { + "source": "^the exit status should be (\\d+)$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:126", + "steps": [ + + ] + }, + { + "source": "^the exit status should not be (\\d+)$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:130", + "steps": [ + + ] + }, + { + "source": "^it should (pass|fail) with:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:134", + "steps": [ + { + "name": "it should fail with:", + "args": [ + { + "offset": 10, + "val": "fail" + } + ] + }, + { + "name": "it should pass with:", + "args": [ + { + "offset": 10, + "val": "pass" + } + ] + } + ] + }, + { + "source": "^it should (pass|fail) with exactly:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:138", + "steps": [ + { + "name": "it should fail with exactly:", + "args": [ + { + "offset": 10, + "val": "fail" + } + ] + }, + { + "name": "it should pass with exactly:", + "args": [ + { + "offset": 10, + "val": "pass" + } + ] + } + ] + }, + { + "source": "^it should (pass|fail) with regexp?:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:142", + "steps": [ + + ] + }, + { + "source": "^the stderr should contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:147", + "steps": [ + + ] + }, + { + "source": "^the stderr should contain:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:151", + "steps": [ + + ] + }, + { + "source": "^the stderr should contain exactly:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:155", + "steps": [ + + ] + }, + { + "source": "^the stdout should contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:159", + "steps": [ + + ] + }, + { + "source": "^the stdout should contain:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:163", + "steps": [ + + ] + }, + { + "source": "^the stdout should contain exactly:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:167", + "steps": [ + + ] + }, + { + "source": "^the stderr should not contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:171", + "steps": [ + + ] + }, + { + "source": "^the stderr should not contain:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:175", + "steps": [ + + ] + }, + { + "source": "^the stdout should not contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:179", + "steps": [ + + ] + }, + { + "source": "^the stdout should not contain:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:183", + "steps": [ + + ] + }, + { + "source": "^the stdout from \"([^\"]*)\" should contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:187", + "steps": [ + + ] + }, + { + "source": "^the stdout from \"([^\"]*)\" should not contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:191", + "steps": [ + + ] + }, + { + "source": "^the stderr from \"([^\"]*)\" should contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:195", + "steps": [ + + ] + }, + { + "source": "^the stderr from \"([^\"]*)\" should not contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:199", + "steps": [ + + ] + }, + { + "source": "^the file \"([^\"]*)\" should not exist$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:203", + "steps": [ + + ] + }, + { + "source": "^the following files should exist:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:207", + "steps": [ + + ] + }, + { + "source": "^the following files should not exist:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:211", + "steps": [ + + ] + }, + { + "source": "^a file named \"([^\"]*)\" should exist$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:215", + "steps": [ + + ] + }, + { + "source": "^a file named \"([^\"]*)\" should not exist$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:219", + "steps": [ + + ] + }, + { + "source": "^a (\\d+) byte file named \"([^\"]*)\" should exist$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:223", + "steps": [ + + ] + }, + { + "source": "^the following directories should exist:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:227", + "steps": [ + + ] + }, + { + "source": "^the following directories should not exist:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:231", + "steps": [ + + ] + }, + { + "source": "^a directory named \"([^\"]*)\" should exist$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:235", + "steps": [ + + ] + }, + { + "source": "^a directory named \"([^\"]*)\" should not exist$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:239", + "steps": [ + + ] + }, + { + "source": "^the file \"([^\"]*)\" should contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:243", + "steps": [ + + ] + }, + { + "source": "^the file \"([^\"]*)\" should not contain \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:247", + "steps": [ + + ] + }, + { + "source": "^the file \"([^\"]*)\" should contain exactly:$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:251", + "steps": [ + + ] + }, + { + "source": "^the file \"([^\"]*)\" should match \\/([^\\/]*)\\/$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:255", + "steps": [ + + ] + }, + { + "source": "^the file \"([^\"]*)\" should not match \\/([^\\/]*)\\/$", + "flags": "", + "file_colon_line": "aruba-0.4.11/lib/aruba/cucumber.rb:259", + "steps": [ + + ] + }, + { + "source": "^I run cucumber \"(.+)\"$", + "flags": "", + "file_colon_line": "features/step_definitions/cucumber_steps.rb:1", + "steps": [ + { + "name": "I run cucumber \"--format json features/doc_string.feature\"", + "args": [ + { + "offset": 16, + "val": "--format json features/doc_string.feature" + } + ] + }, + { + "name": "I run cucumber \"--format json features/one_passing_one_failing.feature\"", + "args": [ + { + "offset": 16, + "val": "--format json features/one_passing_one_failing.feature" + } + ] + }, + { + "name": "I run cucumber \"-b --format json features/embed.feature\"", + "args": [ + { + "offset": 16, + "val": "-b --format json features/embed.feature" + } + ] + }, + { + "name": "I run cucumber \"features/f.feature --format Ze::Formator\"", + "args": [ + { + "offset": 16, + "val": "features/f.feature --format Ze::Formator" + } + ] + }, + { + "name": "I run cucumber \"features/foo.feature\"", + "args": [ + { + "offset": 16, + "val": "features/foo.feature" + } + ] + }, + { + "name": "I run cucumber \"features/one_passing_one_failing.feature -r features -f rerun\"", + "args": [ + { + "offset": 16, + "val": "features/one_passing_one_failing.feature -r features -f rerun" + } + ] + }, + { + "name": "I run cucumber \"features/sample.feature --tags ~@wip\"", + "args": [ + { + "offset": 16, + "val": "features/sample.feature --tags ~@wip" + } + ] + }, + { + "name": "I run cucumber \"features/sample.feature -r features --tags ~@wip\"", + "args": [ + { + "offset": 16, + "val": "features/sample.feature -r features --tags ~@wip" + } + ] + } + ] + }, + { + "source": "^it should (pass|fail) with JSON:$", + "flags": "", + "file_colon_line": "features/step_definitions/cucumber_steps.rb:5", + "steps": [ + { + "name": "it should fail with JSON:", + "args": [ + { + "offset": 10, + "val": "fail" + } + ] + }, + { + "name": "it should pass with JSON:", + "args": [ + { + "offset": 10, + "val": "pass" + } + ] + } + ] + }, + { + "source": "^a directory without standard Cucumber project directory structure$", + "flags": "", + "file_colon_line": "features/step_definitions/cucumber_steps.rb:19", + "steps": [ + { + "name": "a directory without standard Cucumber project directory structure", + "args": [ + + ] + } + ] + }, + { + "source": "^a scenario with a step that looks like this:$", + "flags": "", + "file_colon_line": "features/step_definitions/cucumber_steps.rb:25", + "steps": [ + { + "name": "a scenario with a step that looks like this:", + "args": [ + + ] + } + ] + }, + { + "source": "^a step definition that looks like this:$", + "flags": "", + "file_colon_line": "features/step_definitions/cucumber_steps.rb:31", + "steps": [ + { + "name": "a step definition that looks like this:", + "args": [ + + ] + } + ] + }, + { + "source": "^I run the feature with the (\\w+) formatter$", + "flags": "", + "file_colon_line": "features/step_definitions/cucumber_steps.rb:35", + "steps": [ + { + "name": "I run the feature with the progress formatter", + "args": [ + { + "offset": 27, + "val": "progress" + } + ] + } + ] + }, + { + "source": "^I am running spork in the background$", + "flags": "", + "file_colon_line": "features/step_definitions/drb_steps.rb:1", + "steps": [ + { + "name": "I am running spork in the background", + "args": [ + + ] + } + ] + }, + { + "source": "^jeg drikker en \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "features/step_definitions/iso-8859-1_steps.rb:6", + "steps": [ + { + "name": "jeg drikker en \"øl\"", + "args": [ + { + "offset": 16, + "val": "øl" + } + ] + } + ] + }, + { + "source": "^skal de andre si \"([^\"]*)\"$", + "flags": "", + "file_colon_line": "features/step_definitions/iso-8859-1_steps.rb:10", + "steps": [ + { + "name": "skal de andre si \"skål\"", + "args": [ + { + "offset": 18, + "val": "skål" + } + ] + } + ] + } +] \ No newline at end of file diff --git a/features/background.feature b/features/background.feature index cc45836a61..c03e2983d0 100644 --- a/features/background.feature +++ b/features/background.feature @@ -299,7 +299,7 @@ Feature: Background Then I should have '10' cukes Failing Scenarios: - cucumber features/failing_background.feature:7 # Scenario: failing background + cucumber features/failing_background.feature:7 2 scenarios (1 failed, 1 skipped) 6 steps (1 failed, 5 skipped) @@ -335,7 +335,7 @@ Feature: Background | 10 | Failing Scenarios: - cucumber features/scenario_outline_failing_background.feature:6 # Scenario: failing background + cucumber features/scenario_outline_failing_background.feature:6 2 scenarios (1 failed, 1 skipped) 4 steps (1 failed, 3 skipped) @@ -386,7 +386,7 @@ Feature: Background Then I should have '10' global cukes Failing Scenarios: - cucumber features/failing_background_after_success.feature:10 # Scenario: failing background + cucumber features/failing_background_after_success.feature:10 2 scenarios (1 failed, 1 passed) 6 steps (1 failed, 1 skipped, 4 passed) diff --git a/features/cucumber-features b/features/cucumber-features new file mode 160000 index 0000000000..066a82deea --- /dev/null +++ b/features/cucumber-features @@ -0,0 +1 @@ +Subproject commit 066a82deea93382cb8e185cf47c7647ca5ae1ec5 diff --git a/features/doc_strings.feature b/features/doc_strings.feature new file mode 100644 index 0000000000..2187e8d665 --- /dev/null +++ b/features/doc_strings.feature @@ -0,0 +1,73 @@ +Feature: Doc strings + + If you need to specify information in a scenario that won't fit on a single line, + you can use a DocString. + + A DocString follows a step, and starts and ends with three double quotes, like this: + + ```gherkin + When I ask to reset my password + Then I should receive an email with: + """ + Dear bozo, + + Please click this link to reset your password + """ + ``` + + It's possible to annotate the DocString with the type of content it contains. This is used by + formatting tools like http://relishapp.com which will render the contents of the DocString + appropriately. You specify the content type after the triple quote, like this: + + ```gherkin + Given there is some Ruby code: + """ruby + puts "hello world" + """ + + You can read the content type from the argument passed into your step definition, as shown + in the example below. + + Scenario: Plain text Docstring + Given a scenario with a step that looks like this: + """gherkin + Given I have a lot to say: + \"\"\" + One + Two + Three + \"\"\" + """ + And a step definition that looks like this: + """ruby + Given /say/ do |text| + puts text + end + """ + When I run the feature with the progress formatter + Then the output should contain: + """ + One + Two + Three + """ + + Scenario: DocString with interesting content type + Given a scenario with a step that looks like this: + """gherkin + Given I have some code for you: + \"\"\"ruby + # hello + \"\"\" + """ + And a step definition that looks like this: + """ruby + Given /code/ do |text| + puts text.content_type + end + """ + When I run the feature with the progress formatter + Then the output should contain: + """ + ruby + """ diff --git a/features/drb_server_integration.feature b/features/drb_server_integration.feature new file mode 100644 index 0000000000..81eb4a9ac4 --- /dev/null +++ b/features/drb_server_integration.feature @@ -0,0 +1,63 @@ +@drb +Feature: DRb Server Integration + To prevent waiting for Rails and other large Ruby applications to load their environments + for each feature run Cucumber ships with a DRb client that can speak to a server which + loads up the environment only once. + + This regression test highlights bug related to DRb server arguments processing, for more + details see https://github.com/cucumber/cucumber/issues/117 + + Background: App with Spork support + Spork is a gem that has a DRb server and the scenarios below illustrate how to use it. + However, any DRb server that adheres to the protocol that the client expects would work. + + Given a directory without standard Cucumber project directory structure + And a file named "features/support/env.rb" with: + """ + require 'rubygems' + require 'spork' + + Spork.prefork do + puts "I'm loading all the heavy stuff..." + end + + Spork.each_run do + puts "I'm loading the stuff just for this run..." + end + """ + And a file named "config/cucumber.yml" with: + """ + <% + std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip" + %> + default: --drb <%= std_opts %> features + """ + And a file named "features/sample.feature" with: + """ + # language: en + Feature: Sample + Scenario: this is a test + Given I am just testing stuff + """ + And a file named "features/step_definitions/all_your_steps_are_belong_to_us.rb" with: + """ + Given /^I am just testing stuff$/ do + # no-op + end + """ + + Scenario: Single feature passing with '-r features' option + Given I am running spork in the background + When I run cucumber "features/sample.feature -r features --tags ~@wip" + And it should pass with: + """ + 1 step (1 passed) + """ + + Scenario: Single feature passing without '-r features' option + Given I am running spork in the background + When I run cucumber "features/sample.feature --tags ~@wip" + And it should pass with: + """ + 1 step (1 passed) + """ diff --git a/features/json_formatter.feature b/features/json_formatter.feature index 323967389e..27aaf649bd 100644 --- a/features/json_formatter.feature +++ b/features/json_formatter.feature @@ -60,93 +60,90 @@ Feature: JSON output formatter """ - Scenario: one feature, one passing scenario, one failing scenario - When I run cucumber "--format json features/one_passing_one_failing.feature" - Then the output should match /^\{"features":\[/ - Scenario: one feature, one passing scenario, one failing scenario When I run cucumber "--format json features/one_passing_one_failing.feature" Then it should fail with JSON: """ - { - "features": [ - { - "keyword": "Feature", - "name": "One passing scenario, one failing scenario", - "line": 2, - "description": "", - "tags": [ - { - "name": "@a", - "line": 1 - } - ], - "elements": [ - { - "keyword": "Scenario", - "name": "Passing", - "line": 5, - "description": "", - "tags": [ - { - "name": "@b", - "line": 4 - } - ], - "type": "scenario", - "steps": [ - { - "keyword": "Given ", - "name": "a passing step", - "line": 6, - "match": { - "location": "features/step_definitions/steps.rb:1" - }, - "result": { - "status": "passed" - } - } - ] - }, - { - "keyword": "Scenario", - "name": "Failing", - "line": 9, - "description": "", - "tags": [ - { - "name": "@c", - "line": 8 + [ + { + "uri": "features/one_passing_one_failing.feature", + "keyword": "Feature", + "id": "one-passing-scenario,-one-failing-scenario", + "name": "One passing scenario, one failing scenario", + "line": 2, + "description": "", + "tags": [ + { + "name": "@a", + "line": 1 + } + ], + "elements": [ + { + "keyword": "Scenario", + "id": "one-passing-scenario,-one-failing-scenario;passing", + "name": "Passing", + "line": 5, + "description": "", + "tags": [ + { + "name": "@b", + "line": 4 + } + ], + "type": "scenario", + "steps": [ + { + "keyword": "Given ", + "name": "a passing step", + "line": 6, + "match": { + "location": "features/step_definitions/steps.rb:1" + }, + "result": { + "status": "passed" } - ], - "type": "scenario", - "steps": [ - { - "keyword": "Given ", - "name": "a failing step", - "line": 10, - "match": { - "location": "features/step_definitions/steps.rb:5" - }, - "result": { - "status": "failed", - "error_message": " (RuntimeError)\n./features/step_definitions/steps.rb:6:in `/a failing step/'\nfeatures/one_passing_one_failing.feature:10:in `Given a failing step'" - } + } + ] + }, + { + "keyword": "Scenario", + "id": "one-passing-scenario,-one-failing-scenario;failing", + "name": "Failing", + "line": 9, + "description": "", + "tags": [ + { + "name": "@c", + "line": 8 + } + ], + "type": "scenario", + "steps": [ + { + "keyword": "Given ", + "name": "a failing step", + "line": 10, + "match": { + "location": "features/step_definitions/steps.rb:5" + }, + "result": { + "status": "failed", + "error_message": " (RuntimeError)\n./features/step_definitions/steps.rb:6:in `/a failing step/'\nfeatures/one_passing_one_failing.feature:10:in `Given a failing step'" } - ] - } - ] - } - ] - } + } + ] + } + ] + } + ] """ - @announce - Scenario: pystring - Given a file named "features/pystring.feature" with: + Scenario: DocString + Given a file named "features/doc_string.feature" with: """ - Feature: A pystring feature + Feature: A DocString feature Scenario: Then I should fail with @@ -154,68 +151,26 @@ Feature: JSON output formatter a string \"\"\" """ - And a file named "features/step_definitions/pystring_steps.rb" with: + And a file named "features/step_definitions/doc_string_steps.rb" with: """ Then /I should fail with/ do |s| raise s end """ - When I run cucumber "--format json features/pystring.feature" + When I run cucumber "--format json features/doc_string.feature" Then it should fail with JSON: """ - { - "features": [ - { - "keyword": "Feature", - "name": "A pystring feature", - "line": 1, - "description": "", - "elements": [ - { - "keyword": "Scenario", - "name": "", - "line": 3, - "description": "", - "type": "scenario", - "steps": [ - { - "keyword": "Then ", - "name": "I should fail with", - "line": 4, - "multiline_arg": { - "value": "a string", - "line": 5, - "type": "py_string" - }, - "match": { - "location": "features/step_definitions/pystring_steps.rb:1" - }, - "result": { - "status": "failed", - "error_message": "a string (RuntimeError)\n./features/step_definitions/pystring_steps.rb:2:in `/I should fail with/'\nfeatures/pystring.feature:4:in `Then I should fail with'" - } - } - ] - } - ] - } - ] - } - """ - - Scenario: embedding screenshot - When I run cucumber "-b --format json features/embed.feature" - Then it should pass with JSON: - """ - { - "features": [ + [ { + "id": "a-docstring-feature", + "uri": "features/doc_string.feature", "keyword": "Feature", - "name": "A screenshot feature", + "name": "A DocString feature", "line": 1, "description": "", "elements": [ { + "id": "a-docstring-feature;", "keyword": "Scenario", "name": "", "line": 3, @@ -223,20 +178,20 @@ Feature: JSON output formatter "type": "scenario", "steps": [ { - "keyword": "Given ", - "name": "I embed a screenshot", + "keyword": "Then ", + "name": "I should fail with", "line": 4, - "embeddings": [ - { - "mime_type": "image/png", - "data": "Zm9v" - } - ], + "doc_string": { + "content_type": "", + "value": "a string", + "line": 5 + }, "match": { - "location": "features/step_definitions/steps.rb:29" + "location": "features/step_definitions/doc_string_steps.rb:1" }, "result": { - "status": "passed" + "status": "failed", + "error_message": "a string (RuntimeError)\n./features/step_definitions/doc_string_steps.rb:2:in `/I should fail with/'\nfeatures/doc_string.feature:4:in `Then I should fail with'" } } ] @@ -244,6 +199,50 @@ Feature: JSON output formatter ] } ] - } + """ - """ \ No newline at end of file + Scenario: embedding screenshot + When I run cucumber "-b --format json features/embed.feature" + Then it should pass with JSON: + """ + [ + { + "uri": "features/embed.feature", + "id": "a-screenshot-feature", + "keyword": "Feature", + "name": "A screenshot feature", + "line": 1, + "description": "", + "elements": [ + { + "id": "a-screenshot-feature;", + "keyword": "Scenario", + "name": "", + "line": 3, + "description": "", + "type": "scenario", + "steps": [ + { + "keyword": "Given ", + "name": "I embed a screenshot", + "line": 4, + "embeddings": [ + { + "mime_type": "image/png", + "data": "Zm9v" + } + ], + "match": { + "location": "features/step_definitions/steps.rb:29" + }, + "result": { + "status": "passed" + } + } + ] + } + ] + } + ] + + """ diff --git a/features/nested_steps.feature b/features/nested_steps.feature new file mode 100644 index 0000000000..09c98f3989 --- /dev/null +++ b/features/nested_steps.feature @@ -0,0 +1,60 @@ +Feature: Nested Steps + + + Background: + Given a scenario with a step that looks like this: + """gherkin + Given two turtles + """ + And a step definition that looks like this: + """ruby + Given /a turtle/ do + puts "turtle!" + end + """ + + Scenario: Use #steps to call several steps at once + Given a step definition that looks like this: + """ruby + Given /two turtles/ do + steps %{ + Given a turtle + And a turtle + } + end + """ + When I run the feature with the progress formatter + Then the output should contain: + """ + turtle! + + turtle! + + """ + + Scenario: Use #step to call a single step + Given a step definition that looks like this: + """ruby + Given /two turtles/ do + step "a turtle" + step "a turtle" + end + """ + When I run the feature with the progress formatter + Then the output should contain: + """ + turtle! + + turtle! + + """ + + Scenario: Use deprecated i18n methods + Given a step definition that looks like this: + """ruby + Given /two turtles/ do + Given "a turtle" + end + """ + When I run the feature with the progress formatter + Then the output should contain "WARNING" diff --git a/features/rerun_formatter.feature b/features/rerun_formatter.feature new file mode 100644 index 0000000000..0dfe30b461 --- /dev/null +++ b/features/rerun_formatter.feature @@ -0,0 +1,35 @@ +Feature: Rerun formatter + For details see https://github.com/cucumber/cucumber/issues/57 + + Background: + Given a file named "features/one_passing_one_failing.feature" with: + """ + Feature: One passing example, one failing example + + Scenario Outline: + Given a step + + Examples: + |certain| + |passing| + |failing| + + """ + And a file named "features/step_definitions/steps.rb" with: + """ + Given /a passing step/ do + #does nothing + end + + Given /a failing step/ do + fail + end + """ + + Scenario: Handle examples with the rerun formatter + When I run cucumber "features/one_passing_one_failing.feature -r features -f rerun" + Then it should fail with: + """ + features/one_passing_one_failing.feature:9 + """ + diff --git a/features/step_definitions/cucumber-features/cucumber_ruby_mappings.rb b/features/step_definitions/cucumber-features/cucumber_ruby_mappings.rb new file mode 100644 index 0000000000..3b1071184b --- /dev/null +++ b/features/step_definitions/cucumber-features/cucumber_ruby_mappings.rb @@ -0,0 +1,197 @@ +module CucumberRubyMappings + def features_dir + 'features' + end + + def run_scenario(scenario_name) + run_simple "#{cucumber_bin} features/a_feature.feature --name '#{scenario_name}'", false + end + + def run_feature(filename = 'features/a_feature.feature', formatter = 'progress') + run_simple "#{cucumber_bin} #{filename} --format #{formatter}", false + end + + def cucumber_bin + File.expand_path(File.dirname(__FILE__) + '/../../../bin/cucumber') + end + + def write_passing_mapping(step_name) + erb = ERB.new(<<-EOF, nil, '-') +Given /<%= step_name -%>/ do + # ARUBA_IGNORE_START + File.open("<%= step_file(step_name) %>", "w") + # ARUBA_IGNORE_END +end + +EOF + append_to_file("features/step_definitions/some_stepdefs.rb", erb.result(binding)) + end + + def write_pending_mapping(step_name) + erb = ERB.new(<<-EOF, nil, '-') +Given /<%= step_name -%>/ do + # ARUBA_IGNORE_START + File.open("<%= step_file(step_name) %>", "w") + # ARUBA_IGNORE_END + pending +end + +EOF + append_to_file("features/step_definitions/some_stepdefs.rb", erb.result(binding)) + end + + def write_failing_mapping(step_name) + erb = ERB.new(<<-EOF, nil, '-') +Given /<%= step_name -%>/ do + # ARUBA_IGNORE_START + File.open("<%= step_file(step_name) %>", "w") + # ARUBA_IGNORE_END + raise "bang!" +end + +EOF + append_to_file("features/step_definitions/some_stepdefs.rb", erb.result(binding)) + end + + def write_calculator_code + code = <<-EOF +# http://en.wikipedia.org/wiki/Reverse_Polish_notation +class RpnCalculator + def initialize + @stack = [] + end + + def push(arg) + if(%w{- + * /}.index(arg)) + y, x = @stack.pop(2) + push(x.__send__(arg, y)) + else + @stack.push(arg) + end + end + + def PI + push(Math::PI) + end + + def value + @stack[-1] + end +end +EOF + write_file("lib/rpn_calculator.rb", code) + end + + def write_mappings_for_calculator + write_file("features/support/env.rb", "$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')\n") + mapping_code = <<-EOF +require 'rpn_calculator' + +Given /^a calculator$/ do + @calc = RpnCalculator.new +end + +When /^the calculator computes PI$/ do + @calc.PI +end + +When /^the calculator adds up ([\\d\\.]+) and ([\\d\\.]+)$/ do |n1, n2| + @calc.push(n1.to_f) + @calc.push(n2.to_f) + @calc.push('+') +end + +When /^the calculator adds up "([^"]*)" and "([^"]*)"$/ do |n1, n2| + @calc.push(n1.to_i) + @calc.push(n2.to_i) + @calc.push('+') +end + +When /^the calculator adds up "([^"]*)", "([^"]*)" and "([^"]*)"$/ do |n1, n2, n3| + @calc.push(n1.to_i) + @calc.push(n2.to_i) + @calc.push(n3.to_i) + @calc.push('+') + @calc.push('+') +end + +When /^the calculator adds up the following numbers:$/ do |numbers| + pushed = 0 + numbers.split("\\n").each do |n| + @calc.push(n.to_i) + pushed +=1 + @calc.push('+') if pushed > 1 + end +end + +Then /^the calculator returns PI$/ do + @calc.value.to_f.should be_within(0.00001).of(Math::PI) +end + +Then /^the calculator returns "([^"]*)"$/ do |expected| + @calc.value.to_f.should be_within(0.00001).of(expected.to_f) +end + +Then /^the calculator does not return ([\\d\\.]+)$/ do |unexpected| + @calc.value.to_f.should_not be_within(0.00001).of(unexpected.to_f) +end + +EOF + write_file("features/step_definitions/calculator_mappings.rb", mapping_code) + end + + def assert_passing_scenario + assert_partial_output("1 scenario (1 passed)", all_output) + assert_success true + end + + def assert_failing_scenario + assert_partial_output("1 scenario (1 failed)", all_output) + assert_success false + end + + def assert_pending_scenario + assert_partial_output("1 scenario (1 pending)", all_output) + assert_success true + end + + def assert_undefined_scenario + assert_partial_output("1 scenario (1 undefined)", all_output) + assert_success true + end + + def failed_output + "failed" + end + + def run_spork_in_background(port = nil) + require 'spork' + + pid = fork + in_current_dir do + if pid + background_jobs << pid + else + # STDOUT.close + # STDERR.close + port_arg = port ? "-p #{port}" : '' + cmd = "#{Cucumber::RUBY_BINARY} -I #{Cucumber::LIBDIR} #{Spork::BINARY} cuc #{port_arg}" + exec cmd + end + end + sleep 1.0 + end + + def background_jobs + @background_jobs ||= [] + end + + def terminate_background_jobs + background_jobs.each do |pid| + Process.kill(Signal.list['TERM'], pid) + end + end + +end + +World(CucumberRubyMappings) diff --git a/features/step_definitions/cucumber_steps.rb b/features/step_definitions/cucumber_steps.rb index 629603e4ea..e1e8763a30 100644 --- a/features/step_definitions/cucumber_steps.rb +++ b/features/step_definitions/cucumber_steps.rb @@ -3,8 +3,17 @@ end Then /^it should (pass|fail) with JSON:$/ do |pass_fail, json| - JSON.parse(all_stdout).should == JSON.parse(json) - assert_exiting_with(pass_fail == 'pass') + # Need to store it in a variable. With JRuby we can only do this once it seems :-/ + stdout = all_stdout + + # JRuby has weird traces sometimes (?) + stdout = stdout.gsub(/ `\(root\)':in/, '') + + actual = JSON.parse(stdout) + expected = JSON.parse(json) + + actual.should == expected + assert_success(pass_fail == 'pass') end Given /^a directory without standard Cucumber project directory structure$/ do @@ -12,3 +21,18 @@ FileUtils.rm_rf 'features' if File.directory?('features') end end + +Given /^a scenario with a step that looks like this:$/ do |string| + create_feature do + create_scenario { string } + end +end + +Given /^a step definition that looks like this:$/ do |string| + create_step_definition { string } +end + +When /^I run the feature with the (\w+) formatter$/ do |formatter| + features.length.should == 1 + run_feature features.first, formatter +end diff --git a/features/step_definitions/drb_steps.rb b/features/step_definitions/drb_steps.rb new file mode 100644 index 0000000000..00df00b6e6 --- /dev/null +++ b/features/step_definitions/drb_steps.rb @@ -0,0 +1,3 @@ +Given /^I am running spork in the background$/ do + run_spork_in_background +end \ No newline at end of file diff --git a/features/support/env.rb b/features/support/env.rb index f3f46c6dfe..d9b811b039 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1,31 +1,30 @@ +ENV['FORCE_COLOR'] = 'true' require 'aruba/api' +require 'aruba/cucumber' # Monkey patch aruba to filter out some stuff module Aruba::Api - alias _all_stdout all_stdout + alias __all_stdout all_stdout def all_stdout - out = _all_stdout + unrandom(__all_stdout) + end - # Remove absolute paths - out.gsub!(/#{Dir.pwd}\/tmp\/aruba/, '.') - # Make duration predictable - out.gsub!(/^\d+m\d+\.\d+s$/, '0m0.012s') - # Remove SimpleCov message - out.gsub!(/Coverage report generated for Cucumber Features to #{Dir.pwd}\/coverage.*\n$/, '') - - out + def unrandom(out) + out = out.gsub(/#{Dir.pwd}\/tmp\/aruba/, '.') # Remove absolute paths + out = out.gsub(/^\d+m\d+\.\d+s$/, '0m0.012s') # Make duration predictable + out = out.gsub(/Coverage report generated for Cucumber Features to #{Dir.pwd}\/coverage.*\n$/, '') # Remove SimpleCov message end end -require 'aruba/cucumber' - -Before do |scenario| - @scenario = scenario - +Before do # Make sure bin/cucumber runs with SimpleCov enabled # set_env('SIMPLECOV', 'true') # Set a longer timeout for aruba - @aruba_timeout_seconds = 5 + @aruba_timeout_seconds = 15 +end + +After do + terminate_background_jobs end diff --git a/features/support/feature_factory.rb b/features/support/feature_factory.rb new file mode 100644 index 0000000000..63db8a2d2d --- /dev/null +++ b/features/support/feature_factory.rb @@ -0,0 +1,50 @@ +module FeatureFactory + def create_feature(name = generate_feature_name) + gherkin = <<-GHERKIN +Feature: #{name} +#{yield} + GHERKIN + write_file filename(name), gherkin + end + + def create_scenario(name = generate_scenario_name) + <<-GHERKIN + Scenario: #{name} + #{yield} + GHERKIN + end + + def create_step_definition + write_file generate_step_definition_filename, yield + end + + def generate_feature_name + "Test Feature #{next_increment(:feature)}" + end + + def generate_scenario_name + "Test Scenario #{next_increment(:scenario)}" + end + + def next_increment(label) + @increments ||= {} + @increments[label] ||= 0 + @increments[label] += 1 + end + + def generate_step_definition_filename + "features/step_definitions/test_steps#{next_increment(:step_defs)}.rb" + end + + def filename(name) + "features/#{name.downcase.gsub(' ', '_')}.feature" + end + + def features + in_current_dir do + Dir['features/*.feature'] + end + end +end + +World(FeatureFactory) diff --git a/features/tagged_hooks.feature b/features/tagged_hooks.feature index f9c8be9750..57d59e0378 100644 --- a/features/tagged_hooks.feature +++ b/features/tagged_hooks.feature @@ -58,9 +58,9 @@ Feature: Tag logic Scenario: And yet another Example Failing Scenarios: - cucumber features/tagulicious.feature:4 # Scenario: Example - cucumber features/tagulicious.feature:8 # Scenario: Another Example - cucumber features/tagulicious.feature:12 # Scenario: Yet another Example + cucumber features/tagulicious.feature:4 + cucumber features/tagulicious.feature:8 + cucumber features/tagulicious.feature:12 4 scenarios (3 failed, 1 passed) 3 steps (3 undefined) @@ -97,7 +97,7 @@ Feature: Tag logic Scenario: And yet another Example Failing Scenarios: - cucumber features/tagulicious.feature:4 # Scenario: Example + cucumber features/tagulicious.feature:4 4 scenarios (1 failed, 2 undefined, 1 passed) 3 steps (3 undefined) @@ -170,9 +170,9 @@ Feature: Tag logic Scenario: And yet another Example Failing Scenarios: - cucumber features/tagulicious.feature:4 # Scenario: Example - cucumber features/tagulicious.feature:8 # Scenario: Another Example - cucumber features/tagulicious.feature:12 # Scenario: Yet another Example + cucumber features/tagulicious.feature:4 + cucumber features/tagulicious.feature:8 + cucumber features/tagulicious.feature:12 4 scenarios (3 failed, 1 passed) 3 steps (3 undefined) @@ -209,7 +209,7 @@ Feature: Tag logic Scenario: And yet another Example Failing Scenarios: - cucumber features/tagulicious.feature:4 # Scenario: Example + cucumber features/tagulicious.feature:4 4 scenarios (1 failed, 2 undefined, 1 passed) 3 steps (3 undefined) diff --git a/features/transforms.feature b/features/transforms.feature index 46b565682c..0a7b06d01a 100644 --- a/features/transforms.feature +++ b/features/transforms.feature @@ -33,7 +33,7 @@ Feature: Transforms end Given /^(a Person aged \d+) with blonde hair$/ do |person| - announce "#{person} and I have blonde hair" + puts "#{person} and I have blonde hair" end """ When I run cucumber "features/foo.feature" @@ -53,7 +53,7 @@ Feature: Transforms end Given /^(#{A_PERSON}) with blonde hair$/ do |person| - announce "#{person} and I have blonde hair" + puts "#{person} and I have blonde hair" end """ When I run cucumber "features/foo.feature" diff --git a/fixtures/junit/features/pending.feature b/fixtures/junit/features/pending.feature index a013cdf0d5..db04ff6591 100644 --- a/fixtures/junit/features/pending.feature +++ b/fixtures/junit/features/pending.feature @@ -2,4 +2,6 @@ Feature: Pending step Scenario: Pending Given a pending step - + + Scenario: Undefined + Given an undefined step \ No newline at end of file diff --git a/fixtures/junit/features/scenario_outline.feature b/fixtures/junit/features/scenario_outline.feature new file mode 100644 index 0000000000..cc98892763 --- /dev/null +++ b/fixtures/junit/features/scenario_outline.feature @@ -0,0 +1,9 @@ +Feature: Scenario outlines + + Scenario Outline: Using scenario outlines + Given a scenario + + Examples: + | type | + | passing | + | failing | diff --git a/fixtures/junit/features/some_subdirectory/one_passing_one_failing.feature b/fixtures/junit/features/some_subdirectory/one_passing_one_failing.feature new file mode 100644 index 0000000000..ec3feb16ec --- /dev/null +++ b/fixtures/junit/features/some_subdirectory/one_passing_one_failing.feature @@ -0,0 +1,8 @@ +Feature: Subdirectory - One passing scenario, one failing scenario + + Scenario: Passing + Given a passing scenario + + Scenario: Failing + Given a failing scenario + diff --git a/fixtures/self_test/features/support/bubble_256x256.png b/fixtures/self_test/features/support/bubble_256x256.png new file mode 100644 index 0000000000..18335498ce Binary files /dev/null and b/fixtures/self_test/features/support/bubble_256x256.png differ diff --git a/fixtures/self_test/features/support/env.rb b/fixtures/self_test/features/support/env.rb index 5770e27ce7..1ce0d3adaf 100644 --- a/fixtures/self_test/features/support/env.rb +++ b/fixtures/self_test/features/support/env.rb @@ -1,3 +1,4 @@ +require 'base64' begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; end $KCODE = 'u' unless Cucumber::RUBY_1_9 @@ -16,3 +17,10 @@ After('@background_tagged_before_on_outline') do @cukes.should == '888' end + +After do + png = IO.read(File.join(File.dirname(__FILE__), 'bubble_256x256.png')) + encoded_img = Base64.encode64(png).gsub(/\n/, '') + embed("data:image/png;base64,#{encoded_img}", 'image/png') +end + diff --git a/fixtures/self_test/features/undefined_multiline_args.feature b/fixtures/self_test/features/undefined_multiline_args.feature index ae3c7321b6..ba9d45e7bd 100644 --- a/fixtures/self_test/features/undefined_multiline_args.feature +++ b/fixtures/self_test/features/undefined_multiline_args.feature @@ -3,7 +3,7 @@ Feature: undefined multiline args Scenario: pystring Given a pystring """ - example + example with entities """ Scenario: table diff --git a/fixtures/tickets/features.html b/fixtures/tickets/features.html index dee984f58d..7b9749175b 100644 --- a/fixtures/tickets/features.html +++ b/fixtures/tickets/features.html @@ -135,4 +135,4 @@ ./features/step_definitons/tickets_steps.rb:57:in `/^I have a pending step$/' features/241.feature:10:in `Given I have a pending step'
  • When I run this feature with the progress format
  • Then I should get a no method error for 'backtrace_line'
  • Feature: https://rspec.lighthouseapp.com/projects/16211/tickets/246-distorted-console-output-for-slightly-complicated-step-regexp-match

    Scenario: See "No Record(s) Found" for Zero Existing

    1. Given no public holiday exists in the system

    Feature: pending method causes failure in Scenario Outlines

    Scenario Outline: blah

    1. Given this is pending until we fix it
    2. Given context with <Stuff>
    3. When action
    4. Then outcome with <Blah>

    Examples:

    StuffBlah
    CheesePepper Jack
    TODO (Cucumber::Pending)
     ./features/step_definitons/248_steps.rb:2:in `/^this is pending until we fix it$/'
    -features/248.feature:4:in `Given this is pending until we fix it'

    Feature: Background

    In for background to work properly
    As a user
    I want it to run transactionally and only once when I call an individual scenario

    Background:

    1. Given plop

    Scenario: Barping

    1. When I barp

    Scenario: Wibbling

    1. When I wibble

    Feature: pystring indentaion testcase

    Scenario: example of correct indentation

    1. Given multiline string
        I'm a cucumber and I'm ok
      I sleep all night and test all day
    2. Then string is
        I'm a cucumber and I'm ok
      I sleep all night and test all day

    Scenario: example of wrong indentation

    1. Given I am in tickets/features/279
    2. When I run cucumber -q wrong.feature_
    3. Then it should fail with
    4. And STDERR should match
      wrong.feature_:8:10: Parse error

    Feature https://rspec.lighthouseapp.com/projects/16211/tickets/301

    Background: A background

    1. Given whatever

    Scenario: VB is not cool

    1. Then VB should not be cool

    Feature: woo yeah

    Background:

    1. Given passing step without a table

    Feature: Outlines

    In order to re-use scenario table values
    As a citizen of Cucumbia
    I want to explicitly mark the parameters in a scenario outline

    Scenario Outline: controlling order

    1. Given there are <start> cucumbers
    2. When I eat <eat> cucumbers
    3. Then I should have <left> cucumbers

    Examples:

    leftstarteat
    7125
    15205

    Scenario Outline: reusing place holder

    1. Given there are <start> cucumbers
    2. When I eat <eat> cucumbers
    3. Then I should have <left> cucumbers
    4. And I should have <eat> cucumbers in my belly

    Examples: Lots of cukes

    starteatleft
    1257
    20515

    Examples: Ridiculous amounts of cukes

    starteatleft
    1205070
    20050150

    Scenario Outline: no placeholders

    1. Given there are 12 cucumbers
    2. When I eat 5 cucumbers
    3. Then I should have 7 cucumbers

    Examples:

    starteatleft
    1257
    20515

    Scenario Outline: using '<' and '>' not as placeholder

    1. Given the belly space is < 12 and > 6
    2. And there are <start> cucumbers
    3. When I eat <eat> cucumbers
    4. Then I should have <left> cucumbers

    Examples:

    starteatleft
    1257
    20515

    Scenario Outline: with step tables

    1. Given I have the following fruits in my pantry
      namequantity
      cucumbers10
      strawberrys5
      apricots7
    2. When I eat <number> <fruits> from the pantry
    3. Then I should have <left> <fruits> in the pantry

    Examples:

    numberfruitsleft
    2cucumbers8
    4strawberrys1
    2apricots5

    Scenario Outline: placeholder in a multiline string

    1. Given my shopping list
        Must buy some 
    2. Then my shopping list should equal
        Must buy some cucumbers

    Examples:

    fruits
    cucumbers

    Scenario Outline: placeholder in step table

    1. Given I have the following fruits in my pantry
      namequantity
      cucumbers<quant_cukes>
      strawberrys<quant_straw>
    2. When I eat <number> <fruits> from the pantry
    3. Then I should have <left> <fruits> in the pantry

    Examples:

    quant_cukesquant_strawnumberfruitsleft
    1052cucumbers8
    554strawberrys1

    Feature: Cucumber

    In order to have a happy user base
    As a Cucumber user
    I don't want no stinkin bugs

    Scenario: RSpec be_*

    1. Given be_empty

    Scenario: Call step from step

    1. Given nested step is called
    2. Then nested step should be executed

    Scenario: Call step from step using text table

    1. Given nested step is called using text table
    2. Then nested step should be executed

    Scenario: Reading a table

    1. Given the following table
      bornworking
      OsloLondon
    2. Then I should be working in London
    3. And I should be born in Oslo
    4. And I should see a multiline string like
      A string
      that spans
      several lines
    43 scenarios (12 undefined, 2 pending, 29 passed)
    173 steps (5 skipped, 89 undefined, 2 pending, 77 passed)
    0m0.701s
    \ No newline at end of file +features/248.feature:4:in `Given this is pending until we fix it'

    Feature: Background

    In for background to work properly
    As a user
    I want it to run transactionally and only once when I call an individual scenario

    Background:

    1. Given plop

    Scenario: Barping

    1. When I barp

    Scenario: Wibbling

    1. When I wibble

    Feature: pystring indentaion testcase

    Scenario: example of correct indentation

    1. Given multiline string
        I'm a cucumber and I'm ok
      I sleep all night and test all day
    2. Then string is
        I'm a cucumber and I'm ok
      I sleep all night and test all day

    Scenario: example of wrong indentation

    1. Given I am in tickets/features/279
    2. When I run cucumber -q wrong.feature_
    3. Then it should fail with
    4. And STDERR should match
      wrong.feature_:8:10: Parse error

    Feature https://rspec.lighthouseapp.com/projects/16211/tickets/301

    Background: A background

    1. Given whatever

    Scenario: VB is not cool

    1. Then VB should not be cool

    Feature: woo yeah

    Background:

    1. Given passing step without a table

    Feature: Outlines

    In order to re-use scenario table values
    As a citizen of Cucumbia
    I want to explicitly mark the parameters in a scenario outline

    Scenario Outline: controlling order

    1. Given there are <start> cucumbers
    2. When I eat <eat> cucumbers
    3. Then I should have <left> cucumbers

    Examples:

    leftstarteat
    7125
    15205

    Scenario Outline: reusing place holder

    1. Given there are <start> cucumbers
    2. When I eat <eat> cucumbers
    3. Then I should have <left> cucumbers
    4. And I should have <eat> cucumbers in my belly

    Examples: Lots of cukes

    starteatleft
    1257
    20515

    Examples: Ridiculous amounts of cukes

    starteatleft
    1205070
    20050150

    Scenario Outline: no placeholders

    1. Given there are 12 cucumbers
    2. When I eat 5 cucumbers
    3. Then I should have 7 cucumbers

    Examples:

    starteatleft
    1257
    20515

    Scenario Outline: using '<' and '>' not as placeholder

    1. Given the belly space is < 12 and > 6
    2. And there are <start> cucumbers
    3. When I eat <eat> cucumbers
    4. Then I should have <left> cucumbers

    Examples:

    starteatleft
    1257
    20515

    Scenario Outline: with step tables

    1. Given I have the following fruits in my pantry
      namequantity
      cucumbers10
      strawberrys5
      apricots7
    2. When I eat <number> <fruits> from the pantry
    3. Then I should have <left> <fruits> in the pantry

    Examples:

    numberfruitsleft
    2cucumbers8
    4strawberrys1
    2apricots5

    Scenario Outline: placeholder in a multiline string

    1. Given my shopping list
        Must buy some 
    2. Then my shopping list should equal
        Must buy some cucumbers

    Examples:

    fruits
    cucumbers

    Scenario Outline: placeholder in step table

    1. Given I have the following fruits in my pantry
      namequantity
      cucumbers<quant_cukes>
      strawberrys<quant_straw>
    2. When I eat <number> <fruits> from the pantry
    3. Then I should have <left> <fruits> in the pantry

    Examples:

    quant_cukesquant_strawnumberfruitsleft
    1052cucumbers8
    554strawberrys1

    Feature: Cucumber

    In order to have a happy user base
    As a Cucumber user
    I don't want no stinkin bugs

    Scenario: RSpec be_*

    1. Given be_empty

    Scenario: Call step from step

    1. Given nested step is called
    2. Then nested step should be executed

    Scenario: Call step from step using text table

    1. Given nested step is called using text table
    2. Then nested step should be executed

    Scenario: Reading a table

    1. Given the following table
      bornworking
      OsloLondon
    2. Then I should be working in London
    3. And I should be born in Oslo
    4. And I should see a multiline string like
      A string
      that spans
      several lines
    43 scenarios (12 undefined, 2 pending, 29 passed)
    173 steps (5 skipped, 89 undefined, 2 pending, 77 passed)
    0m0.701s
    \ No newline at end of file diff --git a/gem_tasks/cucumber.rake b/gem_tasks/cucumber.rake index cf2ec279d4..ed916e9c7e 100644 --- a/gem_tasks/cucumber.rake +++ b/gem_tasks/cucumber.rake @@ -1,10 +1,12 @@ -$:.unshift(File.dirname(__FILE__) + '/../lib') require 'cucumber/rake/task' require 'cucumber/platform' -Cucumber::Rake::Task.new(:features) +Cucumber::Rake::Task.new(:features) do |t| + t.fork = false +end Cucumber::Rake::Task.new(:legacy_features) do |t| + t.fork = false t.cucumber_opts = %w{legacy_features} if(Cucumber::JRUBY) t.profile = Cucumber::WINDOWS ? 'jruby_win' : 'jruby' diff --git a/gem_tasks/downloads.rb b/gem_tasks/downloads.rb new file mode 100644 index 0000000000..0ad9b1573b --- /dev/null +++ b/gem_tasks/downloads.rb @@ -0,0 +1,7 @@ +require 'json' +require 'httparty' + +IO.read(File.dirname(__FILE__) + '/versions.txt').each_line do |version| + json = HTTParty.get("http://rubygems.org/api/v1/downloads/cucumber-#{version.strip}.json") + puts JSON.parse(json.body)['version_downloads'] +end \ No newline at end of file diff --git a/gem_tasks/sdoc.rake b/gem_tasks/sdoc.rake deleted file mode 100644 index c3603d24e6..0000000000 --- a/gem_tasks/sdoc.rake +++ /dev/null @@ -1,12 +0,0 @@ -begin - require 'rake/rdoctask' - require 'sdoc' # and use your RDoc task the same way you used it before - - Rake::RDocTask.new(:sdoc) do |rdoc| - rdoc.rdoc_dir = 'doc/sdoc' - rdoc.title = "Cucumber" - rdoc.options += %w{--fmt shtml -N --webcvs=http://github.com/aslakhellesoy/cucumber/blob/v0.3.96/%s --title "Cucumber API" --threads 4 --main README --exclude cucumber/parser lib} - rdoc.template = 'direct' # lighter template used on railsapi.com - end -rescue LoadError => ignore -end diff --git a/gem_tasks/stats b/gem_tasks/stats new file mode 100755 index 0000000000..f5cc95db28 --- /dev/null +++ b/gem_tasks/stats @@ -0,0 +1,14 @@ +echo 'Commits' +git log --pretty=format:'' | wc -l + +echo 'Contributors' +git log --pretty=short --no-merges | git shortlog -ne | egrep -ve '^ +' | egrep -ve '^$' | wc -l + +echo 'Resolved bugs/feature requests' +egrep -e '^\*' History.md | wc -l + +echo 'Open tickets' +curl -s http://github.com/api/v2/json/issues/list/cucumber/cucumber/open | ruby -e "require 'json'; puts JSON.parse(STDIN.read)['issues'].length" + +echo 'Group members' +curl -s http://groups.google.com/group/cukes | grep Members \ No newline at end of file diff --git a/gem_tasks/versions.txt b/gem_tasks/versions.txt new file mode 100644 index 0000000000..84fc9621e8 --- /dev/null +++ b/gem_tasks/versions.txt @@ -0,0 +1,74 @@ +0.10.2 +0.10.1 +0.10.0 +0.9.4 +0.9.3 +0.9.2 +0.9.1 +0.9.0 +0.8.5 +0.8.4 +0.8.3 +0.8.2 +0.8.1 +0.8.0 +0.7.3 +0.7.2 +0.7.1 +0.7.0 +0.6.4 +0.6.3 +0.6.2 +0.6.1 +0.6.0 +0.5.3 +0.5.2 +0.5.1 +0.5.0 +0.4.4 +0.4.3 +0.4.2 +0.4.1 +0.4.0 +0.3.104 +0.3.103 +0.3.102 +0.3.101 +0.3.100 +0.3.99 +0.3.98 +0.3.97 +0.3.96 +0.3.95 +0.3.94 +0.3.93 +0.3.92 +0.3.91 +0.3.90 +0.3.11 +0.3.10 +0.3.9 +0.3.8 +0.3.7 +0.3.6 +0.3.5 +0.3.4 +0.3.3 +0.3.2 +0.3.1 +0.3.0 +0.2.3 +0.2.2 +0.2.1 +0.2.0 +0.1.16 +0.1.15 +0.1.14 +0.1.13 +0.1.12 +0.1.11 +0.1.10 +0.1.9 +0.1.8 +0.1.7 +0.1.6 \ No newline at end of file diff --git a/gem_tasks/yard.rake b/gem_tasks/yard.rake new file mode 100644 index 0000000000..dee83c47cc --- /dev/null +++ b/gem_tasks/yard.rake @@ -0,0 +1,18 @@ +require 'yard' +require 'yard/rake/yardoc_task' +require 'cucumber/platform' + +YARD::Templates::Engine.register_template_path(File.expand_path(File.join(File.dirname(__FILE__), 'yard'))) +YARD::Rake::YardocTask.new(:yard) do |t| + t.options = %w{--no-private --title Cucumber} + t.files = %w{lib - README.md History.md LICENSE} +end + +desc "Push yardoc to http://cukes.info/cucumber/api/#{Cucumber::VERSION}" +task :push_yard => :yard do + sh("tar czf api-#{Cucumber::VERSION}.tgz -C doc .") + sh("scp api-#{Cucumber::VERSION}.tgz cukes.info:/var/www/cucumber/api/ruby") + sh("ssh cukes.info 'cd /var/www/cucumber/api/ruby && rm -rf #{Cucumber::VERSION} && mkdir #{Cucumber::VERSION} && tar xzf api-#{Cucumber::VERSION}.tgz -C #{Cucumber::VERSION} && rm -f latest && ln -s #{Cucumber::VERSION} latest'") +end + +#task :release => :push_yard diff --git a/gem_tasks/yard/default/layout/html/bubble_32x32.png b/gem_tasks/yard/default/layout/html/bubble_32x32.png new file mode 100644 index 0000000000..580b07818d Binary files /dev/null and b/gem_tasks/yard/default/layout/html/bubble_32x32.png differ diff --git a/gem_tasks/yard/default/layout/html/footer.erb b/gem_tasks/yard/default/layout/html/footer.erb new file mode 100644 index 0000000000..3eca7c96a8 --- /dev/null +++ b/gem_tasks/yard/default/layout/html/footer.erb @@ -0,0 +1,5 @@ + diff --git a/gem_tasks/yard/default/layout/html/index.erb b/gem_tasks/yard/default/layout/html/index.erb new file mode 100644 index 0000000000..f2356c3dab --- /dev/null +++ b/gem_tasks/yard/default/layout/html/index.erb @@ -0,0 +1 @@ +<%= yieldall %> diff --git a/gem_tasks/yard/default/layout/html/layout.erb b/gem_tasks/yard/default/layout/html/layout.erb new file mode 100644 index 0000000000..c055ea18fa --- /dev/null +++ b/gem_tasks/yard/default/layout/html/layout.erb @@ -0,0 +1,25 @@ + + + + <%= erb(:headers) %> + + + + + + + + +
    <%= yieldall %>
    + + <%= erb(:footer) %> + + \ No newline at end of file diff --git a/gem_tasks/yard/default/layout/html/logo.erb b/gem_tasks/yard/default/layout/html/logo.erb new file mode 100644 index 0000000000..a4be272e32 --- /dev/null +++ b/gem_tasks/yard/default/layout/html/logo.erb @@ -0,0 +1 @@ +

    Cucumber <%= Cucumber::VERSION %>

    \ No newline at end of file diff --git a/gem_tasks/yard/default/layout/html/setup.rb b/gem_tasks/yard/default/layout/html/setup.rb new file mode 100644 index 0000000000..3f3019ffad --- /dev/null +++ b/gem_tasks/yard/default/layout/html/setup.rb @@ -0,0 +1,4 @@ +def init + super + options[:serializer].serialize('/images/bubble_32x32.png', IO.read(File.dirname(__FILE__) + '/bubble_32x32.png')) +end diff --git a/legacy_features/announce.feature b/legacy_features/announce.feature index f1c2a08f73..515ed1189e 100644 --- a/legacy_features/announce.feature +++ b/legacy_features/announce.feature @@ -1,34 +1,34 @@ -Feature: Delayed announcement +Feature: Delayed message Background: Given a standard Cucumber project directory structure And a file named "features/step_definitions/steps.rb" with: """ - Given /^I use announce with text "(.*)"$/ do |ann| x=1 - announce(ann) + Given /^I use puts with text "(.*)"$/ do |ann| x=1 + puts(ann) end - Given /^I use multiple announces$/ do x=1 - announce("Multiple") - announce(["Announce","Me"]) + Given /^I use multiple putss$/ do x=1 + puts("Multiple") + puts("Announce","Me") end - Given /^I use announcement (.+) in line (.+) (?:with result (.+))$/ do |ann, line, result| x=1 - announce("Last announcement") if line == "3" - announce("Line: #{line}: #{ann}") + Given /^I use message (.+) in line (.+) (?:with result (.+))$/ do |ann, line, result| x=1 + puts("Last message") if line == "3" + puts("Line: #{line}: #{ann}") fail if result =~ /fail/i end - Given /^I use announce and step fails$/ do x=1 - announce("Announce with fail") + Given /^I use puts and step fails$/ do x=1 + puts("Announce with fail") fail end Given /^this step works$/ do x=1 end - Given /^I announce the world$/ do x=1 - announce_world + Given /^I puts the world$/ do x=1 + puts(self) end """ And a file named "features/f.feature" with: @@ -36,15 +36,15 @@ Feature: Delayed announcement Feature: F Scenario: S - Given I use announce with text "Ann" + Given I use puts with text "Ann" And this step works Scenario: S2 - Given I use multiple announces + Given I use multiple putss And this step works Scenario Outline: S3 - Given I use announcement in line + Given I use message in line Examples: | line | ann | @@ -53,11 +53,11 @@ Feature: Delayed announcement | 3 | anno3 | Scenario: S4 - Given I use announce and step fails + Given I use puts and step fails And this step works Scenario Outline: s5 - Given I use announcement in line with result + Given I use message in line with result Examples: | line | ann | result | @@ -65,34 +65,34 @@ Feature: Delayed announcement | 2 | anno2 | pass | """ - And a file named "features/announce_world.feature" with: + And a file named "features/puts_world.feature" with: """ - Feature: announce_world - Scenario: announce_world - Given I announce the world + Feature: puts_world + Scenario: puts_world + Given I puts the world """ - Scenario: Delayed announcements feature + Scenario: Delayed messages feature When I run cucumber --format pretty features/f.feature Then STDERR should be empty And the output should contain """ Feature: F - Scenario: S # features/f.feature:3 - Given I use announce with text "Ann" # features/step_definitions/steps.rb:1 + Scenario: S # features/f.feature:3 + Given I use puts with text "Ann" # features/step_definitions/steps.rb:1 Ann - And this step works # features/step_definitions/steps.rb:21 + And this step works # features/step_definitions/steps.rb:21 - Scenario: S2 # features/f.feature:7 - Given I use multiple announces # features/step_definitions/steps.rb:5 + Scenario: S2 # features/f.feature:7 + Given I use multiple putss # features/step_definitions/steps.rb:5 Multiple Announce Me - And this step works # features/step_definitions/steps.rb:21 + And this step works # features/step_definitions/steps.rb:21 - Scenario Outline: S3 # features/f.feature:11 - Given I use announcement in line # features/f.feature:12 + Scenario Outline: S3 # features/f.feature:11 + Given I use message in line # features/f.feature:12 Examples: | line | ann | @@ -100,27 +100,27 @@ Feature: Delayed announcement | 2 | anno2 | | 3 | anno3 | - Scenario: S4 # features/f.feature:20 - Given I use announce and step fails # features/step_definitions/steps.rb:16 + Scenario: S4 # features/f.feature:20 + Given I use puts and step fails # features/step_definitions/steps.rb:16 Announce with fail (RuntimeError) - ./features/step_definitions/steps.rb:18:in `/^I use announce and step fails$/' - features/f.feature:21:in `Given I use announce and step fails' - And this step works # features/step_definitions/steps.rb:21 + ./features/step_definitions/steps.rb:18:in `/^I use puts and step fails$/' + features/f.feature:21:in `Given I use puts and step fails' + And this step works # features/step_definitions/steps.rb:21 - Scenario Outline: s5 # features/f.feature:24 - Given I use announcement in line with result # features/step_definitions/steps.rb:10 + Scenario Outline: s5 # features/f.feature:24 + Given I use message in line with result # features/step_definitions/steps.rb:10 Examples: | line | ann | result | | 1 | anno1 | fail | Line: 1: anno1 (RuntimeError) - ./features/step_definitions/steps.rb:13:in `/^I use announcement (.+) in line (.+) (?:with result (.+))$/' - features/f.feature:25:in `Given I use announcement in line with result ' + ./features/step_definitions/steps.rb:13:in `/^I use message (.+) in line (.+) (?:with result (.+))$/' + features/f.feature:25:in `Given I use message in line with result ' | 2 | anno2 | pass | Line: 2: anno2 """ - Scenario: Non-delayed announcements feature (progress formatter) + Scenario: Non-delayed messages feature (progress formatter) When I run cucumber --format progress features/f.feature Then the output should contain """ @@ -140,25 +140,13 @@ Feature: Delayed announcement """ @rspec2 - Scenario: announce world - When I run cucumber --format progress features/announce_world.feature - Then the output should contain - """ - WORLD: - Object - - RSpec::Matchers - Cucumber::RbSupport::RbWorld - """ + Scenario: puts world + When I run cucumber --format progress features/puts_world.feature + Then the output should contain "RSpec::Matchers" + And the output should contain "Cucumber::RbSupport::RbWorld" @rspec1 - Scenario: announce world - When I run cucumber --format progress features/announce_world.feature - Then the output should contain - """ - WORLD: - Object - - Spec::Matchers - Cucumber::RbSupport::RbWorld - """ + Scenario: puts world + When I run cucumber --format progress features/puts_world.feature + Then the output should contain "Spec::Matchers" + And the output should contain "Cucumber::RbSupport::RbWorld" diff --git a/legacy_features/bug_371.feature b/legacy_features/bug_371.feature index f35d55d934..dc8a132186 100644 --- a/legacy_features/bug_371.feature +++ b/legacy_features/bug_371.feature @@ -22,9 +22,9 @@ Feature: https://rspec.lighthouseapp.com/projects/16211/tickets/371 Feature: F Scenario: S - B - G Given G + B + G 1 scenario (1 passed) 1 step (1 passed) diff --git a/legacy_features/bug_600.feature b/legacy_features/bug_600.feature index 8d798c2804..ce3e87ed49 100644 --- a/legacy_features/bug_600.feature +++ b/legacy_features/bug_600.feature @@ -52,14 +52,20 @@ Feature: http://rspec.lighthouseapp.com/projects/16211/tickets/600-inconsistent- When I run cucumber -f progress features/t.feature Then it should pass with """ + Before scenario + Within background - .--After scenario + .-- + After scenario + Before scenario + Within background - .After scenario - - + . + After scenario + + 2 scenarios (2 passed) 3 steps (3 passed) diff --git a/legacy_features/call_steps_from_stepdefs.feature b/legacy_features/call_steps_from_stepdefs.feature index df93267188..b096d3d6b4 100644 --- a/legacy_features/call_steps_from_stepdefs.feature +++ b/legacy_features/call_steps_from_stepdefs.feature @@ -46,7 +46,7 @@ Feature: http://gist.github.com/221223 end Given /^I use keyword to call a multiline string with (.*)$/ do |s| x=1 - Given 'a multiline string:', "Hello\n#{s}" + step 'a multiline string:', "Hello\n#{s}" end Given /^I call a table with (.*)$/ do |s| x=1 diff --git a/legacy_features/cucumber_cli.feature b/legacy_features/cucumber_cli.feature index c4a1318b38..9cc47d96c1 100644 --- a/legacy_features/cucumber_cli.feature +++ b/legacy_features/cucumber_cli.feature @@ -82,7 +82,7 @@ Feature: Cucumber command line features/sample.feature:18:in `Given failing' Failing Scenarios: - cucumber features/sample.feature:17 # Scenario: Failing + cucumber features/sample.feature:17 2 scenarios (1 failed, 1 undefined) 2 steps (1 failed, 1 undefined) @@ -160,7 +160,7 @@ Feature: Cucumber command line features/sample.feature:18:in `Given failing' Failing Scenarios: - cucumber features/sample.feature:17 # Scenario: Failing + cucumber features/sample.feature:17 3 scenarios (1 failed, 1 undefined, 1 passed) 3 steps (1 failed, 1 undefined, 1 passed) @@ -323,7 +323,7 @@ Feature: Cucumber command line Scenario: pystring Given a pystring \"\"\" - example + example with entities \"\"\" Scenario: table @@ -464,7 +464,7 @@ Feature: Cucumber command line features/sample.feature:18:in `Given failing' Failing Scenarios: - cucumber features/sample.feature:17 # Scenario: Failing + cucumber features/sample.feature:17 3 scenarios (1 failed, 1 undefined, 1 passed) 3 steps (1 failed, 1 undefined, 1 passed) @@ -551,13 +551,6 @@ Feature: Cucumber command line """ - # Fails on 1.9 because of encoding issues. - @fails_on_1_9 - Scenario: Generate PDF with pdf formatter - When I run cucumber --format pdf --out tmp/sample.pdf --dry-run features/sample.feature - Then STDERR should be empty - Then "fixtures/self_test/tmp/sample.pdf" should match "Pages 2" - Scenario: Run feature elements which match a name using -n When I run cucumber -n Pisang -q features/ Then STDERR should be empty diff --git a/legacy_features/cucumber_cli_outlines.feature b/legacy_features/cucumber_cli_outlines.feature index c91b405922..3f33016c23 100644 --- a/legacy_features/cucumber_cli_outlines.feature +++ b/legacy_features/cucumber_cli_outlines.feature @@ -27,7 +27,7 @@ Feature: Cucumber command line | passing | passing | Failing Scenarios: - cucumber features/outline_sample.feature:5 # Scenario: Test state + cucumber features/outline_sample.feature:5 4 scenarios (1 failed, 1 undefined, 2 passed) 8 steps (1 failed, 2 skipped, 1 undefined, 4 passed) @@ -59,7 +59,7 @@ Feature: Cucumber command line | passing | passing | Failing Scenarios: - cucumber features/outline_sample.feature:5 # Scenario: Test state + cucumber features/outline_sample.feature:5 4 scenarios (1 failed, 1 undefined, 2 passed) 8 steps (1 failed, 2 skipped, 1 undefined, 4 passed) @@ -108,7 +108,7 @@ Feature: Cucumber command line features/outline_sample.feature:6:in `Given without a table' Failing Scenarios: - cucumber features/outline_sample.feature:5 # Scenario: Test state + cucumber features/outline_sample.feature:5 5 scenarios (1 failed, 1 undefined, 3 passed) 8 steps (1 failed, 2 skipped, 1 undefined, 4 passed) diff --git a/legacy_features/default_snippets.feature b/legacy_features/default_snippets.feature index 1ed8fc6654..c40027f058 100644 --- a/legacy_features/default_snippets.feature +++ b/legacy_features/default_snippets.feature @@ -34,8 +34,9 @@ Feature: Print snippets pending # express the regexp above with the code you wish you had end - If you want snippets in a different programming language, just make sure a file - with the appropriate file extension exists where cucumber looks for step definitions. + If you want snippets in a different programming language, + just make sure a file with the appropriate file extension + exists where cucumber looks for step definitions. """ diff --git a/legacy_features/diffing.feature b/legacy_features/diffing.feature index da2d96c83d..9c1ce06539 100644 --- a/legacy_features/diffing.feature +++ b/legacy_features/diffing.feature @@ -17,7 +17,7 @@ Feature: Cucumber command line features/failing_expectation.feature:4:in `Given failing expectation' Failing Scenarios: - cucumber features/failing_expectation.feature:3 # Scenario: Failing expectation + cucumber features/failing_expectation.feature:3 1 scenario (1 failed) 1 step (1 failed) diff --git a/legacy_features/html_formatter/a.html b/legacy_features/html_formatter/a.html index 2b2af52669..f53edffe48 100644 --- a/legacy_features/html_formatter/a.html +++ b/legacy_features/html_formatter/a.html @@ -133,7 +133,7 @@ background: #fcfb98; color: #131313; } -.cucumber table td.announcement, td table td.announcement, th table td.announcement { +.cucumber table td.message, td table td.message, th table td.message { border-left: 5px solid aqua; border-bottom: 1px solid aqua; background: #e0ffff; @@ -185,7 +185,7 @@ background: #fcfb98; color: #131313; } -.cucumber ol li.announcement, td ol li.announcement, th ol li.announcement { +.cucumber ol li.message, td ol li.message, th ol li.message { border-left: 5px solid aqua; border-bottom: 1px solid aqua; background: #e0ffff; @@ -469,18 +469,21 @@ 19Given /^a step definition that calls an undefined step$/ do Given 'this does not exist' 20end
    Given /^$/ do
       pending # express the regexp above with the code you wish you had
    -end
    features/call_undefined_step_from_step_def.feature:6

    Scenario: Call via another

    1. Given call step "a step definition that calls an undefined step"
      features/step_definitions/sample_steps.rb:23
      Undefined step: "this does not exist"
      ./features/step_definitions/sample_steps.rb:19:in `/^a step definition that calls an undefined step$/'
      +end
    Screenshot
      +
    features/call_undefined_step_from_step_def.feature:6

    Scenario: Call via another

    1. Given call step "a step definition that calls an undefined step"
      features/step_definitions/sample_steps.rb:23
      Undefined step: "this does not exist"
      ./features/step_definitions/sample_steps.rb:19:in `/^a step definition that calls an undefined step$/'
       features/call_undefined_step_from_step_def.feature:7:in `Given call step "a step definition that calls an undefined step"'
      17end
       18
       19Given /^a step definition that calls an undefined step$/ do Given 'this does not exist'
       20end
      Given /^$/ do
         pending # express the regexp above with the code you wish you had
      -end

    Feature: Failing expectation

    features/failing_expectation.feature:3

    Scenario: Failing expectation

    1. Given failing expectation
      features/step_definitions/sample_steps.rb:62
      expected: "that"
      +end
    Screenshot
      +

    Feature: Failing expectation

    features/failing_expectation.feature:3

    Scenario: Failing expectation

    1. Given failing expectation
      features/step_definitions/sample_steps.rb:62
      expected: "that"
            got: "this" (using ==)
      ./features/step_definitions/sample_steps.rb:63:in `/^failing expectation$/'
       features/failing_expectation.feature:4:in `Given failing expectation'
      61
       62Given /^failing expectation$/ do x=1
       63  'this'.should == 'that'
      -64end

    Feature: Lots of undefined

    features/lots_of_undefined.feature:3

    Scenario: Implement me

    1. Given it snows in Sahara
      features/lots_of_undefined.feature:4
      Given /^it snows in Sahara$/ do
      +64end
    Screenshot
      +

    Feature: Lots of undefined

    features/lots_of_undefined.feature:3

    Scenario: Implement me

    1. Given it snows in Sahara
      features/lots_of_undefined.feature:4
      Given /^it snows in Sahara$/ do
         pending # express the regexp above with the code you wish you had
       end
    2. Given it's 40 degrees in Norway
      features/lots_of_undefined.feature:5
      Given /^it's (\d+) degrees in Norway$/ do |arg1|
         pending # express the regexp above with the code you wish you had
      @@ -490,45 +493,69 @@
         pending # express the regexp above with the code you wish you had
       end
    3. And there is world peace
      features/lots_of_undefined.feature:8
      When /^there is world peace$/ do
         pending # express the regexp above with the code you wish you had
      -end

    Feature: multiline

    Background I'm a multiline name +end Screenshot
      +

    Feature: multiline

    Background I'm a multiline name which goes on and on and on for three lines yawn

    1. Given passing without a table
      features/step_definitions/sample_steps.rb:12
    features/multiline_name.feature:8

    Scenario: I'm a multiline name which goes on and on and on for three lines - yawn

    1. Given passing without a table
      features/step_definitions/sample_steps.rb:12
    features/multiline_name.feature:13

    Scenario Outline: I'm a multiline name + yawn

    1. Given passing without a table
      features/step_definitions/sample_steps.rb:12
    Screenshot
      +
    features/multiline_name.feature:13

    Scenario Outline: I'm a multiline name which goes on and on and on for three lines - yawn

    1. Given <state> without a table
      features/step_definitions/sample_steps.rb:12

    Examples

    state
    passing
    features/multiline_name.feature:21

    Scenario Outline: name

    1. Given <state> without a table
      features/step_definitions/sample_steps.rb:12

    Examples I'm a multiline name + yawn

    1. Given <state> without a table
      features/step_definitions/sample_steps.rb:12

    Examples

    Screenshot
      +
    state
    passing
    features/multiline_name.feature:21

    Scenario Outline: name

    1. Given <state> without a table
      features/step_definitions/sample_steps.rb:12

    Examples I'm a multiline name which goes on and on and on for three lines - yawn

    state
    passing

    Feature: Outline Sample

    features/outline_sample.feature:3

    Scenario: I have no steps

      features/outline_sample.feature:5

      Scenario Outline: Test state

      1. Given <state> without a table
        features/step_definitions/sample_steps.rb:12
      2. Given <other_state> without a table
        features/step_definitions/sample_steps.rb:12

      Examples Rainbow colours

      state
      other_state
      missing
      passing
      passing
      passing
      failing
      passing
      FAIL
      +        yawnScreenshot
        +
      state
      passing

      Feature: Outline Sample

      features/outline_sample.feature:3

      Scenario: I have no steps

        Screenshot
          +
        features/outline_sample.feature:5

        Scenario Outline: Test state

        1. Given <state> without a table
          features/step_definitions/sample_steps.rb:12
        2. Given <other_state> without a table
          features/step_definitions/sample_steps.rb:12

        Examples Rainbow colours

        Screenshot
          +
        Screenshot
          +
        Screenshot
          +
        state
        other_state
        missing
        passing
        passing
        passing
        failing
        passing
        FAIL
         ./features/step_definitions/sample_steps.rb:2:in `flunker'
         ./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
        -features/outline_sample.feature:6:in `Given  without a table'

        Examples Only passing

        state
        other_state
        passing
        passing
        # Feature comment
        @one

        Feature: Sample

        @two @threefeatures/sample.feature:6

        Scenario: Missing

        1. Given missing
          features/sample.feature:7
          Given /^missing$/ do
          +features/outline_sample.feature:6:in `Given  without a table'

        Examples Only passing

        Screenshot
          +
        state
        other_state
        passing
        passing
        # Feature comment
        @one

        Feature: Sample

        @two @threefeatures/sample.feature:6

        Scenario: Missing

        1. Given missing
          features/sample.feature:7
          Given /^missing$/ do
             pending # express the regexp above with the code you wish you had
          -end
        # Scenario comment
        @threefeatures/sample.feature:11

        Scenario: Passing

        1. Given passing
          features/step_definitions/sample_steps.rb:5
          a
          b
          c
          d
        @fourfeatures/sample.feature:17

        Scenario: Failing

        1. Given failing
          features/step_definitions/sample_steps.rb:8
          hello
          FAIL
          ./features/step_definitions/sample_steps.rb:2:in `flunker'
          +end
        Screenshot
          +
        # Scenario comment
        @threefeatures/sample.feature:11

        Scenario: Passing

        1. Given passing
          features/step_definitions/sample_steps.rb:5
          a
          b
          c
          d
        Screenshot
          +
        @fourfeatures/sample.feature:17

        Scenario: Failing

        1. Given failing
          features/step_definitions/sample_steps.rb:8
          hello
          FAIL
          ./features/step_definitions/sample_steps.rb:2:in `flunker'
           ./features/step_definitions/sample_steps.rb:9:in `/^failing$/'
           features/sample.feature:18:in `Given failing'
          0def flunker
           1  raise "FAIL"
          -2end

        Feature: search examples

        Background Hantu Pisang background match

        1. Given passing without a table
          features/step_definitions/sample_steps.rb:12
        features/search_sample.feature:6

        Scenario: should match Hantu Pisang

        1. Given passing without a table
          features/step_definitions/sample_steps.rb:12
        features/search_sample.feature:9

        Scenario: Ignore me

        1. Given failing without a table
          features/step_definitions/sample_steps.rb:15
          FAIL
          ./features/step_definitions/sample_steps.rb:2:in `flunker'
          +2end
        Screenshot
          +

        Feature: search examples

        Background Hantu Pisang background match

        1. Given passing without a table
          features/step_definitions/sample_steps.rb:12
        features/search_sample.feature:6

        Scenario: should match Hantu Pisang

        1. Given passing without a table
          features/step_definitions/sample_steps.rb:12
        Screenshot
          +
        features/search_sample.feature:9

        Scenario: Ignore me

        1. Given failing without a table
          features/step_definitions/sample_steps.rb:15
          FAIL
          ./features/step_definitions/sample_steps.rb:2:in `flunker'
           ./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
           features/search_sample.feature:10:in `Given failing without a table'
          0def flunker
           1  raise "FAIL"
          -2end
        features/search_sample.feature:12

        Scenario Outline: Ignore me

        1. Given <state> without a table
          features/step_definitions/sample_steps.rb:15

        Examples

        ' if table_row.exception @builder.tr do @builder.td(:colspan => @col_index.to_s, :class => 'failed') do @builder.pre do |pre| - pre << format_exception(table_row.exception) + pre << h(format_exception(table_row.exception)) end end end @@ -333,35 +335,35 @@ def table_cell_value(value, status) @col_index += 1 end - def announce(announcement) - @delayed_announcements << announcement - #@builder.pre(announcement, :class => 'announcement') + def puts(message) + @delayed_messages << message + #@builder.pre(message, :class => 'message') end - def print_announcements - return if @delayed_announcements.empty? + def print_messages + return if @delayed_messages.empty? #@builder.ol do - @delayed_announcements.each do |ann| - @builder.li(:class => 'step announcement') do + @delayed_messages.each do |ann| + @builder.li(:class => 'step message') do @builder << ann end end #end - empty_announcements + empty_messages end - def print_table_row_announcements - return if @delayed_announcements.empty? + def print_table_row_messages + return if @delayed_messages.empty? - @builder.td(:class => 'announcement') do - @builder << @delayed_announcements.join(", ") + @builder.td(:class => 'message') do + @builder << @delayed_messages.join(", ") end - empty_announcements + empty_messages end - def empty_announcements - @delayed_announcements = [] + def empty_messages + @delayed_messages = [] end protected @@ -371,10 +373,16 @@ def build_exception_detail(exception) @builder.div(:class => 'message') do message = exception.message if defined?(RAILS_ROOT) && message.include?('Exception caught') - matches = message.match(/Showing (.+)<\/i>(?:.+)#(\d+)/) - backtrace += ["#{RAILS_ROOT}/#{matches[1]}:#{matches[2]}"] - message = message.match(/([^(\/)]+)<\//m)[1] + matches = message.match(/Showing (.+)<\/i>(?:.+) #(\d+)/) + backtrace += ["#{RAILS_ROOT}/#{matches[1]}:#{matches[2]}"] if matches + matches = message.match(/([^(\/)]+)<\//m) + message = matches ? matches[1] : "" end + + unless exception.instance_of?(RuntimeError) + message = "#{message} (#{exception.class})" + end + @builder.pre do @builder.text!(message) end diff --git a/lib/cucumber/formatter/json.rb b/lib/cucumber/formatter/json.rb index 355829816a..8ac9b721b2 100644 --- a/lib/cucumber/formatter/json.rb +++ b/lib/cucumber/formatter/json.rb @@ -11,17 +11,7 @@ class Json < GherkinFormatterAdapter def initialize(step_mother, io, options) @io = ensure_io(io, "json") - @obj = {'features' => []} - super(Gherkin::Formatter::JSONFormatter.new(nil), false) - end - - def after_feature(feature) - super - @obj['features'] << @gf.gherkin_object - end - - def after_features(features) - @io.write(@obj.to_json) + super(Gherkin::Formatter::JSONFormatter.new(@io), false) end end end diff --git a/lib/cucumber/formatter/junit.rb b/lib/cucumber/formatter/junit.rb index a9ca296d98..b8d82ef6f0 100644 --- a/lib/cucumber/formatter/junit.rb +++ b/lib/cucumber/formatter/junit.rb @@ -21,17 +21,23 @@ def initialize(step_mother, io, options) def before_feature(feature) @current_feature = feature - @failures = @errors = @tests = 0 + @failures = @errors = @tests = @skipped = 0 @builder = OrderedXmlMarkup.new( :indent => 2 ) @time = 0 end + def before_feature_element(feature_element) + @in_examples = Ast::ScenarioOutline === feature_element + @steps_start = Time.now + end + def after_feature(feature) @testsuite = OrderedXmlMarkup.new( :indent => 2 ) @testsuite.instruct! @testsuite.testsuite( :failures => @failures, :errors => @errors, + :skipped => @skipped, :tests => @tests, :time => "%.6f" % @time, :name => @feature_name ) do @@ -56,17 +62,11 @@ def feature_name(keyword, name) end def scenario_name(keyword, name, file_colon_line, source_indent) - # TODO: What's all this ugly weird code doing? Why not just use keyword and name???? - scenario_name = name.strip.delete(".\r\n") - scenario_name = "Unnamed scenario" if name == "" - @scenario = scenario_name - description = "Scenario" - description << " outline" if keyword.include?('Scenario Outline') - @output = "#{description}: #{@scenario}\n\n" + @scenario = (name.nil? || name == "") ? "Unnamed scenario" : name.split("\n")[0] + @output = "#{keyword}: #{@scenario}\n\n" end def before_steps(steps) - @steps_start = Time.now end def after_steps(steps) @@ -96,7 +96,7 @@ def before_table_row(table_row) end def after_table_row(table_row) - return unless @in_examples + return unless @in_examples and Cucumber::Ast::OutlineTable::ExampleRow === table_row duration = Time.now - @table_start unless @header_row name_suffix = " (outline example : #{table_row.name})" @@ -116,20 +116,23 @@ def build_testcase(duration, status, exception = nil, suffix = "") @time += duration classname = "#{@feature_name}.#{@scenario}" name = "#{@scenario}#{suffix}" - failed = (status == :failed || (status == :pending && @options[:strict])) - #puts "FAILED:!!#{failed}" - if status == :passed || failed - @builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do - if failed - @builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do - @builder.cdata! @output - @builder.cdata!(format_exception(exception)) if exception - end - @failures += 1 + pending = [:pending, :undefined].include?(status) + passed = (status == :passed || (pending && !@options[:strict])) + + @builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do + unless passed + @builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do + @builder.cdata! @output + @builder.cdata!(format_exception(exception)) if exception end + @failures += 1 + end + if passed and (status == :skipped || pending) + @builder.skipped + @skipped += 1 end - @tests += 1 end + @tests += 1 end def format_exception(exception) @@ -137,9 +140,11 @@ def format_exception(exception) end def feature_result_filename(feature_file) - ext_length = File.extname(feature_file).length - basename = File.basename(feature_file)[0...-ext_length] - File.join(@reportdir, "TEST-#{basename}.xml") + File.join(@reportdir, "TEST-#{basename(feature_file)}.xml") + end + + def basename(feature_file) + File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature') end def write_file(feature_filename, data) diff --git a/lib/cucumber/formatter/pdf.rb b/lib/cucumber/formatter/pdf.rb deleted file mode 100644 index 3aab408695..0000000000 --- a/lib/cucumber/formatter/pdf.rb +++ /dev/null @@ -1,244 +0,0 @@ -require 'cucumber/formatter/console' -require 'cucumber/formatter/io' -require 'fileutils' - -begin - require 'rubygems' - require 'prawn/core' - require "prawn/layout" -rescue LoadError => e - e.message << "\nYou need the prawn gem. Please do 'gem install prawn'" - raise e -end - -module Cucumber - module Formatter - - BLACK = '000000' - GREY = '999999' - - class Pdf - include FileUtils - include Console - include Io - attr_writer :indent - - def initialize(step_mother, path_or_io, options) - @step_mother = step_mother - @file = ensure_file(path_or_io, "pdf") - - if(options[:dry_run]) - @status_colors = { :passed => BLACK, :skipped => BLACK, :undefined => BLACK, :failed => BLACK, :announced => GREY} - else - @status_colors = { :passed => '055902', :skipped => GREY, :undefined => 'F27405', :failed => '730202', :announced => GREY} - end - - @pdf = Prawn::Document.new - @scrap = Prawn::Document.new - @doc = @scrap - @options = options - @exceptions = [] - @indent = 0 - @buffer = [] - load_cover_page_image - @pdf.text "\n\n\nCucumber features", :align => :center, :size => 32 - @pdf.draw_text "Generated: #{Time.now.strftime("%Y-%m-%d %H:%M")}", :size => 10, :at => [0, 24] - @pdf.draw_text "$ cucumber #{ARGV.join(" ")}", :size => 10, :at => [0,10] - unless options[:dry_run] - @pdf.bounding_box [450,100] , :width => 100 do - @pdf.text 'Legend', :size => 10 - @status_colors.each do |k,v| - @pdf.fill_color v - @pdf.text k.to_s, :size => 10 - @pdf.fill_color BLACK - end - end - end - end - - def load_cover_page_image() - if (!load_image("features/support/logo.png")) - load_image("features/support/logo.jpg") - end - end - - def load_image(image_path) - begin - @pdf.image open(image_path, "rb"), :position => :center, :width => 500 - true - rescue Errno::ENOENT - false - end - end - - def announce(announcement) - @pdf.fill_color(@status_colors[:announced]) - @pdf.text announcement, :size => 10 - @pdf.fill_color BLACK - end - - - def after_features(features) - @pdf.render_file(@file.path) - puts "\ndone" - end - - def feature_name(keyword, name) - @pdf.start_new_page - names = name.split("\n") - @pdf.fill_color GREY - @pdf.text(keyword, :align => :center) - @pdf.fill_color BLACK - names.each_with_index do |nameline, i| - case i - when 0 - @pdf.text(nameline.strip, :size => 30, :align => :center ) - @pdf.text("\n") - else - @pdf.text(nameline.strip, :size => 12) - end - end - @pdf.move_down(30) - end - - def after_feature_element(feature_element) - flush - end - - def after_feature(feature) - flush - end - - def feature_element_name(keyword, name) - names = name.empty? ? [name] : name.split("\n") - print "." - STDOUT.flush - - keep_with do - @doc.move_down(20) - @doc.fill_color GREY - @doc.text("#{keyword}", :size => 8) - @doc.fill_color BLACK - @doc.text("#{names[0]}", :size => 16) - names[1..-1].each { |s| @doc.text(s, :size => 12) } - @doc.text("\n") - end - end - - def step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background) - @hide_this_step = false - if exception - if @exceptions.include?(exception) - @hide_this_step = true - return - end - @exceptions << exception - end - if status != :failed && @in_background ^ background - @hide_this_step = true - return - end - end - - def step_name(keyword, step_match, status, source_indent, background) - return if @hide_this_step - line = "#{keyword} #{step_match.format_args("%s")}" - colorize(line, status) - end - - def before_background(background) - @in_background = true - end - - def after_background(background) - @in_background = nil - end - - def before_multiline_arg(table) - return if @hide_this_step - if(table.kind_of? Cucumber::Ast::Table) - keep_with do - print_table(table, ['ffffff', 'f0f0f0']) - end - end - end - - #using row_color hack to highlight each row correctly - def before_outline_table(table) - return if @hide_this_step - row_colors = table.example_rows.map { |r| @status_colors[r.status] unless r.status == :skipped} - keep_with do - print_table(table, row_colors) - end - end - - def before_py_string(string) - return if @hide_this_step - s = %{"""\n#{string}\n"""}.indent(10) - s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l} - s.each do |line| - keep_with { @doc.text(line, :size => 8) } - end - end - - def tag_name(tag_name) - return if @hide_this_step - tag = format_string(tag_name, :tag).indent(@indent) - # TODO should we render tags at all? skipped for now. difficult to place due to page breaks - end - - def background_name(keyword, name, file_colon_line, source_indent) - feature_element_name(keyword, name) - end - - def examples_name(keyword, name) - feature_element_name(keyword, name) - end - - def scenario_name(keyword, name, file_colon_line, source_indent) - feature_element_name(keyword, name) - end - - private - - def colorize(text, status) - keep_with do - @doc.fill_color(@status_colors[status] || BLACK) - @doc.text(text) - @doc.fill_color(BLACK) - end - end - - def keep_with(&block) - @buffer << block - end - - def render(doc) - @doc = doc - @buffer.each do |proc| - proc.call - end - end - - # This method does a 'test' rendering on a blank page, to see the rendered height of the buffer - # if that too high for the space left on the age in the real document, we do a page break. - # This obviously doesn't work if a scenario is longer than a whole page (God forbid) - def flush - @scrap.start_new_page - oldy = @scrap.y - render @scrap - height = (oldy - @scrap.y) + 36 # whops magic number - if ((@pdf.y - height) < @pdf.bounds.bottom) - @pdf.start_new_page - end - render @pdf - @pdf.move_down(20) - @buffer = [] - end - - def print_table(table, row_colors) - @doc.table(table.rows, :headers => table.headers, :position => :center, :row_colors => row_colors) - end - end - end -end diff --git a/lib/cucumber/formatter/pretty.rb b/lib/cucumber/formatter/pretty.rb index 2d2d4d5c98..23d6983ca7 100644 --- a/lib/cucumber/formatter/pretty.rb +++ b/lib/cucumber/formatter/pretty.rb @@ -25,7 +25,7 @@ def initialize(step_mother, path_or_io, options) @exceptions = [] @indent = 0 @prefixes = options[:prefixes] || {} - @delayed_announcements = [] + @delayed_messages = [] end def after_features(features) @@ -101,7 +101,7 @@ def before_examples_array(examples_array) end def examples_name(keyword, name) - puts unless @visiting_first_example_name + @io.puts unless @visiting_first_example_name @visiting_first_example_name = false names = name.strip.empty? ? [name.strip] : name.split("\n") @io.puts(" #{keyword}: #{names[0]}") @@ -150,10 +150,10 @@ def step_name(keyword, step_match, status, source_indent, background) source_indent = nil unless @options[:source] name_to_report = format_step(keyword, step_match, status, source_indent) @io.puts(name_to_report.indent(@scenario_indent + 2)) - print_announcements + print_messages end - def py_string(string) + def doc_string(string) return if @hide_this_step s = %{"""\n#{string}\n"""}.indent(@indent) s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l}.join("\n") @@ -184,7 +184,7 @@ def before_table_row(table_row) def after_table_row(table_row) return if !@table || @hide_this_step - print_table_row_announcements + print_table_row_messages @io.puts if table_row.exception && !@exceptions.include?(table_row.exception) print_exception(table_row.exception, table_row.status, @indent) @@ -228,7 +228,7 @@ def cell_prefix(status) end def print_summary(features) - print_stats(features, @options.custom_profiles) + print_stats(features, @options) print_snippets(@options) print_passing_wip(@options) end diff --git a/lib/cucumber/formatter/progress.rb b/lib/cucumber/formatter/progress.rb index f46f077c7e..e7df578cf3 100644 --- a/lib/cucumber/formatter/progress.rb +++ b/lib/cucumber/formatter/progress.rb @@ -65,7 +65,7 @@ def exception(*args) def print_summary(features) print_steps(:pending) print_steps(:failed) - print_stats(features, @options.custom_profiles) + print_stats(features, @options) print_snippets(@options) print_passing_wip(@options) end diff --git a/lib/cucumber/formatter/rerun.rb b/lib/cucumber/formatter/rerun.rb index c2de504fb8..92c34195d2 100644 --- a/lib/cucumber/formatter/rerun.rb +++ b/lib/cucumber/formatter/rerun.rb @@ -21,17 +21,23 @@ def initialize(step_mother, path_or_io, options) @file_names = [] @file_colon_lines = Hash.new{|h,k| h[k] = []} end + + def before_feature(feature_element) + @lines = [] + @file = feature_element.file + end + + def after_feature(*) + unless @lines.empty? + after_first_time do + @io.print ' ' + end + @io.print "#{@file}:#{@lines.join(':')}" + @io.flush + end + end - # features() is never executed at all... ? def after_features(features) - files = @file_names.uniq.map do |file| - lines = @file_colon_lines[file] - "#{file}:#{lines.join(':')}" - end - @io.puts files.join(' ') - - # Flusing output to rerun tempfile here... - @io.flush @io.close end @@ -40,16 +46,46 @@ def before_feature_element(feature_element) end def after_feature_element(feature_element) - if @rerun - file, line = *feature_element.file_colon_line.split(':') - @file_colon_lines[file] << line - @file_names << file + if (@rerun || feature_element.failed?) && !(Ast::ScenarioOutline === feature_element) + @lines << feature_element.line end end + def after_table_row(table_row) + return unless @in_examples and Cucumber::Ast::OutlineTable::ExampleRow === table_row + unless @header_row + if table_row.failed? + @rerun = true + @lines << table_row.line + end + end + + @header_row = false if @header_row + end + + def before_examples(*args) + @header_row = true + @in_examples = true + end + + def after_examples(*args) + @in_examples = false + end + + def before_table_row(table_row) + return unless @in_examples + end + def step_name(keyword, step_match, status, source_indent, background) @rerun = true if [:failed, :pending, :undefined].index(status) end + + private + + def after_first_time + yield if @not_first_time + @not_first_time = true + end end end end diff --git a/lib/cucumber/js_support/js_language.rb b/lib/cucumber/js_support/js_language.rb index cddafeafb5..7ebd0c448c 100644 --- a/lib/cucumber/js_support/js_language.rb +++ b/lib/cucumber/js_support/js_language.rb @@ -97,7 +97,7 @@ def val @arg end - def byte_offset + def offset end end diff --git a/lib/cucumber/language_support/language_methods.rb b/lib/cucumber/language_support/language_methods.rb index abbada0388..0bc38e7fa9 100644 --- a/lib/cucumber/language_support/language_methods.rb +++ b/lib/cucumber/language_support/language_methods.rb @@ -4,10 +4,6 @@ module Cucumber module LanguageSupport module LanguageMethods - def create_step_match(step_definition, step_name, name_to_report, step_arguments) - StepMatch.new(step_definition, step_name, name_to_report, step_arguments) - end - def around(scenario) execute_around(scenario) do yield diff --git a/lib/cucumber/parser/gherkin_builder.rb b/lib/cucumber/parser/gherkin_builder.rb index 9833685dfc..ff24fa90e9 100644 --- a/lib/cucumber/parser/gherkin_builder.rb +++ b/lib/cucumber/parser/gherkin_builder.rb @@ -1,5 +1,6 @@ require 'cucumber/ast' require 'gherkin/rubify' +require 'cucumber/ast/multiline_argument' module Cucumber module Parser @@ -17,9 +18,10 @@ def feature(feature) @feature = Ast::Feature.new( nil, Ast::Comment.new(feature.comments.map{|comment| comment.value}.join("\n")), - Ast::Tags.new(nil, feature.tags.map{|tag| tag.name}), + Ast::Tags.new(nil, feature.tags), feature.keyword, - legacy_name_for(feature.name, feature.description), + feature.name.lstrip, + feature.description.rstrip, [] ) @feature.gherkin_statement(feature) @@ -31,7 +33,8 @@ def background(background) Ast::Comment.new(background.comments.map{|comment| comment.value}.join("\n")), background.line, background.keyword, - legacy_name_for(background.name, background.description), + background.name, + background.description, steps=[] ) @feature.background = @background @@ -44,10 +47,11 @@ def scenario(statement) scenario = Ast::Scenario.new( @background, Ast::Comment.new(statement.comments.map{|comment| comment.value}.join("\n")), - Ast::Tags.new(nil, statement.tags.map{|tag| tag.name}), + Ast::Tags.new(nil, statement.tags), statement.line, statement.keyword, - legacy_name_for(statement.name, statement.description), + statement.name, + statement.description, steps=[] ) @feature.add_feature_element(scenario) @@ -60,10 +64,11 @@ def scenario_outline(statement) scenario_outline = Ast::ScenarioOutline.new( @background, Ast::Comment.new(statement.comments.map{|comment| comment.value}.join("\n")), - Ast::Tags.new(nil, statement.tags.map{|tag| tag.name}), + Ast::Tags.new(nil, statement.tags), statement.line, statement.keyword, - legacy_name_for(statement.name, statement.description), + statement.name, + statement.description, steps=[], example_sections=[] ) @@ -81,23 +86,22 @@ def examples(examples) Ast::Comment.new(examples.comments.map{|comment| comment.value}.join("\n")), examples.line, examples.keyword, - legacy_name_for(examples.name, examples.description), + examples.name, + examples.description, matrix(examples.rows) ] @step_container.add_examples(examples_fields, examples) end - def step(step) - @table_owner = Ast::Step.new(step.line, step.keyword, step.name) - @table_owner.gherkin_statement(step) - multiline_arg = rubify(step.multiline_arg) - case(multiline_arg) - when Gherkin::Formatter::Model::PyString - @table_owner.multiline_arg = Ast::PyString.new(multiline_arg.value) - when Array - @table_owner.multiline_arg = Ast::Table.new(matrix(multiline_arg)) - end - @step_container.add_step(@table_owner) + def step(gherkin_step) + step = Ast::Step.new( + gherkin_step.line, + gherkin_step.keyword, + gherkin_step.name, + Ast::MultilineArgument.from(gherkin_step.doc_string || gherkin_step.rows) + ) + step.gherkin_statement(gherkin_step) + @step_container.add_step(step) end def eof @@ -109,12 +113,6 @@ def syntax_error(state, event, legal_events, line) private - def legacy_name_for(name, description) - s = name - s += "\n#{description}" if description != "" - s - end - def matrix(gherkin_table) gherkin_table.map do |gherkin_row| row = gherkin_row.cells diff --git a/lib/cucumber/platform.rb b/lib/cucumber/platform.rb index 5f7a2dc4ad..a143243602 100644 --- a/lib/cucumber/platform.rb +++ b/lib/cucumber/platform.rb @@ -4,7 +4,7 @@ module Cucumber unless defined?(Cucumber::VERSION) - VERSION = '0.10.2' + VERSION = '1.2.0' BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber') LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib') JRUBY = defined?(JRUBY_VERSION) diff --git a/lib/cucumber/py_support/py_language.rb b/lib/cucumber/py_support/py_language.rb index e3406997e1..e238db22c6 100644 --- a/lib/cucumber/py_support/py_language.rb +++ b/lib/cucumber/py_support/py_language.rb @@ -24,10 +24,6 @@ def load_code_file(py_file) def alias_adverbs(adverbs) end - def step_definitions_for(py_file) - mod = import(py_file) - end - def snippet_text(code_keyword, step_name, multiline_arg_class) "python snippet: #{code_keyword}, #{step_name}" end @@ -35,12 +31,12 @@ def snippet_text(code_keyword, step_name, multiline_arg_class) def begin_scenario(scenario) @python_path = [] add_to_python_path(File.dirname(__FILE__)) - @step_def_files.each{|f| add_to_python_path(File.dirname(f))} + @step_def_files.each { |f| add_to_python_path(File.dirname(f)) } RubyPython.start @delegate = import(File.dirname(__FILE__) + '/py_language.py') - @step_def_files.each{|f| import(f)} + @step_def_files.each { |f| import(f) } end def end_scenario @@ -56,7 +52,7 @@ def import(path) modname = File.basename(path)[0...-File.extname(path).length] begin mod = RubyPython.import(modname) - rescue PythonError => e + rescue RubyPython::PythonError => e # e.message << "Couldn't load #{path}\nConsider adding #{File.expand_path(File.dirname(path))} to your PYTHONPATH" raise e end diff --git a/lib/cucumber/rake/task.rb b/lib/cucumber/rake/task.rb index 137ce9e9fa..6596c7f99c 100644 --- a/lib/cucumber/rake/task.rb +++ b/lib/cucumber/rake/task.rb @@ -1,9 +1,8 @@ require 'cucumber/platform' - +require 'gherkin/formatter/ansi_escapes' begin # Support Rake > 0.8.7 require 'rake/dsl_definition' - include Rake::DSL rescue LoadError end @@ -32,7 +31,12 @@ module Rake # # See the attributes for additional configuration possibilities. class Task + include Gherkin::Formatter::AnsiEscapes + include ::Rake::DSL if defined?(::Rake::DSL) + class InProcessCucumberRunner #:nodoc: + include ::Rake::DSL if defined?(::Rake::DSL) + attr_reader :args def initialize(libs, cucumber_opts, feature_files) @@ -52,45 +56,72 @@ def run end class ForkedCucumberRunner #:nodoc: - attr_reader :args - - def initialize(libs, cucumber_bin, cucumber_opts, feature_files) - @args = ( - ['-I'] + load_path(libs) + - quoted_binary(cucumber_bin) + - cucumber_opts + - feature_files - ).flatten + include ::Rake::DSL if defined?(::Rake::DSL) + + def initialize(libs, cucumber_bin, cucumber_opts, bundler, feature_files) + @libs = libs + @cucumber_bin = cucumber_bin + @cucumber_opts = cucumber_opts + @bundler = bundler + @feature_files = feature_files end def load_path(libs) - ['"%s"' % libs.join(File::PATH_SEPARATOR)] + ['"%s"' % @libs.join(File::PATH_SEPARATOR)] end def quoted_binary(cucumber_bin) ['"%s"' % cucumber_bin] end - def runner - File.exist?("./Gemfile") && Gem.available?("bundler") ? ["bundle", "exec", RUBY] : [RUBY] + def use_bundler + @bundler.nil? ? File.exist?("./Gemfile") && gem_available?("bundler") : @bundler + end + + def gem_available?(gemname) + gem_available_new_rubygems?(gemname) || gem_available_old_rubygems?(gemname) + end + + def gem_available_old_rubygems?(gemname) + Gem.available?(gemname) + end + + def gem_available_new_rubygems?(gemname) + Gem::Specification.respond_to?(:find_all_by_name) && Gem::Specification.find_all_by_name(gemname).any? + end + + def cmd + if use_bundler + [ Cucumber::RUBY_BINARY, '-S', 'bundle', 'exec', 'cucumber', @cucumber_opts, + @feature_files ].flatten + else + [ Cucumber::RUBY_BINARY, '-I', load_path(@libs), quoted_binary(@cucumber_bin), + @cucumber_opts, @feature_files ].flatten + end end def run - sh((runner + args).join(" ")) + sh(cmd.join(" ")) end end class RCovCucumberRunner < ForkedCucumberRunner #:nodoc: - def initialize(libs, cucumber_bin, cucumber_opts, feature_files, rcov_opts) - @args = ( - ['-I'] + load_path(libs) + - ['-S', 'rcov'] + rcov_opts + - quoted_binary(cucumber_bin) + - ['--'] + - cucumber_opts + - feature_files - ).flatten + + def initialize(libs, cucumber_bin, cucumber_opts, bundler, feature_files, rcov_opts) + super( libs, cucumber_bin, cucumber_opts, bundler, feature_files ) + @rcov_opts = rcov_opts + end + + def cmd + if use_bundler + [Cucumber::RUBY_BINARY, '-S', 'bundle', 'exec', 'rcov', @rcov_opts, + quoted_binary(@cucumber_bin), '--', @cucumber_opts, @feature_files].flatten + else + [Cucumber::RUBY_BINARY, '-I', load_path(@libs), '-S', 'rcov', @rcov_opts, + quoted_binary(@cucumber_bin), '--', @cucumber_opts, @feature_files].flatten + end end + end LIB = File.expand_path(File.dirname(__FILE__) + '/../..') #:nodoc: @@ -111,6 +142,12 @@ def cucumber_opts=(opts) #:nodoc: # Run cucumber with RCov? Defaults to false. If you set this to # true, +fork+ is implicit. attr_accessor :rcov + def rcov=(flag) + if(flag && Cucumber::RUBY_1_9) + raise failed + "RCov only works on Ruby 1.8.x. You may want to use SimpleCov: https://github.com/colszowka/simplecov" + reset + end + @rcov = flag + end # Extra options to pass to rcov. # It's recommended to pass an Array, but if it's a String it will be #split by ' '. @@ -128,6 +165,13 @@ def rcov_opts=(opts) #:nodoc: # to it. Will be ignored when CUCUMBER_OPTS is used. attr_accessor :profile + # Whether or not to run with bundler (bundle exec). Setting this to false may speed + # up the execution. The default value is true if Bundler is installed and you have + # a Gemfile, false otherwise. + # + # Note that this attribute has no effect if you don't run in forked mode. + attr_accessor :bundler + # Define Cucumber Rake task def initialize(task_name = "cucumber", desc = "Run Cucumber features") @task_name, @desc = task_name, desc @@ -153,9 +197,9 @@ def define_task #:nodoc: def runner(task_args = nil) #:nodoc: cucumber_opts = [(ENV['CUCUMBER_OPTS'] ? ENV['CUCUMBER_OPTS'].split(/\s+/) : nil) || cucumber_opts_with_profile] if(@rcov) - RCovCucumberRunner.new(libs, binary, cucumber_opts, feature_files, rcov_opts) + RCovCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files, rcov_opts) elsif(@fork) - ForkedCucumberRunner.new(libs, binary, cucumber_opts, feature_files) + ForkedCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files) else InProcessCucumberRunner.new(libs, cucumber_opts, feature_files) end diff --git a/lib/cucumber/rb_support/rb_language.rb b/lib/cucumber/rb_support/rb_language.rb index 3762906551..63dbef883d 100644 --- a/lib/cucumber/rb_support/rb_language.rb +++ b/lib/cucumber/rb_support/rb_language.rb @@ -22,7 +22,7 @@ def initialize(first_proc, second_proc) message << first_proc.backtrace_line('World') << "\n" message << second_proc.backtrace_line('World') << "\n\n" message << "Use Ruby modules instead to extend your worlds. See the Cucumber::RbSupport::RbDsl#World RDoc\n" - message << "or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.\n\n" + message << "or http://wiki.github.com/cucumber/cucumber/a-whole-new-world.\n\n" super(message) end end @@ -65,20 +65,6 @@ def enable_rspec_expectations_if_available end end - # Gets called for each file under features (or whatever is overridden - # with --require). - def step_definitions_for(rb_file) # Looks Unused - Delete? - begin - require rb_file # This will cause self.add_step_definition and self.add_hook to be called from RbDsl - step_definitions - rescue LoadError => e - e.message << "\nFailed to load #{code_file}" - raise e - ensure - @step_definitions = nil - end - end - def step_matches(name_to_match, name_to_format) @step_definitions.map do |step_definition| if(arguments = step_definition.arguments_from(name_to_match)) diff --git a/lib/cucumber/rb_support/rb_transform.rb b/lib/cucumber/rb_support/rb_transform.rb index a8e961cb10..d6d4fc26ff 100644 --- a/lib/cucumber/rb_support/rb_transform.rb +++ b/lib/cucumber/rb_support/rb_transform.rb @@ -34,11 +34,14 @@ def invoke(arg) end def to_s - strip_captures(strip_anchors(@regexp.source)) + convert_captures(strip_anchors(@regexp.source)) end private - + def convert_captures(regexp_source) + regexp_source.gsub(/(\()(?!\?:)/,'(?:') + end + def strip_captures(regexp_source) regexp_source. gsub(/(\()/, ''). diff --git a/lib/cucumber/rb_support/rb_world.rb b/lib/cucumber/rb_support/rb_world.rb index ca5c09aac8..b5321a574c 100644 --- a/lib/cucumber/rb_support/rb_world.rb +++ b/lib/cucumber/rb_support/rb_world.rb @@ -1,7 +1,11 @@ +require 'gherkin/formatter/ansi_escapes' + module Cucumber module RbSupport # All steps are run in the context of an object that extends this module. module RbWorld + AnsiEscapes = Gherkin::Formatter::AnsiEscapes + class << self def alias_adverb(adverb) alias_method adverb, :__cucumber_invoke @@ -13,12 +17,16 @@ def Transform(arg) rb = @__cucumber_step_mother.load_programming_language('rb') rb.execute_transforms([arg]).first end - + attr_writer :__cucumber_step_mother, :__natural_language - # Call a step from within a step definition. This method is aliased to - # the same i18n as RbDsl. def __cucumber_invoke(name, multiline_argument=nil) #:nodoc: + STDERR.puts AnsiEscapes.failed + "WARNING: Using 'Given/When/Then' in step definitions is deprecated, use 'step' to call other steps instead:" + caller[0] + AnsiEscapes.reset + @__cucumber_step_mother.invoke(name, multiline_argument) + end + + # Invoke a single step. + def step(name, multiline_argument=nil) @__cucumber_step_mother.invoke(name, multiline_argument) end @@ -32,14 +40,19 @@ def table(text_or_table, file=nil, line_offset=0) @__cucumber_step_mother.table(text_or_table, file, line_offset) end - # See StepMother#py_string - def py_string(string_with_triple_quotes, file=nil, line_offset=0) - @__cucumber_step_mother.py_string(string_with_triple_quotes, file, line_offset) + # See StepMother#doc_string + def doc_string(string_with_triple_quotes, file=nil, line_offset=0) + @__cucumber_step_mother.doc_string(string_with_triple_quotes, file, line_offset) + end + + def announce(*messages) + STDERR.puts AnsiEscapes.failed + "WARNING: #announce is deprecated. Use #puts instead:" + caller[0] + AnsiEscapes.reset + puts(*messages) end - # See StepMother#announce - def announce(announcement) - @__cucumber_step_mother.announce(announcement) + # See StepMother#puts + def puts(*messages) + @__cucumber_step_mother.puts(*messages) end # See StepMother#ask @@ -52,15 +65,6 @@ def embed(file, mime_type, label='Screenshot') @__cucumber_step_mother.embed(file, mime_type, label) end - # Prints out the world class, followed by all included modules. - def announce_world - announce "WORLD:\n #{self.class}" - world = self - (class << self; self; end).instance_eval do - world.announce " #{included_modules.join("\n ")}" - end - end - # Mark the matched step as pending. def pending(message = "TODO") if block_given? @@ -88,7 +92,15 @@ def pending(message = "TODO") # such errors in World we define it to just return a simple String. # def inspect #:nodoc: - sprintf("#<%s:0x%x>", self.class, self.object_id) + modules = [self.class] + (class << self; self; end).instance_eval do + modules += included_modules + end + sprintf("#<%s:0x%x>", modules.join('+'), self.object_id) + end + + def to_s + inspect end end end diff --git a/lib/cucumber/rb_support/regexp_argument_matcher.rb b/lib/cucumber/rb_support/regexp_argument_matcher.rb index da9737d4ee..b1f117362b 100644 --- a/lib/cucumber/rb_support/regexp_argument_matcher.rb +++ b/lib/cucumber/rb_support/regexp_argument_matcher.rb @@ -1,4 +1,4 @@ -require 'cucumber/step_argument' +require 'gherkin/formatter/argument' module Cucumber module RbSupport @@ -9,8 +9,8 @@ def self.arguments_from(regexp, step_name) n = 0 match.captures.map do |val| n += 1 - start = match.offset(n)[0] - StepArgument.new(val, start) + offset = match.offset(n)[0] + Gherkin::Formatter::Argument.new(offset, val) end else nil diff --git a/lib/cucumber/runtime.rb b/lib/cucumber/runtime.rb index e4efd17b48..e47667f725 100644 --- a/lib/cucumber/runtime.rb +++ b/lib/cucumber/runtime.rb @@ -1,3 +1,4 @@ +require 'fileutils' require 'gherkin/rubify' require 'gherkin/i18n' require 'cucumber/configuration' @@ -40,7 +41,7 @@ def run! fire_after_configuration_hook tree_walker = @configuration.build_tree_walker(self) - self.visitor = tree_walker # Ugly circular dependency, but needed to support World#announce + self.visitor = tree_walker # Ugly circular dependency, but needed to support World#puts tree_walker.visit_features(features) end @@ -118,6 +119,43 @@ def unknown_programming_language? @support_code.unknown_programming_language? end + def write_stepdefs_json + if(@configuration.dotcucumber) + stepdefs = [] + @support_code.step_definitions.sort{|a,b| a.to_hash['source'] <=> a.to_hash['source']}.each do |stepdef| + stepdef_hash = stepdef.to_hash + steps = [] + features.each do |feature| + feature.feature_elements.each do |feature_element| + feature_element.raw_steps.each do |step| + args = stepdef.arguments_from(step.name) + if(args) + steps << { + 'name' => step.name, + 'args' => args.map do |arg| + { + 'offset' => arg.offset, + 'val' => arg.val + } + end + } + end + end + end + end + stepdef_hash['file_colon_line'] = stepdef.file_colon_line + stepdef_hash['steps'] = steps.uniq.sort {|a,b| a['name'] <=> b['name']} + stepdefs << stepdef_hash + end + if !File.directory?(@configuration.dotcucumber) + FileUtils.mkdir_p(@configuration.dotcucumber) + end + File.open(File.join(@configuration.dotcucumber, 'stepdefs.json'), 'w') do |io| + io.write(JSON.pretty_generate(stepdefs)) + end + end + end + private def fire_after_configuration_hook #:nodoc @@ -125,11 +163,11 @@ def fire_after_configuration_hook #:nodoc end def features - loader = Runtime::FeaturesLoader.new( + @loader ||= Runtime::FeaturesLoader.new( @configuration.feature_files, @configuration.filters, @configuration.tag_expression) - loader.features + @loader.features end def load_step_definitions diff --git a/lib/cucumber/runtime/for_programming_languages.rb b/lib/cucumber/runtime/for_programming_languages.rb index d8e9aaa02d..3cc5427d65 100644 --- a/lib/cucumber/runtime/for_programming_languages.rb +++ b/lib/cucumber/runtime/for_programming_languages.rb @@ -16,7 +16,7 @@ def initialize(support_code, user_interface) def_delegators :@user_interface, :embed, :ask, - :announce, + :puts, :features_paths, :step_match @@ -59,8 +59,8 @@ def table(text_or_table, file=nil, line_offset=0) # # Is retured as: " hello\nworld" # - def py_string(string_with_triple_quotes, file=nil, line_offset=0) - Ast::PyString.parse(string_with_triple_quotes) + def doc_string(string_with_triple_quotes, file=nil, line_offset=0) + Ast::DocString.parse(string_with_triple_quotes) end end end diff --git a/lib/cucumber/runtime/results.rb b/lib/cucumber/runtime/results.rb index 59076bbaa6..5fb96cc73c 100644 --- a/lib/cucumber/runtime/results.rb +++ b/lib/cucumber/runtime/results.rb @@ -54,11 +54,11 @@ def failure? if @configuration.wip? scenarios(:passed).any? else - scenarios(:failed).any? || + scenarios(:failed).any? || steps(:failed).any? || (@configuration.strict? && (steps(:undefined).any? || steps(:pending).any?)) end end end end -end \ No newline at end of file +end diff --git a/lib/cucumber/runtime/support_code.rb b/lib/cucumber/runtime/support_code.rb index 01673e5cdf..c0571828ca 100644 --- a/lib/cucumber/runtime/support_code.rb +++ b/lib/cucumber/runtime/support_code.rb @@ -1,7 +1,9 @@ require 'cucumber/constantize' +require 'cucumber/ast/multiline_argument' require 'cucumber/runtime/for_programming_languages' module Cucumber + class Runtime class SupportCode @@ -18,15 +20,7 @@ def uri(uri) end def step(step) - cucumber_multiline_arg = case(rubify(step.multiline_arg)) - when Gherkin::Formatter::Model::PyString - step.multiline_arg.value - when Array - Ast::Table.new(step.multiline_arg.map{|row| row.cells}) - else - nil - end - @support_code.invoke(step.name, cucumber_multiline_arg) + @support_code.invoke(step.name, Ast::MultilineArgument.from(step.doc_string || step.rows)) end def eof @@ -58,6 +52,17 @@ def invoke_steps(steps_text, i18n, file_colon_line) parser = Gherkin::Parser::Parser.new(StepInvoker.new(self), true, 'steps') parser.parse(steps_text, file, line.to_i) end + + def invoke(step_name, multiline_argument=nil) + multiline_argument = Cucumber::Ast::MultilineArgument.from(multiline_argument) + # It is very important to leave multiline_argument=nil as a vararg. Cuke4Duke needs it that way. + begin + step_match(step_name).invoke(multiline_argument) + rescue Exception => e + e.nested! if Undefined === e + raise e + end + end # Loads and registers programming language implementation. # Instances are cached, so calling with the same argument @@ -132,16 +137,6 @@ def step_match(step_name, name_to_report=nil) #:nodoc: matches[0] end - def invoke(step_name, multiline_argument=nil) - # It is very important to leave multiline_argument=nil as a vararg. Cuke4Duke needs it that way. - begin - step_match(step_name).invoke(multiline_argument) - rescue Exception => e - e.nested! if Undefined === e - raise e - end - end - private def guess_step_matches? diff --git a/lib/cucumber/runtime/user_interface.rb b/lib/cucumber/runtime/user_interface.rb index e42bd9a8cf..6e11cbc034 100644 --- a/lib/cucumber/runtime/user_interface.rb +++ b/lib/cucumber/runtime/user_interface.rb @@ -5,19 +5,19 @@ class Runtime module UserInterface attr_writer :visitor - - # Output +announcement+ alongside the formatted output. + + # Output +messages+ alongside the formatted output. # This is an alternative to using Kernel#puts - it will display # nicer, and in all outputs (in case you use several formatters) # - def announce(msg) - msg.respond_to?(:join) ? @visitor.announce(msg.join("\n")) : @visitor.announce(msg.to_s) + def puts(*messages) + @visitor.puts(*messages) end # Suspends execution and prompts +question+ to the console (STDOUT). # An operator (manual tester) can then enter a line of text and hit # . The entered text is returned, and both +question+ and - # the result is added to the output using #announce. + # the result is added to the output using #puts. # # If you want a beep to happen (to grab the manual tester's attention), # just prepend ASCII character 7 to the question: @@ -30,7 +30,7 @@ def announce(msg) def ask(question, timeout_seconds) STDOUT.puts(question) STDOUT.flush - announce(question) + puts(question) if(Cucumber::JRUBY) answer = jruby_gets(timeout_seconds) @@ -39,18 +39,19 @@ def ask(question, timeout_seconds) end if(answer) - announce(answer) + puts(answer) answer else raise("Waited for input for #{timeout_seconds} seconds, then timed out.") end end - # Embed +file+ of MIME type +mime_type+ into the output. This may or may - # not be ignored, depending on what kind of formatter(s) are active. + # Embed +src+ of MIME type +mime_type+ into the output. The +src+ argument may + # be a path to a file, or if it's an image it may also be a Base64 encoded image. + # The embedded data may or may not be ignored, depending on what kind of formatter(s) are active. # - def embed(file, mime_type, label) - @visitor.embed(file, mime_type, label) + def embed(src, mime_type, label) + @visitor.embed(src, mime_type, label) end private diff --git a/lib/cucumber/step_argument.rb b/lib/cucumber/step_argument.rb deleted file mode 100644 index c0439b48fc..0000000000 --- a/lib/cucumber/step_argument.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Cucumber - class StepArgument - attr_reader :val, :byte_offset - - def initialize(val, byte_offset) - @val, @byte_offset = val, byte_offset - end - end -end \ No newline at end of file diff --git a/lib/cucumber/step_match.rb b/lib/cucumber/step_match.rb index 56f27eb457..39c863c89d 100644 --- a/lib/cucumber/step_match.rb +++ b/lib/cucumber/step_match.rb @@ -20,7 +20,6 @@ def name end def invoke(multiline_arg) - multiline_arg = Ast::PyString.new(multiline_arg) if String === multiline_arg all_args = args all_args << multiline_arg.to_step_definition_arg if multiline_arg @step_definition.invoke(all_args) @@ -61,7 +60,7 @@ def replace_arguments(string, step_arguments, format, &proc) s = string.dup offset = past_offset = 0 step_arguments.each do |step_argument| - next if step_argument.byte_offset.nil? || step_argument.byte_offset < past_offset + next if step_argument.offset.nil? || step_argument.offset < past_offset replacement = if block_given? proc.call(step_argument.val) @@ -71,9 +70,9 @@ def replace_arguments(string, step_arguments, format, &proc) format % step_argument.val end - s[step_argument.byte_offset + offset, step_argument.val.length] = replacement + s[step_argument.offset + offset, step_argument.val.length] = replacement offset += replacement.unpack('U*').length - step_argument.val.unpack('U*').length - past_offset = step_argument.byte_offset + step_argument.val.length + past_offset = step_argument.offset + step_argument.val.length end s end diff --git a/lib/cucumber/wire_support/wire_protocol.rb b/lib/cucumber/wire_support/wire_protocol.rb index 6ba6382403..8d994b0bbc 100644 --- a/lib/cucumber/wire_support/wire_protocol.rb +++ b/lib/cucumber/wire_support/wire_protocol.rb @@ -1,4 +1,3 @@ -require 'cucumber/step_argument' require 'cucumber/wire_support/wire_protocol/requests' module Cucumber diff --git a/lib/cucumber/wire_support/wire_protocol/requests.rb b/lib/cucumber/wire_support/wire_protocol/requests.rb index bbee92250d..e7fd2b312d 100644 --- a/lib/cucumber/wire_support/wire_protocol/requests.rb +++ b/lib/cucumber/wire_support/wire_protocol/requests.rb @@ -1,4 +1,6 @@ require 'cucumber/wire_support/request_handler' +require 'gherkin/formatter/argument' + module Cucumber module WireSupport module WireProtocol @@ -25,7 +27,7 @@ def handle_success(params) def create_step_match(raw_step_match) step_definition = WireStepDefinition.new(@connection, raw_step_match) step_args = raw_step_match['args'].map do |raw_arg| - StepArgument.new(raw_arg['val'], raw_arg['pos']) + Gherkin::Formatter::Argument.new(raw_arg['pos'], raw_arg['val']) end step_match(step_definition, step_args) end @@ -92,13 +94,13 @@ class DiffOk < RequestHandler end module Tags - def clean_tags(scenario) - scenario.source_tag_names.map { |tag| tag.gsub(/^@/, '') }.sort + def clean_tag_names(scenario) + scenario.source_tags.map { |tag| tag.name.gsub(/^@/, '') }.sort end def request_params(scenario) - return nil unless scenario.source_tag_names.any? - { "tags" => clean_tags(scenario) } + return nil unless scenario.source_tags.any? + { "tags" => clean_tag_names(scenario) } end end diff --git a/spec/cucumber/ast/background_spec.rb b/spec/cucumber/ast/background_spec.rb index b76908d288..9cc6212671 100644 --- a/spec/cucumber/ast/background_spec.rb +++ b/spec/cucumber/ast/background_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/ast' require 'cucumber/rb_support/rb_language' @@ -29,7 +29,8 @@ module Ast comment=Comment.new(''), line=2, keyword="", - name="", + title="", + description="", steps=[ Step.new(7, "Given", "y is 5") ]) @@ -40,7 +41,8 @@ module Ast tags=Tags.new(98,[]), line=99, keyword="", - name="", + title="", + description="", steps=[] ) background.feature = @feature @@ -55,7 +57,8 @@ module Ast comment=Comment.new(''), line=2, keyword="", - name="background name", + title="background name", + description="", steps=[]) lambda{ background.name }.should_not raise_error background.name.should == 'background name' @@ -65,7 +68,8 @@ module Ast comment=Comment.new(''), line=2, keyword="", - name=nil, + title="", + description="", steps=[]) lambda{ background.name }.should_not raise_error end @@ -85,7 +89,8 @@ module Ast comment=Comment.new(''), line=2, keyword="", - name="", + title="", + description="", steps=[ Step.new(7, "Given", "y is 5") ]) diff --git a/spec/cucumber/ast/doc_string_spec.rb b/spec/cucumber/ast/doc_string_spec.rb new file mode 100644 index 0000000000..ef82c94806 --- /dev/null +++ b/spec/cucumber/ast/doc_string_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' +require 'cucumber/ast/doc_string' + +module Cucumber + module Ast + describe DocString do + describe "replacing arguments" do + + before(:each) do + @ps = DocString.new("\n\n", '') + end + + it "should return a new doc_string with arguments replaced with values" do + doc_string_with_replaced_arg = @ps.arguments_replaced({'' => 'Life is elsewhere', '' => '5'}) + + doc_string_with_replaced_arg.to_step_definition_arg.should == "Life is elsewhere\n5\n" + end + + it "should not change the original doc_string" do + doc_string_with_replaced_arg = @ps.arguments_replaced({'' => 'Life is elsewhere'}) + + @ps.to_s.should_not include("Life is elsewhere") + end + + it "should replaced nil with empty string" do + ps = DocString.new("''", '') + doc_string_with_replaced_arg = ps.arguments_replaced({'' => nil}) + + doc_string_with_replaced_arg.to_step_definition_arg.should == "''" + end + + it "should recognise when just a subset of a cell is delimited" do + @ps.should have_text('') + end + + end + + end + end +end \ No newline at end of file diff --git a/spec/cucumber/ast/feature_factory.rb b/spec/cucumber/ast/feature_factory.rb index fcdbf697e8..2f798eef7b 100644 --- a/spec/cucumber/ast/feature_factory.rb +++ b/spec/cucumber/ast/feature_factory.rb @@ -1,5 +1,6 @@ require 'cucumber/ast' require 'cucumber/step_mother' +require 'gherkin/formatter/model' module Cucumber module Ast @@ -24,9 +25,9 @@ def create_feature(dsl) %w{1 22 333}, %w{4444 55555 666666} ]) - py_string = Ast::PyString.new(%{\n I like\nCucumber sandwich\n}) + doc_string = Ast::DocString.new(%{\n I like\nCucumber sandwich\n}, '') - background = Ast::Background.new(Ast::Comment.new(""), 2, "Background:", "", + background = Ast::Background.new(Ast::Comment.new(""), 2, "Background:", "", "", [ Step.new(3, "Given", "a passing step") ] @@ -35,18 +36,19 @@ def create_feature(dsl) f = Ast::Feature.new( background, Ast::Comment.new("# My feature comment\n"), - Ast::Tags.new(6, ['one', 'two']), + Ast::Tags.new(6, [Gherkin::Formatter::Model::Tag.new('one', 6), Gherkin::Formatter::Model::Tag.new('two', 6)]), "Feature", "Pretty printing", + "", [Ast::Scenario.new( background, Ast::Comment.new(" # My scenario comment \n# On two lines \n"), - Ast::Tags.new(8, ['three', 'four']), + Ast::Tags.new(8, [Gherkin::Formatter::Model::Tag.new('three', 8), Gherkin::Formatter::Model::Tag.new('four', 8)]), 9, - "Scenario:", "A Scenario", + "Scenario:", "A Scenario", "", [ Step.new(10, "Given", "a passing step with an inline arg:", table), - Step.new(11, "Given", "a happy step with an inline arg:", py_string), + Step.new(11, "Given", "a happy step with an inline arg:", doc_string), Step.new(12, "Given", "a failing step") ] )] diff --git a/spec/cucumber/ast/feature_spec.rb b/spec/cucumber/ast/feature_spec.rb index 0fe4697639..bdadec85d8 100644 --- a/spec/cucumber/ast/feature_spec.rb +++ b/spec/cucumber/ast/feature_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/ast/feature_factory' module Cucumber @@ -40,7 +40,7 @@ module Ast [:row, -1, [:cell, "4444"], [:cell, "55555"], [:cell, "666666"]]]], [:step_invocation, 11, "Given", "a happy step with an inline arg:", - [:py_string, "\n I like\nCucumber sandwich\n"]], + [:doc_string, "\n I like\nCucumber sandwich\n"]], [:step_invocation, 12, "Given", "a failing step"]]] end diff --git a/spec/cucumber/ast/outline_table_spec.rb b/spec/cucumber/ast/outline_table_spec.rb index 25e60fda94..eacd2c20a5 100644 --- a/spec/cucumber/ast/outline_table_spec.rb +++ b/spec/cucumber/ast/outline_table_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' module Cucumber::Ast describe OutlineTable do diff --git a/spec/cucumber/ast/py_string_spec.rb b/spec/cucumber/ast/py_string_spec.rb deleted file mode 100644 index 4b0653be77..0000000000 --- a/spec/cucumber/ast/py_string_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') -require 'cucumber/ast/py_string' - -module Cucumber - module Ast - describe PyString do - describe "replacing arguments" do - - before(:each) do - @ps = PyString.new("\n\n") - end - - it "should return a new py_string with arguments replaced with values" do - py_string_with_replaced_arg = @ps.arguments_replaced({'' => 'Life is elsewhere', '' => '5'}) - - py_string_with_replaced_arg.to_step_definition_arg.should == "Life is elsewhere\n5\n" - end - - it "should not change the original py_string" do - py_string_with_replaced_arg = @ps.arguments_replaced({'' => 'Life is elsewhere'}) - - @ps.to_s.should_not include("Life is elsewhere") - end - - it "should replaced nil with empty string" do - ps = PyString.new("''") - py_string_with_replaced_arg = ps.arguments_replaced({'' => nil}) - - py_string_with_replaced_arg.to_step_definition_arg.should == "''" - end - - it "should recognise when just a subset of a cell is delimited" do - @ps.should have_text('') - end - - end - - end - end -end \ No newline at end of file diff --git a/spec/cucumber/ast/scenario_outline_spec.rb b/spec/cucumber/ast/scenario_outline_spec.rb index 82c21ee96e..11e272abe4 100644 --- a/spec/cucumber/ast/scenario_outline_spec.rb +++ b/spec/cucumber/ast/scenario_outline_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/step_mother' require 'cucumber/ast' require 'cucumber/core_ext/string' @@ -31,7 +31,7 @@ module Ast Comment.new(""), Tags.new(18, []), 19, - "Scenario:", "My outline", + "Scenario:", "My outline", "", [ Step.new(20, 'Given', 'there are cucumbers'), Step.new(21, 'When', 'I eat cucumbers'), @@ -45,16 +45,16 @@ module Ast 24, 'Examples:', 'First table', + '', [ %w{start eat left}, %w{12 5 7}, %w{20 6 14} ] ], - Gherkin::Formatter::Model::Examples.new(nil, nil, nil, nil, nil, nil) + Gherkin::Formatter::Model::Examples.new(nil, nil, nil, nil, nil, nil, nil, nil) ] ] - ) end diff --git a/spec/cucumber/ast/scenario_spec.rb b/spec/cucumber/ast/scenario_spec.rb deleted file mode 100644 index 2a4df82377..0000000000 --- a/spec/cucumber/ast/scenario_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') -require 'cucumber/step_mother' -require 'cucumber/ast' -require 'cucumber/rb_support/rb_language' - -module Cucumber - module Ast - describe Scenario do - before do - @step_mother = Cucumber::Runtime.new - @step_mother.load_programming_language('rb') - @dsl = Object.new - @dsl.extend(Cucumber::RbSupport::RbDsl) - - $x = $y = nil - @dsl.Given /y is (\d+)/ do |n| - $y = n.to_i - end - @visitor = TreeWalker.new(@step_mother) - end - - it "should skip steps when previous is not passed" do - scenario = Scenario.new( - background=nil, - comment=Comment.new(""), - tags=Tags.new(98, []), - line=99, - keyword="", - name="", - steps=[ - Step.new(7, "Given", "this is missing"), - Step.new(8, "Given", "y is 5") - ] - ) - scenario.feature = mock('feature').as_null_object - @visitor.visit_feature_element(scenario) - - $y.should == nil - end - - end - end -end diff --git a/spec/cucumber/ast/step_spec.rb b/spec/cucumber/ast/step_spec.rb index 1e2698dbd7..64533aeff2 100644 --- a/spec/cucumber/ast/step_spec.rb +++ b/spec/cucumber/ast/step_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/step_mother' require 'cucumber/ast' require 'cucumber/core_ext/string' @@ -48,9 +48,9 @@ module Ast end it "should replace arguments in py string arg" do - py_string = PyString.new('taste_ color_') + doc_string = DocString.new('taste_ color_', '') - step = Step.new(1, 'Given', 'a cucumber', py_string) + step = Step.new(1, 'Given', 'a cucumber', doc_string) invocation_table = Table.new([ %w{color taste}, diff --git a/spec/cucumber/ast/table_spec.rb b/spec/cucumber/ast/table_spec.rb index 547dd4af68..ee8a6068c4 100644 --- a/spec/cucumber/ast/table_spec.rb +++ b/spec/cucumber/ast/table_spec.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/ast/table' module Cucumber @@ -45,36 +45,54 @@ def @table.columns; super; end @table.hashes.first[:one].should == '4444' end - it "should allow mapping columns" do - @table.map_column!('one') { |v| v.to_i } - @table.hashes.first['one'].should == 4444 + it "should return the row values in order" do + @table.rows.first.should == %w{4444 55555 666666} end - it "should allow mapping columns and take a symbol as the column name" do - @table.map_column!(:one) { |v| v.to_i } - @table.hashes.first['one'].should == 4444 - end + describe '#map_column!' do + it "should allow mapping columns" do + @table.map_column!('one') { |v| v.to_i } + @table.hashes.first['one'].should == 4444 + end - it "should allow mapping columns and modify the rows as well" do - @table.map_column!(:one) { |v| v.to_i } - @table.rows.first.should include(4444) - @table.rows.first.should_not include('4444') - end + it "applies the block once to each value" do + headers = ['header'] + rows = ['value'] + table = Table.new [headers, rows] + count = 0 + table.map_column!('header') { |value| count +=1 } + table.rows + count.should eq rows.size + end - it "should pass silently if a mapped column does not exist in non-strict mode" do - lambda { - @table.map_column!('two', false) { |v| v.to_i } - }.should_not raise_error - end + it "should allow mapping columns and take a symbol as the column name" do + @table.map_column!(:one) { |v| v.to_i } + @table.hashes.first['one'].should == 4444 + end - it "should fail if a mapped column does not exist in strict mode" do - lambda { - @table.map_column!('two', true) { |v| v.to_i } - }.should raise_error('The column named "two" does not exist') - end + it "should allow mapping columns and modify the rows as well" do + @table.map_column!(:one) { |v| v.to_i } + @table.rows.first.should include(4444) + @table.rows.first.should_not include('4444') + end - it "should return the table" do - (@table.map_column!(:one) { |v| v.to_i }).should == @table + it "should pass silently if a mapped column does not exist in non-strict mode" do + lambda { + @table.map_column!('two', false) { |v| v.to_i } + @table.hashes + }.should_not raise_error + end + + it "should fail if a mapped column does not exist in strict mode" do + lambda { + @table.map_column!('two', true) { |v| v.to_i } + @table.hashes + }.should raise_error('The column named "two" does not exist') + end + + it "should return the table" do + (@table.map_column!(:one) { |v| v.to_i }).should == @table + end end describe "#match" do @@ -128,6 +146,16 @@ def @table.columns; super; end faulty_table.rows_hash }.should raise_error('The table must have exactly 2 columns') end + + it "should support header and column mapping" do + table = Table.new([ + %w{one 1111}, + %w{two 22222} + ]) + table.map_headers!({ 'two' => 'Two' }) { |header| header.upcase } + table.map_column!('two', false) { |val| val.to_i } + table.rows_hash.should == { 'ONE' => '1111', 'Two' => 22222 } + end end describe '#map_headers' do @@ -374,6 +402,7 @@ def @table.columns; super; end ]) lambda do t1.map_headers!(/uk/ => 'u') + t1.hashes end.should raise_error(%{2 headers matched /uk/: ["Cuke", "Duke"]}) end diff --git a/spec/cucumber/ast/tree_walker_spec.rb b/spec/cucumber/ast/tree_walker_spec.rb index 5167fb1ffc..83b8317cd0 100644 --- a/spec/cucumber/ast/tree_walker_spec.rb +++ b/spec/cucumber/ast/tree_walker_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' module Cucumber::Ast describe TreeWalker do diff --git a/spec/cucumber/broadcaster_spec.rb b/spec/cucumber/broadcaster_spec.rb index 8f4963acf6..0de68b5e54 100644 --- a/spec/cucumber/broadcaster_spec.rb +++ b/spec/cucumber/broadcaster_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'spec_helper' module Cucumber describe Broadcaster do diff --git a/spec/cucumber/cli/configuration_spec.rb b/spec/cucumber/cli/configuration_spec.rb index 51a6ffd7ca..0e6845b8b4 100644 --- a/spec/cucumber/cli/configuration_spec.rb +++ b/spec/cucumber/cli/configuration_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'yaml' module Cucumber diff --git a/spec/cucumber/cli/drb_client_spec.rb b/spec/cucumber/cli/drb_client_spec.rb index 33934351f9..c3d00ffb38 100644 --- a/spec/cucumber/cli/drb_client_spec.rb +++ b/spec/cucumber/cli/drb_client_spec.rb @@ -1,5 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') - +require 'spec_helper' module Cucumber module Cli diff --git a/spec/cucumber/cli/main_spec.rb b/spec/cucumber/cli/main_spec.rb index 88f691270b..2358a5e1a7 100644 --- a/spec/cucumber/cli/main_spec.rb +++ b/spec/cucumber/cli/main_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'yaml' require 'cucumber/parser/gherkin_builder' require 'gherkin/formatter/model' @@ -47,7 +47,7 @@ def do_execute before(:each) do b = Cucumber::Parser::GherkinBuilder.new - @empty_feature = b.feature(Gherkin::Formatter::Model::Feature.new([], [], "Feature", "Foo", "", 99)) + @empty_feature = b.feature(Gherkin::Formatter::Model::Feature.new([], [], "Feature", "Foo", "", 99, "")) end it "should show feature files parsed" do @@ -95,7 +95,7 @@ def do_execute context "--drb" do before(:each) do - @configuration = mock('Configuration', :drb? => true).as_null_object + @configuration = mock('Configuration', :drb? => true, :dotcucumber => false).as_null_object Configuration.stub!(:new).and_return(@configuration) @args = ['features'] diff --git a/spec/cucumber/cli/options_spec.rb b/spec/cucumber/cli/options_spec.rb index b8c5054a9f..8521d321a9 100644 --- a/spec/cucumber/cli/options_spec.rb +++ b/spec/cucumber/cli/options_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'yaml' require 'cucumber/cli/options' diff --git a/spec/cucumber/cli/profile_loader_spec.rb b/spec/cucumber/cli/profile_loader_spec.rb index 1e6788a400..8e4714df43 100644 --- a/spec/cucumber/cli/profile_loader_spec.rb +++ b/spec/cucumber/cli/profile_loader_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'yaml' module Cucumber diff --git a/spec/cucumber/constantize_spec.rb b/spec/cucumber/constantize_spec.rb new file mode 100644 index 0000000000..d04ff0a24e --- /dev/null +++ b/spec/cucumber/constantize_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +module Cucumber + describe Constantize do + include Constantize + + it "loads html formatter" do + clazz = constantize('Cucumber::Formatter::Html') + clazz.name.should == 'Cucumber::Formatter::Html' + end + end +end \ No newline at end of file diff --git a/spec/cucumber/core_ext/proc_spec.rb b/spec/cucumber/core_ext/proc_spec.rb index 7be866a0c3..f5fcb485ed 100644 --- a/spec/cucumber/core_ext/proc_spec.rb +++ b/spec/cucumber/core_ext/proc_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/core_ext/proc' describe Proc do diff --git a/spec/cucumber/formatter/ansicolor_spec.rb b/spec/cucumber/formatter/ansicolor_spec.rb index d481f58e89..570509b3c6 100644 --- a/spec/cucumber/formatter/ansicolor_spec.rb +++ b/spec/cucumber/formatter/ansicolor_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/formatter/ansicolor' module Cucumber diff --git a/spec/cucumber/formatter/duration_spec.rb b/spec/cucumber/formatter/duration_spec.rb index e4914ca883..a9a5cf0b77 100644 --- a/spec/cucumber/formatter/duration_spec.rb +++ b/spec/cucumber/formatter/duration_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/formatter/duration' module Cucumber diff --git a/spec/cucumber/formatter/html_spec.rb b/spec/cucumber/formatter/html_spec.rb index edf46a9612..9469697e66 100644 --- a/spec/cucumber/formatter/html_spec.rb +++ b/spec/cucumber/formatter/html_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') -require File.expand_path(File.dirname(__FILE__) + '/spec_helper') +require 'spec_helper' +require 'cucumber/formatter/spec_helper' require 'cucumber/formatter/html' require 'nokogiri' require 'cucumber/rb_support/rb_language' @@ -193,7 +193,7 @@ module Formatter describe "with a step that fails in the scenario" do define_steps do - Given(/boo/) { raise 'eek' } + Given(/boo/) { raise StandardError, 'eek'.freeze } end define_feature(<<-FEATURE) @@ -202,8 +202,9 @@ module Formatter Scenario: Monkey gets a fright Given boo FEATURE - - it { @doc.should have_css_node('.feature .scenario .step.failed', /eek/) } + + it { @doc.should have_css_node('.feature .scenario .step.failed .message', /eek/) } + it { @doc.should have_css_node('.feature .scenario .step.failed .message', /StandardError/) } end describe "with a step that fails in the backgound" do diff --git a/spec/cucumber/formatter/junit_spec.rb b/spec/cucumber/formatter/junit_spec.rb index d621a9afd3..9b58fccd91 100644 --- a/spec/cucumber/formatter/junit_spec.rb +++ b/spec/cucumber/formatter/junit_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') -require File.expand_path(File.dirname(__FILE__) + '/spec_helper') +require 'spec_helper' +require 'cucumber/formatter/spec_helper' require 'cucumber/formatter/junit' require 'nokogiri' @@ -51,6 +51,19 @@ def write_file(feature_filename, data) it { @doc.to_s.should =~ /One passing scenario, one failing scenario/ } end + + describe "with a scenario in a subdirectory" do + define_feature %{ + Feature: One passing scenario, one failing scenario + + Scenario: Passing + Given a passing scenario + }, File.join('features', 'some', 'path', 'spec.feature') + + it 'writes the filename including the subdirectory' do + @formatter.written_files.keys.first.should == File.join('', 'TEST-features-some-path-spec.xml') + end + end describe "with a scenario outline table" do define_steps do @@ -81,6 +94,7 @@ def write_file(feature_filename, data) it { @doc.to_s.should =~ /Big Mac/ } it { @doc.to_s.should_not =~ /Things/ } it { @doc.to_s.should_not =~ /Good|Evil/ } + it { @doc.to_s.should_not =~ /type="skipped"/} end describe "with a regular data table scenario" do diff --git a/spec/cucumber/formatter/progress_spec.rb b/spec/cucumber/formatter/progress_spec.rb index 2c55ff88d7..4e49e471c7 100644 --- a/spec/cucumber/formatter/progress_spec.rb +++ b/spec/cucumber/formatter/progress_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/formatter/progress' module Cucumber diff --git a/spec/cucumber/formatter/spec_helper.rb b/spec/cucumber/formatter/spec_helper.rb index a72196a388..aa9c4a0612 100644 --- a/spec/cucumber/formatter/spec_helper.rb +++ b/spec/cucumber/formatter/spec_helper.rb @@ -2,10 +2,11 @@ module Cucumber module Formatter module SpecHelperDsl - attr_reader :feature_content, :step_defs + attr_reader :feature_content, :step_defs, :feature_filename - def define_feature(string) + def define_feature(string, feature_file = 'spec.feature') @feature_content = string + @feature_filename = feature_file end def define_steps(&block) @@ -25,7 +26,7 @@ def step_mother end def load_features(content) - feature_file = FeatureFile.new('spec.feature', content) + feature_file = FeatureFile.new(self.class.feature_filename, content) features = Ast::Features.new filters = [] feature = feature_file.parse(filters, {}) diff --git a/spec/cucumber/rake/forked_spec.rb b/spec/cucumber/rake/forked_spec.rb new file mode 100644 index 0000000000..86ff45e685 --- /dev/null +++ b/spec/cucumber/rake/forked_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' +require 'cucumber/rake/task' +require 'rake' + +module Cucumber + module Rake + + describe Task::ForkedCucumberRunner do + + let(:libs) { ['lib'] } + let(:binary) { Cucumber::BINARY } + let(:cucumber_opts) { ['--cuke-option'] } + let(:feature_files) { ['./some.feature'] } + + context "when running with bundler" do + + let(:bundler) { true } + + subject { Task::ForkedCucumberRunner.new( + libs, binary, cucumber_opts, bundler, feature_files) } + + it "does use bundler if bundler is set to true" do + subject.use_bundler.should be_true + end + + it "uses bundle exec to find cucumber and libraries" do + subject.cmd.should == [Cucumber::RUBY_BINARY, + '-S', + 'bundle', + 'exec', + 'cucumber', + '--cuke-option'] + feature_files + end + + end + + context "when running without bundler" do + + let(:bundler) { false } + + subject { Task::ForkedCucumberRunner.new( + libs, binary, cucumber_opts, bundler, feature_files) } + + it "does not use bundler if bundler is set to false" do + subject.use_bundler.should be_false + end + + it "uses well known cucumber location and specified libraries" do + subject.cmd.should == [Cucumber::RUBY_BINARY, + "-I", + "\"lib\"", + "\"#{Cucumber::BINARY }\"", + "--cuke-option"] + feature_files + end + + end + + + end + + end +end \ No newline at end of file diff --git a/spec/cucumber/rake/rcov_spec.rb b/spec/cucumber/rake/rcov_spec.rb new file mode 100644 index 0000000000..819cb714e9 --- /dev/null +++ b/spec/cucumber/rake/rcov_spec.rb @@ -0,0 +1,71 @@ +require 'spec_helper' +require 'cucumber/rake/task' +require 'rake' + +module Cucumber + module Rake + + describe Task::RCovCucumberRunner do + + let(:libs) { ['lib'] } + let(:binary) { Cucumber::BINARY } + let(:cucumber_opts) { ['--cuke-option'] } + let(:feature_files) { [] } + let(:rcov_opts) { ['--rcov-option'] } + + + context "when running with bundler" do + + let(:bundler) { true } + + subject { Task::RCovCucumberRunner.new( + libs, binary, cucumber_opts, bundler, feature_files, rcov_opts) } + + it "does use bundler if bundler is set to true" do + subject.use_bundler.should be_true + end + + it "uses bundle exec to find cucumber and libraries" do + subject.cmd.should == [Cucumber::RUBY_BINARY, + '-S', + 'bundle', + 'exec', + 'rcov', + '--rcov-option', + "\"#{Cucumber::BINARY }\"", + '--', + '--cuke-option'] + feature_files + end + + end + + context "when running without bundler" do + + let(:bundler) { false } + + subject { Task::RCovCucumberRunner.new( + libs, binary, cucumber_opts, bundler, feature_files, rcov_opts) } + + it "does not use bundler if bundler is set to false" do + subject.use_bundler.should be_false + end + + it "uses well known cucumber location and specified libraries" do + subject.cmd.should == [Cucumber::RUBY_BINARY, + '-I', + '"lib"', + '-S', + 'rcov', + '--rcov-option', + "\"#{Cucumber::BINARY }\"", + '--', + '--cuke-option'] + feature_files + end + + end + + + end + + end +end \ No newline at end of file diff --git a/spec/cucumber/rb_support/rb_language_spec.rb b/spec/cucumber/rb_support/rb_language_spec.rb index 8253bfe1d5..8f6da390bd 100644 --- a/spec/cucumber/rb_support/rb_language_spec.rb +++ b/spec/cucumber/rb_support/rb_language_spec.rb @@ -1,5 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') - +require 'spec_helper' require 'cucumber/step_mother' require 'cucumber/rb_support/rb_language' @@ -144,7 +143,7 @@ class << rb.current_world spec/cucumber/rb_support/rb_language_spec.rb:\\d+:in `World' Use Ruby modules instead to extend your worlds. See the Cucumber::RbSupport::RbDsl#World RDoc -or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world. +or http://wiki.github.com/cucumber/cucumber/a-whole-new-world. } dsl.World { Hash.new } diff --git a/spec/cucumber/rb_support/rb_step_definition_spec.rb b/spec/cucumber/rb_support/rb_step_definition_spec.rb index 842e70a7b3..805bc63d9c 100644 --- a/spec/cucumber/rb_support/rb_step_definition_spec.rb +++ b/spec/cucumber/rb_support/rb_step_definition_spec.rb @@ -1,5 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') - +require 'spec_helper' require 'cucumber/ast' require 'cucumber/step_mother' require 'cucumber/rb_support/rb_language' @@ -23,7 +22,7 @@ module RbSupport it "should allow calling of other steps" do dsl.Given /Outside/ do - Given "Inside" + step "Inside" end dsl.Given /Inside/ do $inside = true @@ -35,7 +34,7 @@ module RbSupport it "should allow calling of other steps with inline arg" do dsl.Given /Outside/ do - Given "Inside", Cucumber::Ast::Table.new([['inside']]) + step "Inside", Cucumber::Ast::Table.new([['inside']]) end dsl.Given /Inside/ do |table| $inside = table.raw[0][0] @@ -47,7 +46,7 @@ module RbSupport it "should raise Undefined when inside step is not defined" do dsl.Given /Outside/ do - Given 'Inside' + step 'Inside' end lambda do @@ -74,10 +73,10 @@ module RbSupport end.should raise_error(Cucumber::ArityMismatchError) end - it "should allow announce" do - user_interface.should_receive(:announce).with('wasup') + it "should allow puts" do + user_interface.should_receive(:puts).with('wasup') dsl.Given /Loud/ do - announce 'wasup' + puts 'wasup' end support_code.step_match("Loud").invoke(nil) diff --git a/spec/cucumber/rb_support/rb_transform_spec.rb b/spec/cucumber/rb_support/rb_transform_spec.rb index b0888ce9b7..fa3077bfbc 100644 --- a/spec/cucumber/rb_support/rb_transform_spec.rb +++ b/spec/cucumber/rb_support/rb_transform_spec.rb @@ -8,8 +8,12 @@ def transform(regexp) RbTransform.new(nil, regexp, lambda { |a| }) end describe "#to_s" do - it "removes the capture group parentheses" do - transform(/(a)bc/).to_s.should == "abc" + it "converts captures groups to non-capture groups" do + transform(/(a|b)bc/).to_s.should == "(?:a|b)bc" + end + + it "leaves non capture groups alone" do + transform(/(?:a|b)bc/).to_s.should == "(?:a|b)bc" end it "strips away anchors" do diff --git a/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb b/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb index ebe2bbbd5d..967669390c 100644 --- a/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +++ b/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/rb_support/regexp_argument_matcher' module Cucumber @@ -6,12 +6,12 @@ module RbSupport describe RegexpArgumentMatcher do it "should create 2 arguments" do arguments = RegexpArgumentMatcher.arguments_from(/I (\w+) (\w+)/, "I like fish") - arguments.map{|argument| [argument.val, argument.byte_offset]}.should == [["like", 2], ["fish", 7]] + arguments.map{|argument| [argument.val, argument.offset]}.should == [["like", 2], ["fish", 7]] end it "should create 2 arguments when first group is optional" do arguments = RegexpArgumentMatcher.arguments_from(/should( not)? be flashed '([^']*?)'$/, "I should be flashed 'Login failed.'") - arguments.map{|argument| [argument.val, argument.byte_offset]}.should == [[nil, nil], ["Login failed.", 21]] + arguments.map{|argument| [argument.val, argument.offset]}.should == [[nil, nil], ["Login failed.", 21]] end end end diff --git a/spec/cucumber/runtime/results_spec.rb b/spec/cucumber/runtime/results_spec.rb new file mode 100644 index 0000000000..6ede690ca2 --- /dev/null +++ b/spec/cucumber/runtime/results_spec.rb @@ -0,0 +1,81 @@ +require 'spec_helper' + +module Cucumber + describe Runtime::Results do + + let(:configuration) {double 'Configuration', :strict? => false} + let(:passed_scenario) {double 'Scenario', :status => :passed} + let(:failed_scenario) {double 'Scenario', :status => :failed} + let(:passed_step) {double 'Step', :status => :passed} + let(:failed_step) {double 'Step', :status => :failed} + let(:pending_step) {double 'Step', :status => :pending} + let(:undefined_step) {double 'Step', :status => :undefined} + + subject {described_class.new(configuration)} + + describe '#failure?' do + context 'feature is not work in progress' do + before do + configuration.stub(:wip? => false) + end + + it 'should return true if a scenario failed' do + subject.scenario_visited(passed_scenario) + subject.scenario_visited(failed_scenario) + subject.should be_failure + end + + it 'should return true if a step failed' do + subject.step_visited(failed_step) + subject.should be_failure + end + + it 'should return false if there are no scenarios' do + subject.should_not be_failure + end + + it 'should return false if all scenarios passed' do + subject.scenario_visited(passed_scenario) + subject.scenario_visited(passed_scenario) + subject.should_not be_failure + end + + context 'configuration is strict' do + before do + configuration.stub(:strict? => true) + end + + it 'should return true if a step is pending' do + subject.step_visited(pending_step) + subject.should be_failure + end + + it 'should return true if a step is undefined' do + subject.step_visited(undefined_step) + subject.should be_failure + end + end + end + + context 'feature is work in progress' do + before do + configuration.stub(:wip? => true) + end + + it 'should return true if a scenario passed' do + subject.scenario_visited(passed_scenario) + subject.should be_failure + end + + it 'should return false if there are no scenarios' do + subject.should_not be_failure + end + + it 'should return false if all scenarios fail' do + subject.scenario_visited(failed_scenario) + subject.should_not be_failure + end + end + end + end +end diff --git a/spec/cucumber/step_match_spec.rb b/spec/cucumber/step_match_spec.rb index 91dc350a46..a6c24fe314 100644 --- a/spec/cucumber/step_match_spec.rb +++ b/spec/cucumber/step_match_spec.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'spec_helper' require 'cucumber/rb_support/rb_step_definition' require 'cucumber/rb_support/rb_language' diff --git a/spec/cucumber/wire_support/configuration_spec.rb b/spec/cucumber/wire_support/configuration_spec.rb index 5a0fa56400..bfa7c6c30f 100644 --- a/spec/cucumber/wire_support/configuration_spec.rb +++ b/spec/cucumber/wire_support/configuration_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/wire_support/wire_language' require 'tempfile' diff --git a/spec/cucumber/wire_support/connection_spec.rb b/spec/cucumber/wire_support/connection_spec.rb index 40ab5e5eba..f2d20a825d 100644 --- a/spec/cucumber/wire_support/connection_spec.rb +++ b/spec/cucumber/wire_support/connection_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/wire_support/wire_language' module Cucumber diff --git a/spec/cucumber/wire_support/wire_exception_spec.rb b/spec/cucumber/wire_support/wire_exception_spec.rb index 0cf8fb607b..d959586107 100644 --- a/spec/cucumber/wire_support/wire_exception_spec.rb +++ b/spec/cucumber/wire_support/wire_exception_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/wire_support/wire_language' module Cucumber diff --git a/spec/cucumber/wire_support/wire_language_spec.rb b/spec/cucumber/wire_support/wire_language_spec.rb index 893b39ce92..834367b01e 100644 --- a/spec/cucumber/wire_support/wire_language_spec.rb +++ b/spec/cucumber/wire_support/wire_language_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/wire_support/wire_language' module Cucumber diff --git a/spec/cucumber/wire_support/wire_packet_spec.rb b/spec/cucumber/wire_support/wire_packet_spec.rb index d5260d7b15..1b8d9b44bd 100644 --- a/spec/cucumber/wire_support/wire_packet_spec.rb +++ b/spec/cucumber/wire_support/wire_packet_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/wire_support/wire_language' module Cucumber diff --git a/spec/cucumber/wire_support/wire_step_definition_spec.rb b/spec/cucumber/wire_support/wire_step_definition_spec.rb index a0226e213c..4370426031 100644 --- a/spec/cucumber/wire_support/wire_step_definition_spec.rb +++ b/spec/cucumber/wire_support/wire_step_definition_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/wire_support/wire_language' module Cucumber diff --git a/spec/cucumber/world/pending_spec.rb b/spec/cucumber/world/pending_spec.rb index ac1093071f..86dfca5769 100644 --- a/spec/cucumber/world/pending_spec.rb +++ b/spec/cucumber/world/pending_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') +require 'spec_helper' require 'cucumber/rb_support/rb_language' module Cucumber diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5ce200f2fb..8b25fdfbd6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,9 +2,21 @@ $:.unshift(File.dirname(__FILE__) + '/../lib') $:.unshift(File.dirname(__FILE__)) +# For Travis.... +if defined? Encoding + Encoding.default_external = 'utf-8' + Encoding.default_internal = 'utf-8' +end + require 'rubygems' require 'bundler' Bundler.setup require 'cucumber' $KCODE='u' unless Cucumber::RUBY_1_9 + +RSpec.configure do |c| + c.before do + ::Term::ANSIColor.coloring = true + end +end
        state
        failing
        FAIL
        +2end
        Screenshot
          +
        features/search_sample.feature:12

        Scenario Outline: Ignore me

        1. Given <state> without a table
          features/step_definitions/sample_steps.rb:15

        Examples

        Screenshot
          +
        state
        failing
        FAIL
         ./features/step_definitions/sample_steps.rb:2:in `flunker'
         ./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
        -features/search_sample.feature:13:in `Given  without a table'
        features/search_sample.feature:18

        Scenario Outline: Hantu Pisang match

        1. Given <state> without a table
          features/step_definitions/sample_steps.rb:12

        Examples

        state
        passing
        features/search_sample.feature:24

        Scenario Outline: no match in name but in examples

        1. Given <state> without a table
          features/step_definitions/sample_steps.rb:12

        Examples Hantu Pisang

        state
        passing

        Examples Ignore me

        state
        failing
        FAIL
        +features/search_sample.feature:13:in `Given  without a table'
        features/search_sample.feature:18

        Scenario Outline: Hantu Pisang match

        1. Given <state> without a table
          features/step_definitions/sample_steps.rb:12

        Examples

        Screenshot
          +
        state
        passing
        features/search_sample.feature:24

        Scenario Outline: no match in name but in examples

        1. Given <state> without a table
          features/step_definitions/sample_steps.rb:12

        Examples Hantu Pisang

        Screenshot
          +
        state
        passing

        Examples Ignore me

        Screenshot
          +
        state
        failing
        FAIL
         ./features/step_definitions/sample_steps.rb:2:in `flunker'
         ./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
         features/search_sample.feature:25:in `Given  without a table'
        @sample_one

        Feature: Tag samples

        @sample_two @sample_fourfeatures/tags_sample.feature:5

        Scenario: Passing

        1. Given missing
          features/tags_sample.feature:6
          Given /^missing$/ do
             pending # express the regexp above with the code you wish you had
          -end
        @sample_threefeatures/tags_sample.feature:9

        Scenario Outline:

        1. Given <state>
          features/tags_sample.feature:10

        Examples

        state
        missing
        @sample_three @sample_fourfeatures/tags_sample.feature:16

        Scenario: Skipped

        1. Given missing
          features/tags_sample.feature:17
          Given /^missing$/ do
          +end
        Screenshot
          +
        @sample_threefeatures/tags_sample.feature:9

        Scenario Outline:

        1. Given <state>
          features/tags_sample.feature:10

        Examples

        Screenshot
          +
        state
        missing
        @sample_three @sample_fourfeatures/tags_sample.feature:16

        Scenario: Skipped

        1. Given missing
          features/tags_sample.feature:17
          Given /^missing$/ do
             pending # express the regexp above with the code you wish you had
          -end
        @lots

        Feature: Tons of cukes

        features/tons_of_cukes.feature:3

        Scenario: Lots and lots

        1. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        2. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
          We already have 2 cukes!
          ./features/step_definitions/sample_steps.rb:28:in `/^'(.+)' cukes$/'
          +end
        Screenshot
          +
        @lots

        Feature: Tons of cukes

        features/tons_of_cukes.feature:3

        Scenario: Lots and lots

        1. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        2. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
          We already have 2 cukes!
          ./features/step_definitions/sample_steps.rb:28:in `/^'(.+)' cukes$/'
           features/tons_of_cukes.feature:5:in `Given '2' cukes'
          26
           27Given /^'(.+)' cukes$/ do |cukes| x=1
           28  raise "We already have #{@cukes} cukes!" if @cukes
           29  @cukes = cukes
          -30end
        3. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        4. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        5. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        6. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        7. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        8. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        9. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        10. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        11. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        12. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        13. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        14. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        15. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        16. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        17. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        18. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        19. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        20. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        21. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        22. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        23. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        24. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        25. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        26. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        27. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        28. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        29. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        30. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        31. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        32. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        33. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        34. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        35. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        36. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        37. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        38. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        39. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        40. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        41. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        42. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        43. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        44. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        45. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        46. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        47. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        48. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        49. Given '2' cukes
          features/step_definitions/sample_steps.rb:27

        Feature: undefined multiline args

        features/undefined_multiline_args.feature:3

        Scenario: pystring

        1. Given a pystring
          features/undefined_multiline_args.feature:4
            example
          Given /^a pystring$/ do |string|
          +30end
        2. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        3. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        4. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        5. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        6. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        7. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        8. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        9. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        10. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        11. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        12. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        13. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        14. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        15. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        16. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        17. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        18. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        19. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        20. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        21. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        22. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        23. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        24. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        25. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        26. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        27. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        28. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        29. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        30. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        31. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        32. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        33. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        34. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        35. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        36. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        37. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        38. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        39. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        40. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        41. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        42. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        43. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        44. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        45. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        46. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        47. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        48. Given '2' cukes
          features/step_definitions/sample_steps.rb:27
        Screenshot
          +

        Feature: undefined multiline args

        features/undefined_multiline_args.feature:3

        Scenario: pystring

        1. Given a pystring
          features/undefined_multiline_args.feature:4
            example with <html> entities
          Given /^a pystring$/ do |string|
             pending # express the regexp above with the code you wish you had
          -end
        features/undefined_multiline_args.feature:9

        Scenario: table

        1. Given a table
          features/undefined_multiline_args.feature:10
          table
          example
          Given /^a table$/ do |table|
          +end
        Screenshot
          +
        features/undefined_multiline_args.feature:9

        Scenario: table

        1. Given a table
          features/undefined_multiline_args.feature:10
          table
          example
          Given /^a table$/ do |table|
             # table is a Cucumber::Ast::Table
             pending # express the regexp above with the code you wish you had
          -end
        \ No newline at end of file +end Screenshot
          +
        \ No newline at end of file diff --git a/legacy_features/junit_formatter.feature b/legacy_features/junit_formatter.feature index 723f228727..73ed7b8ba4 100644 --- a/legacy_features/junit_formatter.feature +++ b/legacy_features/junit_formatter.feature @@ -12,10 +12,10 @@ Feature: JUnit output formatter """ """ - And "fixtures/junit/tmp/TEST-one_passing_one_failing.xml" with junit duration "0.005" should contain + And "fixtures/junit/tmp/TEST-features-one_passing_one_failing.xml" with junit duration "0.005" should contain """ - + @@ -34,30 +34,64 @@ Feature: JUnit output formatter """ - Scenario: pending steps are simply skipped + Scenario: one feature in a subdirectory, one passing scenario, one failing scenario + When I run cucumber --format junit --out tmp/ features/some_subdirectory/one_passing_one_failing.feature --require features + Then it should fail with + """ + + """ + And "fixtures/junit/tmp/TEST-features-some_subdirectory-one_passing_one_failing.xml" with junit duration "0.005" should contain + """ + + + + + + + + + + + + + """ + + Scenario: pending and undefined steps are reported as skipped When I run cucumber --format junit --out tmp/ features/pending.feature Then it should pass with """ """ - And "fixtures/junit/tmp/TEST-pending.xml" with junit duration "0.009" should contain + And "fixtures/junit/tmp/TEST-features-pending.xml" with junit duration "0.009" should contain """ - + + + + + + + """ - Scenario: pending step with strict option should fail + Scenario: pending and undefined steps with strict option should fail When I run cucumber --format junit --out tmp/ features/pending.feature --strict Then it should fail with """ """ - And "fixtures/junit/tmp/TEST-pending.xml" with junit duration "0.000160" should contain + And "fixtures/junit/tmp/TEST-features-pending.xml" with junit duration "0.000160" should contain """ - + + + + + + + """ @@ -77,8 +120,8 @@ Feature: JUnit output formatter """ """ - And "fixtures/junit/tmp/TEST-one_passing_one_failing.xml" should exist - And "fixtures/junit/tmp/TEST-pending.xml" should exist + And "fixtures/junit/tmp/TEST-features-one_passing_one_failing.xml" should exist + And "fixtures/junit/tmp/TEST-features-pending.xml" should exist Scenario: show correct error message if no --out is passed When I run cucumber --format junit features @@ -89,4 +132,33 @@ can't convert .* into String \(TypeError\) And STDERR should match """ You \*must\* specify \-\-out DIR for the junit formatter - """ \ No newline at end of file + """ + + Scenario: one feature, one scenario outline, two examples: one passing, one failing + When I run cucumber --format junit --out tmp/ features/scenario_outline.feature + Then it should fail with + """ + + """ + And "fixtures/junit/tmp/TEST-features-scenario_outline.xml" with junit duration "0.005" should contain + """ + + + + + + + + scenario']]> + + + + + """ + \ No newline at end of file diff --git a/legacy_features/language_help.feature b/legacy_features/language_help.feature index 41881c6b98..a0429bc8cd 100644 --- a/legacy_features/language_help.feature +++ b/legacy_features/language_help.feature @@ -12,12 +12,12 @@ Feature: Language help | scenario | "Cenário", "Cenario" | | scenario_outline | "Esquema do Cenário", "Esquema do Cenario" | | examples | "Exemplos" | - | given | "* ", "Dado " | + | given | "* ", "Dado ", "Dada ", "Dados ", "Dadas " | | when | "* ", "Quando " | | then | "* ", "Então ", "Entao " | | and | "* ", "E " | | but | "* ", "Mas " | - | given (code) | "Dado" | + | given (code) | "Dado", "Dada", "Dados", "Dadas" | | when (code) | "Quando" | | then (code) | "Então", "Entao" | | and (code) | "E" | @@ -51,6 +51,7 @@ Feature: Language help | hr | Croatian | hrvatski | | hu | Hungarian | magyar | | id | Indonesian | Bahasa Indonesia | + | is | Icelandic | Íslenska | | it | Italian | italiano | | ja | Japanese | 日本語 | | ko | Korean | 한국어 | diff --git a/legacy_features/profiles.feature b/legacy_features/profiles.feature index e9819c5e2c..4023a7a25e 100644 --- a/legacy_features/profiles.feature +++ b/legacy_features/profiles.feature @@ -4,7 +4,7 @@ Feature: Profiles These named arguments are called profiles and the yml file should be in the root of your project. Any cucumber argument is valid in a profile. To see all the available flags type 'cucumber --help' For more information about profiles please see the wiki: - http://wiki.github.com/aslakhellesoy/cucumber/cucumberyml + http://wiki.github.com/cucumber/cucumber/cucumber.yml Background: Basic App Given a standard Cucumber project directory structure @@ -118,7 +118,7 @@ Feature: Profiles Then it should fail And the output should contain """ - cucumber -p super features/sample.feature:2 # Scenario: this is a test + cucumber -p super features/sample.feature:2 """ Examples: | format | diff --git a/legacy_features/rerun_formatter.feature b/legacy_features/rerun_formatter.feature index 44a0343287..a8487f0bb8 100644 --- a/legacy_features/rerun_formatter.feature +++ b/legacy_features/rerun_formatter.feature @@ -20,6 +20,13 @@ Feature: Rerun Debugger Scenario: Pending Given pending + Scenario: Passing + Given passing + """ + And a file named "features/all_good.feature" with: + """ + Feature: Rerun + Scenario: Passing Given passing """ @@ -37,7 +44,7 @@ Feature: Rerun Debugger end """ - When I run cucumber -f rerun features/sample.feature + When I run cucumber -f rerun features/sample.feature features/all_good.feature Then it should fail with """ features/sample.feature:3:6:9 diff --git a/legacy_features/snippets_when_using_star_keyword.feature b/legacy_features/snippets_when_using_star_keyword.feature index 5c151123c3..ee908641d5 100644 --- a/legacy_features/snippets_when_using_star_keyword.feature +++ b/legacy_features/snippets_when_using_star_keyword.feature @@ -29,8 +29,9 @@ Feature: Use * keywords and still get snippets pending # express the regexp above with the code you wish you had end - If you want snippets in a different programming language, just make sure a file - with the appropriate file extension exists where cucumber looks for step definitions. + If you want snippets in a different programming language, + just make sure a file with the appropriate file extension + exists where cucumber looks for step definitions. """ diff --git a/legacy_features/step_definitions/cucumber_steps.rb b/legacy_features/step_definitions/cucumber_steps.rb index 5a456010f7..6d5738d223 100644 --- a/legacy_features/step_definitions/cucumber_steps.rb +++ b/legacy_features/step_definitions/cucumber_steps.rb @@ -75,7 +75,11 @@ unless combined_output.index(output) combined_output.should == output end - Then("it should #{success}") + step("it should #{success}") +end + +Then /^the output should contain "([^"]*)"$/ do |text| + last_stdout.should include(text) end Then /^the output should contain:?$/ do |text| diff --git a/legacy_features/support/env.rb b/legacy_features/support/env.rb index cde8c7e13b..8a3d8481fa 100644 --- a/legacy_features/support/env.rb +++ b/legacy_features/support/env.rb @@ -126,7 +126,7 @@ def run_spork_in_background(port = nil) exec cmd end end - sleep 1.0 + sleep 2.0 end def terminate_background_jobs diff --git a/legacy_features/wire_protocol.feature b/legacy_features/wire_protocol.feature index 8d3838d1b6..f15749bb36 100644 --- a/legacy_features/wire_protocol.feature +++ b/legacy_features/wire_protocol.feature @@ -329,4 +329,4 @@ Feature: Wire Protocol Then STDERR should match """ undefined method `handle_yikes' - """ + """ \ No newline at end of file diff --git a/legacy_features/work_in_progress.feature b/legacy_features/work_in_progress.feature index a42490755d..05e71cb658 100644 --- a/legacy_features/work_in_progress.feature +++ b/legacy_features/work_in_progress.feature @@ -64,7 +64,7 @@ Feature: Cucumber --work-in-progress switch features/wip.feature:4:in `Given a failing step' Failing Scenarios: - cucumber features/wip.feature:3 # Scenario: Failing + cucumber features/wip.feature:3 1 scenario (1 failed) 1 step (1 failed) diff --git a/lib/cucumber/ast.rb b/lib/cucumber/ast.rb index 2e21109bb1..9c07e55c34 100644 --- a/lib/cucumber/ast.rb +++ b/lib/cucumber/ast.rb @@ -9,7 +9,7 @@ require 'cucumber/ast/step' require 'cucumber/ast/table' require 'cucumber/ast/tags' -require 'cucumber/ast/py_string' +require 'cucumber/ast/doc_string' require 'cucumber/ast/outline_table' require 'cucumber/ast/examples' require 'cucumber/ast/visitor' diff --git a/lib/cucumber/ast/background.rb b/lib/cucumber/ast/background.rb index 1749e13c2a..ad20cfec07 100644 --- a/lib/cucumber/ast/background.rb +++ b/lib/cucumber/ast/background.rb @@ -1,13 +1,15 @@ require 'cucumber/ast/feature_element' +require 'cucumber/ast/names' module Cucumber module Ast class Background #:nodoc: include FeatureElement - attr_reader :feature_elements, :name + include Names + attr_reader :feature_elements - def initialize(comment, line, keyword, name, raw_steps) - @comment, @line, @keyword, @name, @raw_steps = comment, line, keyword, name, raw_steps + def initialize(comment, line, keyword, title, description, raw_steps) + @comment, @line, @keyword, @title, @description, @raw_steps = comment, line, keyword, title, description, raw_steps @feature_elements = [] end @@ -32,7 +34,7 @@ def accept(visitor) return if Cucumber.wants_to_quit init visitor.visit_comment(@comment) unless @comment.empty? - visitor.visit_background_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length)) + visitor.visit_background_name(@keyword, name, file_colon_line(@line), source_indent(first_line_length)) with_visitor(hook_context, visitor) do visitor.step_mother.before(hook_context) skip_invoke! if failed? @@ -79,7 +81,7 @@ def hook_context def to_sexp init sexp = [:background, @line, @keyword] - sexp += [@name] unless @name.empty? + sexp += [name] unless name.empty? comment = @comment.to_sexp sexp += [comment] if comment steps = @steps.to_sexp @@ -94,6 +96,17 @@ def fail!(exception) end + # Override this method, as there are situations where the background + # wind up being the one called fore Before scenarios, and + # backgrounds don't have tags. + def source_tags + [] + end + + def source_tag_names + source_tags.map { |tag| tag.name } + end + end end end diff --git a/lib/cucumber/ast/py_string.rb b/lib/cucumber/ast/doc_string.rb similarity index 61% rename from lib/cucumber/ast/py_string.rb rename to lib/cucumber/ast/doc_string.rb index dee3cc93be..e89e70ceb2 100644 --- a/lib/cucumber/ast/py_string.rb +++ b/lib/cucumber/ast/doc_string.rb @@ -8,7 +8,7 @@ module Ast # Cucumber sandwich # """ # - # The text between the pair of """ is stored inside a PyString, + # The text between the pair of """ is stored inside a DocString, # which is yielded to the StepDefinition block as the last argument. # # The StepDefinition can then access the String via the #to_s method. In the @@ -16,64 +16,45 @@ module Ast # # Note how the indentation from the source is stripped away. # - class PyString #:nodoc: - class Builder - attr_reader :string - - def initialize - @string = '' - end - - def py_string(string, line_number) - @string = string - end - - def eof - end - end - + class DocString < String #:nodoc: attr_accessor :file def self.default_arg_name "string" end - def self.parse(text) - builder = Builder.new - lexer = Gherkin::I18nLexer.new(builder) - lexer.scan(text) - new(builder.string) - end + attr_reader :content_type - def initialize(string) - @string = string + def initialize(string, content_type) + @content_type = content_type + super string end def to_step_definition_arg - @string + self end def accept(visitor) return if Cucumber.wants_to_quit - visitor.visit_py_string(@string) + visitor.visit_doc_string(self) end def arguments_replaced(arguments) #:nodoc: - string = @string + string = self arguments.each do |name, value| value ||= '' string = string.gsub(name, value) end - PyString.new(string) + DocString.new(string, content_type) end def has_text?(text) - @string.index(text) + index(text) end # For testing only def to_sexp #:nodoc: - [:py_string, to_step_definition_arg] + [:doc_string, to_step_definition_arg] end end end diff --git a/lib/cucumber/ast/examples.rb b/lib/cucumber/ast/examples.rb index eedd9f47c7..69eab64be9 100644 --- a/lib/cucumber/ast/examples.rb +++ b/lib/cucumber/ast/examples.rb @@ -1,10 +1,13 @@ +require 'cucumber/ast/names' + module Cucumber module Ast class Examples #:nodoc: + include Names attr_writer :outline_table - def initialize(comment, line, keyword, name, outline_table) - @comment, @keyword, @name, @outline_table = comment, keyword, name, outline_table + def initialize(comment, line, keyword, title, description, outline_table) + @comment, @keyword, @title, @description, @outline_table = comment, keyword, title, description, outline_table end attr_reader :gherkin_statement @@ -15,7 +18,7 @@ def gherkin_statement(statement=nil) def accept(visitor) return if Cucumber.wants_to_quit visitor.visit_comment(@comment) unless @comment.empty? - visitor.visit_examples_name(@keyword, @name) + visitor.visit_examples_name(@keyword, name) visitor.visit_outline_table(@outline_table) end @@ -32,7 +35,7 @@ def failed? end def to_sexp - sexp = [:examples, @keyword, @name] + sexp = [:examples, @keyword, name] comment = @comment.to_sexp sexp += [comment] if comment sexp += [@outline_table.to_sexp] diff --git a/lib/cucumber/ast/feature.rb b/lib/cucumber/ast/feature.rb index bf1603adca..f286e1032c 100644 --- a/lib/cucumber/ast/feature.rb +++ b/lib/cucumber/ast/feature.rb @@ -1,14 +1,17 @@ +require 'cucumber/ast/names' + module Cucumber module Ast # Represents the root node of a parsed feature. class Feature #:nodoc: + include Names + attr_accessor :language attr_writer :features, :background - attr_reader :file - attr_reader :name + attr_reader :file, :feature_elements - def initialize(background, comment, tags, keyword, name, feature_elements) - @background, @comment, @tags, @keyword, @name, @feature_elements = background, comment, tags, keyword, name.strip, feature_elements + def initialize(background, comment, tags, keyword, title, description, feature_elements) + @background, @comment, @tags, @keyword, @title, @description, @feature_elements = background, comment, tags, keyword, title, description, feature_elements end attr_reader :gherkin_statement @@ -43,15 +46,19 @@ def accept(visitor) def indented_name indent = "" - @name.split("\n").map do |l| + name.split("\n").map do |l| s = "#{indent}#{l}" indent = " " s end.join("\n") end + def source_tags + @tags.tags + end + def source_tag_names - @tags.tag_names + source_tags.map { |tag| tag.name } end def accept_hook?(hook) @@ -89,7 +96,7 @@ def short_name def to_sexp init - sexp = [:feature, @file, @name] + sexp = [:feature, @file, name] comment = @comment.to_sexp sexp += [comment] if comment tags = @tags.to_sexp diff --git a/lib/cucumber/ast/feature_element.rb b/lib/cucumber/ast/feature_element.rb index f96d6c0462..d11809de8a 100644 --- a/lib/cucumber/ast/feature_element.rb +++ b/lib/cucumber/ast/feature_element.rb @@ -6,7 +6,7 @@ module Ast module FeatureElement #:nodoc: attr_accessor :feature - attr_reader :gherkin_statement, :raw_steps + attr_reader :gherkin_statement, :raw_steps, :title, :description def gherkin_statement(statement=nil) @gherkin_statement ||= statement end @@ -32,10 +32,10 @@ def text_length end def name_line_lengths - if @name.strip.empty? + if name.strip.empty? [Ast::Step::INDENT + @keyword.unpack('U*').length + ': '.length] else - @name.split("\n").enum_for(:each_with_index).map do |line, line_number| + name.split("\n").enum_for(:each_with_index).map do |line, line_number| if line_number == 0 Ast::Step::INDENT + @keyword.unpack('U*').length + ': '.length + line.unpack('U*').length else @@ -46,10 +46,10 @@ def name_line_lengths end def matches_scenario_names?(scenario_name_regexps) - scenario_name_regexps.detect{|name| name =~ @name} + scenario_name_regexps.detect{|n| n =~ name} end - def backtrace_line(name = "#{@keyword}: #{@name}", line = @line) + def backtrace_line(name = "#{@keyword}: #{name}", line = @line) @feature.backtrace_line(name, line) if @feature end @@ -63,11 +63,15 @@ def max_line_length end def accept_hook?(hook) - Gherkin::TagExpression.new(hook.tag_expressions).eval(source_tag_names) + Gherkin::TagExpression.new(hook.tag_expressions).eval(source_tags) end - + def source_tag_names - (@tags.tag_names.to_a + (@feature ? @feature.source_tag_names.to_a : [])).uniq + source_tags.map { |tag| tag.name } + end + + def source_tags + (@tags.tags.to_a + (@feature ? @feature.source_tags.to_a : [])).uniq end def language diff --git a/lib/cucumber/ast/multiline_argument.rb b/lib/cucumber/ast/multiline_argument.rb new file mode 100644 index 0000000000..92078005ed --- /dev/null +++ b/lib/cucumber/ast/multiline_argument.rb @@ -0,0 +1,30 @@ +require 'gherkin/rubify' + +module Cucumber + module Ast + module MultilineArgument + + class << self + include Gherkin::Rubify + + def from(argument) + return unless argument + return argument if argument.respond_to?(:to_step_definition_arg) + + case(rubify(argument)) + when String + # TODO: this duplicates work that gherkin does. We should really pass the string to gherkin and let it parse it. + Ast::DocString.new(argument, '') + when Gherkin::Formatter::Model::DocString + Ast::DocString.new(argument.value, argument.content_type) + when Array + Ast::Table.new(argument.map{|row| row.cells}) + else + raise ArgumentError, "Don't know how to convert #{argument} into a MultilineArgument" + end + end + + end + end + end +end \ No newline at end of file diff --git a/lib/cucumber/ast/names.rb b/lib/cucumber/ast/names.rb new file mode 100644 index 0000000000..157dab854e --- /dev/null +++ b/lib/cucumber/ast/names.rb @@ -0,0 +1,13 @@ +module Cucumber + module Ast + module Names + attr_reader :title, :description + + def name + s = @title + s += "\n#{@description}" if @description != "" + s + end + end + end +end \ No newline at end of file diff --git a/lib/cucumber/ast/outline_table.rb b/lib/cucumber/ast/outline_table.rb index abbae2c4bc..812c159367 100644 --- a/lib/cucumber/ast/outline_table.rb +++ b/lib/cucumber/ast/outline_table.rb @@ -33,9 +33,13 @@ def accept(visitor) def accept_hook?(hook) @scenario_outline.accept_hook?(hook) end - + + def source_tags + @scenario_outline.source_tags + end + def source_tag_names - @scenario_outline.source_tag_names + source_tags.map { |tag| tag.name } end def skip_invoke! @@ -52,7 +56,7 @@ def create_step_invocations_for_example_rows!(scenario_outline) cells.create_step_invocations!(scenario_outline) end end - + def example_rows cells_rows[1..-1] end @@ -65,29 +69,33 @@ def language @scenario_outline.language end - class ExampleRow < Cells #:nodoc: + class ExampleRow < Cells #:nodoc: class InvalidForHeaderRowError < NoMethodError def initialize(*args) super 'This is a header row and cannot pass or fail' end end - + attr_reader :scenario_outline # https://rspec.lighthouseapp.com/projects/16211/tickets/342 def initialize(table, cells) super @scenario_exception = nil end - + def source_tag_names - @table.source_tag_names + source_tags.map { |tag| tag.name } + end + + def source_tags + @table.source_tags end def create_step_invocations!(scenario_outline) @scenario_outline = scenario_outline @step_invocations = scenario_outline.step_invocations(self) end - + def skip_invoke! @step_invocations.each do |step_invocation| step_invocation.skip_invoke! @@ -115,7 +123,7 @@ def accept_plain(visitor) @cells.each do |cell| visitor.visit_table_cell(cell) end - + visitor.visit_exception(@scenario_exception, :failed) if @scenario_exception end end @@ -138,15 +146,15 @@ def accept_expand(visitor) def accept_hook?(hook) @table.accept_hook?(hook) end - + def exception @exception || @scenario_exception end - + def fail!(exception) @scenario_exception = exception end - + # Returns true if one or more steps failed def failed? raise InvalidForHeaderRowError if header? diff --git a/lib/cucumber/ast/scenario.rb b/lib/cucumber/ast/scenario.rb index d827b46930..3997661456 100644 --- a/lib/cucumber/ast/scenario.rb +++ b/lib/cucumber/ast/scenario.rb @@ -1,11 +1,13 @@ require 'cucumber/ast/feature_element' +require 'cucumber/ast/names' module Cucumber module Ast class Scenario #:nodoc: include FeatureElement + include Names - attr_reader :name, :line + attr_reader :line class EmptyBackground def failed? @@ -24,9 +26,9 @@ def init end end - def initialize(background, comment, tags, line, keyword, name, raw_steps) + def initialize(background, comment, tags, line, keyword, title, description, raw_steps) @background = background || EmptyBackground.new - @comment, @tags, @line, @keyword, @name, @raw_steps = comment, tags, line, keyword, name, raw_steps + @comment, @tags, @line, @keyword, @title, @description, @raw_steps = comment, tags, line, keyword, title, description, raw_steps @exception = @executed = nil end @@ -45,7 +47,7 @@ def accept(visitor) with_visitor(visitor) do visitor.visit_comment(@comment) unless @comment.empty? visitor.visit_tags(@tags) - visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length)) + visitor.visit_scenario_name(@keyword, name, file_colon_line(@line), source_indent(first_line_length)) skip_invoke! if @background.failed? visitor.step_mother.with_hooks(self, skip_hooks?) do @@ -90,7 +92,7 @@ def skip_invoke! end def to_sexp - sexp = [:scenario, @line, @keyword, @name] + sexp = [:scenario, @line, @keyword, name] comment = @comment.to_sexp sexp += [comment] if comment tags = @tags.to_sexp diff --git a/lib/cucumber/ast/scenario_outline.rb b/lib/cucumber/ast/scenario_outline.rb index 618c453b40..1eb49c76ae 100644 --- a/lib/cucumber/ast/scenario_outline.rb +++ b/lib/cucumber/ast/scenario_outline.rb @@ -1,10 +1,12 @@ +require 'cucumber/ast/feature_element' +require 'cucumber/ast/names' + module Cucumber module Ast class ScenarioOutline #:nodoc: include FeatureElement + include Names - attr_reader :name - module ExamplesArray #:nodoc: def accept(visitor) return if Cucumber.wants_to_quit @@ -20,8 +22,8 @@ def accept(visitor) # * Examples keyword # * Examples section name # * Raw matrix - def initialize(background, comment, tags, line, keyword, name, raw_steps, example_sections) - @background, @comment, @tags, @line, @keyword, @name, @raw_steps, @example_sections = background, comment, tags, line, keyword, name, raw_steps, example_sections + def initialize(background, comment, tags, line, keyword, title, description, raw_steps, example_sections) + @background, @comment, @tags, @line, @keyword, @title, @description, @raw_steps, @example_sections = background, comment, tags, line, keyword, title, description, raw_steps, example_sections end def add_examples(example_section, gherkin_examples) @@ -37,14 +39,15 @@ def init example_section = example_section_and_gherkin_examples[0] gherkin_examples = example_section_and_gherkin_examples[1] - examples_comment = example_section[0] - examples_line = example_section[1] - examples_keyword = example_section[2] - examples_name = example_section[3] - examples_matrix = example_section[4] + examples_comment = example_section[0] + examples_line = example_section[1] + examples_keyword = example_section[2] + examples_title = example_section[3] + examples_description = example_section[4] + examples_matrix = example_section[5] examples_table = OutlineTable.new(examples_matrix, self) - ex = Examples.new(examples_comment, examples_line, examples_keyword, examples_name, examples_table) + ex = Examples.new(examples_comment, examples_line, examples_keyword, examples_title, examples_description, examples_table) ex.gherkin_statement(gherkin_examples) ex end @@ -58,7 +61,7 @@ def accept(visitor) return if Cucumber.wants_to_quit visitor.visit_comment(@comment) unless @comment.empty? visitor.visit_tags(@tags) - visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length)) + visitor.visit_scenario_name(@keyword, name, file_colon_line(@line), source_indent(first_line_length)) visitor.visit_steps(@steps) skip_invoke! if @background && @background.failed? @@ -107,7 +110,7 @@ def failed? def to_sexp init - sexp = [:scenario_outline, @keyword, @name] + sexp = [:scenario_outline, @keyword, name] comment = @comment.to_sexp sexp += [comment] if comment tags = @tags.to_sexp diff --git a/lib/cucumber/ast/step_invocation.rb b/lib/cucumber/ast/step_invocation.rb index 9c1bd578bf..0a37c1ca4c 100644 --- a/lib/cucumber/ast/step_invocation.rb +++ b/lib/cucumber/ast/step_invocation.rb @@ -8,10 +8,6 @@ module Ast class StepInvocation #:nodoc: include Gherkin::Rubify - BACKTRACE_FILTER_PATTERNS = [ - /vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\// - ] - attr_writer :step_collection, :background attr_reader :name, :matched_cells, :status, :reported_exception attr_accessor :exception @@ -97,9 +93,23 @@ def find_step_match!(step_mother, configuration) end def failed(configuration, e, clear_backtrace) - e = filter_backtrace(e) - e.set_backtrace([]) if clear_backtrace + if Cucumber::JRUBY && e.class.name == 'NativeException' + # JRuby's NativeException ignores #set_backtrace. + # We're fixing it. + e.instance_eval do + def set_backtrace(backtrace) + @backtrace = backtrace + end + + def backtrace + @backtrace + end + end + end + + e.set_backtrace([]) if e.backtrace.nil? || clear_backtrace e.backtrace << @step.backtrace_line unless @step.backtrace_line.nil? + e = filter_backtrace(e) @exception = e if(configuration.strict? || !(Undefined === e) || e.nested?) @reported_exception = e @@ -108,29 +118,26 @@ def failed(configuration, e, clear_backtrace) end end + # This constant is appended to by Cuke4Duke. Do not change its name + BACKTRACE_FILTER_PATTERNS = [/vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\/|minitest|test\/unit/] PWD_PATTERN = /#{Regexp.escape(Dir.pwd)}\//m + # This is to work around double ":in " segments in JRuby backtraces. JRuby bug? def filter_backtrace(e) return e if Cucumber.use_full_backtrace - (e.backtrace || []).each{|line| line.gsub!(PWD_PATTERN, "./")} + e.backtrace.each{|line| line.gsub!(PWD_PATTERN, "./")} filtered = (e.backtrace || []).reject do |line| BACKTRACE_FILTER_PATTERNS.detect { |p| line =~ p } end - - if Cucumber::JRUBY && e.class.name == 'NativeException' - # JRuby's NativeException ignores #set_backtrace. - # We're fixing it. - e.instance_eval do - def set_backtrace(backtrace) - @backtrace = backtrace - end - def backtrace - @backtrace - end + if ENV['CUCUMBER_TRUNCATE_OUTPUT'] + # Strip off file locations + filtered = filtered.map do |line| + line =~ /(.*):in `/ ? $1 : line end end + e.set_backtrace(filtered) e end diff --git a/lib/cucumber/ast/table.rb b/lib/cucumber/ast/table.rb index d176e65d7e..ba838cb123 100644 --- a/lib/cucumber/ast/table.rb +++ b/lib/cucumber/ast/table.rb @@ -51,7 +51,7 @@ def eof include Enumerable include Gherkin::Rubify - NULL_CONVERSIONS = Hash.new(lambda{ |cell_value| cell_value }).freeze + NULL_CONVERSIONS = Hash.new({ :strict => false, :proc => lambda{ |cell_value| cell_value } }).freeze attr_accessor :file @@ -71,26 +71,27 @@ def self.parse(text, uri, offset) # You don't typically create your own Table objects - Cucumber will do # it internally and pass them to your Step Definitions. # - def initialize(raw, conversion_procs = NULL_CONVERSIONS.dup) + def initialize(raw, conversion_procs = NULL_CONVERSIONS.dup, header_mappings = {}, header_conversion_proc = nil) @cells_class = Cells @cell_class = Cell - raw = ensure_array_of_array(rubify(raw)) # Verify that it's square transposed = raw.transpose create_cell_matrix(raw) @conversion_procs = conversion_procs + @header_mappings = header_mappings + @header_conversion_proc = header_conversion_proc end def to_step_definition_arg dup end - # Creates a copy of this table, inheriting any column mappings. - # registered with #map_headers! + # Creates a copy of this table, inheriting any column and header mappings + # registered with #map_column! and #map_headers!. # def dup - self.class.new(raw.dup, @conversion_procs.dup) + self.class.new(raw.dup, @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc) end # Returns a new, transposed table. Example: @@ -105,9 +106,9 @@ def dup # | 4 | 2 | # def transpose - self.class.new(raw.transpose, @conversion_procs.dup) + self.class.new(raw.transpose, @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc) end - + # Converts this table into an Array of Hash where the keys of each # Hash are the headers in the table. For example, a Table built from # the following plain text: @@ -123,9 +124,7 @@ def transpose # Use #map_column! to specify how values in a column are converted. # def hashes - @hashes ||= cells_rows[1..-1].map do |row| - row.to_hash - end + @hashes ||= build_hashes end # Converts this table into a Hash where the first column is @@ -169,7 +168,9 @@ def column_names #:nodoc: end def rows - hashes.map(&:values) + hashes.map do |hash| + hash.values_at *headers + end end def each_cells_row(&proc) #:nodoc: @@ -237,22 +238,8 @@ def to_sexp #:nodoc: # # => ['phone number', 'ADDRESS'] # def map_headers!(mappings={}, &block) - header_cells = cell_matrix[0] - - if block_given? - header_values = header_cells.map { |cell| cell.value } - mappings.keys - mappings = mappings.merge(Hash[*header_values.zip(header_values.map(&block)).flatten]) - end - - mappings.each_pair do |pre, post| - mapped_cells = header_cells.select{|cell| pre === cell.value} - raise "No headers matched #{pre.inspect}" if mapped_cells.empty? - raise "#{mapped_cells.length} headers matched #{pre.inspect}: #{mapped_cells.map{|c| c.value}.inspect}" if mapped_cells.length > 1 - mapped_cells[0].value = post - if @conversion_procs.has_key?(pre) - @conversion_procs[post] = @conversion_procs.delete(pre) - end - end + @header_mappings = mappings + @header_conversion_proc = block end # Returns a new Table where the headers are redefined. See #map_headers! @@ -275,8 +262,7 @@ def map_headers(mappings={}) # end # def map_column!(column_name, strict=true, &conversion_proc) - verify_column(column_name.to_s) if strict - @conversion_procs[column_name.to_s] = conversion_proc + @conversion_procs[column_name.to_s] = { :strict => strict, :proc => conversion_proc } self end @@ -318,8 +304,12 @@ def diff!(other_table, options={}) options = {:missing_row => true, :surplus_row => true, :missing_col => true, :surplus_col => false}.merge(options) other_table = ensure_table(other_table) + other_table.convert_headers! other_table.convert_columns! ensure_green! + + convert_headers! + convert_columns! original_width = cell_matrix[0].length other_table_cell_matrix = pad!(other_table.cell_matrix) @@ -330,7 +320,6 @@ def diff!(other_table, options={}) require_diff_lcs cell_matrix.extend(Diff::LCS) - convert_columns! changes = cell_matrix.diff(other_table_cell_matrix).flatten inserted = 0 @@ -385,8 +374,7 @@ def to_hash(cells) #:nodoc: hash[key.to_s] if key.is_a?(Symbol) end column_names.each_with_index do |column_name, column_index| - value = @conversion_procs[column_name].call(cells.value(column_index)) - hash[column_name] = value + hash[column_name] = cells.value(column_index) end hash end @@ -469,6 +457,14 @@ def to_s(options = {}) #:nodoc: protected + def build_hashes + convert_headers! + convert_columns! + cells_rows[1..-1].map do |row| + row.to_hash + end + end + def inspect_rows(missing_row, inserted_row) #:nodoc: missing_row.each_with_index do |missing_cell, col| inserted_cell = inserted_row[col] @@ -489,14 +485,38 @@ def create_cell_matrix(raw) #:nodoc: end def convert_columns! #:nodoc: + @conversion_procs.each do |column_name, conversion_proc| + verify_column(column_name) if conversion_proc[:strict] + end + cell_matrix.transpose.each do |col| - conversion_proc = @conversion_procs[col[0].value] + column_name = col[0].value + conversion_proc = @conversion_procs[column_name][:proc] col[1..-1].each do |cell| cell.value = conversion_proc.call(cell.value) end end end + def convert_headers! #:nodoc: + header_cells = cell_matrix[0] + + if @header_conversion_proc + header_values = header_cells.map { |cell| cell.value } - @header_mappings.keys + @header_mappings = @header_mappings.merge(Hash[*header_values.zip(header_values.map(&@header_conversion_proc)).flatten]) + end + + @header_mappings.each_pair do |pre, post| + mapped_cells = header_cells.select { |cell| pre === cell.value } + raise "No headers matched #{pre.inspect}" if mapped_cells.empty? + raise "#{mapped_cells.length} headers matched #{pre.inspect}: #{mapped_cells.map { |c| c.value }.inspect}" if mapped_cells.length > 1 + mapped_cells[0].value = post + if @conversion_procs.has_key?(pre) + @conversion_procs[post] = @conversion_procs.delete(pre) + end + end + end + def require_diff_lcs #:nodoc: begin require 'diff/lcs' diff --git a/lib/cucumber/ast/tags.rb b/lib/cucumber/ast/tags.rb index 23bd5911b8..7d522906a4 100644 --- a/lib/cucumber/ast/tags.rb +++ b/lib/cucumber/ast/tags.rb @@ -3,25 +3,25 @@ module Cucumber module Ast class Tags #:nodoc: - attr_reader :tag_names + attr_reader :tags - def initialize(line, tag_names) - @line, @tag_names = line, tag_names + def initialize(line, tags) + @line, @tags = line, tags end def accept(visitor) return if Cucumber.wants_to_quit - @tag_names.each do |tag_name| - visitor.visit_tag_name(tag_name) + @tags.each do |tag| + visitor.visit_tag_name(tag.name) end end def accept_hook?(hook) - Gherkin::TagExpression.new(hook.tag_expressions).eval(@tag_names) + Gherkin::TagExpression.new(hook.tag_expressions).eval(@tags) end def to_sexp - @tag_names.map{|tag_name| [:tag, tag_name]} + @tags.map{|tag| [:tag, tag.name]} end end end diff --git a/lib/cucumber/ast/tree_walker.rb b/lib/cucumber/ast/tree_walker.rb index fedaeebc63..298c594f9e 100644 --- a/lib/cucumber/ast/tree_walker.rb +++ b/lib/cucumber/ast/tree_walker.rb @@ -122,7 +122,7 @@ def visit_exception(exception, status) #:nodoc: broadcast(exception, status) end - def visit_py_string(string) + def visit_doc_string(string) broadcast(string) end @@ -142,9 +142,9 @@ def visit_table_cell_value(value, status) broadcast(value, status) end - # Print +announcement+. This method can be called from within StepDefinitions. - def announce(announcement) - broadcast(announcement) + # Print +messages+. This method can be called from within StepDefinitions. + def puts(*messages) + broadcast(*messages) end # Embed +file+ of +mime_type+ in the formatter. This method can be called from within StepDefinitions. @@ -158,7 +158,6 @@ def embed(file, mime_type, label) def broadcast(*args, &block) message = extract_method_name_from(caller) message.gsub!('visit_', '') - if block_given? send_to_all("before_#{message}", *args) yield if block_given? diff --git a/lib/cucumber/cli/configuration.rb b/lib/cucumber/cli/configuration.rb index bd7751d2dc..d067396562 100644 --- a/lib/cucumber/cli/configuration.rb +++ b/lib/cucumber/cli/configuration.rb @@ -64,6 +64,10 @@ def expand? @options[:expand] end + def dotcucumber + @options[:dotcucumber] + end + def build_tree_walker(step_mother) Ast::TreeWalker.new(step_mother, formatters(step_mother), self) end diff --git a/lib/cucumber/cli/main.rb b/lib/cucumber/cli/main.rb index 976481722e..e13f9102d0 100644 --- a/lib/cucumber/cli/main.rb +++ b/lib/cucumber/cli/main.rb @@ -41,6 +41,7 @@ def execute!(existing_runtime = nil) end runtime.run! + runtime.write_stepdefs_json runtime.results.failure? rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e @error_stream.puts e.message diff --git a/lib/cucumber/cli/options.rb b/lib/cucumber/cli/options.rb index a8cae574bd..05ee9abe6a 100644 --- a/lib/cucumber/cli/options.rb +++ b/lib/cucumber/cli/options.rb @@ -9,10 +9,6 @@ class Options BUILTIN_FORMATS = { 'html' => ['Cucumber::Formatter::Html', 'Generates a nice looking HTML report.'], 'pretty' => ['Cucumber::Formatter::Pretty', 'Prints the feature as is - in colours.'], - 'pdf' => ['Cucumber::Formatter::Pdf', "Generates a PDF report. You need to have the\n" + - "#{INDENT}prawn gem installed. Will pick up logo from\n" + - "#{INDENT}features/support/logo.png or\n" + - "#{INDENT}features/support/logo.jpg if present."], 'progress' => ['Cucumber::Formatter::Progress', 'Prints one character per scenario.'], 'rerun' => ['Cucumber::Formatter::Rerun', 'Prints failing files with line numbers.'], 'usage' => ['Cucumber::Formatter::Usage', "Prints where step definitions are used.\n" + @@ -46,7 +42,10 @@ class Options NO_PROFILE_SHORT_FLAG = '-P' PROFILE_LONG_FLAG = '--profile' NO_PROFILE_LONG_FLAG = '--no-profile' - + OPTIONS_WITH_ARGS = ['-r', '--require', '--i18n', '-f', '--format', '-o', '--out', + '-t', '--tags', '-n', '--name', '-e', '--exclude', + PROFILE_SHORT_FLAG, PROFILE_LONG_FLAG, + '-a', '--autoformat', '-l', '--lines', '--port'] def self.parse(args, out_stream, error_stream, options = {}) new(out_stream, error_stream, options).parse!(args) @@ -77,7 +76,10 @@ def expanded_args_without_drb return @expanded_args_without_drb if @expanded_args_without_drb @expanded_args_without_drb = ( previous_flag_was_profile = false + previous_flag_requires_arg = false + @expanded_args.reject do |arg| + # ignore profiles if previous_flag_was_profile previous_flag_was_profile = false next true @@ -86,6 +88,19 @@ def expanded_args_without_drb previous_flag_was_profile = true next true end + + # accept all options which requires arguments + # and don't try to look @overridden_paths in it's arguments! + if previous_flag_requires_arg + previous_flag_requires_arg = false + next false + end + if OPTIONS_WITH_ARGS.include?(arg) + previous_flag_requires_arg = true + next false + end + + # ignore --drb flag and overridden features paths arg == DRB_FLAG || @overridden_paths.include?(arg) end ) @@ -204,7 +219,7 @@ def parse!(args) opts.on("-a", "--autoformat DIR", "Reformats (pretty prints) feature files and write them to DIRECTORY.", "Be careful if you choose to overwrite the originals.", - "Implies --dry-run --formatter pretty.") do |directory| + "Implies --dry-run --format pretty.") do |directory| @options[:autoformat] = directory Cucumber::Term::ANSIColor.coloring = false @options[:dry_run] = true @@ -252,6 +267,9 @@ def parse!(args) opts.on("--port PORT", "Specify DRb port. Ignored without --drb") do |port| @options[:drb_port] = port end + opts.on("--dotcucumber DIR", "Write metadata to DIR") do |dir| + @options[:dotcucumber] = dir + end opts.on_tail("--version", "Show version.") do @out_stream.puts Cucumber::VERSION Kernel.exit(0) diff --git a/lib/cucumber/constantize.rb b/lib/cucumber/constantize.rb index 7917390a77..9cbe102665 100644 --- a/lib/cucumber/constantize.rb +++ b/lib/cucumber/constantize.rb @@ -7,7 +7,7 @@ def constantize(camel_cased_word) names = camel_cased_word.split('::') names.shift if names.empty? || names.first.empty? - constant = Object + constant = ::Object names.each do |name| constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name) end diff --git a/lib/cucumber/core_ext/disable_mini_and_test_unit_autorun.rb b/lib/cucumber/core_ext/disable_mini_and_test_unit_autorun.rb index ec900b0f96..4f46e79367 100644 --- a/lib/cucumber/core_ext/disable_mini_and_test_unit_autorun.rb +++ b/lib/cucumber/core_ext/disable_mini_and_test_unit_autorun.rb @@ -1,13 +1,20 @@ # Why: http://groups.google.com/group/cukes/browse_thread/thread/5682d41436e235d7 begin require 'minitest/unit' - class MiniTest::Unit - class << self - @@installed_at_exit = true - end + # Don't attempt to monkeypatch if the require succeeded but didn't + # define the actual module. + # + # https://github.com/cucumber/cucumber/pull/93 + # http://youtrack.jetbrains.net/issue/TW-17414 + if defined?(MiniTest::Unit) + class MiniTest::Unit + class << self + @@installed_at_exit = true + end - def run(*) - 0 + def run(*) + 0 + end end end rescue LoadError => ignore @@ -15,10 +22,17 @@ def run(*) # Do the same for Test::Unit begin - require 'test/unit' - module Test::Unit - def self.run? - true + require 'test/unit' + # Don't attempt to monkeypatch if the require succeeded but didn't + # define the actual module. + # + # https://github.com/cucumber/cucumber/pull/93 + # http://youtrack.jetbrains.net/issue/TW-17414 + if defined?(Test::Unit) + module Test::Unit + def self.run? + true + end end end rescue LoadError => ignore diff --git a/lib/cucumber/formatter/console.rb b/lib/cucumber/formatter/console.rb index db023baa23..c83700fbfc 100644 --- a/lib/cucumber/formatter/console.rb +++ b/lib/cucumber/formatter/console.rb @@ -26,13 +26,15 @@ def format_step(keyword, step_match, status, source_indent) format_string(line, status) end - def format_string(string, status) + def format_string(o, status) fmt = format_for(status) - if Proc === fmt - fmt.call(string) - else - fmt % string - end + o.to_s.split("\n").map do |line| + if Proc === fmt + fmt.call(line) + else + fmt % line + end + end.join("\n") end def print_steps(status) @@ -57,21 +59,16 @@ def print_elements(elements, status, kind) end end - def print_counts - STDERR.puts("The #print_counts method is deprecated and will be removed in 0.4. Use #print_stats instead") - print_stats(nil) - end - - def print_stats(features, profiles = []) + def print_stats(features, options) @failures = step_mother.scenarios(:failed).select { |s| s.is_a?(Cucumber::Ast::Scenario) || s.is_a?(Cucumber::Ast::OutlineTable::ExampleRow) } @failures.collect! { |s| (s.is_a?(Cucumber::Ast::OutlineTable::ExampleRow)) ? s.scenario_outline : s } if !@failures.empty? @io.puts format_string("Failing Scenarios:", :failed) @failures.each do |failure| - profiles_string = profiles.empty? ? '' : (profiles.map{|profile| "-p #{profile}" }).join(' ') + ' ' - @io.puts format_string("cucumber #{profiles_string}" + failure.file_colon_line, :failed) + - format_string(" # Scenario: " + failure.name, :comment) + profiles_string = options.custom_profiles.empty? ? '' : (options.custom_profiles.map{|profile| "-p #{profile}" }).join(' ') + ' ' + source = options[:source] ? format_string(" # Scenario: " + failure.name, :comment) : '' + @io.puts format_string("cucumber #{profiles_string}" + failure.file_colon_line, :failed) + source end @io.puts end @@ -85,7 +82,18 @@ def print_stats(features, profiles = []) end def print_exception(e, status, indent) - @io.puts(format_string("#{e.message} (#{e.class})\n#{e.backtrace.join("\n")}".indent(indent), status)) + message = "#{e.message} (#{e.class})" + if ENV['CUCUMBER_TRUNCATE_OUTPUT'] + message = linebreaks(message, ENV['CUCUMBER_TRUNCATE_OUTPUT'].to_i) + end + + string = "#{message}\n#{e.backtrace.join("\n")}".indent(indent) + @io.puts(format_string(string, status)) + end + + # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/10655 + def linebreaks(s, max) + s.gsub(/.{1,#{max}}(?:\s|\Z)/){($& + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n")}.rstrip end def print_snippets(options) @@ -106,8 +114,9 @@ def print_snippets(options) @io.puts format_string(text, :undefined) if unknown_programming_language - @io.puts format_string("\nIf you want snippets in a different programming language, just make sure a file\n" + - "with the appropriate file extension exists where cucumber looks for step definitions.", :failed) + @io.puts format_string("\nIf you want snippets in a different programming language,\n" + + "just make sure a file with the appropriate file extension\n" + + "exists where cucumber looks for step definitions.", :failed) end @io.puts @@ -129,39 +138,41 @@ def embed(file, mime_type, label) # no-op end - #define @delayed_announcements = [] in your Formatter if you want to + #define @delayed_messages = [] in your Formatter if you want to #activate this feature - def announce(announcement) - if @delayed_announcements - @delayed_announcements << announcement + def puts(*messages) + if @delayed_messages + @delayed_messages += messages else if @io @io.puts - @io.puts(format_string(announcement, :tag)) + messages.each do |message| + @io.puts(format_string(message, :tag)) + end @io.flush end end end - def print_announcements() - @delayed_announcements.each {|ann| print_announcement(ann)} - empty_announcements + def print_messages + @delayed_messages.each {|message| print_message(message)} + empty_messages end - def print_table_row_announcements - return if @delayed_announcements.empty? - @io.print(format_string(@delayed_announcements.join(', '), :tag).indent(2)) + def print_table_row_messages + return if @delayed_messages.empty? + @io.print(format_string(@delayed_messages.join(', '), :tag).indent(2)) @io.flush - empty_announcements + empty_messages end - def print_announcement(announcement) - @io.puts(format_string(announcement, :tag).indent(@indent)) + def print_message(message) + @io.puts(format_string(message, :tag).indent(@indent)) @io.flush end - def empty_announcements - @delayed_announcements = [] + def empty_messages + @delayed_messages = [] end private diff --git a/lib/cucumber/formatter/cucumber.css b/lib/cucumber/formatter/cucumber.css index ec0ec33bdc..ac33f19ecc 100755 --- a/lib/cucumber/formatter/cucumber.css +++ b/lib/cucumber/formatter/cucumber.css @@ -133,7 +133,7 @@ body { background: #fcfb98; color: #131313; } -.cucumber table td.announcement, td table td.announcement, th table td.announcement { +.cucumber table td.message, td table td.message, th table td.message { border-left: 5px solid aqua; border-bottom: 1px solid aqua; background: #e0ffff; @@ -185,7 +185,7 @@ body { background: #fcfb98; color: #131313; } -.cucumber ol li.announcement, td ol li.announcement, th ol li.announcement { +.cucumber ol li.message, td ol li.message, th ol li.message { border-left: 5px solid aqua; border-bottom: 1px solid aqua; background: #e0ffff; diff --git a/lib/cucumber/formatter/cucumber.sass b/lib/cucumber/formatter/cucumber.sass index 542c78e6cf..a870eeddf7 100755 --- a/lib/cucumber/formatter/cucumber.sass +++ b/lib/cucumber/formatter/cucumber.sass @@ -24,9 +24,9 @@ $undefined: #fcfb98 $undefined_border: #faf834 $undefined_text: #131313 -$announcement: #e0ffff -$announcement_border: aqua -$announcement_text: #001111 +$message: #e0ffff +$message_border: aqua +$message_text: #001111 body font-size: 0px @@ -136,11 +136,11 @@ body border-bottom: $step_bottom $undefined_border background: $undefined color: $undefined_text - td.announcement - border-left: $step_left $announcement_border - border-bottom: $step_bottom $announcement_border - background: $announcement - color: $announcement_text + td.message + border-left: $step_left $message_border + border-bottom: $step_bottom $message_border + background: $message + color: $message_text ol list-style: none margin: 0px @@ -178,11 +178,11 @@ body border-bottom: $step_bottom $undefined_border background: $undefined color: $undefined_text - li.announcement - border-left: $step_left $announcement_border - border-bottom: $step_bottom $announcement_border - background: $announcement - color: $announcement_text + li.message + border-left: $step_left $message_border + border-bottom: $step_bottom $message_border + background: $message + color: $message_text margin-left: 10px #summary margin: 0px diff --git a/lib/cucumber/formatter/gherkin_formatter_adapter.rb b/lib/cucumber/formatter/gherkin_formatter_adapter.rb index 1589cc67aa..440fcd953d 100644 --- a/lib/cucumber/formatter/gherkin_formatter_adapter.rb +++ b/lib/cucumber/formatter/gherkin_formatter_adapter.rb @@ -11,9 +11,6 @@ def initialize(gherkin_formatter, print_emtpy_match) @print_emtpy_match = print_emtpy_match end - def before_features(features) - end - def before_feature(feature) @gf.uri(feature.file) @gf.feature(feature.gherkin_statement) @@ -21,12 +18,10 @@ def before_feature(feature) def before_background(background) @outline = false - @gf.steps(background.raw_steps) @gf.background(background.gherkin_statement) end def before_feature_element(feature_element) - @gf.steps(feature_element.raw_steps) case(feature_element) when Ast::Scenario @outline = false @@ -52,7 +47,7 @@ def before_step(step) end def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background) - arguments = step_match.step_arguments.map{|a| Gherkin::Formatter::Argument.new(a.byte_offset, a.val)} + arguments = step_match.step_arguments.map{|a| Gherkin::Formatter::Argument.new(a.offset, a.val)} location = step_match.file_colon_line match = Gherkin::Formatter::Model::Match.new(arguments, location) if @print_emtpy_match @@ -76,8 +71,16 @@ def after_feature(feature) @gf.eof end + def after_features(features) + @gf.done + end + def embed(file, mime_type, label) - @gf.embedding(mime_type, File.read(file)) + data = File.read(file) + if defined?(JRUBY_VERSION) + data = data.to_java_bytes + end + @gf.embedding(mime_type, data) end end end diff --git a/lib/cucumber/formatter/html.rb b/lib/cucumber/formatter/html.rb index e645458ea5..59a55fc5fd 100644 --- a/lib/cucumber/formatter/html.rb +++ b/lib/cucumber/formatter/html.rb @@ -20,21 +20,23 @@ def initialize(step_mother, path_or_io, options) @scenario_number = 0 @step_number = 0 @header_red = nil - @delayed_announcements = [] + @delayed_messages = [] + @img_id = 0 end - def embed(file, mime_type, label) + def embed(src, mime_type, label) case(mime_type) when /^image\/(png|gif|jpg|jpeg)/ - embed_image(file, label) + embed_image(src, label) end end - def embed_image(file, label) - id = file.hash + def embed_image(src, label) + id = "img_#{@img_id}" + @img_id += 1 @builder.span(:class => 'embed') do |pre| pre << %{#{label}
          - } + } end end @@ -249,7 +251,7 @@ def after_step_result(keyword, step_match, multiline_arg, status, exception, sou end end @builder << '' - print_announcements + print_messages end def step_name(keyword, step_match, status, source_indent, background) @@ -286,10 +288,10 @@ def after_multiline_arg(multiline_arg) end end - def py_string(string) + def doc_string(string) return if @hide_this_step @builder.pre(:class => 'val') do |pre| - @builder << string.gsub("\n", ' ') + @builder << h(string).gsub("\n", ' ') end end @@ -303,13 +305,13 @@ def before_table_row(table_row) def after_table_row(table_row) return if @hide_this_step - print_table_row_announcements + print_table_row_messages @builder << '