flatware 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +83 -39
  3. data/lib/flatware-cucumber.rb +1 -0
  4. data/lib/flatware-rspec.rb +1 -0
  5. data/lib/flatware.rb +2 -10
  6. data/lib/flatware/broadcaster.rb +15 -0
  7. data/lib/flatware/cli.rb +10 -34
  8. data/lib/flatware/cucumber.rb +37 -12
  9. data/lib/flatware/cucumber/checkpoint.rb +28 -0
  10. data/lib/flatware/cucumber/cli.rb +22 -0
  11. data/lib/flatware/cucumber/formatter.rb +36 -84
  12. data/lib/flatware/{formatters/cucumber → cucumber/formatters}/console.rb +5 -3
  13. data/lib/flatware/{formatters/cucumber → cucumber/formatters}/console/summary.rb +3 -3
  14. data/lib/flatware/cucumber/result.rb +27 -0
  15. data/lib/flatware/cucumber/scenario_result.rb +38 -0
  16. data/lib/flatware/cucumber/step_result.rb +30 -0
  17. data/lib/flatware/poller.rb +2 -2
  18. data/lib/flatware/rspec.rb +28 -0
  19. data/lib/flatware/rspec/checkpoint.rb +29 -0
  20. data/lib/flatware/rspec/cli.rb +16 -0
  21. data/lib/flatware/rspec/example_notification.rb +21 -0
  22. data/lib/flatware/rspec/examples_notification.rb +24 -0
  23. data/lib/flatware/rspec/formatter.rb +50 -0
  24. data/lib/flatware/rspec/formatters/console.rb +33 -0
  25. data/lib/flatware/rspec/summary.rb +40 -0
  26. data/lib/flatware/serialized_exception.rb +12 -8
  27. data/lib/flatware/sink.rb +43 -33
  28. data/lib/flatware/socket.rb +89 -25
  29. data/lib/flatware/version.rb +1 -1
  30. data/lib/flatware/worker.rb +16 -9
  31. metadata +27 -55
  32. data/lib/flatware/checkpoint.rb +0 -28
  33. data/lib/flatware/checkpoint_handler.rb +0 -45
  34. data/lib/flatware/dispatcher.rb +0 -31
  35. data/lib/flatware/fireable.rb +0 -34
  36. data/lib/flatware/formatters.rb +0 -27
  37. data/lib/flatware/formatters/cucumber/http.rb +0 -83
  38. data/lib/flatware/result.rb +0 -25
  39. data/lib/flatware/scenario_decorator.rb +0 -22
  40. data/lib/flatware/scenario_result.rb +0 -36
  41. data/lib/flatware/step_result.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfb0b2fec0892b096fda85d7117ecb063ead5624
4
- data.tar.gz: be3acf00d8248975adb052c4004bd2017b66c8f8
3
+ metadata.gz: 00a71ce8a23e22600391980c40aac3425a1efd27
4
+ data.tar.gz: '082d74e5882c2cb99bfc4af567618e70817bb08d'
5
5
  SHA512:
6
- metadata.gz: 8154c907e8c51bb3a83771cbfba07e4751b9b284965cfcd5ea634f8dd9563c28ee5da2f6c44ddbd6d326bff5ce440b42e3c30981e3f2ef3131c494037d5086a1
7
- data.tar.gz: 4d1d8adb80cb44a973427cb1af117f321c597279246bb804d13c8978e22d33f2b2f367ebc0df7b6247b9423aae49dc1e42f487d5776c3eeafb87d71c4669abf0
6
+ metadata.gz: c591c042ab1bae59ba7e25309ceae39ca389f60b1d6f340882db31e3b0806e9acd0a8dfaa512e5529a2f1f636c297c9ba5335e247d3de3b65b90e3929b2adbf3
7
+ data.tar.gz: 33043b7af9e2d929e7a99c8e53c127ac9bbc4bb366f78e74ae32e53432980d64bb2b61aa7eecf818b2611df25da68d12c0ff975a463125b35748c4227d22ab16
data/README.md CHANGED
@@ -1,83 +1,124 @@
1
1
  # Flatware [![Build Status][travis-badge]][travis] [![Code Climate][code-climate-badge]][code-climate]
2
2
 
3
- [travis-badge]: https://travis-ci.org/briandunn/flatware.png
3
+ [travis-badge]: https://travis-ci.org/briandunn/flatware.svg?branch=master
4
4
  [travis]: http://travis-ci.org/briandunn/flatware
5
5
  [code-climate-badge]: https://codeclimate.com/github/briandunn/flatware.png
6
6
  [code-climate]: https://codeclimate.com/github/briandunn/flatware
7
7
 
8
- Flatware is a distributed cucumber runner.
8
+ Flatware parallelizes your test suite to significantly reduce test time.
9
9
 
10
10
  ## Requirements
11
11
 
12
- * ZeroMQ > 2.1
12
+ * ZeroMQ > 4.0
13
13
 
14
14
  ## Installation
15
15
 
16
- Add this to your Gemfile:
16
+ ### ZeroMQ
17
17
 
18
+ #### Linux Ubuntu
19
+
20
+ ```sh
21
+ sudo apt-get install -qq libzmq3-dev
18
22
  ```
19
- gem 'flatware'
23
+
24
+ (Never you mind the 3. This package contains ZMQ version 4.)
25
+
26
+ #### Mac OSX
27
+
28
+ Ruby FFI isn't getting along with the latest ZMQ formula. A tweaked verson is available in the Hashrocket tap.
29
+
30
+ ```sh
31
+ brew tap hashrocket/formulas
32
+ brew install hashrocket/formulas/zeromq
33
+ brew install zeromq
20
34
  ```
21
35
 
22
- and `bundle install`.
36
+ ### Flatware
37
+
38
+ Add the runners you need to your Gemfile:
39
+
40
+ ```ruby
41
+ gem 'flatware-rspec' # one
42
+ gem 'flatware-cucumber' # or both
43
+ ```
44
+
45
+ then run
46
+
47
+ ```sh
48
+ bundle install
49
+ ```
23
50
 
24
51
  ## Usage
25
52
 
26
- To run your entire suite with the default cucumber options, just:
53
+ ### Cucumber
54
+
55
+ To run your entire suite with the default cucumber options, add the `flatware-cucumber` gem and just:
27
56
 
57
+ ```sh
58
+ $ flatware cucumber
28
59
  ```
29
- $ flatware
60
+
61
+ ### RSpec
62
+
63
+ To run your entire suite with the default rspec options add the `flatware-rspec` gem and just:
64
+
65
+ ```sh
66
+ $ flatware rspec
30
67
  ```
31
68
 
69
+ ### Options
70
+
32
71
  If you'd like to limit the number of forked workers, you can pass the 'w' flag:
33
72
 
34
- ```
73
+ ```sh
35
74
  $ flatware -w 3
36
75
  ```
37
76
 
38
- You can also pass most cucumber options to Flatware. For example, to run only
77
+ You can also pass most cucumber/rspec options to Flatware. For example, to run only
39
78
  features that are not tagged 'javascript', you can:
40
79
 
41
- ```
80
+ ```sh
42
81
  $ flatware cucumber -t ~@javascript
43
82
  ```
44
83
 
84
+ Additionally, for either cucumber or rspec you can specify a directory:
85
+
86
+ ```sh
87
+ $ flatware rspec spec/features
88
+ ```
89
+
45
90
  ## Typical Usage in a Rails App
46
91
 
47
- Add the following to your config/database.yml:
92
+ Add the following to your `config/database.yml`:
48
93
 
49
- ```
94
+ ```yml
50
95
  test:
51
96
  database: foo_test
52
97
  ```
53
98
 
54
99
  becomes:
55
100
 
56
- ```
101
+ ```yml
57
102
  test:
58
103
  database: foo_test<%=ENV['TEST_ENV_NUMBER']%>
59
104
  ```
60
105
 
61
106
  Run the following:
62
107
 
63
- ```
108
+ ```sh
64
109
  $ rake db:setup # if not already done
65
110
  $ flatware fan rake db:test:prepare
66
111
  ```
67
112
 
68
113
  Now you are ready to rock:
69
114
 
70
- ```
71
- $ flatware
115
+ ```sh
116
+ $ flatware rspec && flatware cucumber
72
117
  ```
73
118
 
74
119
  ## Planned Features
75
120
 
76
- * Reliable enough to use as part of your Continuous Integration system
77
- * Always accounts for every feature you ask it to run
78
121
  * Use heuristics to run your slowest tests first
79
- * speak Cucumber's DRB protocol; if you know how to use Spork you know how to
80
- use Flatware
81
122
 
82
123
  ## Design Goals
83
124
 
@@ -86,28 +127,35 @@ $ flatware
86
127
  * Fully test at an integration level. Don't be afraid to change the code. If you
87
128
  break it you'll know.
88
129
  * Couple as loosely as possible, and only to the most stable/public bits of
89
- Cucumber.
130
+ Cucumber and RSpec.
90
131
 
91
132
  ### Minimal
92
133
 
93
- * Projects define their own preperation scripts
134
+ * Projects define their own preparation scripts
94
135
  * Only distribute to local cores (for now)
95
- * Only handle cucumber
96
136
 
97
137
  ### Robust
98
138
 
99
139
  * Depend on a dedicated messaging library
100
- * Be acountable for completed work; provide progress report regardless of
140
+ * Be accountable for completed work; provide progress report regardless of
101
141
  completing the suite.
102
142
 
103
143
  ## Tinkering
104
144
 
105
- Flatware is tested with [aruba][]. In order to get a demo cucumber project you
145
+ Flatware integration tests use [aruba][a]. In order to get a demo cucumber project you
106
146
  can add the `@no-clobber` tag to `features/flatware.feature` and run the test
107
147
  with `cucumber features/flatware.feature`. Now you should have a `./tmp/aruba`
108
148
  directory. CD there and `flatware` will be in your path so you can tinker away.
109
149
 
110
- [aruba]: https://github.com/cucumber/aruba
150
+ ## How it works
151
+
152
+ Flatware relies on a message passing system to enable concurrency.
153
+ The main process declares a worker for each cpu in the computer. Each
154
+ worker forks from the main process and is then assigned a portion of the
155
+ test suite. As the worker runs the test suite it sends progress
156
+ messages to the main process. These messages are collected and when
157
+ the last worker is finished the main process provides a report on the
158
+ collected progress messages.
111
159
 
112
160
  ## Resources
113
161
 
@@ -115,18 +163,14 @@ To learn more about the messaging system that Flatware uses, take a look at the
115
163
  [excellent ZeroMQ guide][z].
116
164
 
117
165
  [z]: http://zguide.zeromq.org/page:all
166
+ [a]: https://github.com/cucumber/aruba
118
167
 
119
168
  ## Contributing to Flatware
120
169
 
121
- * Check out the latest master to make sure the feature hasn't been implemented
122
- or the bug hasn't been fixed yet
123
- * Check out the issue tracker to make sure someone already hasn't requested it
124
- and/or contributed it
125
- * Fork the project
126
- * Start a feature/bugfix branch
127
- * Commit and push until you are happy with your contribution
128
- * Make sure to add tests for it. This is important so I don't break it in a
129
- future version unintentionally.
130
- * Please try not to mess with the Rakefile, version, or history. If you want to
131
- have your own version, or is otherwise necessary, that is fine, but please
132
- isolate to its own commit so I can cherry-pick around it.
170
+ Do whatever you want. I'd love to help make sure Flatware meets your needs.
171
+
172
+ ## About
173
+
174
+ [![Hashrocket logo](https://hashrocket.com/hashrocket_logo.svg)](https://hashrocket.com)
175
+
176
+ Flatware is supported by the team at [Hashrocket](https://hashrocket.com), a multidisciplinary design & development consultancy. If you'd like to [work with us](https://hashrocket.com/contact-us/hire-us) or [join our team](https://hashrocket.com/contact-us/jobs), don't hesitate to get in touch.
@@ -0,0 +1 @@
1
+ require 'flatware/cucumber'
@@ -0,0 +1 @@
1
+ require 'flatware/rspec'
@@ -1,17 +1,9 @@
1
1
  module Flatware
2
- require 'flatware/checkpoint'
3
- require 'flatware/checkpoint_handler'
4
2
  require 'flatware/processor_info'
5
3
  require 'flatware/cli'
6
- require 'flatware/cucumber'
7
- require 'flatware/dispatcher'
8
- require 'flatware/fireable'
9
- require 'flatware/formatters'
10
- require 'flatware/result'
11
- require 'flatware/scenario_decorator'
12
- require 'flatware/scenario_result'
4
+ require 'flatware/poller'
13
5
  require 'flatware/sink'
14
6
  require 'flatware/socket'
15
- require 'flatware/step_result'
16
7
  require 'flatware/worker'
8
+ require 'flatware/broadcaster'
17
9
  end
@@ -0,0 +1,15 @@
1
+ module Flatware
2
+ class Broadcaster
3
+ attr_reader :formatters
4
+
5
+ def initialize(formatters)
6
+ @formatters = formatters
7
+ end
8
+
9
+ def method_missing(name, *args)
10
+ formatters.each do |formatter|
11
+ formatter.send name, *args if formatter.respond_to? name
12
+ end
13
+ end
14
+ end
15
+ end
@@ -13,26 +13,6 @@ module Flatware
13
13
 
14
14
  class_option :log, aliases: "-l", type: :boolean, desc: "Print debug messages to $stderr"
15
15
 
16
- default_task :default
17
- worker_option
18
- desc "default [FLATWARE_OPTS]", "parallelizes cucumber with default arguments"
19
- def default(*)
20
- invoke :cucumber
21
- end
22
-
23
- worker_option
24
- method_option 'fail-fast', type: :boolean, default: false, desc: "Abort the run on first failure"
25
- method_option 'formatters', aliases: "-f", type: :array, default: %w[console], desc: "The formatters to use for output"
26
- method_option 'dispatch-endpoint', type: :string, default: 'ipc://dispatch'
27
- method_option 'sink-endpoint', type: :string, default: 'ipc://task'
28
- desc "[FLATWARE_OPTS] cucumber [CUCUMBER_ARGS]", "parallelizes cucumber with custom arguments"
29
- def cucumber(*)
30
- jobs = Cucumber.extract_jobs_from_args cucumber_args
31
- Worker.spawn workers, Cucumber, options['dispatch-endpoint'], options['sink-endpoint']
32
- formatter = Formatters.load_by_name(:cucumber, options['formatters'])
33
- start_sink jobs, formatter
34
- end
35
-
36
16
  worker_option
37
17
  desc "fan [COMMAND]", "executes the given job on all of the workers"
38
18
  def fan(*command)
@@ -49,7 +29,6 @@ module Flatware
49
29
  Process.waitall
50
30
  end
51
31
 
52
-
53
32
  desc "clear", "kills all flatware processes"
54
33
  def clear
55
34
  (Flatware.pids - [$$]).each do |pid|
@@ -59,24 +38,13 @@ module Flatware
59
38
 
60
39
  private
61
40
 
62
- def start_sink(jobs, formatter)
41
+ def start_sink(jobs:, workers:, formatter:)
63
42
  $0 = 'flatware sink'
64
43
  Process.setpgrp
65
- Flatware.verbose = options[:log]
66
- Dispatcher.spawn jobs, options['dispatch-endpoint']
67
- passed = Sink.start_server jobs, formatter, options['sink-endpoint'], fail_fast: options['fail-fast']
68
- Process.waitall
44
+ passed = Sink.start_server jobs: jobs, formatter: Flatware::Broadcaster.new([formatter]), sink: options['sink-endpoint'], dispatch: options['dispatch-endpoint'], worker_count: workers
69
45
  exit passed ? 0 : 1
70
46
  end
71
47
 
72
- def cucumber_args
73
- if index = ARGV.index('cucumber')
74
- ARGV[index + 1..-1]
75
- else
76
- []
77
- end
78
- end
79
-
80
48
  def log(*args)
81
49
  Flatware.log(*args)
82
50
  end
@@ -86,3 +54,11 @@ module Flatware
86
54
  end
87
55
  end
88
56
  end
57
+
58
+ flatware_gems = Gem.loaded_specs.keys.grep(/^flatware-/)
59
+
60
+ if flatware_gems.count > 0
61
+ flatware_gems.each(&method(:require))
62
+ else
63
+ puts "The flatware gem is a dependency of flatware runners for rspec and cucumber. Try adding flatware-rspec or flatware-cucumber to your Gemfile."
64
+ end
@@ -1,26 +1,51 @@
1
1
  require 'cucumber'
2
- require 'flatware/cucumber/runtime'
2
+ require 'flatware/cucumber/checkpoint'
3
+ require 'flatware/cucumber/formatter'
4
+ require 'flatware/cucumber/result'
5
+ require 'flatware/cucumber/scenario_result'
6
+ require 'flatware/cucumber/step_result'
7
+ require 'flatware/cucumber/formatters/console'
8
+ require 'flatware/cucumber/cli'
9
+
3
10
  module Flatware
4
11
  module Cucumber
12
+ class Config
13
+ attr_reader :config, :args
14
+ def initialize(cucumber_config, args)
15
+ @config, @args = cucumber_config, args
16
+ end
5
17
 
6
- extend self
18
+ def feature_dir
19
+ @config.feature_dirs.first
20
+ end
21
+
22
+ def jobs
23
+ feature_files.map { |file| Job.new file, args }.to_a
24
+ end
25
+
26
+ private
7
27
 
8
- attr_reader :jobs
28
+ def feature_files
29
+ config.feature_files - config.feature_dirs
30
+ end
31
+ end
32
+
33
+ extend self
9
34
 
10
- def extract_jobs_from_args(args=[], out_stream=$stdout, error_stream=$stderr)
35
+ def configure(args, out_stream=$stdout, error_stream=$stderr)
11
36
  raw_args = args.dup
12
- config = ::Cucumber::Cli::Configuration.new(out_stream, error_stream)
13
- config.parse! args
14
- options = raw_args - args
15
- @jobs = config.feature_files.map { |file| Job.new file, options }
37
+ cli_config = ::Cucumber::Cli::Configuration.new(out_stream, error_stream)
38
+ cli_config.parse! args + %w[--format Flatware::Cucumber::Formatter]
39
+ cucumber_config = ::Cucumber::Configuration.new cli_config
40
+ Config.new cucumber_config, raw_args
16
41
  end
17
42
 
18
- def run(feature_files=[], options=[])
19
- runtime.run feature_files, options
43
+ def run(feature_files, options)
44
+ runtime(Array(feature_files) + options).run!
20
45
  end
21
46
 
22
- def runtime
23
- @runtime ||= Runtime.new
47
+ def runtime(args)
48
+ ::Cucumber::Runtime.new(configure(args).config)
24
49
  end
25
50
  end
26
51
  end
@@ -0,0 +1,28 @@
1
+ module Flatware
2
+ module Cucumber
3
+ class Checkpoint
4
+ attr_reader :steps, :scenarios
5
+ def initialize(steps, scenarios)
6
+ @steps, @scenarios = serialize_steps(steps), serialize_scenarios(scenarios)
7
+ end
8
+
9
+ def failures?
10
+ scenarios.any? &:failed?
11
+ end
12
+
13
+ private
14
+
15
+ def serialize_steps(steps)
16
+ steps.map do |step|
17
+ StepResult.new step.status, step.exception
18
+ end
19
+ end
20
+
21
+ def serialize_scenarios(scenarios)
22
+ scenarios.map do |scenario|
23
+ ScenarioResult.new scenario.status, scenario.file_colon_line, scenario.name, scenario.exception
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ require 'flatware/cli'
2
+
3
+ module Flatware
4
+ class CLI
5
+ worker_option
6
+ method_option 'dispatch-endpoint', type: :string, default: 'ipc://dispatch'
7
+ method_option 'sink-endpoint', type: :string, default: 'ipc://task'
8
+ desc "cucumber [FLATWARE_OPTS] [CUCUMBER_ARGS]", "parallelizes cucumber with custom arguments"
9
+ def cucumber(*args)
10
+ config = Cucumber.configure args
11
+
12
+ unless config.jobs.any?
13
+ puts "Please create some feature files in the #{config.feature_dir} directory."
14
+ exit 1
15
+ end
16
+
17
+ Flatware.verbose = options[:log]
18
+ Worker.spawn count: workers, runner: Cucumber, dispatch: options['dispatch-endpoint'], sink: options['sink-endpoint']
19
+ start_sink jobs: config.jobs, workers: workers, formatter: Flatware::Cucumber::Formatters::Console.new($stdout, $stderr)
20
+ end
21
+ end
22
+ end