grunit 1.0.4

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: 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: []