guard-ocunit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cba6bfe95a4f901658a14c7111990bcac70fbd1a
4
+ data.tar.gz: 6d15615d67f17e36627c0d9dd665cc84903f6225
5
+ SHA512:
6
+ metadata.gz: c3f934c4046491b03dacb5bcfc32097f05930f052754187228b92d8f416d1a753d11de70c7a182fadae1527224d3c4800adbf223cd1454d9687ded0c9731909c
7
+ data.tar.gz: e9302369a697fe5e5deb2c440eb4c111f5d736330aa2eba715333da8a702925db89dc728fdb6a930c17856035c09070740cdf3dd6030b67a3f485b4cf352812f
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Arthur Evstifeev
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # Guard::OCUnit [![Build Status](https://secure.travis-ci.org/ap4y/guard-ocunit.png?branch=master)](http://travis-ci.org/ap4y/guard-ocunit)
2
+
3
+ OCUnit guard allows to automatically launch tests when files are modified.
4
+
5
+ * Compatible with XCode 4.x
6
+ * Tested with XCode 4.5.
7
+
8
+ ## Install
9
+
10
+ Please be sure to have [Guard](https://github.com/guard/guard) and [ios-sim](https://github.com/phonegap/ios-sim) installed before continue. `guard-ocunit` uses `ios-sim` for running `application` tests from command line, for more info refer to the [SO](http://stackoverflow.com/questions/12557935/xcode-4-5-command-line-unit-testing) question.
11
+
12
+ Install the gem:
13
+
14
+ ```
15
+ $ gem install guard-ocunit
16
+ ```
17
+
18
+ Add guard definition to your Guardfile by running this command:
19
+
20
+ ```
21
+ $ guard init ocunit
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ Please read [Guard usage doc](https://github.com/guard/guard#readme)
27
+
28
+ ## Guardfile
29
+
30
+ OCUnit guard can be adapted to your projects.
31
+
32
+ ### Standard Cocoapods project
33
+
34
+ ``` ruby
35
+ guard :ocunit,
36
+ :derived_data => '/tmp/tests',
37
+ :workspace => 'SampleApp.xcworkspace',
38
+ :scheme => 'SampleApp',
39
+ :test_bundle => 'SampleAppTests' do
40
+
41
+ watch(%r{^SampleAppTests/.+Tests\.m})
42
+ watch(%r{^SampleApp/Models/(.+)\.[m,h]$}) { |m| "SampleAppTests/#{m[1]}Tests.m" }
43
+ end
44
+ ```
45
+
46
+ Please read [Guard doc](https://github.com/guard/guard#readme) for more information about the Guardfile DSL.
47
+
48
+ ## Options
49
+
50
+ By default, Guard::OCUnit will only look for test files within `Tests` in your project root. You can configure Guard::OCUnit to look in additional paths by using the `:test_paths` option:
51
+
52
+ ``` ruby
53
+ guard 'ocunit', :test_paths => ["Tests", "/Models/Tests"],:test_bundle => 'SampleAppTests' do
54
+ # ...
55
+ end
56
+ ```
57
+
58
+ ### List of available options:
59
+
60
+ ``` ruby
61
+ :test_bundle => '', # test ocunit bundle with provided name, mandatory parameter
62
+ :derived_data => ''/tmp/tests/, # build into provided path, default: current folder
63
+ :workspace => nil, # build provided workspace, default: nil, use with :scheme
64
+ :scheme => nil, # build provided scheme, default: nil, use with :workspace
65
+ :project => nil, # path to the project to test, defaults to current folder
66
+ :sdk => '', # link and test against provided device sdk, default: 'iphonesimulator'
67
+ :verbose => false # dump all tests information in console
68
+ :notification => false # display notification after the tests are done running, default: true
69
+ :all_after_pass => false # run all tests after changed tests pass, default: true
70
+ :all_on_start => false # run all tests at startup, default: true
71
+ :keep_failed => false # keep failed tests until they pass, default: true
72
+ :tests_paths => ["Tests"] # specify an array of paths that contain test files
73
+ :focus_on_failed => false # focus on the first 10 failed tests first, rerun till they pass
74
+ :clean => false # defines all builds as clean. By default run all command doing clean build
75
+ :build_variables => '' # passes provided parameters to the xcodebuild
76
+ :ios_sim_opts => '' # passes provided options to the ios-sim
77
+ ```
78
+
79
+ ## Credits
80
+
81
+ * [guard-rspec](https://github.com/guard/guard-rspec) by [Thibaud Guillaume-Gentil](https://github.com/thibaudgg)
82
+ * [https://gist.github.com/alloy/3011214](https://gist.github.com/alloy/3011214) by
83
+ [Eloy Durán](https://github.com/alloy)
@@ -0,0 +1,75 @@
1
+ require 'guard/ocunit'
2
+ require 'colored'
3
+
4
+ if RUBY_VERSION =~ /1.9/ #bug with output parsing
5
+ Encoding.default_external = Encoding::UTF_8
6
+ Encoding.default_internal = Encoding::UTF_8
7
+ end
8
+
9
+ class Guard::OCUnit::Formatter < Array
10
+ attr_reader :passed, :failed, :start_time
11
+
12
+ def initialize(io, verbose)
13
+ @io, @verbose = io, verbose
14
+ @failed, @passed = 0, 0
15
+ @start_time = Time.now
16
+ end
17
+
18
+ def <<(line)
19
+ super
20
+ @io << case line
21
+ when /passed/
22
+ @passed += 1
23
+ @verbose ? line.green : ''
24
+ when /failed/
25
+ @failed += 1
26
+ line.red
27
+ when /(error|otest)/
28
+ line.red
29
+ else
30
+ @verbose ? line : ''
31
+ end
32
+ self
33
+ end
34
+
35
+ def dump_summary(with_notification=true)
36
+ end_time = Time.now
37
+ duration = end_time - @start_time
38
+ message = guard_message(@passed + @failed, @failed, 0, duration)
39
+ image = guard_image(@failed, 0)
40
+ Guard::UI.info(message.gsub("\n", ' '), :reset => true)
41
+ notify(message, image) if with_notification
42
+ end
43
+
44
+ def guard_message(example_count, failure_count, pending_count, duration)
45
+ message = "#{example_count} examples, #{failure_count} failures"
46
+ if pending_count > 0
47
+ message << " (#{pending_count} pending)"
48
+ end
49
+ message << "\nin #{duration.round(4)} seconds"
50
+ message
51
+ end
52
+
53
+ # failed | pending | success
54
+ def guard_image(failure_count, pending_count)
55
+ if failure_count > 0
56
+ :failed
57
+ elsif pending_count > 0
58
+ :pending
59
+ else
60
+ :success
61
+ end
62
+ end
63
+
64
+ def priority(image)
65
+ { :failed => 2,
66
+ :pending => -1,
67
+ :success => -2
68
+ }[image]
69
+ end
70
+
71
+ def notify(message, image)
72
+ Guard::Notifier.notify(message, :title => "OCUnit results", :image => image,
73
+ :priority => priority(image))
74
+ end
75
+ end
@@ -0,0 +1,64 @@
1
+ module Guard
2
+ class OCUnit
3
+ class Inspector
4
+
5
+ def initialize(options = {})
6
+ self.excluded = options[:exclude]
7
+ self.test_paths = options[:test_paths]
8
+ end
9
+
10
+ def excluded
11
+ @excluded || []
12
+ end
13
+
14
+ def excluded=(pattern)
15
+ @excluded = Dir[pattern.to_s]
16
+ end
17
+
18
+ def test_paths
19
+ @test_paths || []
20
+ end
21
+
22
+ def test_paths=(paths)
23
+ @test_paths = Array(paths)
24
+ end
25
+
26
+ def clean(paths)
27
+ paths.uniq!
28
+ paths.compact!
29
+ clear_test_files_list_after do
30
+ paths = paths.select { |path| should_run_test_file?(path) }
31
+ end
32
+ paths.reject { |p| included_in_other_path?(p, paths) }
33
+ end
34
+
35
+ private
36
+
37
+ def should_run_test_file?(path)
38
+ (test_file?(path) || test_folder?(path)) && !excluded.include?(path)
39
+ end
40
+
41
+ def test_file?(path)
42
+ test_files.include?(path)
43
+ end
44
+
45
+ def test_folder?(path)
46
+ path.match(%r{^(#{test_paths.join("|")})[^\.]*$})
47
+ end
48
+
49
+ def test_files
50
+ @test_files ||= test_paths.collect { |path| Dir[File.join(path, "**{,/*/**}", "*.m")] }.flatten
51
+ end
52
+
53
+ def clear_test_files_list_after
54
+ yield
55
+ @test_files = nil
56
+ end
57
+
58
+ def included_in_other_path?(path, paths)
59
+ (paths - [path]).any? { |p| path.include?(p) && path.sub(p, '').include?('/') }
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,133 @@
1
+ require 'xcodebuild'
2
+ require 'open4'
3
+ require 'guard/ocunit/formatter'
4
+
5
+ module Guard
6
+ class OCUnit
7
+ class Runner
8
+
9
+ SUCCESS_BUILD_CODE = 0
10
+ #octool returns 0 if wasn't able to run
11
+ #also 0 if passed and 1 if tests failed
12
+ SUCCESS_EXIT_CODE = 0
13
+ MISC_ERROR_EXIT_CODE = 1
14
+
15
+ attr_accessor :options
16
+
17
+ def initialize(options = {})
18
+ @options = {
19
+ :test_bundle => nil,
20
+ :derived_data => '/tmp/tests/',
21
+ :workspace => nil,
22
+ :scheme => nil,
23
+ :project => nil,
24
+ :sdk => 'iphonesimulator',
25
+ :verbose => false,
26
+ :notification => true,
27
+ :clean => false,
28
+ :build_variables => nil,
29
+ :ios_sim_opts => nil
30
+ }.merge(options)
31
+ end
32
+
33
+ def run(paths, options = {})
34
+ return false if paths.empty?
35
+
36
+ message = options[:message] || "Running: #{paths.join(' ')}"
37
+ UI.info(message, :reset => true)
38
+
39
+ options = @options.merge(options)
40
+ run_via_shell(paths, options)
41
+ end
42
+
43
+ def xcodebuild(options = {})
44
+ options = @options.merge(options)
45
+ path_variables(options)
46
+
47
+ # REVIEW: currently not all error messages are going to the output via
48
+ # formatter, decided to disable it
49
+
50
+ # formatter = XcodeBuild::Formatters::ProgressFormatter.new
51
+ # reporter = XcodeBuild::Reporter.new(formatter)
52
+ # output_buffer = XcodeBuild::OutputTranslator.new(reporter)
53
+
54
+ arguments = []
55
+ arguments << "-workspace #{options[:workspace]}" unless options[:workspace].to_s.empty?
56
+ arguments << "-scheme #{options[:scheme]}" unless options[:scheme].to_s.empty?
57
+ arguments << "-project #{options[:project]}" unless options[:project].to_s.empty?
58
+ arguments << "-sdk #{options[:sdk].downcase}"
59
+ arguments << "-configuration Debug"
60
+ arguments << "-alltargets" if options[:workspace].to_s.empty?
61
+ arguments << "clean" if options[:clean]
62
+ arguments << "build"
63
+ arguments << "CONFIGURATION_BUILD_DIR=#{@built_products_dir}"
64
+ arguments << options[:build_variables] unless options[:build_variables].to_s.empty?
65
+
66
+ XcodeBuild.run(arguments.compact.join(' '), STDOUT)
67
+ end
68
+
69
+ private
70
+
71
+ def path_variables(options)
72
+ project_folder = options[:project] && File.dirname(options[:project])
73
+ @derived_data = project_folder || options[:derived_data]
74
+ @built_products_dir = File.join(@derived_data, 'build/')
75
+
76
+ scheme_name = options[:scheme]
77
+ @test_bundle_path = File.join(@built_products_dir, "#{options[:test_bundle]}.octest")
78
+ @test_host = File.join(@built_products_dir, "#{scheme_name}.app", "#{scheme_name}")
79
+ end
80
+
81
+ def run_via_shell(paths, options)
82
+ build_status = xcodebuild(options)
83
+
84
+ status = run_otest(paths, options) if build_status == SUCCESS_BUILD_CODE
85
+
86
+ if options[:notification] &&
87
+ ( !( (0..1) === status ) || build_status != SUCCESS_BUILD_CODE )
88
+ Notifier.notify("Failed", :title => "OCUnit results",
89
+ :image => :failed,
90
+ :priority => 2)
91
+ end
92
+
93
+ build_status == SUCCESS_BUILD_CODE && (0..1) === status
94
+ end
95
+
96
+ def run_otest(paths, options)
97
+ test_suites = paths.uniq.join(',')
98
+
99
+ stderr = OCUnit::Formatter.new(STDERR, options[:verbose])
100
+ command = otest_command(test_suites)
101
+
102
+ status = Open4.spawn(command, :stderr => stderr, :status => true)
103
+ stderr.dump_summary(options[:notification])
104
+ status.exitstatus
105
+ end
106
+
107
+ def otest_environment_variables()
108
+ environment_variables = {
109
+ 'DYLD_INSERT_LIBRARIES' => "/../../Library/PrivateFrameworks/IDEBundleInjection.framework/IDEBundleInjection",
110
+ 'XCInjectBundle' => @test_bundle_path,
111
+ 'XCInjectBundleInto' => @test_host
112
+ }
113
+
114
+ mapped = environment_variables.map do |key, value|
115
+ "--setenv #{key}=\"#{value}\""
116
+ end
117
+ mapped.join(' ')
118
+ end
119
+
120
+ def otest_command(test_suites)
121
+ command = []
122
+ command << 'ios-sim launch'
123
+ command << "\"#{File.dirname(@test_host)}\""
124
+ command << "#{otest_environment_variables()}"
125
+ command << options[:ios_sim_opts] unless options[:ios_sim_opts].to_s.empty?
126
+ command << '--args'
127
+ command << "-SenTest #{File.basename(test_suites, '.m')}"
128
+ command << "#@test_bundle_path"
129
+ command.compact.join(' ')
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,14 @@
1
+ guard :ocunit,
2
+ :test_paths => ['SampleAppTests'],
3
+ :workspace => 'SampleApp.xcworkspace',
4
+ :scheme => 'SampleApp',
5
+ :test_bundle => 'SampleAppTests' do
6
+
7
+ watch(%r{^SampleAppTests/Models/.+Tests\.m})
8
+ watch(%r{^SampleAppTests/Helpers/.+Tests\.m})
9
+ watch(%r{^SampleAppTests/ViewControllers/.+Tests\.m})
10
+
11
+ watch(%r{^SampleApp/Models/(.+)\.[m,h]$}) { |m| "SampleAppTests/Models/#{m[1]}Tests.m" }
12
+ watch(%r{^SampleApp/Helpers/(.+)\.[m,h]$}) { |m| "SampleAppTests/Helpers/#{m[1]}Tests.m" }
13
+ watch(%r{^SampleApp/ViewControllers/(.+)\.[m,h]$}) { |m| "SampleAppTests/ViewControllers/#{m[1]}Tests.m" }
14
+ end
@@ -0,0 +1,5 @@
1
+ module Guard
2
+ module OCUnitVersion
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,129 @@
1
+ require 'guard'
2
+ require 'guard/guard'
3
+
4
+ module Guard
5
+ class OCUnit < Guard
6
+ autoload :Runner, 'guard/ocunit/runner'
7
+ autoload :Inspector, 'guard/ocunit/inspector'
8
+
9
+ attr_accessor :last_failed, :failed_paths, :runner, :inspector
10
+
11
+ def initialize(watchers = [], options = {})
12
+ super
13
+ @options = {
14
+ :focus_on_failed => false,
15
+ :all_after_pass => true,
16
+ :all_on_start => true,
17
+ :keep_failed => true,
18
+ :test_paths => ["Tests"],
19
+ :run_all => {}
20
+ }.merge(options)
21
+ @last_failed = false
22
+ @failed_paths = []
23
+
24
+ @inspector = Inspector.new(@options)
25
+ @runner = Runner.new(@options)
26
+ end
27
+
28
+ # Call once when guard starts
29
+ def start
30
+ UI.info "Guard::OCUnit is running"
31
+ run_all if @options[:all_on_start]
32
+ end
33
+
34
+ def run_all
35
+ options = @options[:run_all].merge(:message => 'Running all tests',
36
+ :clean => true)
37
+ passed = @runner.run(['All'], options)
38
+
39
+ unless @last_failed = !passed
40
+ @failed_paths = []
41
+ else
42
+ throw :task_has_failed
43
+ end
44
+ end
45
+
46
+ def reload
47
+ @failed_paths = []
48
+ end
49
+
50
+ def run_on_changes(paths)
51
+ original_paths = paths.dup
52
+
53
+ focused = false
54
+ if last_failed && @options[:focus_on_failed]
55
+ path = './tmp/ocunit_guard_result'
56
+ if File.exist?(path)
57
+ single_test = paths && paths.length == 1 ? paths[0] : nil#&& paths[0].include?("_test")
58
+ failed_tests = File.open(path) { |file| file.read.split("\n") }
59
+
60
+ File.delete(path)
61
+
62
+ if single_test && @inspector.clean([single_test]).length == 1
63
+ failed_tests = failed_tests.select{|p| p.include? single_test}
64
+ end
65
+
66
+ if failed_tests.any?
67
+ # some sane limit, stuff will explode if all tests fail
68
+ # ... cap at 10
69
+
70
+ paths = failed_tests[0..10]
71
+ focused = true
72
+ end
73
+
74
+ # switch focus to the single spec
75
+ if single_test and failed_tests.length > 0
76
+ focused = true
77
+ end
78
+ end
79
+ end
80
+
81
+ if focused
82
+ add_failed(original_paths)
83
+ add_failed(paths.map{|p| p.split(":")[0]})
84
+ else
85
+ paths += failed_paths if @options[:keep_failed]
86
+ paths = @inspector.clean(paths).uniq
87
+ end
88
+
89
+ if passed = @runner.run(paths)
90
+ unless focused
91
+ remove_failed(paths)
92
+ end
93
+
94
+ if last_failed && focused
95
+ run_on_changes(failed_paths)
96
+ # run all the tests if the run before this one failed
97
+ elsif last_failed && @options[:all_after_pass]
98
+ @last_failed = false
99
+ run_all
100
+ end
101
+ else
102
+ @last_failed = true
103
+ unless focused
104
+ add_failed(paths)
105
+ end
106
+
107
+ throw :task_has_failed
108
+ end
109
+ end
110
+
111
+ private
112
+
113
+ def run(paths)
114
+ end
115
+
116
+ def remove_failed(paths)
117
+ @failed_paths -= paths if @options[:keep_failed]
118
+ end
119
+
120
+ def add_failed(paths)
121
+ if @options[:keep_failed]
122
+ @failed_paths += paths
123
+ @failed_paths.uniq!
124
+ end
125
+ end
126
+
127
+ end
128
+ end
129
+
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guard-ocunit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Arthur Evstifeev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: guard
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: open4
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: xcodebuild-rb
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: colored
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '2.11'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '2.11'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '1.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '1.1'
111
+ description: Guard::OCUnit automatically runs your tests.
112
+ email:
113
+ - lod@pisem.net
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - lib/guard/ocunit/formatter.rb
119
+ - lib/guard/ocunit/inspector.rb
120
+ - lib/guard/ocunit/runner.rb
121
+ - lib/guard/ocunit/templates/Guardfile
122
+ - lib/guard/ocunit/version.rb
123
+ - lib/guard/ocunit.rb
124
+ - LICENSE
125
+ - README.md
126
+ homepage: https://github.com/ap4y/guard-ocunit
127
+ licenses: []
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - '>='
141
+ - !ruby/object:Gem::Version
142
+ version: 1.3.6
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.0.3
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: Guard gem for OCUnit
149
+ test_files: []