guard-xctool-test 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: 1784e9f38e9085bfb1c1385ab806671fbb85c1c2
4
+ data.tar.gz: 06f2ba6dc15c8e24dec0126d4fd93fc3d28631c9
5
+ SHA512:
6
+ metadata.gz: 347d74162692a7468167fa1070c3c243c7cb2b60b4f070fb3c6686d984d51432b0664b6f4560f7a22aeeed7ca61f86ed03db8d6deefab9c10236c71664def933
7
+ data.tar.gz: ab96309cf9564946cf3e0df3a0fc3629bd8fdf4242a73b2099b7ad31a7cbb3c92afd8bb4bf0a4f03415bb19f172e8f08ad45690c6510f536fb3db4e3bac806dc
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/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - ruby-head
7
+ - jruby-19mode
8
+ - jruby-head
9
+ - rbx-19mode
10
+ - rbx-head
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: ruby-head
14
+ - rvm: jruby-head
15
+ - rvm: rbx-head
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in guard-xctool-test.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Francis Chong
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,88 @@
1
+ # guard-xctool-test
2
+
3
+ Xctool test guard allows you to automically & intelligently aunch specs when files are modified.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'guard-xctool-test'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install guard-xctool-test
18
+
19
+ ## Dependency
20
+
21
+ - Ruby 1.9.3 or above
22
+ - [xctool](https://github.com/facebook/xctool)
23
+
24
+
25
+ ## Guardfile
26
+
27
+ ```ruby
28
+ guard 'xctool-test' do
29
+ watch(%r{YourApp/(.+)\.(m|mm)$})
30
+ watch(%r{YourAppTests/(.+)\.(m|mm)$})
31
+ end
32
+ ```
33
+
34
+ ## Options
35
+
36
+ By default, xctool-test find the folder for projects and find a target that look like test.
37
+ You can supply your target by using ```test_target``` option.
38
+
39
+ ```ruby
40
+ guard 'xctool-test', :test_target => 'YourAppTests' do
41
+ watch(%r{YourApp/(.+)\.(m|mm)$})
42
+ watch(%r{YourAppTests/(.+)\.(m|mm)$})
43
+ end
44
+ ```
45
+
46
+ By default, xctool-test check all files under current folder for tests. You can specify a
47
+ specific folder, or array of folders, as test path.
48
+
49
+ ```ruby
50
+ guard 'xctool-test', :test_paths => 'YourAppTests' do
51
+ watch(%r{YourApp/(.+)\.(m|mm)$})
52
+ watch(%r{YourAppTests/(.+)\.(m|mm)$})
53
+ end
54
+ ```
55
+
56
+ ```ruby
57
+ guard 'xctool-test', :test_paths => ['YourAppUITests', 'YourAppTests'] do
58
+ watch(%r{YourApp/(.+)\.(m|mm)$})
59
+ watch(%r{YourAppTests/(.+)\.(m|mm)$})
60
+ end
61
+ ```
62
+
63
+ You can pass any of the standard xctool CLI options using the ```:cli``` option:
64
+
65
+ ```ruby
66
+ guard 'xctool-test', :cli => '-workspace A.workspace' do
67
+ watch(%r{YourApp/(.+)\.(m|mm)$})
68
+ watch(%r{YourAppTests/(.+)\.(m|mm)$})
69
+ end
70
+ ```
71
+
72
+ You might specify the full path to the xctool with ```:xctool``` option:
73
+
74
+ ```ruby
75
+ guard 'xctool-test', :xctool => '/usr/local/bin/xctool' do
76
+ watch(%r{YourApp/(.+)\.(m|mm)$})
77
+ watch(%r{YourAppTests/(.+)\.(m|mm)$})
78
+ end
79
+ ```
80
+
81
+
82
+ ## Contributing
83
+
84
+ 1. Fork it
85
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
86
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
87
+ 4. Push to the branch (`git push origin my-new-feature`)
88
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'guard/xctool-test/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "guard-xctool-test"
8
+ spec.version = Guard::XctoolTestVersion::VERSION
9
+ spec.authors = ["Francis Chong"]
10
+ spec.email = ["francis@ignition.hk"]
11
+ spec.description = %q{Xctool test guard allows you to automically & intelligently aunch specs when files are modified. This gem use xctool to build and run tests, and xcodeproj gem to parse project file.}
12
+ spec.summary = %q{Xctool test guard allows you to automically & intelligently aunch specs when files are modified.}
13
+ spec.homepage = "https://github.com/siuying/guard-xctool-test"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ spec.add_dependency "guard"
21
+ spec.add_dependency "xcodeproj"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ end
@@ -0,0 +1,77 @@
1
+ require_relative './xctool_helper'
2
+ require 'guard/guard'
3
+ require 'guard'
4
+ module Guard
5
+ class XctoolTest < ::Guard::Guard
6
+ include XctoolHelper
7
+
8
+ attr_reader :xctool, :test_paths, :test_target, :cli
9
+
10
+ # Initializes a Guard plugin.
11
+ # Don't do any work here, especially as Guard plugins get initialized even if they are not in an active group!
12
+ #
13
+ # @param [Array<Guard::Watcher>] watchers the Guard plugin file watchers
14
+ # @param [Hash] options the custom Guard plugin options
15
+ # @option options [Symbol] group the group this Guard plugin belongs to
16
+ # @option options [Boolean] any_return allow any object to be returned from a watcher
17
+ #
18
+ def initialize(watchers = [], options = {})
19
+ super
20
+
21
+ @cli = options[:cli] || ""
22
+ @test_paths = options[:test_paths] || "."
23
+ @test_target = options[:test_target] || find_test_target
24
+ @xctool = options[:xctool_command] || "xctool"
25
+ end
26
+
27
+ # Called once when Guard starts. Please override initialize method to init stuff.
28
+ #
29
+ # @raise [:task_has_failed] when start has failed
30
+ # @return [Object] the task result
31
+ #
32
+ def start
33
+ # required user having xctool to start
34
+ unless system("which #{xctool}")
35
+ UI.info "xctool not found, please specify :xctool_command option"
36
+ throw :task_has_failed
37
+ end
38
+
39
+ unless test_target
40
+ UI.info "Cannot find test target, please specify :test_target option"
41
+ throw :task_has_failed
42
+ end
43
+ end
44
+
45
+ # Called when just `enter` is pressed
46
+ # This method should be principally used for long action like running all specs/tests/...
47
+ #
48
+ # @raise [:task_has_failed] when run_all has failed
49
+ # @return [Object] the task result
50
+ #
51
+ def run_all
52
+ UI.info "Running all tests..."
53
+ xctool_command("test")
54
+ end
55
+
56
+ def run_on_changes(paths)
57
+ test_files = test_classes_with_paths(paths, test_paths)
58
+
59
+ if test_files.size > 0
60
+ filenames = test_files.join(",")
61
+
62
+ UI.info "Running tests on classes: #{filenames}"
63
+ xctool_command("test -only #{test_target}:#{filenames}")
64
+ else
65
+ run_all
66
+ end
67
+ end
68
+
69
+ def xctool_command(command)
70
+ commands = []
71
+ commands << xctool
72
+ commands << cli if cli && cli.strip != ""
73
+ commands << command
74
+ system(commands.join(" "))
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,5 @@
1
+ module Guard
2
+ module XctoolTestVersion
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,63 @@
1
+ require 'xcodeproj'
2
+
3
+ module Guard
4
+ module XctoolHelper
5
+ TEST_FILE_REGEXP = /(Test|Spec)\.(m|mm)$/
6
+
7
+ # Find test class from input paths.
8
+ #
9
+ # - if the path is end with Test.m/Test.mm/Spec.m/Spec.mm, then it is a test class, return the class name of it
10
+ #
11
+ # @param [Array<String>] paths
12
+ # @param [Array<String>] test_path
13
+ #
14
+ def test_classes_with_paths(paths, test_path=[])
15
+ test_classes = paths.select{|path| path =~ TEST_FILE_REGEXP } # get only Test/Spec
16
+ .collect {|path| classname_with_file(path) }
17
+
18
+ non_test_classes = paths.select{|path| path !=~ TEST_FILE_REGEXP }
19
+ .collect {|path| test_file(path, test_path) }
20
+ .compact
21
+ .collect {|path| classname_with_file(path) }
22
+
23
+ test_classes = non_test_classes + test_classes
24
+
25
+ test_classes.uniq
26
+ end
27
+
28
+ # Give a file and a test path, find the test for the given file in the test path.
29
+ # return nil if the test do not exists.
30
+ #
31
+ def test_file(file, test_paths=[])
32
+ test_paths = [] unless test_paths
33
+ test_paths = [test_paths] unless test_paths.is_a?(Array)
34
+ class_name = classname_with_file(file)
35
+
36
+ # for each test path, check if we can find corresponding test file
37
+ test_paths.each do |path|
38
+ files = Dir.glob("#{path}/**/#{class_name}*.*").select {|file| file =~ /#{class_name}(Test|Spec)\.(m|mm)$/ }
39
+ first_file = files.first
40
+ return first_file if first_file
41
+ end
42
+ return nil
43
+ end
44
+
45
+ # Find first project and first Test target from current folder
46
+ def find_test_target
47
+ project_name = Dir["*.xcodeproj"].first
48
+ if project_name
49
+ project = Xcodeproj::Project.new(project_name)
50
+
51
+ # find first targets with name ends with Spec or Target
52
+ return project.targets.collect(&:name).find {|f| f =~ /(Spec|Test)s?$/}
53
+ end
54
+ nil
55
+ end
56
+
57
+ protected
58
+ # Given a path of m or mm file, and return the class name
59
+ def classname_with_file(path)
60
+ path.split("/").last.gsub(/(\.(.+))$/, "")
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH << "./lib"
2
+ require 'guard/xctool-test'
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Guard::XctoolTest" do
4
+ let(:options) {
5
+ {
6
+ :test_target => 'MyTests'
7
+ }
8
+ }
9
+ subject {
10
+ watcher = stub(:watcher).as_null_object
11
+ Guard::XctoolTest.new([watcher], options)
12
+ }
13
+
14
+ describe "new" do
15
+ it "should set default option" do
16
+ subject.test_target.should == "MyTests"
17
+ subject.cli.should == ""
18
+ end
19
+ end
20
+
21
+ describe "run_all" do
22
+ it "should run all test" do
23
+ subject.should_receive(:xctool_command).with("test")
24
+ subject.run_all
25
+ end
26
+ end
27
+
28
+ describe "run_on_changes" do
29
+ it "should run test of the change files" do
30
+ subject.stub(:test_classes_with_paths).and_return(["MyFirstFileSpec", "MySecondSpec"])
31
+ subject.should_receive(:xctool_command).with("test -only MyTests:MyFirstFileSpec,MySecondSpec")
32
+ subject.run_on_changes(["A/B/C/MyFirstFile.m", "B/D/F/MySecondSpec.m"])
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Guard::XctoolHelper" do
4
+ subject {
5
+ object = Object.new
6
+ object.send :extend, Guard::XctoolHelper
7
+ }
8
+ describe "::test_classes_with_paths" do
9
+ it "should return list of file name that ends with Spec or Test" do
10
+ files = ["ProjectTests/A/B/C/File1Test.m", "ProjectTests/A/B/C/File2Spec.m", "Project/A/B/C/File3.h", "Project/A/B/C/File2.m"]
11
+ test_files = subject.test_classes_with_paths(files, "ProjectTests")
12
+ test_files.should be_include("File1Test")
13
+ test_files.should be_include("File2Spec")
14
+ test_files.should_not be_include("File2")
15
+ test_files.should_not be_include("File3")
16
+ end
17
+
18
+ it "should return test file of non-test classes" do
19
+ # mock glob op, pretent we have File3Spec on disk
20
+ Dir.stub(:glob).and_return(["ProjectTests/A/File3Spec.m"])
21
+
22
+ files = ["ProjectTests/A/B/C/File1Test.m", "ProjectTests/A/B/C/File2Spec.m", "Project/A/B/C/File3.h", "Project/A/B/C/File2.m"]
23
+ test_files = subject.test_classes_with_paths(files, "ProjectTests")
24
+ test_files.should be_include("File1Test")
25
+ test_files.should be_include("File2Spec")
26
+ test_files.should be_include("File3Spec")
27
+ test_files.should_not be_include("File2")
28
+ test_files.should_not be_include("File3")
29
+ end
30
+ end
31
+
32
+ describe "::test_file" do
33
+ it "should use glob to find the target file" do
34
+ Dir.should_receive(:glob).with("ProjectTests/**/MyFile*.*").and_return(["ProjectTests/A/MyFileSpec.m"])
35
+ test_file = subject.test_file("Project/A/MyFile.m", "ProjectTests")
36
+ test_file.should == "ProjectTests/A/MyFileSpec.m"
37
+ end
38
+
39
+ it "should find correct test file if glob return two files having same prefix" do
40
+ Dir.stub(:glob).and_return(["ProjectTests/A/MyFile2Spec.m", "ProjectTests/A/MyFileSpec.m"])
41
+ test_file = subject.test_file("Project2/A/MyFile.m", ["ProjectTests"])
42
+ test_file.should == "ProjectTests/A/MyFileSpec.m"
43
+ end
44
+
45
+ it "should accept array of paths" do
46
+ Dir.stub(:glob).and_return([], ["ProjectTests2/A/MyFileSpec.m"])
47
+ test_file = subject.test_file("Project2/A/MyFile.m", ["ProjectTests", "ProjectTests2"])
48
+ test_file.should == "ProjectTests2/A/MyFileSpec.m"
49
+ end
50
+
51
+ it "should return nil if one does not exists" do
52
+ Dir.stub(:glob).and_return([])
53
+ test_file = subject.test_file("Project/A/MyFile.m", "ProjectTests")
54
+ test_file.should be_nil
55
+ end
56
+ end
57
+
58
+ describe "::find_test_target" do
59
+ it "should use xcodeproj to find test target" do
60
+ Dir.stub(:'[]').and_return(["MyProject.xcodeproj"])
61
+ stub_target = stub(:target)
62
+ stub_target.stub(:name).and_return("MyProjectSpec")
63
+ stub_project = stub(:project)
64
+ stub_project.stub(:targets).and_return([stub_target])
65
+ Xcodeproj::Project.stub(:new).and_return(stub_project)
66
+
67
+ target = subject.find_test_target
68
+ target.should == "MyProjectSpec"
69
+ end
70
+ end
71
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guard-xctool-test
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Francis Chong
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-14 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: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: xcodeproj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Xctool test guard allows you to automically & intelligently aunch specs
84
+ when files are modified. This gem use xctool to build and run tests, and xcodeproj
85
+ gem to parse project file.
86
+ email:
87
+ - francis@ignition.hk
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - .gitignore
93
+ - .travis.yml
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - guard-xctool-test.gemspec
99
+ - lib/guard/xctool-test.rb
100
+ - lib/guard/xctool-test/version.rb
101
+ - lib/guard/xctool_helper.rb
102
+ - spec/spec_helper.rb
103
+ - spec/xctool-test_spec.rb
104
+ - spec/xctool_helper_spec.rb
105
+ homepage: https://github.com/siuying/guard-xctool-test
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.0.3
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Xctool test guard allows you to automically & intelligently aunch specs when
129
+ files are modified.
130
+ test_files:
131
+ - spec/spec_helper.rb
132
+ - spec/xctool-test_spec.rb
133
+ - spec/xctool_helper_spec.rb