cuukie 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,8 +1,9 @@
1
1
  source :rubygems
2
2
 
3
- gem 'sinatra'
4
- gem 'rest-client'
5
- gem 'cucumber'
3
+ gem 'sinatra', "~> 1.3"
4
+ gem 'cucumber', "~> 1.1"
5
+ gem 'rest-client', "~> 1.6"
6
+ gem 'launchy'
6
7
  gem 'syntax'
7
8
 
8
9
  group :development do
@@ -4,48 +4,48 @@ Cuukie shows your Cucumber results on a web page.
4
4
 
5
5
  [![Build Status](https://secure.travis-ci.org/nusco/cuukie.png)](http://travis-ci.org/nusco/cuukie.png)
6
6
 
7
- ## Using it
8
-
9
- Install Cuukie:
7
+ Install Cuukie via Bundler, or directly with:
10
8
 
11
9
  gem install cuukie
12
10
 
13
- (Or better still, you can use Bundler).
14
-
15
- Require Cuukie from any file in your _features/support_ directory:
11
+ Go to your Cucumber folder and add this line to any file in _features/support_:
16
12
 
17
13
  require 'cuukie'
18
14
 
19
- Add this line to any Ruby file in your _features/support_ directory:
15
+ Run Cuukie:
20
16
 
21
- require 'cuukie'
17
+ cuukie --showpage
18
+
19
+ Cuukie passes any command-line argument that it doesn't recognize to Cucumber, so just use _cuukie_ instead of _cucumber_ when you want to see your features in the browser.
22
20
 
23
- Start the Cuukie server from a terminal window:
21
+ ## Advanced Cuuking
24
22
 
25
- cuukie_server
23
+ Cuukie is actually two things: a server that displays running features on a web page, and a Cucumber formatter that sends data to the server. You can run these two components independently. For example, you might want to keep the server running all the time:
26
24
 
27
- Leave the server running. When you run Cucumber, ask it to use the _cuukie_ formatter:
25
+ cuukie --server
26
+
27
+ When you run Cucumber, ask it to use the _cuukie_ formatter to send data to the server:
28
28
 
29
29
  cucumber --format cuukie
30
-
31
- To look at the results, open this page in a browser:
32
30
 
33
- http://localhost:4569
31
+ To look at the results, visit:
34
32
 
35
- ## Custom port/server
33
+ http://localhost:4569
36
34
 
37
- You can pick a port when you start the cuukie_server...
35
+ You can pick a port when you start the cuukie server...
38
36
 
39
- cuukie_server 4570
37
+ cuukie --server --cuukieport 4570
40
38
 
41
39
  ...and you can tell the cuukie formatter where to look for the server:
42
40
 
43
41
  cucumber --format cuukie CUUKIE_SERVER=http://my.server:4570
44
42
 
45
- ## Cuukie Vision
43
+ This stuff is useful if you want to put the Cuukie server on your build machine. For more options:
44
+
45
+ cuukie --help
46
46
 
47
- Right now, Cuukie is not any more useful than Cucumber's own HTML formatter. My plan is to make it more dynamic. You'll be able to see your steps as they run, just like you do with the default command-line formatter - but on a web page. Cuukie wants to be a good choice both when you want to run Cucumber tests locally, and when you want to show Cucumber tests on your build machine.
47
+ Enjoy!
48
48
 
49
49
  ## License
50
50
 
51
- MIT License. Copyright (c) 2011 Paolo "Nusco" Perrotta. I ripped a few lines of code off Cucumber's HTML formatter.
51
+ MIT License. Copyright (c) 2011 Paolo "Nusco" Perrotta. I also ripped a few lines of code off Cucumber's HTML formatter.
data/Rakefile CHANGED
@@ -7,8 +7,8 @@ namespace :test do
7
7
  desc "Run all specs"
8
8
  RSpec::Core::RakeTask.new(:specs)
9
9
 
10
- desc "Run Cuukie on the test project (needs a cuukie_server on localhost, default port)"
11
- task :smoke do
10
+ desc "Run Cuukie on the test project (needs a cuukie server on localhost, default port)"
11
+ task :manual do
12
12
  system "cd spec/test_project && \
13
13
  cucumber --format cuukie"
14
14
  end
@@ -19,8 +19,8 @@ Jeweler::Tasks.new do |gem|
19
19
  gem.name = "cuukie"
20
20
  gem.homepage = "http://github.com/nusco/cuukie"
21
21
  gem.license = "MIT"
22
+ gem.description = %Q{A drop-in replacement for the "cucumber" command. It shows running features on a web page.}
22
23
  gem.summary = %Q{A continuous view on Cucumber features}
23
- gem.description = %Q{Shows Cucumber results on a web page as they run.}
24
24
  gem.email = "paolo.nusco.perrotta@gmail.com"
25
25
  gem.authors = ['Paolo "Nusco" Perrotta']
26
26
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.2.0
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ lib = File.dirname(__FILE__) + '/../lib'
3
+ $:.unshift lib unless $:.include? lib
4
+
5
+ require 'cuukie/cli'
6
+ include Cuukie::Cli
7
+ options = parse_options ARGV
8
+
9
+ exit if options.empty?
10
+
11
+ server_command = "ruby #{File.dirname(__FILE__)}/../lib/cuukie/server.rb #{options[:cuukieport]}"
12
+ if options[:server]
13
+ system server_command
14
+ exit
15
+ else
16
+ Process.detach(fork { system "#{server_command} >/dev/null 2>&1" })
17
+ end
18
+
19
+ unless options[:keepserver]
20
+ at_exit do
21
+ require 'rest-client'
22
+ begin
23
+ RestClient.delete "http://localhost:#{options[:cuukieport]}"
24
+ rescue; end
25
+ end
26
+ end
27
+
28
+ if options[:showpage]
29
+ require 'launchy'
30
+ Launchy.open("http://localhost:#{options[:cuukieport]}")
31
+ else
32
+ puts "View your features at http://localhost:#{options[:cuukieport]}"
33
+ end
34
+
35
+ # TODO: auto-require formatter (warning: if you tell Cucumber to --require
36
+ # something, it will want to --require everything!)
37
+ system "cucumber #{ARGV.join(' ')} --format cuukie"
38
+
39
+ unless options[:nowait]
40
+ puts 'Press a key to exit'
41
+ gets
42
+ end
@@ -5,14 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cuukie"
8
- s.version = "0.1.4"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Paolo \"Nusco\" Perrotta"]
12
- s.date = "2011-12-08"
13
- s.description = "Shows Cucumber results on a web page as they run."
12
+ s.date = "2011-12-15"
13
+ s.description = "A drop-in replacement for the \"cucumber\" command. It shows running features on a web page."
14
14
  s.email = "paolo.nusco.perrotta@gmail.com"
15
- s.executables = ["cuukie_server"]
15
+ s.executables = ["cuukie"]
16
16
  s.extra_rdoc_files = [
17
17
  "README.markdown"
18
18
  ]
@@ -24,19 +24,21 @@ Gem::Specification.new do |s|
24
24
  "README.markdown",
25
25
  "Rakefile",
26
26
  "VERSION",
27
- "bin/cuukie_server",
27
+ "bin/cuukie",
28
28
  "cuukie.gemspec",
29
29
  "doc/LICENSE.txt",
30
30
  "doc/backlog.txt",
31
31
  "doc/pomodoro.txt",
32
32
  "lib/cuukie.rb",
33
- "lib/cuukie/cucumber/formatter/code_snippets.rb",
34
- "lib/cuukie/cucumber/formatter/cuukie.rb",
33
+ "lib/cuukie/cli.rb",
34
+ "lib/cuukie/code_snippets.rb",
35
+ "lib/cuukie/formatter.rb",
35
36
  "lib/cuukie/public/cucumber.css",
36
37
  "lib/cuukie/public/cuukie.js",
37
38
  "lib/cuukie/public/jquery-1.7.min.js",
38
39
  "lib/cuukie/server.rb",
39
40
  "lib/cuukie/views/index.erb",
41
+ "spec/cli_spec.rb",
40
42
  "spec/code_snippets_spec.rb",
41
43
  "spec/commands_spec.rb",
42
44
  "spec/cuukie_spec.rb",
@@ -59,24 +61,27 @@ Gem::Specification.new do |s|
59
61
  s.specification_version = 3
60
62
 
61
63
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
62
- s.add_runtime_dependency(%q<sinatra>, [">= 0"])
63
- s.add_runtime_dependency(%q<rest-client>, [">= 0"])
64
- s.add_runtime_dependency(%q<cucumber>, [">= 0"])
64
+ s.add_runtime_dependency(%q<sinatra>, ["~> 1.3"])
65
+ s.add_runtime_dependency(%q<cucumber>, ["~> 1.1"])
66
+ s.add_runtime_dependency(%q<rest-client>, ["~> 1.6"])
67
+ s.add_runtime_dependency(%q<launchy>, [">= 0"])
65
68
  s.add_runtime_dependency(%q<syntax>, [">= 0"])
66
69
  s.add_development_dependency(%q<rake>, [">= 0"])
67
70
  s.add_development_dependency(%q<jeweler>, [">= 0"])
68
71
  else
69
- s.add_dependency(%q<sinatra>, [">= 0"])
70
- s.add_dependency(%q<rest-client>, [">= 0"])
71
- s.add_dependency(%q<cucumber>, [">= 0"])
72
+ s.add_dependency(%q<sinatra>, ["~> 1.3"])
73
+ s.add_dependency(%q<cucumber>, ["~> 1.1"])
74
+ s.add_dependency(%q<rest-client>, ["~> 1.6"])
75
+ s.add_dependency(%q<launchy>, [">= 0"])
72
76
  s.add_dependency(%q<syntax>, [">= 0"])
73
77
  s.add_dependency(%q<rake>, [">= 0"])
74
78
  s.add_dependency(%q<jeweler>, [">= 0"])
75
79
  end
76
80
  else
77
- s.add_dependency(%q<sinatra>, [">= 0"])
78
- s.add_dependency(%q<rest-client>, [">= 0"])
79
- s.add_dependency(%q<cucumber>, [">= 0"])
81
+ s.add_dependency(%q<sinatra>, ["~> 1.3"])
82
+ s.add_dependency(%q<cucumber>, ["~> 1.1"])
83
+ s.add_dependency(%q<rest-client>, ["~> 1.6"])
84
+ s.add_dependency(%q<launchy>, [">= 0"])
80
85
  s.add_dependency(%q<syntax>, [">= 0"])
81
86
  s.add_dependency(%q<rake>, [">= 0"])
82
87
  s.add_dependency(%q<jeweler>, [">= 0"])
@@ -1,12 +1,12 @@
1
- MMF 0.1.5
2
- - show incomplete suite
3
- - show undefined Scenarios/suite
4
- - show undefined Steps
5
- - show incomplete wrap-up for steps/scenarios
6
- - show incomplete running time
7
- MMF 0.1.6
1
+ MMF 0.2.1
2
+ - better error messages
3
+ - work on any cucumber project out of the box (no need to add require())
4
+ MMF 0.2.2
8
5
  - deal with Scenario Examples
6
+ MMF 0.2.3
9
7
  - open/close steps
8
+ MMF 0.2.4
9
+ - show incomplete wrap-up for steps/scenarios
10
10
  MMF 1.0.0
11
11
  - nice graphics
12
12
  - self-updating Steps
@@ -22,6 +22,9 @@ Then...
22
22
 
23
23
  - filter by tag
24
24
 
25
+ - default policy for open/close elements (like: close
26
+ successfull scenarios/steps, open unsuccessful ones)
27
+
25
28
  - instead of showing scenarios that appear one by one,
26
29
  show the entire suite ASAP, and then proceed to make
27
30
  each scenario red or green (or whatever). this
@@ -1,6 +1,28 @@
1
1
  I use this file to track my own work on the project. Each line is a pomodoro (a 25' slot).
2
2
  Latest pomodoro comes first:
3
3
 
4
+ - release
5
+ - refactoring and README
6
+ - refactoring
7
+ - command-line options
8
+ - roll bin/cuukie_server into bin/cuukie
9
+ - command-line options
10
+ - command-line options
11
+ - command-line options
12
+ - command-line options
13
+ - command-line options
14
+ - command-line options
15
+ - command-line options
16
+ - hide stats until run completion
17
+ - show incomplete running time
18
+ - show incomplete running time
19
+ - fix feature keywords
20
+ - "cuukie" command
21
+ - "cuukie" command
22
+ - show undefined scenarios and steps
23
+ - show incomplete status bar suite
24
+ - refactoring
25
+ - refactoring
4
26
  - show code snippets (and release 0.1.4)
5
27
  - show code snippets
6
28
  - show code snippets
@@ -1 +1 @@
1
- require File.dirname(__FILE__) + '/cuukie/cucumber/formatter/cuukie'
1
+ require File.dirname(__FILE__) + '/cuukie/formatter'
@@ -0,0 +1,48 @@
1
+ require 'optparse'
2
+
3
+ Version = File.read File.dirname(__FILE__) + '/../../VERSION' unless Kernel.const_defined? :Version
4
+
5
+ module Cuukie
6
+ module Cli
7
+ def parse_options(options)
8
+ to_options_hash extract_cuukie_options(options)
9
+ end
10
+
11
+ private
12
+
13
+ def extract_cuukie_options(options)
14
+ result = []
15
+ ['--server', '--showpage', '--nowait', '--keepserver', '-h', '--help'].each do |opt|
16
+ result << options.delete(opt)
17
+ end
18
+ if (options.include? '--cuukieport')
19
+ port = options.delete_at(options.index('--cuukieport') + 1)
20
+ result << options.delete('--cuukieport') << port
21
+ end
22
+ result.compact!
23
+ end
24
+
25
+ def to_options_hash(options)
26
+ result = { :cuukieport => 4569 }
27
+ [:server, :showpage, :nowait, :keepserver].each do |opt|
28
+ result[opt] = false
29
+ end
30
+
31
+ OptionParser.new do |opts|
32
+ opts.banner = "cuukie #{::Version}\nUsage: cuukie [options] [cucumber-options]"
33
+
34
+ opts.on("--cuukieport PORT", Integer, "Start the server on PORT") {|port| result[:cuukieport] = port }
35
+ opts.on("--server", "Run as a server") { result[:server] = true }
36
+ opts.on("--showpage", "Open the features in the default browser") { result[:showpage] = true }
37
+ opts.on("--nowait", "Don't wait for keypress on exit") { result[:nowait] = true }
38
+ opts.on("--keepserver", "Leave the server running on exit") { result[:keepserver] = true }
39
+
40
+ opts.on_tail("-h", "--help", "You're looking at it") do
41
+ puts opts.help
42
+ return {}
43
+ end
44
+ end.parse! options
45
+ result
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ module Cuukie
2
+ module CodeSnippets
3
+ def code_snippet(file, line)
4
+ return null_snippet unless File.exist? file
5
+
6
+ all_lines = File.open(file) {|f| f.readlines}
7
+ return null_snippet unless line <= all_lines.size
8
+
9
+ first_line = [1, line - 2].max
10
+
11
+ { :raw_lines => all_lines[(first_line - 1)..line].join,
12
+ :first_line => first_line,
13
+ :marked_line => line }
14
+ end
15
+
16
+ def backtrace_to_snippet(backtrace)
17
+ return null_snippet unless backtrace[0] =~ /(.*):(\d+)/
18
+ code_snippet $1, $2.to_i
19
+ end
20
+
21
+ private
22
+
23
+ def null_snippet; Hash.new; end
24
+ end
25
+ end
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/code_snippets'
2
+ require 'rest-client'
3
+ require 'json'
4
+
5
+ module Cuukie
6
+ class Formatter
7
+ include CodeSnippets
8
+
9
+ def initialize(*)
10
+ @server = ENV['CUUKIE_SERVER'] || 'http://localhost:4569'
11
+ RestClient.get "#{@server}/ping"
12
+ rescue
13
+ puts "I cannot find the cuukie server on #{@server}."
14
+ puts "Please start the server with cuukie --server."
15
+ exit
16
+ end
17
+
18
+ def before_features(*)
19
+ post 'before_features'
20
+ end
21
+
22
+ def before_feature(feature)
23
+ post 'before_feature', { :short_name => feature.short_name,
24
+ :description => feature.description }
25
+ end
26
+
27
+ def feature_name(keyword, *)
28
+ post 'feature_name', { :keyword => keyword }
29
+ end
30
+
31
+ def scenario_name(keyword, name, file_colon_line, *)
32
+ post 'scenario_name', { :keyword => keyword,
33
+ :name => name,
34
+ :file_colon_line => file_colon_line }
35
+ end
36
+
37
+ def before_step(step)
38
+ post 'before_step', { :keyword => step.keyword,
39
+ :name => step.name,
40
+ :file_colon_line => step.file_colon_line }
41
+ end
42
+
43
+ def before_table_row(*)
44
+ post 'before_table_row'
45
+ end
46
+
47
+ def table_cell_value(value, *)
48
+ post 'table_cell_value', { :value => value }
49
+ end
50
+
51
+ def doc_string(string)
52
+ post 'doc_string', { :multiline_string => string }
53
+ end
54
+
55
+ def exception(exception, *)
56
+ source = backtrace_to_snippet(exception.backtrace)
57
+ post 'exception', { :message => exception.message,
58
+ :backtrace => exception.backtrace.join('\n'),
59
+ :raw_lines => source[:raw_lines],
60
+ :first_line => source[:first_line],
61
+ :marked_line => source[:marked_line] }
62
+ end
63
+
64
+ def after_step_result(keyword, step_match, multiline_arg, status, *)
65
+ post 'after_step_result', { :status => status }
66
+ end
67
+
68
+ def after_steps(*)
69
+ post 'after_steps'
70
+ end
71
+
72
+ def after_features(features)
73
+ post 'after_features', { :duration => features.duration }
74
+ end
75
+
76
+ private
77
+
78
+ def post(url, params = {})
79
+ RestClient.post "#{@server}/#{url}", params.to_json
80
+ end
81
+ end
82
+ end
83
+
84
+ require 'cucumber/cli/options'
85
+ Cucumber::Cli::Options::BUILTIN_FORMATS['cuukie'] = [
86
+ 'Cuukie::Formatter',
87
+ 'Shows Cucumber results on a web page as they run'
88
+ ]