purobu 0.0.1

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.
data/.gitignore ADDED
@@ -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 purobu.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Harold Giménez
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.
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # Purobu
2
+
3
+ Black-box integration test framework for components on the Heroku platform.
4
+
5
+ ## Installation
6
+
7
+ Install the gem
8
+
9
+ $ gem install purobu
10
+
11
+ ## Usage
12
+
13
+ Tests [go through four phases](http://xunitpatterns.com/Four%20Phase%20Test.html):
14
+
15
+ * _Setup_ the context for the test by creating test fixtures that are required
16
+ for the *System Under Test* (SUT) to expose the desired behavior.
17
+ * _Exercise_ the SUT
18
+ * _Verify_ the result to determine if the intended behavior was met.
19
+ * _Teardown_ the state of the system by removing all fixtures and test
20
+ artifacts so that there are no state spills or interdependencies across
21
+ tests.
22
+
23
+ Purobu recognizes and embraces this by defining these phases in implicit blocks
24
+ within your tests.
25
+
26
+ For example:
27
+
28
+ ```ruby
29
+ # test_can_create_crane_database.rb
30
+ test 'can create crane database' do
31
+ setup do
32
+ heroku "apps:create --name some-app"
33
+ end
34
+
35
+ exercise do
36
+ heroku "addons:add heroku-postgresql:crane some-app"
37
+ end
38
+
39
+ verify do
40
+ addons = heroku "addons --app some-app"
41
+ addons.include?("heroku-postgresql:crane") #return true or false
42
+ end
43
+
44
+ teardown do
45
+ heroku "apps:remove some-app"
46
+ end
47
+ end
48
+ ```
49
+
50
+ Then run it with 4 concurrent jobs:
51
+
52
+ $ purobu -j 4
53
+
54
+ Purobu will load any files that match `/test_.*\.rb/` recursively. An
55
+ alternative is to specify files to run:
56
+
57
+ $ purobu -j 4 -f test_one.rb,test_two.rb
58
+
59
+ For more command line switches, try `purobu -h`
60
+
61
+ ## Global setup
62
+
63
+ It can be useful to have global setups, for example, to create an app to run a
64
+ bunch of tests against.
65
+
66
+ You can create a ruby file called purobu_config.rb to set up a global context.
67
+ The global context will run once before the entire suite. Be sure to create a
68
+ global teardown as well:
69
+
70
+ ```ruby
71
+ # purobu_config.rb
72
+ Purobu::Configuration.run do |config|
73
+ config.global_setup do
74
+ heroku "apps:create harolds-test-app"
75
+ end
76
+ config.global_teardown do
77
+ heroku "apps:destroy harolds-test-app --confirm harolds-test-app"
78
+ end
79
+ end
80
+ ```
81
+
82
+ ## Interacting with heroku
83
+
84
+ Access to heroku is facilitated in two ways:
85
+
86
+ 1. The `heroku` helper is a wrapper around the latest version of the heroku
87
+ CLI. You give it a string, and it shells out to execute the given command.
88
+ For example:
89
+
90
+ ```ruby
91
+ heroku "addons:add heroku-postgresql:dev"
92
+ ```
93
+
94
+ 2. The `heroku_api` helper exposes the [heroku api
95
+ client](https://github.com/heroku/heroku.rb) for more convenient retreival
96
+ of information on heroku such as an app's config vars.
97
+
98
+ *Note*: To use it, set the HEROKU_API_KEY environment variable or set it in a
99
+ `Purobu::Configuration.run`
100
+
101
+ For example:
102
+
103
+ ```ruby
104
+ heroku_api.get_config_vars('some-app').body
105
+ # {"HEROKU_POSTGRESQL_PURPLE_URL"=>"postgres://user:pass@host:5732/database"}
106
+ heroku_api.get_addons('some-app').body
107
+ # [{"slug"=>"crane", "selective"=>false,
108
+ "configured"=>true,
109
+ "url"=>nil,
110
+ "state"=>"public",
111
+ "group_description"=>"Heroku Postgresql",
112
+ "consumes_dyno_hours"=>false,
113
+ "price"=>{"cents"=>0, "unit"=>"month"},
114
+ "attachment_name"=>"HEROKU_POSTGRESQL_TEAL",
115
+ "plan_description"=>"Crane",
116
+ "name"=>"heroku-postgresql:crane",
117
+ "beta"=>false,
118
+ "attachable"=>false,
119
+ "description"=>"Heroku Postgres Crane",
120
+ "terms_of_service"=>false}]
121
+ ```
122
+
123
+ ## Meta
124
+
125
+ purobu was written by Harold Giménez and is Copyright 2012 Heroku
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/bin/purobu ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "optparse"
4
+
5
+ options = {}
6
+ parser = OptionParser.new do |opts|
7
+ opts.banner = "usage: purobu [--file file1,file2,...]"
8
+ opts.on("-f", "--files f", Array, "File or files to load and run") do |fs|
9
+ options[:files] = fs
10
+ end
11
+ opts.on("-j", "--jobs j", Integer, "Number of jobs") do |j|
12
+ options[:thread_count] = j
13
+ end
14
+ opts.on("-v", "--verbose", "Run verbosely") do |v|
15
+ options[:verbose] = v
16
+ end
17
+ opts.on("-h", "--help", "Display this help") { abort(opts.to_s) }
18
+ end
19
+ parser.parse!
20
+
21
+ $:.unshift File.expand_path(File.join('..', 'lib'), File.dirname(__FILE__))
22
+
23
+ require 'purobu'
24
+
25
+ load './purobu_config.rb' if File.exists?('./purobu_config.rb')
26
+
27
+ Purobu::Configuration.run do |conf|
28
+ conf.verbose = options[:verbose] || false
29
+ conf.thread_count = options[:thread_count]
30
+ conf.files = options[:files]
31
+ end
32
+
33
+ Purobu::DSL.new(files: Purobu::Configuration.files).run
@@ -0,0 +1,57 @@
1
+ require 'singleton'
2
+ module Purobu
3
+ class Configuration
4
+ include Singleton
5
+
6
+ # Run verbosely
7
+ attr_accessor :verbose
8
+
9
+ # Concurrency
10
+ attr_accessor :thread_count
11
+
12
+ # Which test files to run
13
+ attr_accessor :files
14
+
15
+ # Global teardown to run after the entire suite
16
+ attr_accessor :global_teardown
17
+
18
+ # Heroku api key to be used by the heroku-api client
19
+ attr_accessor :heroku_api_key
20
+
21
+ def self.run(&block)
22
+ self.instance.heroku_api_key = ENV['HEROKU_API_KEY']
23
+
24
+ yield self.instance
25
+ end
26
+
27
+ def global_setup(&block)
28
+ if block_given?
29
+ @global_setup = block
30
+ else
31
+ @global_setup
32
+ end
33
+ end
34
+
35
+ def global_teardown(&block)
36
+ if block_given?
37
+ @global_teardown = block
38
+ else
39
+ @global_teardown
40
+ end
41
+ end
42
+
43
+ class << self
44
+ def method_missing(method)
45
+ if self.instance.respond_to?(method)
46
+ self.instance.send(method)
47
+ else
48
+ super
49
+ end
50
+ end
51
+
52
+ def respond_to?(method)
53
+ self.instance.respond_to?(method) || super
54
+ end
55
+ end
56
+ end
57
+ end
data/lib/purobu/dsl.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Purobu
2
+ class DSL
3
+ attr_reader :runner, :files
4
+ def initialize(opts = {})
5
+ @runner = Runner.new
6
+ @files = opts[:files] || Dir['**/test_*.rb']
7
+ end
8
+
9
+ def test(name = nil, &block)
10
+ runner.tests.push( Test.new(name).tap { |t| t.instance_eval(&block) } )
11
+ end
12
+
13
+ def tests
14
+ runner.tests
15
+ end
16
+
17
+ def run
18
+ load_tests
19
+ runner.run
20
+ end
21
+
22
+ def load_tests
23
+ files.each { |f| instance_eval(File.read(f)) }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ require 'fileutils'
2
+ module Purobu
3
+ class Heroku
4
+ class FailedCommand < Exception; end
5
+
6
+ def self.run(command)
7
+ result = nil
8
+ Purobu.log(heroku: true, command: command) do
9
+ result = `#{heroku_path} #{command}`
10
+ end
11
+ raise FailedCommand.new(result) unless $?.exitstatus.zero?
12
+ result
13
+ end
14
+
15
+ def self.heroku_path
16
+ @heroku_path ||= begin
17
+ FileUtils.cd File.expand_path(File.join("..", ".."), File.dirname(__FILE__)) do
18
+ eval(File.read('purobu.gemspec'))
19
+ end
20
+ Gem.bin_path("heroku", "heroku")
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ require 'heroku-api'
2
+ module Purobu
3
+ module HerokuHelpers
4
+ def heroku(*args)
5
+ ::Purobu::Heroku.run(*args)
6
+ end
7
+
8
+ def heroku_api
9
+ ::Heroku::API.new(api_key: Configuration.heroku_api_key)
10
+ end
11
+ end
12
+ end
data/lib/purobu/log.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'scrolls'
2
+ module Purobu
3
+ def self.log(data, &block)
4
+ if Configuration.verbose
5
+ Scrolls.log(data, &block)
6
+ else
7
+ yield
8
+ end
9
+ end
10
+
11
+ def self.log_context(data, &block)
12
+ if Configuration.verbose
13
+ Scrolls.context(data, &block)
14
+ else
15
+ yield
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ module Purobu
2
+ class Reporter
3
+ attr_reader :test
4
+ def initialize(test)
5
+ @test = test
6
+ end
7
+
8
+ def report_pass
9
+ puts "#{green("PASS")} #{@test.name}"
10
+ end
11
+
12
+ def report_fail
13
+ puts "#{red("FAIL")} #{@test.name}"
14
+ end
15
+
16
+ private
17
+ def green(string)
18
+ "[\e[32m#{string}\e[0m]"
19
+ end
20
+
21
+ def red(string)
22
+ "[\e[31m#{string}\e[0m]"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ require 'thread'
2
+ module Purobu
3
+ class Runner
4
+ include HerokuHelpers
5
+
6
+ attr_reader :tests, :thread_count
7
+
8
+ def initialize
9
+ @tests = Queue.new
10
+ @thread_count = Configuration.thread_count || 1
11
+ end
12
+
13
+ def run
14
+ Purobu.log(global_setup: true) do
15
+ run_global_setup
16
+ end
17
+ pool = Array.new(thread_count) do
18
+ Thread.new do
19
+ loop do
20
+ begin
21
+ test = tests.pop(true)
22
+ test.run
23
+ test.report_result
24
+ rescue
25
+ Thread.exit
26
+ end
27
+ end
28
+ end
29
+ end
30
+ pool.each(&:join)
31
+ Purobu.log(global_teardown: true) do
32
+ run_global_teardown
33
+ end
34
+ end
35
+
36
+ private
37
+ def run_global_setup
38
+ if setup = Configuration.global_setup
39
+ instance_eval &setup
40
+ end
41
+ end
42
+
43
+ def run_global_teardown
44
+ if teardown = Configuration.global_teardown
45
+ instance_eval &teardown
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,77 @@
1
+ require 'heroku'
2
+ module Purobu
3
+ class Test
4
+ include HerokuHelpers
5
+
6
+ attr_reader :setups, :teardowns, :name
7
+ attr_writer :exercise, :verification
8
+
9
+ def initialize(name = nil)
10
+ @setups = []
11
+ @exercise = -> {}
12
+ @verification = -> {}
13
+ @teardowns = []
14
+ @fail = true
15
+ @name = name
16
+ end
17
+
18
+ def run
19
+ begin
20
+ Purobu.log_context(test: name) do
21
+ Purobu.log(setups: true) do
22
+ @setups.each { |s| s.call }
23
+ end
24
+ Purobu.log(exercise: true) do
25
+ @exercise.call
26
+ end
27
+ Purobu.log(verification: true) do
28
+ @fail = !@verification.call
29
+ end
30
+ Purobu.log(teardown: true) do
31
+ @teardowns.each { |s| s.call }
32
+ end
33
+ end
34
+ rescue => e
35
+ @fail = true
36
+ end
37
+ pass?
38
+ end
39
+
40
+ def pass?
41
+ !@fail
42
+ end
43
+
44
+ def setup(&block)
45
+ @setups << block
46
+ end
47
+
48
+ def exercise(&block)
49
+ @exercise = block
50
+ end
51
+
52
+ def verify(&block)
53
+ @verification = block
54
+ end
55
+
56
+ def teardown(&block)
57
+ @teardowns << block
58
+ end
59
+
60
+ def reporter
61
+ @reporter ||= Reporter.new(self)
62
+ end
63
+
64
+ def reporter=(new_reporter)
65
+ @reporter = new_reporter
66
+ end
67
+
68
+ def report_result
69
+ if pass?
70
+ reporter.report_pass
71
+ else
72
+ reporter.report_fail
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module Purobu
2
+ VERSION = "0.0.1"
3
+ end
data/lib/purobu.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "purobu/version"
2
+ require "purobu/log"
3
+ require "purobu/configuration"
4
+ require "purobu/heroku_helpers"
5
+ require "purobu/test"
6
+ require "purobu/runner"
7
+ require "purobu/dsl"
8
+ require "purobu/heroku"
9
+ require "purobu/reporter"
data/purobu.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/purobu/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Harold Giménez"]
6
+ gem.email = ["harold.gimenez@gmail.com"]
7
+ gem.description = %q{ Probe your production or staging environment for behavior correctness }
8
+ gem.summary = %q{ Black-box integration test framework for components on the Heroku platform. }
9
+ gem.homepage = "http://practiceovertheory.com"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "purobu"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Purobu::VERSION
17
+
18
+ gem.add_dependency "heroku", "2.28.2"
19
+ gem.add_dependency "heroku-api"
20
+ gem.add_dependency "scrolls", "0.2.1"
21
+ gem.add_development_dependency "rspec"
22
+ gem.add_development_dependency "fakefs"
23
+ end
@@ -0,0 +1,42 @@
1
+ require 'purobu'
2
+ require 'fakefs/safe'
3
+ require 'fakefs/spec_helpers'
4
+
5
+ describe Purobu::DSL do
6
+ let(:dsl) { Purobu::DSL.new }
7
+ it 'adds tests to the runner' do
8
+ dsl.test do
9
+ verify { true }
10
+ end
11
+
12
+ dsl.tests.size.should == 1
13
+ test = dsl.tests.pop
14
+ test.should be_a Purobu::Test
15
+ end
16
+
17
+ it 'supports adding names to tests' do
18
+ dsl.test 'a name' do
19
+ verify { true }
20
+ end
21
+ end
22
+ end
23
+
24
+ describe Purobu::DSL, 'loading tests files' do
25
+ include FakeFS::SpecHelpers
26
+
27
+ before { FakeFS.activate! }
28
+ after { FakeFS.deactivate! }
29
+
30
+ it 'loads tests' do
31
+ 2.times do |i|
32
+ File.open("test_#{i}.rb", 'w') do |file|
33
+ file << "test { verify { true } }"
34
+ end
35
+ end
36
+
37
+ dsl = Purobu::DSL.new
38
+ dsl.load_tests
39
+
40
+ dsl.tests.size.should == 2
41
+ end
42
+ end
File without changes
@@ -0,0 +1,39 @@
1
+ require 'purobu'
2
+
3
+ describe Purobu::Runner, 'running tests' do
4
+ let(:runner) { Purobu::Runner.new }
5
+ it 'invokes each test and reports its result' do
6
+ test = Purobu::Test.new
7
+
8
+ test.should_receive(:run).once
9
+ test.should_receive(:report_result).once
10
+
11
+ runner.tests.push(test)
12
+
13
+ runner.run
14
+ end
15
+
16
+ it 'invokes the global setup before running any test' do
17
+ setup = nil
18
+ Purobu::Configuration.run do |config|
19
+ config.global_setup do
20
+ setup = :global_setup
21
+ end
22
+ end
23
+ setup.should be_nil
24
+ runner.run
25
+ setup.should == :global_setup
26
+ end
27
+
28
+ it 'invokes the global teardown before running any test' do
29
+ teardown = nil
30
+ Purobu::Configuration.run do |config|
31
+ config.global_teardown do
32
+ teardown = :global_teardown
33
+ end
34
+ end
35
+ teardown.should be_nil
36
+ runner.run
37
+ teardown.should == :global_teardown
38
+ end
39
+ end
@@ -0,0 +1,100 @@
1
+ require 'purobu'
2
+
3
+ describe Purobu::Test, '#run' do
4
+ it 'sets up' do
5
+ test = Purobu::Test.new
6
+ test.setup { throw :setup }
7
+ -> { test.run }.should throw_symbol :setup
8
+ end
9
+
10
+ it 'exercises' do
11
+ test = Purobu::Test.new
12
+ test.exercise { throw :exercise }
13
+
14
+ -> { test.run }.should throw_symbol :exercise
15
+ end
16
+
17
+ it 'verifies' do
18
+ test = Purobu::Test.new
19
+ test.verify { throw :validation }
20
+
21
+ -> { test.run }.should throw_symbol :validation
22
+ end
23
+
24
+ it 'tears down' do
25
+ test = Purobu::Test.new
26
+ test.teardown { throw :teardown }
27
+
28
+ -> { test.run }.should throw_symbol :teardown
29
+ end
30
+ end
31
+
32
+ describe Purobu::Test, 'pass/fail' do
33
+ it 'is failing be default' do
34
+ test = Purobu::Test.new
35
+ test.pass?.should be_false
36
+ end
37
+ it 'passes if the validation returns true' do
38
+ test = Purobu::Test.new
39
+ test.verification = -> { true }
40
+
41
+ test.run.should be_true
42
+ test.pass?.should be_true
43
+ end
44
+
45
+ it 'fails when validation returns false' do
46
+ test = Purobu::Test.new
47
+ test.verification = -> { false }
48
+
49
+ test.run.should be_false
50
+ test.pass?.should be_false
51
+ end
52
+
53
+ it 'fails when anything raises' do
54
+ test = Purobu::Test.new
55
+ test.verification = -> { raise "waa" }
56
+
57
+ test.run.should be_false
58
+ test.pass?.should be_false
59
+ end
60
+ end
61
+
62
+ describe Purobu::Test, '#heroku' do
63
+ it 'delegates to the heroku run command' do
64
+ Purobu::Heroku.should_receive(:run).with('addons')
65
+
66
+ Purobu::Test.new.heroku 'addons'
67
+ end
68
+ end
69
+
70
+ describe Purobu::Test, '#report_result' do
71
+ it 'reports to the reporter whether it passed or failed' do
72
+ reporter = double(:reporter)
73
+ reporter.should_receive(:report_pass).once
74
+ test = Purobu::Test.new
75
+ test.reporter = reporter
76
+
77
+ test.verify { true }
78
+ test.run
79
+
80
+ test.report_result
81
+
82
+
83
+ reporter.should_receive(:report_fail).once
84
+ test.verify { false }
85
+ test.run
86
+
87
+ test.report_result
88
+ end
89
+ end
90
+
91
+ describe Purobu::Test, '#heroku_api' do
92
+ it 'exposes the heroku api' do
93
+ test = Purobu::Test.new
94
+ heroku_api = double
95
+ heroku_api.should_receive(:something).once
96
+ Heroku::API.stub(new: heroku_api)
97
+
98
+ test.heroku_api.something
99
+ end
100
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: purobu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Harold Giménez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: heroku
16
+ requirement: &70132005273080 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: 2.28.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70132005273080
25
+ - !ruby/object:Gem::Dependency
26
+ name: heroku-api
27
+ requirement: &70132005172240 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70132005172240
36
+ - !ruby/object:Gem::Dependency
37
+ name: scrolls
38
+ requirement: &70132005159400 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - =
42
+ - !ruby/object:Gem::Version
43
+ version: 0.2.1
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70132005159400
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &70132005150920 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70132005150920
58
+ - !ruby/object:Gem::Dependency
59
+ name: fakefs
60
+ requirement: &70132005148440 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70132005148440
69
+ description: ! ' Probe your production or staging environment for behavior correctness '
70
+ email:
71
+ - harold.gimenez@gmail.com
72
+ executables:
73
+ - purobu
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - bin/purobu
83
+ - lib/purobu.rb
84
+ - lib/purobu/configuration.rb
85
+ - lib/purobu/dsl.rb
86
+ - lib/purobu/heroku.rb
87
+ - lib/purobu/heroku_helpers.rb
88
+ - lib/purobu/log.rb
89
+ - lib/purobu/reporter.rb
90
+ - lib/purobu/runner.rb
91
+ - lib/purobu/test.rb
92
+ - lib/purobu/version.rb
93
+ - purobu.gemspec
94
+ - spec/purobu/dsl_spec.rb
95
+ - spec/purobu/reporter_spec.rb
96
+ - spec/purobu/runner_spec.rb
97
+ - spec/purobu/test_spec.rb
98
+ homepage: http://practiceovertheory.com
99
+ licenses: []
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 1.8.10
119
+ signing_key:
120
+ specification_version: 3
121
+ summary: Black-box integration test framework for components on the Heroku platform.
122
+ test_files:
123
+ - spec/purobu/dsl_spec.rb
124
+ - spec/purobu/reporter_spec.rb
125
+ - spec/purobu/runner_spec.rb
126
+ - spec/purobu/test_spec.rb