qspec 0.1.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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in qspec.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 tomykaira
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,69 @@
1
+ # Qspec
2
+
3
+ Qspec makes rspec test fast. Q is for **queue** and **quick**.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'qspec'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install qspec
18
+
19
+ ## Additional Installation
20
+
21
+ You can use `spork` to cut the overhead of Qspec startup.
22
+ **Use 1.0**. Old `spork` does not detect Qspec.
23
+
24
+ ```ruby
25
+ gem 'spork', '~> 1.0rc'
26
+ ```
27
+
28
+ If you are on rails, remember to add `spork-rails` too.
29
+
30
+ By default, qspec uses file based inter-process communication.
31
+ This is poorly implemented and becomes a burden.
32
+
33
+ We recommend to use `redis`.
34
+
35
+ - Setting up redis-server with default port
36
+ - Add `redis` gem to your Gemfile
37
+ - Specify `redis` for IPC method in `.qspec.yml`
38
+
39
+ ## Usage
40
+
41
+ Installing this gem adds `qspec` and `qspec-helper` commands.
42
+
43
+ ### Setup
44
+
45
+ ```sh
46
+ $ bundle exec qspec-helper init
47
+ # edit .qspec.yml
48
+ ```
49
+
50
+ ### Run spec
51
+
52
+ ```sh
53
+ bundle exec qspec spec/
54
+ ```
55
+
56
+ ### Run with spork
57
+
58
+ ```sh
59
+ bundle exec qspec-helper spork
60
+ bundle exec qspec spec/
61
+ ```
62
+
63
+ ## Contributing
64
+
65
+ 1. Fork it
66
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
67
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
68
+ 4. Push to the branch (`git push origin my-new-feature`)
69
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'qspec'
4
+ status = Qspec::CommandLine.new(ARGV).run($stderr, $stdout).to_i
5
+ exit status
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'qspec'
4
+ Qspec::Helper.new(ARGV).serve
@@ -0,0 +1,19 @@
1
+ require 'rspec/core'
2
+ require 'qspec/version'
3
+ require 'qspec/ipc'
4
+ require 'qspec/manager'
5
+ require 'qspec/spork_helper'
6
+ require 'qspec/command_line'
7
+ require 'qspec/formatters/redis_formatter'
8
+ require 'qspec/config'
9
+ require 'qspec/helper'
10
+
11
+ module Qspec
12
+ DIRECTORY = File.expand_path('tmp/qspec')
13
+
14
+ FileUtils.mkdir_p(DIRECTORY) unless FileTest.exists?(DIRECTORY)
15
+
16
+ def self.path(filename)
17
+ File.join(DIRECTORY, filename)
18
+ end
19
+ end
@@ -0,0 +1,54 @@
1
+ require 'rspec/core/command_line'
2
+
3
+ module Qspec
4
+ class CommandLine < ::RSpec::Core::CommandLine
5
+ include Manager # defines start_worker
6
+ include SporkHelper
7
+ attr_reader :output, :ipc, :config, :id
8
+
9
+ def initialize(options)
10
+ @config = Config.new()
11
+ @ipc = IPC.from_config(@config['ipc'])
12
+ @id = ENV['qspec_id']
13
+
14
+ super(options)
15
+ end
16
+
17
+ def run(err, out)
18
+ @configuration.error_stream = err
19
+ @output = @configuration.output_stream ||= out
20
+ @options.configure(@configuration)
21
+
22
+ if @id
23
+ process
24
+ else
25
+ start_worker
26
+ end
27
+ end
28
+
29
+ def process
30
+ success = true
31
+ while f = ipc.lpop("to_run_#{id}")
32
+ @configuration.add_formatter(Qspec::Formatters::RedisFormatterFactory.build(id, f))
33
+ begin
34
+ load File.expand_path(f)
35
+ @configuration.reporter.report(@world.example_count, @configuration.randomize? ? @configuration.seed : nil) do |reporter|
36
+ begin
37
+ GC.disable if @config['no_gc']
38
+ @configuration.run_hook(:before, :suite)
39
+ success &&= @world.example_groups.ordered.all? {|g| g.run(reporter)}
40
+ ensure
41
+ @configuration.run_hook(:after, :suite)
42
+ GC.enable if @config['no_gc']
43
+ GC.start if @config['no_gc']
44
+ end
45
+ end
46
+ ensure
47
+ @world.example_groups.clear
48
+ @configuration.reset # formatter, reporter
49
+ end
50
+ end
51
+ success ? 0 : @configuration.failure_exit_code
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+ require 'yaml'
2
+
3
+ module Qspec
4
+ class Config
5
+ DEFAULT_PATH = '.qspec.yml'
6
+
7
+ def initialize(path = DEFAULT_PATH)
8
+ @path = path
9
+ if File.exists?(path)
10
+ @config = YAML.load_file(path)
11
+ else
12
+ STDERR.puts "You do not have #{path}. Initialize with `qspec-helper init`"
13
+ exit 1
14
+ end
15
+ end
16
+
17
+ def [](key)
18
+ @config[key]
19
+ end
20
+
21
+ def self.create_template(path = DEFAULT_PATH)
22
+ if File.exists?(path)
23
+ STDERR.puts "You already have a template file #{path}. Remove it if you want to reset."
24
+ exit 1
25
+ end
26
+ File.open(path, 'w') do |f|
27
+ f.write <<TMPL
28
+ # DO NOT check this file into VCS (e.g. git).
29
+ # Parallelization setting differs between machines.
30
+ no_gc: false
31
+ ipc: file # 'file' or 'redis', if 'redis', gem and server are required
32
+ sort_by: time # 'time' or 'size', if 'time', store execution time and use it next time
33
+ workers: 4 # half of cpu - number of cpu
34
+ spork_port: 9240 # specified port..port+N-1 are used
35
+ TMPL
36
+ end
37
+ puts "Config file created in #{path}. Check it before run `qspec spec`."
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+
3
+ module Qspec
4
+ module Formatters
5
+ module RedisFormatterFactory
6
+ def self.build(id, file)
7
+ Class.new(RSpec::Core::Formatters::BaseFormatter) do
8
+ @@id = id
9
+ @@file = file
10
+ include RedisFormatterFactory
11
+ end
12
+ end
13
+
14
+ def initialize(output)
15
+ @ipc = IPC.default
16
+ super
17
+ end
18
+
19
+ def dump_failures
20
+ failed_examples.each do |example|
21
+ ex = example.execution_result[:exception]
22
+ data = {
23
+ description: example.full_description,
24
+ exception: format_exception(example, ex),
25
+ backtrace: format_backtrace(ex.backtrace, example)
26
+ }
27
+ @ipc.rpush("failure_#{@@id}", Marshal.dump(data))
28
+ end
29
+ end
30
+
31
+ def dump_summary(duration, example_count, failure_count, pending_count)
32
+ data = [@@file, duration, example_count, failure_count, pending_count]
33
+ @ipc.rpush("stat_#{@@id}", Marshal.dump(data))
34
+ end
35
+
36
+ def format_exception(example, ex)
37
+ exception_class_name = ex.class.to_s
38
+ output = StringIO.new
39
+ output.puts "* #{example.full_description}"
40
+ output.puts "\tFailure/Error: #{read_failed_line(ex, example)}"
41
+ output.puts "\t#{exception_class_name}:" unless exception_class_name =~ /RSpec/
42
+ ex.message.to_s.split("\n").each { |line| output.puts "\t #{line}" } if ex.message
43
+ output.string
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ module Qspec
2
+ class Helper
3
+ include SporkHelper
4
+
5
+ def initialize(argv)
6
+ @argv = argv
7
+ end
8
+
9
+ def serve
10
+ case @argv.last
11
+ when 'init'
12
+ puts "Creating template"
13
+ Config.create_template
14
+ when 'spork'
15
+ @config = Config.new
16
+ puts "Start #{@config['workers']} sporks"
17
+ start_spork_workers(@config['workers'])
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module Qspec
2
+ # abstract
3
+ class IPC
4
+ def self.from_config(name)
5
+ @@default =
6
+ case name
7
+ when 'redis'
8
+ require 'qspec/ipc/redis'
9
+ IPC::Redis.new
10
+ when 'file', nil
11
+ require 'qspec/ipc/file'
12
+ IPC::File.new
13
+ else
14
+ raise "Unknown IPC method #{name}"
15
+ end
16
+ end
17
+
18
+ def self.default
19
+ @@default || (raise 'Default IPC module not set')
20
+ end
21
+
22
+ def del(key)
23
+ end
24
+
25
+ def lpop(key)
26
+ end
27
+
28
+ def rpush(key, value)
29
+ end
30
+
31
+ def llen(key)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,62 @@
1
+ require 'fileutils'
2
+
3
+ module Qspec
4
+ class IPC
5
+ class File < IPC
6
+ DIRECTORY = 'tmp/qspec'
7
+
8
+ def initialize
9
+ FileUtils.mkdir_p(DIRECTORY) unless FileTest.exists?(DIRECTORY)
10
+ end
11
+
12
+ def del(key)
13
+ ::File.unlink(Qspec.path(key)) rescue nil
14
+ end
15
+
16
+ def lpop(key)
17
+ open(key, :rw) do |f|
18
+ list = safe_load(f)
19
+ f.truncate(0)
20
+ f.rewind
21
+ data = list.shift
22
+ f.write(Marshal.dump(list))
23
+ data
24
+ end
25
+ end
26
+
27
+ def rpush(key, value)
28
+ open(key, :rw) do |f|
29
+ list = safe_load(f)
30
+ f.truncate(0)
31
+ f.rewind
32
+ list.push(value)
33
+ f.write(Marshal.dump(list))
34
+ end
35
+ end
36
+
37
+ def llen(key)
38
+ open(key, :r) do |f|
39
+ safe_load(f).length
40
+ end
41
+ end
42
+
43
+ private
44
+ def open(key, type)
45
+ mode, lock = case type
46
+ when :rw then [::File::RDWR|::File::CREAT|::File::BINARY, ::File::LOCK_EX]
47
+ when :r then [::File::RDONLY|::File::CREAT|::File::BINARY, ::File::LOCK_SH]
48
+ end
49
+ ::File.open(Qspec.path(key), mode) do |f|
50
+ f.flock(lock)
51
+ f.set_encoding('ASCII-8BIT')
52
+ yield(f)
53
+ end
54
+ end
55
+
56
+ def safe_load(f)
57
+ data = f.read
58
+ data.strip == '' ? [] : Marshal.load(data)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,16 @@
1
+ require 'redis'
2
+ module Qspec
3
+ class IPC
4
+ class Redis < IPC
5
+ def initialize
6
+ @redis = ::Redis.new
7
+ end
8
+
9
+ [:del, :lpop, :rpush, :llen].each do |method|
10
+ define_method(method) do |*args|
11
+ @redis.send(method, *args)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,131 @@
1
+ require 'rspec/core/formatters/helpers'
2
+
3
+ module Qspec
4
+ module Manager
5
+ TIME_LOG_NAME = 'elapsed_time'
6
+ DEFAULT_ELAPSED_TIME = 3.0
7
+ attr_reader :output
8
+ attr_reader :id
9
+
10
+ def start_worker
11
+ @id = rand(10000)
12
+ output.puts "ID: #{id}"
13
+ register_files(id)
14
+ if runnning_ports
15
+ puts "Connecting to spork: #{runnning_ports.inspect}"
16
+ runnning_ports.each do |port|
17
+ fork do
18
+ connect_spork(port, id, @configuration.error_stream, output)
19
+ end
20
+ end
21
+ else
22
+ puts "Forking #{@config['workers']} workers"
23
+ command = "qspec #{@options.drb_argv.join " "}"
24
+ @config['workers'].times do |i|
25
+ env = {
26
+ "qspec_id" => id.to_s,
27
+ "TEST_ENV_NUMBER" => i == 0 ? '' : (i + 1).to_s }
28
+ spawn(env,
29
+ command,
30
+ out: '/dev/null')
31
+ end
32
+ end
33
+
34
+ @stats = []
35
+ thread = start_progress_thread(id)
36
+ success = Process.waitall.all? { |pid, status| status.exitstatus == 0 }
37
+ thread.exit
38
+
39
+ pop_stat(id)
40
+
41
+ output.puts "Failures: " if ipc.llen("failure_#{id}") > 0
42
+
43
+ each_object("failure_#{id}") do |failure|
44
+ dump_failure(failure)
45
+ end
46
+
47
+ log_elapsed_times
48
+ dump_summary
49
+ exit(success ? 0 : 1)
50
+ ensure
51
+ if ipc
52
+ ipc.del("to_run_#{id}")
53
+ ipc.del("stat_#{id}")
54
+ ipc.del("failure_#{id}")
55
+ end
56
+ end
57
+
58
+ private
59
+ def start_progress_thread(id)
60
+ Thread.new do
61
+ loop do
62
+ pop_stat(id)
63
+ sleep 1
64
+ end
65
+ end
66
+ end
67
+
68
+ def pop_stat(id)
69
+ each_object("stat_#{id}") do |obj|
70
+ @stats << obj
71
+ output.print "!!! " if obj[3] > 0
72
+ output.puts obj.inspect
73
+ end
74
+ end
75
+
76
+ def each_object(key)
77
+ while data = ipc.lpop(key)
78
+ yield(Marshal.load(data))
79
+ end
80
+ end
81
+
82
+ def dump_summary
83
+ sum = @stats.each_with_object({ example: 0, failure: 0, pending: 0 }) do |stat, sum|
84
+ sum[:example] += stat[2]
85
+ sum[:failure] += stat[3]
86
+ sum[:pending] += stat[4]
87
+ end
88
+ output.puts "\n#{sum[:example]} examples, #{sum[:failure]} failures, #{sum[:pending]} pendings"
89
+ end
90
+
91
+ def dump_failure(failure)
92
+ puts ""
93
+ puts failure[:exception]
94
+ failure[:backtrace].each do |line|
95
+ output.puts "\t#{line}"
96
+ end
97
+ end
98
+
99
+ def log_elapsed_times
100
+ File.open(Qspec.path(TIME_LOG_NAME), 'w') do |f|
101
+ @stats.each do |stat|
102
+ f.puts "#{File.expand_path(stat[0])}:#{stat[1].to_f}"
103
+ end
104
+ end
105
+ end
106
+
107
+ def register_files(id)
108
+ sorted_files_to_run.uniq.each do |f|
109
+ ipc.rpush "to_run_#{id}", f
110
+ end
111
+ end
112
+
113
+ def sorted_files_to_run
114
+ @sorted_files_to_run ||= if @config['sort_by'] == 'time' && File.exists?(Qspec.path(TIME_LOG_NAME))
115
+ sort_by_time(@configuration.files_to_run)
116
+ else
117
+ sort_by_size(@configuration.files_to_run)
118
+ end
119
+ end
120
+
121
+ def sort_by_time(files)
122
+ log = Hash[File.readlines(Qspec.path(TIME_LOG_NAME)).map { |line| line.strip.split(":") }]
123
+ files.sort_by { |file| log[File.expand_path(file)].to_f || DEFAULT_ELAPSED_TIME }.reverse
124
+ end
125
+
126
+ # large to small
127
+ def sort_by_size(files)
128
+ files.sort_by { |file| -File.stat(file).size }
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,65 @@
1
+ # spork is optional
2
+ begin
3
+ require 'drb/drb'
4
+ require 'spork/test_framework/qspec'
5
+ rescue LoadError
6
+ end
7
+
8
+ require 'rspec/core/drb_options'
9
+
10
+ module Qspec
11
+ module SporkHelper
12
+ def start_spork_workers(count)
13
+ Signal.trap(:INT){
14
+ puts "Stop spork processes"
15
+ remove_port_file
16
+ exit(0)
17
+ }
18
+
19
+ default_port = (@config['spork_port'] || ::Spork::TestFramework::Qspec::DEFAULT_PORT).to_i
20
+ ports = []
21
+ count.times do |i|
22
+ port = default_port+i
23
+ spawn({ "TEST_ENV_NUMBER" => i == 0 ? '' : (i + 1).to_s },
24
+ "spork qspec --port #{port}")
25
+ ports << port
26
+ end
27
+ create_port_file(ports)
28
+ Process.waitall.all? { |pid, status| status.exitstatus == 0 } ? 0 : 1
29
+ end
30
+
31
+ def connect_spork(port, id, err, out)
32
+ begin
33
+ DRb.start_service("druby://localhost:0")
34
+ rescue SocketError, Errno::EADDRNOTAVAIL
35
+ DRb.start_service("druby://:0")
36
+ end
37
+ spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{port||PORT}")
38
+ exit spec_server.run(@options.drb_argv + [id], err, out).to_i
39
+ end
40
+
41
+ def create_port_file(ports)
42
+ File.open(port_file, 'w') do |f|
43
+ f.puts ports.join("\n")
44
+ end
45
+ end
46
+
47
+ def runnning_ports
48
+ @runnning_ports ||= begin
49
+ ports = File.readlines(port_file).map { |line| line.strip.to_i }
50
+ ports.empty? ? nil : ports
51
+ rescue Errno::ENOENT
52
+ nil
53
+ end
54
+ end
55
+
56
+ def remove_port_file
57
+ File.unlink(port_file)
58
+ end
59
+
60
+ private
61
+ def port_file
62
+ @port_file ||= Qspec.path('spork_ports')
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ module Qspec
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,11 @@
1
+ require 'spork'
2
+ class Spork::TestFramework::Qspec < Spork::TestFramework
3
+ DEFAULT_PORT = 9240
4
+ HELPER_FILE = File.join(Dir.pwd, "spec/spec_helper.rb")
5
+
6
+ def run_tests(argv, stderr, stdout)
7
+ require 'qspec'
8
+ ENV['qspec_id'] = argv.pop.to_s
9
+ ::Qspec::CommandLine.new(argv).run(stderr, stdout)
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'qspec/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "qspec"
8
+ gem.version = Qspec::VERSION
9
+ gem.authors = ["tomykaira"]
10
+ gem.email = ["tomykaira@gmail.com"]
11
+ gem.description = %q{QSpec inserts spec files to a queue. Workers process that queue one by one.}
12
+ gem.summary = %q{QSpec is extension of RSpec. Q is for queue, and quick.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.post_install_message = "Run qspec-helper init to create your config file"
21
+
22
+ gem.add_dependency 'rspec-core', '~>2.13.1'
23
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qspec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - tomykaira
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec-core
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.13.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.13.1
30
+ description: QSpec inserts spec files to a queue. Workers process that queue one
31
+ by one.
32
+ email:
33
+ - tomykaira@gmail.com
34
+ executables:
35
+ - qspec
36
+ - qspec-helper
37
+ extensions: []
38
+ extra_rdoc_files: []
39
+ files:
40
+ - .gitignore
41
+ - Gemfile
42
+ - LICENSE.txt
43
+ - README.md
44
+ - Rakefile
45
+ - bin/qspec
46
+ - bin/qspec-helper
47
+ - lib/qspec.rb
48
+ - lib/qspec/command_line.rb
49
+ - lib/qspec/config.rb
50
+ - lib/qspec/formatters/redis_formatter.rb
51
+ - lib/qspec/helper.rb
52
+ - lib/qspec/ipc.rb
53
+ - lib/qspec/ipc/file.rb
54
+ - lib/qspec/ipc/redis.rb
55
+ - lib/qspec/manager.rb
56
+ - lib/qspec/spork_helper.rb
57
+ - lib/qspec/version.rb
58
+ - lib/spork/test_framework/qspec.rb
59
+ - qspec.gemspec
60
+ homepage: ''
61
+ licenses: []
62
+ post_install_message: Run qspec-helper init to create your config file
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ segments:
73
+ - 0
74
+ hash: -177445891
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ segments:
82
+ - 0
83
+ hash: -177445891
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 1.8.23
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: QSpec is extension of RSpec. Q is for queue, and quick.
90
+ test_files: []