flatware 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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