paulanthonywilson-iphone_testify 0.0.1

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.
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.1.0 / 2009-02-25
2
+
3
+ * Getting started
data/README.rdoc ADDED
@@ -0,0 +1,89 @@
1
+ iphone_testify
2
+ by Paul Wilson
3
+ http://merecomplexities.com
4
+
5
+ == DESCRIPTION:
6
+
7
+ Utility to help set up and iPhone project for testing using code from {The Google Toolbox for Mac}[http://code.google.com/p/google-toolbox-for-mac/].
8
+
9
+ == FEATURES:
10
+
11
+ * Copies google test files into the "google_testing" directory
12
+ * Creates a UnitTests directory
13
+ * Adds Rakefile for compiling (via xcode) and reporting test failures (on console and via Growl)
14
+ * Adds an 'autoiphonetest.rb' file for _autotest_ style running of all tests when a change has been detected.
15
+
16
+ == TODO:
17
+
18
+ There are a few more things I'd like this gem to do.
19
+
20
+ * Generation of test stubs
21
+ * Automatic setup of _Unit Test_ target through XCode (via automation?)
22
+ * Automatic addition of test files to _Unit Test_ target
23
+
24
+ == SYNOPSIS:
25
+
26
+ From console cd to your project root directory. Type
27
+ % iphone_testify
28
+
29
+ Unfortunately there are some manual stages needed to add a _Unit Test_ target to your Xcode project. This is based on the {Google Toolbox Wiki instructions}[http://code.google.com/p/google-toolbox-for-mac/wiki/iPhoneUnitTesting]
30
+
31
+ 1. Create a new iPhone Target (Cocoa Touch Application) via "Project Menu > New Target..." called "Unit Test".
32
+ 2. Add all the ObjectiveC files that have been copied to your 'google_testing' directory to this target
33
+ 3. Add your project files to this target
34
+ 4. Add a new 'run script' build phase as the last step of your target build via "Project Menu > New Build Phase > New Run Script Build Phase", and dragging it to the end of the build steps if needed.
35
+ 5. Edit your Run Script Build Phase by double clicking it, and set the shell to "/bin/sh" and the script to "google_testing/RunIPhoneUnitTest.sh"
36
+
37
+
38
+ To autocompile/autorun all tests every time code changes
39
+
40
+ % ./autoiphonetest.rb
41
+
42
+
43
+ To compile and run tests if code has changed since the last run
44
+
45
+ % rake
46
+
47
+ To compile and run all tests even if nothing has changed since the last time
48
+
49
+ % rake test_all
50
+
51
+
52
+ == REQUIREMENTS:
53
+
54
+ * OS X Leopard
55
+ * XCode 3.1 (containing the iPhone SDK)
56
+ * Ruby (comes on Leopard)
57
+
58
+ == INSTALL:
59
+
60
+ % sudo gem sources -a http://gems.github.com # (you only need to do this once)
61
+ % sudo gem install paulanthonywilson-iphone_testify
62
+
63
+ == LICENSE:
64
+
65
+ Contains file taken from {The Google Toolbox for Mac}[http://code.google.com/p/google-toolbox-for-mac/]. See skeleton/google_testing/GoogleToolboxForMac.license which is also copied into the google_testing directory.
66
+
67
+
68
+ (The MIT License)
69
+
70
+ Copyright (c) 2008
71
+
72
+ Permission is hereby granted, free of charge, to any person obtaining
73
+ a copy of this software and associated documentation files (the
74
+ 'Software'), to deal in the Software without restriction, including
75
+ without limitation the rights to use, copy, modify, merge, publish,
76
+ distribute, sublicense, and/or sell copies of the Software, and to
77
+ permit persons to whom the Software is furnished to do so, subject to
78
+ the following conditions:
79
+
80
+ The above copyright notice and this permission notice shall be
81
+ included in all copies or substantial portions of the Software.
82
+
83
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
84
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
85
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
86
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
87
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
88
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
89
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ begin
6
+ require 'bones'
7
+ Bones.setup
8
+ rescue LoadError
9
+ begin
10
+ load 'tasks/setup.rb'
11
+ rescue LoadError
12
+ raise RuntimeError, '### please install the "bones" gem ###'
13
+ end
14
+ end
15
+
16
+ ensure_in_path 'lib'
17
+ require 'iphone_testify'
18
+
19
+ task :default => 'test:run'
20
+
21
+ PROJ.name = 'iphone_testify'
22
+ PROJ.authors = 'Paul Wilson'
23
+ PROJ.email = 'paul.wilson@merecomplexities.com'
24
+ PROJ.url = 'http://github.com/paulanthonywilson/iphone_testify/'
25
+ PROJ.version = IphoneTestify::VERSION
26
+
27
+ PROJ.exclude << '\.gitignore'
28
+ PROJ.notes.exclude = %w(^README\.txt$ ^data/)
29
+ PROJ.readme_file = 'README.rdoc'
30
+
31
+ depend_on "paulanthonywilson-osx_filewatcher"
32
+ depend_on "rake"
33
+
34
+ # EOF
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), %w[.. lib iphone_testify]))
5
+
6
+ # Put your code here
7
+ IphoneTestify::Setup::setup
8
+
9
+ # EOF
Binary file
@@ -0,0 +1,13 @@
1
+ require 'fileutils'
2
+
3
+ module IphoneTestify
4
+
5
+ module Setup
6
+ SKELETONDIR = GEMDIR + "/skeleton"
7
+ extend FileUtils
8
+ def self.setup
9
+ cp_r "#{SKELETONDIR}/.", "."
10
+ mkdir_p "UnitTests"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+
2
+ module IphoneTestify
3
+ GEMDIR = File.expand_path(File.dirname(__FILE__) + "/..")
4
+ # :stopdoc:
5
+ VERSION = '0.0.1'
6
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
7
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
8
+ # :startdoc:
9
+
10
+ # Returns the version string for the library.
11
+ #
12
+ def self.version
13
+ VERSION
14
+ end
15
+
16
+ # Returns the library path for the module. If any arguments are given,
17
+ # they will be joined to the end of the libray path using
18
+ # <tt>File.join</tt>.
19
+ #
20
+ def self.libpath( *args )
21
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
22
+ end
23
+
24
+ # Returns the lpath for the module. If any arguments are given,
25
+ # they will be joined to the end of the path using
26
+ # <tt>File.join</tt>.
27
+ #
28
+ def self.path( *args )
29
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
30
+ end
31
+
32
+ # Utility method used to require all files ending in .rb that lie in the
33
+ # directory below this file that has the same name as the filename passed
34
+ # in. Optionally, a specific _directory_ name can be passed in such that
35
+ # the _filename_ does not have to be equivalent to the directory.
36
+ #
37
+ def self.require_all_libs_relative_to( fname, dir = nil )
38
+ dir ||= ::File.basename(fname, '.*')
39
+ search_me = ::File.expand_path(
40
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
41
+
42
+ Dir.glob(search_me).sort.each {|rb| require rb}
43
+ end
44
+
45
+ end # module IphoneTestify
46
+
47
+ IphoneTestify.require_all_libs_relative_to(__FILE__)
48
+
49
+ # EOF
data/skeleton/Rakefile ADDED
@@ -0,0 +1,68 @@
1
+
2
+ BUILD_STATUS_FILE=".built"
3
+
4
+ class String
5
+ attr_accessor :colour
6
+ RESET="\e[00;m"
7
+
8
+ def coloured(colour = nil)
9
+ colour||=@colour
10
+ "#{colour_code(colour)}#{self}#{RESET}"
11
+ end
12
+
13
+ private
14
+ def colour_code colour
15
+ case colour
16
+ when :red : "\e[01;31m"
17
+ when :green : "\e[01;32m"
18
+ end
19
+ end
20
+ end
21
+
22
+ file BUILD_STATUS_FILE => Dir.glob("Classes/*.[hm]") + Dir.glob("UnitTests/*.m") do
23
+ failure_line = test
24
+ if failure_line
25
+ notice = ['Fail', failure_line.chomp]
26
+ else
27
+ notice = ['Pass']
28
+ end
29
+ growl *notice
30
+ File.open(BUILD_STATUS_FILE, 'w') {|f| f.write(notice * ": ")}
31
+ end
32
+
33
+ task :remove_built_file do
34
+ FileUtils.rm(BUILD_STATUS_FILE)
35
+ end
36
+
37
+ task :test_all=>[:remove_built_file, :test]
38
+
39
+ task :test=>[BUILD_STATUS_FILE] do
40
+ out = File.open('.built') {|f| f.read}
41
+ print out.coloured(out =~ /Pass/ ? :green : :red) + "\n"
42
+ end
43
+
44
+
45
+
46
+ task :default => [:test]
47
+
48
+ def test
49
+ output = `xcodebuild -target "Unit Test" -configuration Debug -sdk iphonesimulator2.1`
50
+ failure_line = nil
51
+ output.each do |line|
52
+ if line =~ /error:|^Executed.*(\d+) failures/
53
+ if $1.nil? || $1.to_i > 0
54
+ failure_line||= line
55
+ line.colour = :red
56
+ else
57
+ line.colour = :green
58
+ end
59
+ end
60
+ print line.coloured
61
+ end
62
+ failure_line
63
+ end
64
+
65
+ def growl title, msg =""
66
+ img = "~/.autotest_images/#{title.downcase}.png"
67
+ `growlnotify -H localhost -n autotest --image #{img} -p 0 -m #{msg.inspect} #{title}`
68
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'osx_watchfolder'
5
+ gem 'rake'
6
+
7
+
8
+ ARGV.clear
9
+
10
+ fork do
11
+ ARGV << 'test_all'
12
+ load 'rake'
13
+ end
14
+ OsxWatchfolder::FolderWatcher.new("Classes", "UnitTests") do
15
+ fork{load 'rake'}
16
+ end.start
@@ -0,0 +1,166 @@
1
+ //
2
+ // GTMDefines.h
3
+ //
4
+ // Copyright 2008 Google Inc.
5
+ //
6
+ // Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ // use this file except in compliance with the License. You may obtain a copy
8
+ // of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ // License for the specific language governing permissions and limitations under
16
+ // the License.
17
+ //
18
+
19
+ // ============================================================================
20
+
21
+ // ----------------------------------------------------------------------------
22
+ // CPP symbols that can be overridden in a prefix to control how the toolbox
23
+ // is compiled.
24
+ // ----------------------------------------------------------------------------
25
+
26
+
27
+ // GTMHTTPFetcher will support logging by default but only hook its input
28
+ // stream support for logging when requested. You can control the inclusion of
29
+ // the code by providing your own definitions for these w/in a prefix header.
30
+ //
31
+ #ifndef GTM_HTTPFETCHER_ENABLE_LOGGING
32
+ # define GTM_HTTPFETCHER_ENABLE_LOGGING 1
33
+ #endif // GTM_HTTPFETCHER_ENABLE_LOGGING
34
+ #ifndef GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING
35
+ # define GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING 0
36
+ #endif // GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING
37
+
38
+
39
+ // _GTMDevLog & _GTMDevAssert
40
+ //
41
+ // _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
42
+ // developer level errors. This implementation simply macros to NSLog/NSAssert.
43
+ // It is not intended to be a general logging/reporting system.
44
+ //
45
+ // Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
46
+ // for a little more background on the usage of these macros.
47
+ //
48
+ // _GTMDevLog log some error/problem in debug builds
49
+ // _GTMDevAssert assert if conditon isn't met w/in a method/function
50
+ // in all builds.
51
+ //
52
+ // To replace this system, just provide different macro definitions in your
53
+ // prefix header. Remember, any implementation you provide *must* be thread
54
+ // safe since this could be called by anything in what ever situtation it has
55
+ // been placed in.
56
+ //
57
+
58
+ // We only define the simple macros if nothing else has defined this.
59
+ #ifndef _GTMDevLog
60
+
61
+ #ifdef DEBUG
62
+ #define _GTMDevLog(...) NSLog(__VA_ARGS__)
63
+ #else
64
+ #define _GTMDevLog(...) do { } while (0)
65
+ #endif
66
+
67
+ #endif // _GTMDevLog
68
+
69
+ // Declared here so that it can easily be used for logging tracking if
70
+ // necessary. See GTMUnitTestDevLog.h for details.
71
+ @class NSString;
72
+ extern void _GTMUnittestDevLog(NSString *format, ...);
73
+
74
+ #ifndef _GTMDevAssert
75
+ // we directly invoke the NSAssert handler so we can pass on the varargs
76
+ // (NSAssert doesn't have a macro we can use that takes varargs)
77
+ #if !defined(NS_BLOCK_ASSERTIONS)
78
+ #define _GTMDevAssert(condition, ...) \
79
+ do { \
80
+ if (!(condition)) { \
81
+ [[NSAssertionHandler currentHandler] \
82
+ handleFailureInFunction:[NSString stringWithCString:__PRETTY_FUNCTION__] \
83
+ file:[NSString stringWithCString:__FILE__] \
84
+ lineNumber:__LINE__ \
85
+ description:__VA_ARGS__]; \
86
+ } \
87
+ } while(0)
88
+ #else // !defined(NS_BLOCK_ASSERTIONS)
89
+ #define _GTMDevAssert(condition, ...) do { } while (0)
90
+ #endif // !defined(NS_BLOCK_ASSERTIONS)
91
+
92
+ #endif // _GTMDevAssert
93
+
94
+ // _GTMCompileAssert
95
+ // _GTMCompileAssert is an assert that is meant to fire at compile time if you
96
+ // want to check things at compile instead of runtime. For example if you
97
+ // want to check that a wchar is 4 bytes instead of 2 you would use
98
+ // _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
99
+ // Note that the second "arg" is not in quotes, and must be a valid processor
100
+ // symbol in it's own right (no spaces, punctuation etc).
101
+
102
+ // Wrapping this in an #ifndef allows external groups to define their own
103
+ // compile time assert scheme.
104
+ #ifndef _GTMCompileAssert
105
+ // We got this technique from here:
106
+ // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
107
+
108
+ #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
109
+ #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
110
+ #define _GTMCompileAssert(test, msg) \
111
+ typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
112
+ #endif // _GTMCompileAssert
113
+
114
+ // ============================================================================
115
+
116
+ // ----------------------------------------------------------------------------
117
+ // CPP symbols defined based on the project settings so the GTM code has
118
+ // simple things to test against w/o scattering the knowledge of project
119
+ // setting through all the code.
120
+ // ----------------------------------------------------------------------------
121
+
122
+ // Provide a single constant CPP symbol that all of GTM uses for ifdefing
123
+ // iPhone code.
124
+ #include <TargetConditionals.h>
125
+ #if TARGET_OS_IPHONE // iPhone SDK
126
+ // For iPhone specific stuff
127
+ #define GTM_IPHONE_SDK 1
128
+ #else
129
+ // For MacOS specific stuff
130
+ #define GTM_MACOS_SDK 1
131
+ #endif
132
+
133
+ // To simplify support for 64bit (and Leopard in general), we provide the type
134
+ // defines for non Leopard SDKs
135
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
136
+ // NSInteger/NSUInteger and Max/Mins
137
+ #ifndef NSINTEGER_DEFINED
138
+ #if __LP64__ || NS_BUILD_32_LIKE_64
139
+ typedef long NSInteger;
140
+ typedef unsigned long NSUInteger;
141
+ #else
142
+ typedef int NSInteger;
143
+ typedef unsigned int NSUInteger;
144
+ #endif
145
+ #define NSIntegerMax LONG_MAX
146
+ #define NSIntegerMin LONG_MIN
147
+ #define NSUIntegerMax ULONG_MAX
148
+ #define NSINTEGER_DEFINED 1
149
+ #endif // NSINTEGER_DEFINED
150
+ // CGFloat
151
+ #ifndef CGFLOAT_DEFINED
152
+ #if defined(__LP64__) && __LP64__
153
+ // This really is an untested path (64bit on Tiger?)
154
+ typedef double CGFloat;
155
+ #define CGFLOAT_MIN DBL_MIN
156
+ #define CGFLOAT_MAX DBL_MAX
157
+ #define CGFLOAT_IS_DOUBLE 1
158
+ #else /* !defined(__LP64__) || !__LP64__ */
159
+ typedef float CGFloat;
160
+ #define CGFLOAT_MIN FLT_MIN
161
+ #define CGFLOAT_MAX FLT_MAX
162
+ #define CGFLOAT_IS_DOUBLE 0
163
+ #endif /* !defined(__LP64__) || !__LP64__ */
164
+ #define CGFLOAT_DEFINED 1
165
+ #endif // CGFLOAT_DEFINED
166
+ #endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
@@ -0,0 +1,29 @@
1
+ //
2
+ // GTMIPhoneUnitTestDelegate.h
3
+ //
4
+ // Copyright 2008 Google Inc.
5
+ //
6
+ // Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ // use this file except in compliance with the License. You may obtain a copy
8
+ // of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ // License for the specific language governing permissions and limitations under
16
+ // the License.
17
+ //
18
+
19
+ // Application delegate that runs all test methods in registered classes
20
+ // extending SenTestCase. The application is terminated afterwards.
21
+ // You can also run the tests directly from your application by invoking
22
+ // gtm_runTests and clean up, restore data, etc. before the application
23
+ // terminates.
24
+ @interface GTMIPhoneUnitTestDelegate : NSObject
25
+ // Runs through all the registered classes and runs test methods on any
26
+ // that are subclasses of SenTestCase. Prints results and run time to
27
+ // the default output.
28
+ - (void)runTests;
29
+ @end
@@ -0,0 +1,160 @@
1
+ //
2
+ // GTMIPhoneUnitTestDelegate.m
3
+ //
4
+ // Copyright 2008 Google Inc.
5
+ //
6
+ // Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ // use this file except in compliance with the License. You may obtain a copy
8
+ // of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ // License for the specific language governing permissions and limitations under
16
+ // the License.
17
+ //
18
+
19
+ #import "GTMIPhoneUnitTestDelegate.h"
20
+
21
+ #import "GTMDefines.h"
22
+ #if !GTM_IPHONE_SDK
23
+ #error GTMIPhoneUnitTestDelegate for iPhone only
24
+ #endif
25
+ #import <objc/runtime.h>
26
+ #import <stdio.h>
27
+ #import <UIKit/UIKit.h>
28
+ #import "GTMSenTestCase.h"
29
+
30
+ // Used for sorting methods below
31
+ static int MethodSort(const void *a, const void *b) {
32
+ const char *nameA = sel_getName(method_getName(*(Method*)a));
33
+ const char *nameB = sel_getName(method_getName(*(Method*)b));
34
+ return strcmp(nameA, nameB);
35
+ }
36
+
37
+ @interface UIApplication (iPhoneUnitTestAdditions)
38
+ // "Private" method that we need
39
+ - (void)terminate;
40
+ @end
41
+
42
+ @implementation GTMIPhoneUnitTestDelegate
43
+
44
+ // Return YES if class is subclass (1 or more generations) of SenTestCase
45
+ - (BOOL)isTestFixture:(Class)aClass {
46
+ BOOL iscase = NO;
47
+ Class testCaseClass = [SenTestCase class];
48
+ Class superclass;
49
+ for (superclass = aClass;
50
+ !iscase && superclass;
51
+ superclass = class_getSuperclass(superclass)) {
52
+ iscase = superclass == testCaseClass ? YES : NO;
53
+ }
54
+ return iscase;
55
+ }
56
+
57
+ // Run through all the registered classes and run test methods on any
58
+ // that are subclasses of SenTestCase. Terminate the application upon
59
+ // test completion.
60
+ - (void)applicationDidFinishLaunching:(UIApplication *)application {
61
+ [self runTests];
62
+ // Using private call to end our tests
63
+ [[UIApplication sharedApplication] terminate];
64
+ }
65
+
66
+ // Run through all the registered classes and run test methods on any
67
+ // that are subclasses of SenTestCase. Print results and run time to
68
+ // the default output.
69
+ - (void)runTests {
70
+ int count = objc_getClassList(NULL, 0);
71
+ Class *classes = (Class*)malloc(sizeof(Class) * count);
72
+ _GTMDevAssert(classes, @"Couldn't allocate class list");
73
+ objc_getClassList(classes, count);
74
+ int suiteSuccesses = 0;
75
+ int suiteFailures = 0;
76
+ int suiteTotal = 0;
77
+ NSString *suiteName = [[NSBundle mainBundle] bundlePath];
78
+ NSDate *suiteStartDate = [NSDate date];
79
+ NSString *suiteStartString = [NSString stringWithFormat:@"Test Suite '%@' started at %@\n",
80
+ suiteName, suiteStartDate];
81
+ fputs([suiteStartString UTF8String], stderr);
82
+ fflush(stderr);
83
+ for (int i = 0; i < count; ++i) {
84
+ Class currClass = classes[i];
85
+ if ([self isTestFixture:currClass]) {
86
+ NSDate *fixtureStartDate = [NSDate date];
87
+ NSString *fixtureName = NSStringFromClass(currClass);
88
+ NSString *fixtureStartString = [NSString stringWithFormat:@"Test Suite '%@' started at %@\n",
89
+ fixtureName, fixtureStartDate];
90
+ int fixtureSuccesses = 0;
91
+ int fixtureFailures = 0;
92
+ int fixtureTotal = 0;
93
+ fputs([fixtureStartString UTF8String], stderr);
94
+ fflush(stderr);
95
+ id testcase = [[currClass alloc] init];
96
+ _GTMDevAssert(testcase, @"Unable to instantiate Test Suite: '%@'\n",
97
+ fixtureName);
98
+ unsigned int methodCount;
99
+ Method *methods = class_copyMethodList(currClass, &methodCount);
100
+ // Sort our methods so they are called in Alphabetical order just
101
+ // because we can.
102
+ qsort(methods, methodCount, sizeof(Method), MethodSort);
103
+ for (size_t j = 0; j < methodCount; ++j) {
104
+ Method currMethod = methods[j];
105
+ SEL sel = method_getName(currMethod);
106
+ const char *name = sel_getName(sel);
107
+ // If it starts with test, run it.
108
+ if (strstr(name, "test") == name) {
109
+ fixtureTotal += 1;
110
+ BOOL failed = NO;
111
+ NSDate *caseStartDate = [NSDate date];
112
+ @try {
113
+ [testcase performTest:sel];
114
+ } @catch (NSException *exception) {
115
+ failed = YES;
116
+ }
117
+ if (failed) {
118
+ fixtureFailures += 1;
119
+ } else {
120
+ fixtureSuccesses += 1;
121
+ }
122
+ NSTimeInterval caseEndTime = [[NSDate date] timeIntervalSinceDate:caseStartDate];
123
+ NSString *caseEndString = [NSString stringWithFormat:@"Test Case '-[%@ %s]' %s (%0.3f seconds).\n",
124
+ fixtureName, name,
125
+ failed ? "failed" : "passed", caseEndTime];
126
+ fputs([caseEndString UTF8String], stderr);
127
+ fflush(stderr);
128
+ }
129
+ }
130
+ if (methods) {
131
+ free(methods);
132
+ }
133
+ [testcase release];
134
+ NSDate *fixtureEndDate = [NSDate date];
135
+ NSTimeInterval fixtureEndTime = [fixtureEndDate timeIntervalSinceDate:fixtureStartDate];
136
+ NSString *fixtureEndString = [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n"
137
+ "Executed %d tests, with %d failures (%d unexpected) in %0.3f (%0.3f) seconds\n",
138
+ fixtureName, fixtureEndDate, fixtureTotal,
139
+ fixtureFailures, fixtureFailures,
140
+ fixtureEndTime, fixtureEndTime];
141
+
142
+ fputs([fixtureEndString UTF8String], stderr);
143
+ fflush(stderr);
144
+ suiteTotal += fixtureTotal;
145
+ suiteSuccesses += fixtureSuccesses;
146
+ suiteFailures += fixtureFailures;
147
+ }
148
+ }
149
+ NSDate *suiteEndDate = [NSDate date];
150
+ NSTimeInterval suiteEndTime = [suiteEndDate timeIntervalSinceDate:suiteStartDate];
151
+ NSString *suiteEndString = [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n"
152
+ "Executed %d tests, with %d failures (%d unexpected) in %0.3f (%0.3f) seconds\n",
153
+ suiteName, suiteEndDate, suiteTotal,
154
+ suiteFailures, suiteFailures,
155
+ suiteEndTime, suiteEndTime];
156
+ fputs([suiteEndString UTF8String], stderr);
157
+ fflush(stderr);
158
+ }
159
+
160
+ @end
@@ -0,0 +1,33 @@
1
+ //
2
+ // GTMIPhoneUnitTestMain.m
3
+ //
4
+ // Copyright 2008 Google Inc.
5
+ //
6
+ // Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ // use this file except in compliance with the License. You may obtain a copy
8
+ // of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ // License for the specific language governing permissions and limitations under
16
+ // the License.
17
+ //
18
+
19
+ #import "GTMDefines.h"
20
+ #if !GTM_IPHONE_SDK
21
+ #error GTMIPhoneUnitTestMain for iPhone only
22
+ #endif
23
+ #import <UIKit/UIKit.h>
24
+
25
+ // Creates an application that runs all tests from classes extending
26
+ // SenTestCase, outputs results and test run time, and terminates right
27
+ // afterwards.
28
+ int main(int argc, char *argv[]) {
29
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
30
+ int retVal = UIApplicationMain(argc, argv, nil, @"GTMIPhoneUnitTestDelegate");
31
+ [pool release];
32
+ return retVal;
33
+ }