From 0a93b377d61b718872889ffd5d41ad2664313f30 Mon Sep 17 00:00:00 2001 From: Blake Watters Date: Wed, 9 Mar 2011 15:07:20 -0500 Subject: [PATCH] Upgraded to UISpecRunner 0.4.0. Added Rakefile for running all the specs. --- Gemfile | 5 ++ Gemfile.lock | 18 +++++++ Rakefile | 35 ++++++++++++ RestKit.xcodeproj/project.pbxproj | 8 ++- Specs/UISpec+UISpecRunner.h | 6 +++ Specs/UISpec+UISpecRunner.m | 89 +++++++++++++++++++++++++++++-- Specs/main.m | 1 - uispec | 84 ----------------------------- uispec.opts | 1 + 9 files changed, 153 insertions(+), 94 deletions(-) create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Rakefile delete mode 100755 uispec create mode 100644 uispec.opts diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..79213bcd --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source "http://rubygems.org" + +gem "rake" +gem "uispecrunner", ">= 0.4.0" +gem "bundler", "~> 1.0.0" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..041681a3 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,18 @@ +GEM + remote: http://rubygems.org/ + specs: + open4 (1.0.1) + rake (0.8.7) + uispecrunner (0.4.0) + open4 (= 1.0.1) + +PLATFORMS + ruby + +DEPENDENCIES + bundler (~> 1.0.0) + rake + uispecrunner (>= 0.4.0) + +METADATA + version: 1.0.6 diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..e91f97cb --- /dev/null +++ b/Rakefile @@ -0,0 +1,35 @@ +require 'rubygems' + +begin + gem 'uispecrunner' + require 'uispecrunner' + require 'uispecrunner/options' +rescue LoadError => error + puts "Unable to load UISpecRunner: #{error}" +end + +namespace :uispec do + desc "Run all specs" + task :all do + options = UISpecRunner::Options.from_file('uispec.opts') rescue {} + uispec_runner = UISpecRunner.new(options) + uispec_runner.run_all! + end + + desc "Run all unit specs (those that implement UISpecUnit)" + task :units do + options = UISpecRunner::Options.from_file('uispec.opts') rescue {} + uispec_runner = UISpecRunner.new(options) + uispec_runner.run_protocol!('UISpecUnit') + end + + desc "Run all integration specs (those that implement UISpecIntegration)" + task :integration do + options = UISpecRunner::Options.from_file('uispec.opts') rescue {} + uispec_runner = UISpecRunner.new(options) + uispec_runner.run_protocol!('UISpecIntegration') + end +end + +desc "Run all specs" +task :default => 'uispec:all' diff --git a/RestKit.xcodeproj/project.pbxproj b/RestKit.xcodeproj/project.pbxproj index dcfe1482..33ea7107 100644 --- a/RestKit.xcodeproj/project.pbxproj +++ b/RestKit.xcodeproj/project.pbxproj @@ -995,7 +995,7 @@ 25956992126DF283004BAC4C /* Products */ = { isa = PBXGroup; children = ( - 25956999126DF283004BAC4C /* UISpec_Simulator.a */, + 25956999126DF283004BAC4C /* libUISpec.a */, 2595699D126DF283004BAC4C /* Specs.app */, ); name = Products; @@ -1342,10 +1342,10 @@ remoteRef = 250BC43611F6260100F3FE5A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 25956999126DF283004BAC4C /* UISpec_Simulator.a */ = { + 25956999126DF283004BAC4C /* libUISpec.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = UISpec_Simulator.a; + path = libUISpec.a; remoteRef = 25956998126DF283004BAC4C /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1925,7 +1925,6 @@ IPHONEOS_DEPLOYMENT_TARGET = 3.2; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/Specs/Support/UISpec/bin/UISpec\"", "\"$(SRCROOT)/Specs/Support/OCMock\"", "\"$(SRCROOT)\"", ); @@ -1965,7 +1964,6 @@ IPHONEOS_DEPLOYMENT_TARGET = 3.2; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/Specs/Support/UISpec/bin/UISpec\"", "\"$(SRCROOT)/Specs/Support/OCMock\"", "\"$(SRCROOT)\"", ); diff --git a/Specs/UISpec+UISpecRunner.h b/Specs/UISpec+UISpecRunner.h index 1944cab6..d5d3aa31 100644 --- a/Specs/UISpec+UISpecRunner.h +++ b/Specs/UISpec+UISpecRunner.h @@ -16,11 +16,17 @@ */ +(void)runSpecsConformingToProtocol:(Protocol *)protocol afterDelay:(NSTimeInterval)delay; +/** + * Run all UISpec classes inheriting from a given base class + */ ++(void)runSpecsInheritingFromClass:(Class)class afterDelay:(NSTimeInterval)delay; + /** * Infers which set of UISpec classes to run from the following environment variables: * UISPEC_PROTOCOL - Specifies a protocol to run * UISPEC_SPEC - Specifies a spec class to run * UISPEC_METHOD - Specifies an example to run (requires UISPEC_SPEC to be set) + * UISPEC_EXIT_ON_FINISH - When YES, instructs UISpecRunner to terminate the application when specs run is complete */ +(void)runSpecsFromEnvironmentAfterDelay:(int)seconds; diff --git a/Specs/UISpec+UISpecRunner.m b/Specs/UISpec+UISpecRunner.m index 4351129a..1e3c94e7 100644 --- a/Specs/UISpec+UISpecRunner.m +++ b/Specs/UISpec+UISpecRunner.m @@ -6,8 +6,42 @@ // Copyright 2010 Two Toasters. All rights reserved. // -#import #import "UISpec+UISpecRunner.h" +#import +#import "UIConsoleLog.h" +#import "UISpec.h" + +@interface UISpecRunnerLog : UIConsoleLog { + BOOL _exitOnFinish; +} + +// When YES, the application will terminate after specs finish running +@property (nonatomic, assign) BOOL exitOnFinish; + +@end + +@implementation UISpecRunnerLog + +@synthesize exitOnFinish = _exitOnFinish; + +- (id)init { + self = [super init]; + if (self) { + _exitOnFinish = NO; + } + + return self; +} + +-(void)onFinish:(int)count { + [super onFinish:count]; + + if (self.exitOnFinish) { + exit(errors.count); + } +} + +@end @interface UISpec () @@ -53,10 +87,56 @@ [self performSelector:@selector(runSpecClasses:) withObject:specClasses afterDelay:delay]; } ++(NSArray*)specClassesInheritingFromClass:(Class)parentClass { + int numClasses = objc_getClassList(NULL, 0); + Class *classes = NULL; + + classes = malloc(sizeof(Class) * numClasses); + numClasses = objc_getClassList(classes, numClasses); + + NSMutableArray *result = [NSMutableArray arrayWithObject:parentClass]; + for (NSInteger i = 0; i < numClasses; i++) + { + Class superClass = classes[i]; + do + { + superClass = class_getSuperclass(superClass); + } while(superClass && superClass != parentClass); + + if (superClass == nil) + { + continue; + } + + if ([self isASpec:classes[i]]) { + [result addObject:classes[i]]; + } + } + + free(classes); + + return result; +} + ++(void)runSpecsInheritingFromClass:(Class)class afterDelay:(NSTimeInterval)delay { + NSArray* specClasses = [self specClassesInheritingFromClass:class]; + NSLog(@"Executing Specs: %@", specClasses); + [self performSelector:@selector(runSpecClasses:) withObject:specClasses afterDelay:delay]; +} + +(void)runSpecsFromEnvironmentAfterDelay:(int)seconds { char* protocolName = getenv("UISPEC_PROTOCOL"); char* specName = getenv("UISPEC_SPEC"); char* exampleName = getenv("UISPEC_EXAMPLE"); + char* exitOnFinish = getenv("UISPEC_EXIT_ON_FINISH"); + + UISpecRunnerLog* log = [[UISpecRunnerLog alloc] init]; + [UISpec setLog:(UILog*)log]; + + if (NULL == exitOnFinish || [[NSString stringWithUTF8String:exitOnFinish] isEqualToString:@"YES"]) { + log.exitOnFinish = YES; + } + if (protocolName) { Protocol* protocol = NSProtocolFromString([NSString stringWithUTF8String:protocolName]); NSLog(@"[UISpecRunner] Running Specs conforming to Protocol: %@", [NSString stringWithUTF8String:protocolName]); @@ -68,11 +148,12 @@ NSLog(@"[UISpecRunner] Running Examples %s on Spec %s", exampleName, specName); [UISpec runSpec:[NSString stringWithUTF8String:specName] example:[NSString stringWithUTF8String:exampleName] afterDelay:seconds]; } else if (specName) { - NSLog(@"[UISpecRunner] Running Spec %s", specName); - [UISpec runSpec:[NSString stringWithUTF8String:specName] afterDelay:seconds]; + NSLog(@"[UISpecRunner] Running Spec classes inheriting from %s", specName); + Class class = NSClassFromString([NSString stringWithUTF8String:specName]); + [UISpec runSpecsInheritingFromClass:class afterDelay:seconds]; } else { [UISpec runSpecsAfterDelay:seconds]; - } + } } @end diff --git a/Specs/main.m b/Specs/main.m index 5ab30a06..f375a6ac 100644 --- a/Specs/main.m +++ b/Specs/main.m @@ -7,7 +7,6 @@ // #import -#import "UISpec.h" #import "UISpec+UISpecRunner.h" int main(int argc, char *argv[]) { diff --git a/uispec b/uispec deleted file mode 100755 index 478c41e4..00000000 --- a/uispec +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/zsh -# UISpec CLI Runner -# By Blake Watters -# Base code taken from: http://stackoverflow.com/questions/1514302/build-and-run-an-xcode-project-via-applescript - -BUILD_PATH=$(dirname $0) - -while [[ -z $BUILD_FILE && $BUILD_PATH != "/" ]]; do - BUILD_FILE=$(find $BUILD_PATH -name '*.xcodeproj' -maxdepth 1) - BUILD_PATH=$(dirname $BUILD_PATH) -done - -if [[ -z $BUILD_FILE ]]; then - echo "Couldn't find an xcode project file in directory" - exit 1 -fi - -# Applescript likes's : instead of / (because it's insane) -BUILD_FILE=${BUILD_FILE//\//:} - -# Find the latest Simulator SDK -SIMULATOR_SDKS=( /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/*.sdk ) - -SIMULATOR_SDK=${SIMULATOR_SDKS[-1]} -SIMULATOR_SDK_STRING=$(basename ${(L)SIMULATOR_SDK%.[a-z]*}) - -if [[ -z $SIMULATOR_SDK ]]; then - echo "Couldn't find a simulator SDK" - exit 1 -fi - -# Use the first arg as the spec to run... -UISPEC_RUN_SPEC=$1 - -osascript <