guard-xctool-test 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.
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