grunit 1.0.4

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: f76e2b22e99eb20179514f820d3e8cd08b3bbb34
4
+ data.tar.gz: 98d0ad954f71cd68e21bc037c3970c0df0b3e954
5
+ SHA512:
6
+ metadata.gz: 194e318a6618962bcbf9e0332b3dfc8116a8f0dcf148a92d0aaa61504dee04fbc98839d26e9b8a8025697f5dbf448e68bdbd14f44a9410fd54d7d098781dc3af
7
+ data.tar.gz: 3a496e9589ca6b590b9751a024eaa19fafb1972b24a1a7dcaa53df068ccb1446c9f87fdd1fa09933cdbaedd7e089846e4415f8c5a28641bb0465f467b9e47557
data/bin/grunit ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'slop'
4
+ require 'grunit'
5
+
6
+ def require_opt(opts, key, desc)
7
+ if !opts[key]
8
+ puts " "
9
+ puts desc.red
10
+ puts " "
11
+ puts opts.to_s
12
+ puts " "
13
+ exit 1
14
+ end
15
+ end
16
+
17
+ Slop.parse do
18
+ banner "Usage: grunit install|run|add|sync [options]"
19
+
20
+ command "install" do
21
+ on :n, :name=, "Project name"
22
+ on :p, :path=, "Project path, defaults to <Project Name>.xcodeproj", argument: :optional
23
+ on :t, :test_target=, "Test target name, defaults to Tests", argument: :optional
24
+
25
+ run do |opts, args|
26
+ project = GRUnit::Project.open_from_opts(opts)
27
+ project.create_test_target
28
+ end
29
+ end
30
+
31
+ command "add" do
32
+ on :n, :name=, "Project name"
33
+ on :f, :file=, "Test name, MyTest"
34
+ #on :r, :framework=, "Test case framework (kiwi,grunit), defaults to grunit"
35
+ on :p, :path=, "Project path, defaults to <Project Name>.xcodeproj", argument: :optional
36
+ on :t, :test_target=, "Test target name, defaults to Tests", argument: :optional
37
+
38
+ run do |opts, args|
39
+ require_opt(opts, :file, "Need to specify a test name with -f.")
40
+ project = GRUnit::Project.open_from_opts(opts)
41
+ project.create_test(opts[:file]) #, opts[:framework])
42
+ project.save
43
+ end
44
+ end
45
+
46
+ command "run" do
47
+ on :n, :name=, "Project name"
48
+ on :t, :test_target=, "Test target name, defaults to Tests", argument: :optional
49
+ on :p, :path=, "Workspace path, defaults to <Project Name>.xcworkspace", argument: :optional
50
+
51
+ run do |opts, args|
52
+ require_opt(opts, :name, "Need to specify a project name with -n.")
53
+
54
+ name = opts[:name]
55
+ # Scheme name should match the test target name
56
+ test_target = opts[:test_target] || "Tests"
57
+ path = opts[:path] || "#{name}.xcworkspace"
58
+ system("GRUNIT_CLI=1 xcodebuild -workspace #{path} -scheme #{test_target} -configuration Debug -sdk iphonesimulator build")
59
+ end
60
+ end
61
+
62
+ command "install_cli" do
63
+ on :n, :name=, "Project name"
64
+ on :t, :test_target=, "Test target name, defaults to Tests", argument: :optional
65
+ on :p, :path=, "Workspace path, defaults to <Project Name>.xcworkspace", argument: :optional
66
+
67
+ run do |opts, args|
68
+ project = GRUnit::Project.open_from_opts(opts)
69
+ project.install_run_tests_script
70
+ end
71
+ end
72
+
73
+ command "sync" do
74
+ on :n, :name=, "Project name"
75
+ on :t, :test_target=, "Test target name, defaults to Tests", argument: :optional
76
+ on :p, :path=, "Workspace path, defaults to <Project Name>.xcworkspace", argument: :optional
77
+
78
+ run do |opts, args|
79
+ project = GRUnit::Project.open_from_opts(opts)
80
+ project.sync_test_target_membership
81
+ end
82
+ end
83
+
84
+ end
data/lib/grunit.rb ADDED
@@ -0,0 +1,4 @@
1
+
2
+ module GRUnit; end
3
+
4
+ require 'grunit/project'
@@ -0,0 +1,329 @@
1
+ require 'xcodeproj'
2
+ require 'xcodeproj/ext'
3
+ require 'fileutils'
4
+ require 'logger'
5
+ require 'colorize'
6
+ require 'erb'
7
+ require 'ostruct'
8
+
9
+ class ErbalT < OpenStruct
10
+ def render(template)
11
+ ERB.new(template).result(binding)
12
+ end
13
+ end
14
+
15
+ class GRUnit::Project
16
+
17
+ attr_reader :project_path, :target_name, :test_target_name, :logger
18
+
19
+ attr_reader :project, :main_target
20
+
21
+ def initialize(project_path, target_name, test_target_name, logger=nil)
22
+ @target_name = target_name
23
+ @project_path = project_path
24
+ @test_target_name = test_target_name
25
+ @logger ||= begin
26
+ logger = Logger.new(STDOUT)
27
+ logger.formatter = proc do |severity, datetime, progname, msg|
28
+ case severity
29
+ when "ERROR"
30
+ "#{msg}\n".red
31
+ when "DEBUG"
32
+ "#{msg}\n".green
33
+ else
34
+ "#{msg}\n"
35
+ end
36
+ end
37
+ logger
38
+ end
39
+ end
40
+
41
+ def open
42
+ if !File.exists?(project_path)
43
+ logger.error "Can't find project path at #{project_path}"
44
+ return false
45
+ end
46
+
47
+ @project = Xcodeproj::Project.open(project_path)
48
+
49
+ # Find the main target for the test dependency
50
+ @main_target = project.targets.select { |t| t.name == target_name }.first
51
+ if !@main_target
52
+ logger.error "No target with name #{target_name}"
53
+ return false
54
+ end
55
+
56
+ true
57
+ end
58
+
59
+ class << self
60
+
61
+ # Initialize and open a project.
62
+ #
63
+ def open(project_path, target_name, test_target_name, logger=nil)
64
+ project = GRUnit::Project.new(project_path, target_name, test_target_name, logger)
65
+ if project.open
66
+ project
67
+ else
68
+ nil
69
+ end
70
+ end
71
+
72
+ # Open from slop options.
73
+ # This is only meant to be called from the grunit bin executable,
74
+ # it outputs to STDOUT and calls exit.
75
+ #
76
+ def open_from_opts(opts)
77
+ target_name = opts[:name]
78
+ project_path = opts[:path] || "#{target_name}.xcodeproj"
79
+ test_target_name = opts[:test_target] || "Tests"
80
+
81
+ if !target_name
82
+ puts " "
83
+ puts "Need to specify a project name.".red
84
+ puts " "
85
+ puts opts.to_s
86
+ puts " "
87
+ exit 1
88
+ end
89
+
90
+ self.open(project_path, target_name, test_target_name)
91
+ end
92
+ end
93
+
94
+ def find_test_target
95
+ project.targets.select { |t| t.name == test_target_name }.first
96
+ end
97
+
98
+ # Create the test target and setup everything
99
+ #
100
+ def create_test_target
101
+ Dir.chdir(File.dirname(project_path))
102
+ FileUtils.mkdir_p(test_target_name)
103
+
104
+ # Write the Tests-Info.plist
105
+ test_info = {
106
+ "CFBundleDisplayName" => "${PRODUCT_NAME}",
107
+ "CFBundleExecutable" => "${EXECUTABLE_NAME}",
108
+ "CFBundleIdentifier" => "tests.${PRODUCT_NAME:rfc1034identifier}",
109
+ "CFBundleInfoDictionaryVersion" => "6.0",
110
+ "CFBundleName" => "${PRODUCT_NAME}",
111
+ "CFBundlePackageType" => "APPL",
112
+ "CFBundleShortVersionString" => "1.0",
113
+ "CFBundleVersion" => "1.0",
114
+ "LSRequiresIPhoneOS" => true,
115
+ "UISupportedInterfaceOrientations" => ["UIInterfaceOrientationPortrait"]
116
+ }
117
+ test_info_path = File.join(test_target_name, "#{test_target_name}-Info.plist")
118
+ if !File.exists?(test_info_path)
119
+ logger.debug "Creating: #{test_info_path}"
120
+ Xcodeproj.write_plist(test_info, test_info_path)
121
+ else
122
+ logger.debug "#{test_info_path} already exists, skipping..."
123
+ end
124
+
125
+ test_target = find_test_target
126
+ if !test_target
127
+
128
+ # Create the test target
129
+ logger.debug "Creating target: #{test_target_name}"
130
+ test_target = project.new_target(:application, test_target_name, :ios, "7.0")
131
+ test_target.add_dependency(main_target)
132
+
133
+ create_test_file("main.m", template("main.m"), true)
134
+ create_test("MyTest")
135
+
136
+ #
137
+ # No longer doing this (using same resource build phase as main target).
138
+ # It causes crashes in latest xCode.
139
+ #
140
+ # Use same resources build phase as main target
141
+ # Have to compare with class name because of funky const loading in xcodeproj gem
142
+ # resources_build_phase = main_target.build_phases.select { |p|
143
+ # p.class == Xcodeproj::Project::Object::PBXResourcesBuildPhase }.first
144
+ # test_target.build_phases << resources_build_phase if resources_build_phase
145
+
146
+ # Add resources build phase if one doesn't exist
147
+ resources_build_phase = test_target.build_phases.select { |p|
148
+ p.class == Xcodeproj::Project::Object::PBXResourcesBuildPhase }.first
149
+
150
+ test_target.build_phases << project.new(Xcodeproj::Project::Object::PBXResourcesBuildPhase) unless resources_build_phase
151
+ else
152
+ logger.debug "Test target already exists, skipping..."
153
+ end
154
+
155
+ # Get main target prefix header
156
+ prefix_header = main_target.build_settings("Debug")["GCC_PREFIX_HEADER"]
157
+
158
+ # Clear default OTHER_LDFLAGS (otherwise CocoaPods gives a warning)
159
+ test_target.build_configurations.each do |c|
160
+ c.build_settings.delete("OTHER_LDFLAGS")
161
+ c.build_settings["INFOPLIST_FILE"] = test_info_path
162
+ c.build_settings["GCC_PREFIX_HEADER"] = prefix_header if prefix_header
163
+ end
164
+
165
+ # Write any test support files
166
+ write_test_file("RunTests.sh", template("RunTests.sh"), true)
167
+
168
+ # Create test scheme if it doesn't exist
169
+ logger.debug "Checking for Test scheme..."
170
+ schemes = Xcodeproj::Project.schemes(project_path)
171
+ test_scheme = schemes.select { |s| s == test_target_name }.first
172
+ if !test_scheme
173
+ logger.debug "Test scheme not found, creating..."
174
+ scheme = Xcodeproj::XCScheme.new
175
+ scheme.set_launch_target(test_target)
176
+ scheme.save_as(project_path, test_target_name)
177
+ else
178
+ logger.debug "Test scheme already exists, skipping..."
179
+ end
180
+
181
+ logger.debug "Saving project..."
182
+ project.save
183
+
184
+ check_pod
185
+ end
186
+
187
+ def template(name, template_vars=nil)
188
+ template_path = File.join(File.dirname(__FILE__), "templates", name)
189
+ content = File.read(template_path)
190
+
191
+ if template_path.end_with?(".erb")
192
+ et = ErbalT.new(template_vars)
193
+ content = et.render(content)
194
+ end
195
+ content
196
+ end
197
+
198
+ def write_test_file(file_name, content, force=false)
199
+ # Create file in tests dir
200
+ path = File.join(test_target_name, file_name)
201
+
202
+ if !force && File.exists?(path)
203
+ logger.info "Test file already exists, skipping"
204
+ end
205
+
206
+ logger.debug "Creating: #{path}"
207
+ File.open(path, "w") { |f| f.write(content) }
208
+ path
209
+ end
210
+
211
+ # Create a file with content and add to the test target
212
+ #
213
+ def create_test_file(file_name, content, force=false)
214
+ path = write_test_file(file_name, content, force)
215
+ add_test_file(path)
216
+ path
217
+ end
218
+
219
+ # Add a file to the test target
220
+ #
221
+ def add_test_file(path)
222
+ test_target = find_test_target
223
+ if !test_target
224
+ logger.error "No test target to add to"
225
+ return false
226
+ end
227
+
228
+ tests_group = project.groups.select { |g| g.name == test_target_name }.first
229
+ tests_group ||= project.new_group(test_target_name)
230
+
231
+ test_file = tests_group.find_file_by_path(path)
232
+ if !test_file
233
+ test_file = tests_group.new_file(path)
234
+ end
235
+ test_target.add_file_references([test_file])
236
+ true
237
+ end
238
+
239
+ # Create test file and add it to the test target.
240
+ #
241
+ # @param name Name of test class and file name
242
+ # @param template_type nil or "kiwi"
243
+ #
244
+ def create_test(name, template_type=nil)
245
+ template_type ||= :grunit
246
+
247
+ template_name = case template_type.to_sym
248
+ when :kiwi
249
+ "TestKiwi.m.erb"
250
+ when :grunit
251
+ "Test.m.erb"
252
+ end
253
+
254
+ if name.end_with?(".m")
255
+ name = name[0...-2]
256
+ end
257
+ template_vars = {test_class_name: name}
258
+ path = create_test_file("#{name}.m", template(template_name, template_vars))
259
+ path
260
+ end
261
+
262
+ def save
263
+ @project.save
264
+ end
265
+
266
+ # Check the Podfile or just display some Podfile help
267
+ #
268
+ def check_pod
269
+ logger.info <<-EOS
270
+
271
+ Add the following to your Podfile and run pod install.
272
+
273
+ #{template("Podfile")}
274
+
275
+ Make sure to open the .xcworkspace.
276
+
277
+ EOS
278
+ end
279
+
280
+ def sync_test_target_membership
281
+ test_target = find_test_target
282
+ if !test_target
283
+ logger.error "No test target to add to"
284
+ return false
285
+ end
286
+
287
+ tests_group = project.groups.select { |g| g.name == test_target_name }.first
288
+ if !tests_group
289
+ logger.error "No test group to add to"
290
+ return false
291
+ end
292
+
293
+ sources_phase = main_target.build_phases.select { |p|
294
+ p.class == Xcodeproj::Project::Object::PBXSourcesBuildPhase }.first
295
+
296
+ if !sources_phase
297
+ logger.error "No main target source phase found"
298
+ return false
299
+ end
300
+
301
+ logger.debug "Adding to test target: "
302
+ sources_phase.files_references.each do |file_ref|
303
+ next if file_ref.path == "main.m"
304
+ test_file = tests_group.find_file_by_path(file_ref.path)
305
+ if !test_file
306
+ logger.debug " #{file_ref.path}"
307
+ test_target.add_file_references([file_ref])
308
+ end
309
+ end
310
+ project.save
311
+ end
312
+
313
+ def install_run_tests_script
314
+ run_script_name = "Run Tests (CLI)"
315
+ # Find run script build phase and install RunTests.sh
316
+ test_target = find_test_target
317
+ run_script_phase = test_target.build_phases.select { |p|
318
+ p.class == Xcodeproj::Project::Object::PBXShellScriptBuildPhase &&
319
+ p.name == run_script_name }.first
320
+ if !run_script_phase
321
+ logger.debug "Installing run tests script..."
322
+ run_script_phase = project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
323
+ run_script_phase.name = run_script_name
324
+ run_script_phase.shell_script = "sh Tests/RunTests.sh"
325
+ test_target.build_phases << run_script_phase
326
+ end
327
+ project.save
328
+ end
329
+ end
@@ -0,0 +1,3 @@
1
+ target :Tests do
2
+ pod 'GRUnit'
3
+ end
@@ -0,0 +1,29 @@
1
+ #!/bin/sh
2
+
3
+ # If we aren't running from the command line, then exit
4
+ if [ "$GRUNIT_CLI" = "" ] && [ "$GRUNIT_AUTORUN" = "" ]; then
5
+ exit 0
6
+ fi
7
+
8
+ TEST_TARGET_EXECUTABLE_PATH="$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH"
9
+
10
+ if [ ! -e "$TEST_TARGET_EXECUTABLE_PATH" ]; then
11
+ echo ""
12
+ echo " ------------------------------------------------------------------------"
13
+ echo " Missing executable path: "
14
+ echo " $TEST_TARGET_EXECUTABLE_PATH."
15
+ echo " The product may have failed to build."
16
+ echo " ------------------------------------------------------------------------"
17
+ echo ""
18
+ exit 1
19
+ fi
20
+
21
+ RUN_CMD="ios-sim launch \"$TEST_TARGET_EXECUTABLE_PATH\""
22
+
23
+ echo "Running: $RUN_CMD"
24
+ set +o errexit # Disable exiting on error so script continues if tests fail
25
+ eval $RUN_CMD
26
+ RETVAL=$?
27
+ set -o errexit
28
+
29
+ exit $RETVAL
@@ -0,0 +1,15 @@
1
+ //
2
+ // <%= test_class_name %>.m
3
+ //
4
+ #import <GRUnit/GRUnit.h>
5
+
6
+ @interface <%= test_class_name %> : GRTestCase
7
+ @end
8
+
9
+ @implementation <%= test_class_name %>
10
+
11
+ - (void)test {
12
+
13
+ }
14
+
15
+ @end
@@ -0,0 +1,16 @@
1
+ //
2
+ // <%= test_class_name %>.m
3
+ //
4
+ #import "Kiwi.h"
5
+
6
+ SPEC_BEGIN(<%= test_class_name %>)
7
+
8
+ describe(@"Math", ^{
9
+ it(@"is pretty cool", ^{
10
+ NSUInteger a = 16;
11
+ NSUInteger b = 26;
12
+ [[theValue(a + b) should] equal:theValue(43)];
13
+ });
14
+ });
15
+
16
+ SPEC_END
@@ -0,0 +1,8 @@
1
+ // This file auto-generated by grunit gem
2
+ #import <UIKit/UIKit.h>
3
+
4
+ int main(int argc, char *argv[]) {
5
+ @autoreleasepool {
6
+ return UIApplicationMain(argc, argv, nil, @"GRUnitIOSAppDelegate");
7
+ }
8
+ }
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grunit
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Gabriel Handford
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: xcodeproj
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: slop
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: colorize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: xcpretty
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Utilities for GRUnit.
70
+ email: gabrielh@gmail.com
71
+ executables:
72
+ - grunit
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - bin/grunit
77
+ - lib/grunit.rb
78
+ - lib/grunit/project.rb
79
+ - lib/grunit/templates/Podfile
80
+ - lib/grunit/templates/RunTests.sh
81
+ - lib/grunit/templates/Test.m.erb
82
+ - lib/grunit/templates/TestKiwi.m.erb
83
+ - lib/grunit/templates/main.m
84
+ homepage: https://github.com/gabriel/GRUnit
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.2.2
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: GRUnit
108
+ test_files: []