Permalink
Browse files

Added a colorized reporter; added environment variable for specifying…

… a custom reporter; rake now uses colorized reporter by default for all spec runs; iPhone specs now attempt to exit more cleanly.
  • Loading branch information...
1 parent ac5237c commit ffc3d457d08ffd8ad6ac1e4710d66a478145a7b2 Adam Milligan committed Dec 23, 2010
@@ -34,6 +34,11 @@
AE91CA6C11DE64A3002BA6B9 /* CDRSharedExampleGroupPool.h in Headers */ = {isa = PBXBuildFile; fileRef = AEFD17B311DD1E8200F4448A /* CDRSharedExampleGroupPool.h */; settings = {ATTRIBUTES = (Public, ); }; };
AE91CA6D11DE64B3002BA6B9 /* CDRSharedExampleGroupPool.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AEFD17B311DD1E8200F4448A /* CDRSharedExampleGroupPool.h */; };
AE9855AE1236E7080024094E /* CDRSharedExampleGroupPool.m in Sources */ = {isa = PBXBuildFile; fileRef = AEFD17B111DD1E7200F4448A /* CDRSharedExampleGroupPool.m */; };
+ AEC9DEED12C2CC7E0039512D /* CDRColorizedReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = AEC9DEEA12C2CC7E0039512D /* CDRColorizedReporter.h */; };
+ AEC9DEEE12C2CC7E0039512D /* CDRColorizedReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = AEC9DEEB12C2CC7E0039512D /* CDRColorizedReporter.m */; };
+ AEC9DEEF12C2CC7E0039512D /* CDRColorizedReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = AEC9DEEA12C2CC7E0039512D /* CDRColorizedReporter.h */; };
+ AEC9DEF112C2CC7E0039512D /* CDRColorizedReporter.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AEC9DEEA12C2CC7E0039512D /* CDRColorizedReporter.h */; };
+ AEC9DEF412C2CC8F0039512D /* CDRColorizedReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = AEC9DEEB12C2CC7E0039512D /* CDRColorizedReporter.m */; };
AEEE1FF311DC27B800029872 /* CDRDefaultReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEE1FC411DC27B800029872 /* CDRDefaultReporter.m */; };
AEEE1FF411DC27B800029872 /* CDRExample.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEE1FC511DC27B800029872 /* CDRExample.m */; };
AEEE1FF511DC27B800029872 /* CDRExampleBase.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEE1FC611DC27B800029872 /* CDRExampleBase.m */; };
@@ -210,6 +215,7 @@
AE91CA6D11DE64B3002BA6B9 /* CDRSharedExampleGroupPool.h in Copy headers to framework */,
AEEE226111DC2C8300029872 /* Cedar.h in Copy headers to framework */,
AEEE226211DC2C8300029872 /* SpecHelper.h in Copy headers to framework */,
+ AEC9DEF112C2CC7E0039512D /* CDRColorizedReporter.h in Copy headers to framework */,
);
name = "Copy headers to framework";
runOnlyForDeploymentPostprocessing = 0;
@@ -220,6 +226,8 @@
AE135D1611DEA69A00A922D4 /* OCHamcrest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = OCHamcrest.xcodeproj; path = OCHamcrest/Source/OCHamcrest.xcodeproj; sourceTree = "<group>"; };
AE135D2611DEA6A900A922D4 /* OCMock.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = OCMock.xcodeproj; path = OCMock/Source/OCMock.xcodeproj; sourceTree = "<group>"; };
AE135E8311DEB4E400A922D4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Foundation.framework; sourceTree = SDKROOT; };
+ AEC9DEEA12C2CC7E0039512D /* CDRColorizedReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDRColorizedReporter.h; sourceTree = "<group>"; };
+ AEC9DEEB12C2CC7E0039512D /* CDRColorizedReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDRColorizedReporter.m; sourceTree = "<group>"; };
AEEE1FB611DC271300029872 /* Cedar */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Cedar; sourceTree = BUILT_PRODUCTS_DIR; };
AEEE1FB811DC271300029872 /* Cedar-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Cedar-Info.plist"; sourceTree = "<group>"; };
AEEE1FC411DC27B800029872 /* CDRDefaultReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDRDefaultReporter.m; sourceTree = "<group>"; };
@@ -374,14 +382,15 @@
AEEE1FCA11DC27B800029872 /* Headers */,
AEEE1FDC11DC27B800029872 /* iPhone */,
AEEE1FE311DC27B800029872 /* Matchers */,
- AEEE1FC411DC27B800029872 /* CDRDefaultReporter.m */,
AEEE1FC511DC27B800029872 /* CDRExample.m */,
AEEE1FC611DC27B800029872 /* CDRExampleBase.m */,
AEEE1FC711DC27B800029872 /* CDRExampleGroup.m */,
AEEE1FC811DC27B800029872 /* CDRFunctions.m */,
AEEE1FC911DC27B800029872 /* CDRSpec.m */,
AEEE1FE611DC27B800029872 /* SpecHelper.m */,
AEFD17B111DD1E7200F4448A /* CDRSharedExampleGroupPool.m */,
+ AEEE1FC411DC27B800029872 /* CDRDefaultReporter.m */,
+ AEC9DEEB12C2CC7E0039512D /* CDRColorizedReporter.m */,
);
path = Source;
sourceTree = "<group>";
@@ -390,7 +399,6 @@
isa = PBXGroup;
children = (
AEEE1FD411DC27B800029872 /* iPhone */,
- AEEE1FCB11DC27B800029872 /* CDRDefaultReporter.h */,
AEEE1FCC11DC27B800029872 /* CDRExample.h */,
AEEE1FCD11DC27B800029872 /* CDRExampleBase.h */,
AEEE1FCE11DC27B800029872 /* CDRExampleGroup.h */,
@@ -401,6 +409,8 @@
AEEE1FD311DC27B800029872 /* Cedar.h */,
AEEE1FDB11DC27B800029872 /* SpecHelper.h */,
AEFD17B311DD1E8200F4448A /* CDRSharedExampleGroupPool.h */,
+ AEEE1FCB11DC27B800029872 /* CDRDefaultReporter.h */,
+ AEC9DEEA12C2CC7E0039512D /* CDRColorizedReporter.h */,
);
path = Headers;
sourceTree = "<group>";
@@ -491,13 +501,15 @@
AEEE200111DC27B800029872 /* Cedar.h in Headers */,
AEEE200811DC27B800029872 /* SpecHelper.h in Headers */,
AE91CA6C11DE64A3002BA6B9 /* CDRSharedExampleGroupPool.h in Headers */,
+ AEC9DEED12C2CC7E0039512D /* CDRColorizedReporter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
AEEE222511DC2B0600029872 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ AEC9DEEF12C2CC7E0039512D /* CDRColorizedReporter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -724,6 +736,7 @@
AEEE1FF811DC27B800029872 /* CDRSpec.m in Sources */,
AEEE201111DC27B800029872 /* SpecHelper.m in Sources */,
AEFD17BB11DD1E9E00F4448A /* CDRSharedExampleGroupPool.m in Sources */,
+ AEC9DEEE12C2CC7E0039512D /* CDRColorizedReporter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -759,6 +772,7 @@
AEEE223C11DC2B6D00029872 /* CDRSpecStatusViewController.m in Sources */,
AEEE223D11DC2B6D00029872 /* CedarApplicationDelegate.m in Sources */,
AE9855AE1236E7080024094E /* CDRSharedExampleGroupPool.m in Sources */,
+ AEC9DEF412C2CC8F0039512D /* CDRColorizedReporter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
@@ -56,6 +56,7 @@ end
task :specs => :build_specs do
build_dir = build_dir("")
ENV["DYLD_FRAMEWORK_PATH"] = build_dir
+ ENV["CEDAR_REPORTER_CLASS"] = "CDRColorizedReporter"
system_or_exit(File.join(build_dir, SPECS_TARGET_NAME))
end
@@ -65,6 +66,7 @@ task :uispecs => :build_uispecs do
ENV["IPHONE_SIMULATOR_ROOT"] = SDK_DIR
ENV["CFFIXED_USER_HOME"] = Dir.tmpdir
ENV["CEDAR_HEADLESS_SPECS"] = "1"
+ ENV["CEDAR_REPORTER_CLASS"] = "CDRColorizedReporter"
system_or_exit(%Q[#{File.join(build_dir("-iphonesimulator"), "#{UI_SPECS_TARGET_NAME}.app", UI_SPECS_TARGET_NAME)} -RegisterForSystemEvents]);
end
@@ -0,0 +1,39 @@
+#import "CDRColorizedReporter.h"
+
+static const char * const ANSI_NORMAL = "\033[0m";
+static const char * const ANSI_GREEN = "\033[0;40;32m";
+static const char * const ANSI_RED = "\033[0;40;31m";
+static const char * const ANSI_YELLOW = "\033[0;40;33m";
+
+@implementation CDRColorizedReporter
+
+#pragma mark Protected interface
+- (NSString *)successToken {
+ return [NSString stringWithFormat:@"%s%@%s", ANSI_GREEN, [super successToken], ANSI_NORMAL];
+}
+
+- (NSString *)pendingToken {
+ return [NSString stringWithFormat:@"%s%@%s", ANSI_YELLOW, [super pendingToken], ANSI_NORMAL];
+}
+
+- (NSString *)pendingMessageForExample:(CDRExample *)example {
+ return [NSString stringWithFormat:@"%s%@%s", ANSI_YELLOW, [super pendingMessageForExample:example], ANSI_NORMAL];
+}
+
+- (NSString *)failureToken {
+ return [NSString stringWithFormat:@"%s%@%s", ANSI_RED, [super failureToken], ANSI_NORMAL];
+}
+
+- (NSString *)failureMessageForExample:(CDRExample *)example {
+ return [NSString stringWithFormat:@"%s%@%s", ANSI_RED, [super failureMessageForExample:example], ANSI_NORMAL];
+}
+
+- (NSString *)errorToken {
+ return [NSString stringWithFormat:@"%s%@%s", ANSI_RED, [super errorToken], ANSI_NORMAL];
+}
+
+- (NSString *)errorMessageForExample:(CDRExample *)example {
+ return [NSString stringWithFormat:@"%s%@%s", ANSI_RED, [super errorMessageForExample:example], ANSI_NORMAL];
+}
+
+@end
@@ -59,8 +59,36 @@ - (int)result {
}
}
-#pragma mark private interface
+#pragma mark Protected interface
+- (NSString *)successToken {
+ return @".";
+}
+
+- (NSString *)pendingToken {
+ return @"P";
+}
+
+- (NSString *)pendingMessageForExample:(CDRExample *)example {
+ return [NSString stringWithFormat:@"PENDING %@", [example fullText]];
+}
+
+- (NSString *)failureToken {
+ return @"F";
+}
+- (NSString *)failureMessageForExample:(CDRExample *)example {
+ return [NSString stringWithFormat:@"FAILURE %@\n%@\n", [example fullText], [example message]];
+}
+
+- (NSString *)errorToken {
+ return @"E";
+}
+
+- (NSString *)errorMessageForExample:(CDRExample *)example {
+ return [NSString stringWithFormat:@"EXCEPTION %@\n%@\n", [example fullText], [example message]];
+}
+
+#pragma mark Private interface
- (void)printMessages:(NSArray *)messages {
printf("\n");
@@ -93,19 +121,19 @@ - (void)stopObservingExamples:(NSArray *)examples {
- (void)reportOnExample:(CDRExample *)example {
switch (example.state) {
case CDRExampleStatePassed:
- printf(".");
+ printf("%s", [[self successToken] cStringUsingEncoding:NSUTF8StringEncoding]);
break;
case CDRExampleStatePending:
- printf("P");
- [pendingMessages_ addObject:[NSString stringWithFormat:@"PENDING %@", [example fullText]]];
+ printf("%s", [[self pendingToken] cStringUsingEncoding:NSUTF8StringEncoding]);
+ [pendingMessages_ addObject:[self pendingMessageForExample:example]];
break;
case CDRExampleStateFailed:
- printf("F");
- [failureMessages_ addObject:[NSString stringWithFormat:@"FAILURE %@\n%@\n", [example fullText], [example message]]];
+ printf("%s", [[self failureToken] cStringUsingEncoding:NSUTF8StringEncoding]);
+ [failureMessages_ addObject:[self failureMessageForExample:example]];
break;
case CDRExampleStateError:
- printf("E");
- [failureMessages_ addObject:[NSString stringWithFormat:@"EXCEPTION %@\n%@\n", [example fullText], [example message]]];
+ printf("%s", [[self errorToken] cStringUsingEncoding:NSUTF8StringEncoding]);
+ [failureMessages_ addObject:[self errorMessageForExample:example]];
break;
default:
break;
@@ -126,5 +154,4 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
[self reportOnExample:object];
}
-
@end
View
@@ -77,9 +77,21 @@ int runSpecsWithCustomExampleReporter(NSArray *specClasses, id<CDRExampleReporte
}
int runAllSpecs() {
- id<CDRExampleReporter> reporter = [[CDRDefaultReporter alloc] init];
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ char *reporterClassName = getenv("CEDAR_REPORTER_CLASS");
+ if (!reporterClassName) {
+ reporterClassName = "CDRDefaultReporter";
+ }
+ Class reporterClass = NSClassFromString([NSString stringWithCString:reporterClassName encoding:NSUTF8StringEncoding]);
+ if (!reporterClass) {
+ printf("***** The specified reporter class \"%s\" does not exist. *****\n", reporterClassName);
+ return -999;
+ }
+
+ id<CDRExampleReporter> reporter = [[[reporterClass alloc] init] autorelease];
int result = runSpecsWithCustomExampleReporter(NULL, reporter);
- [reporter release];
+ [pool drain];
return result;
}
@@ -0,0 +1,6 @@
+#import <Foundation/Foundation.h>
+#import "CDRDefaultReporter.h"
+
+@interface CDRColorizedReporter : CDRDefaultReporter
+
+@end
@@ -1,5 +1,7 @@
#import "CDRExampleReporter.h"
+@class CDRExample;
+
@interface CDRDefaultReporter : NSObject <CDRExampleReporter> {
NSArray *rootGroups_;
@@ -9,5 +11,14 @@
NSDate *startTime_;
unsigned int exampleCount_;
}
+@end
+@interface CDRDefaultReporter (Protected)
+- (NSString *)successToken;
+- (NSString *)pendingToken;
+- (NSString *)pendingMessageForExample:(CDRExample *)example;
+- (NSString *)failureToken;
+- (NSString *)failureMessageForExample:(CDRExample *)example;
+- (NSString *)errorToken;
+- (NSString *)errorMessageForExample:(CDRExample *)example;
@end
@@ -10,16 +10,21 @@ - (void)viewDidLoad {
[super viewDidLoad];
if (getenv("CEDAR_HEADLESS_SPECS")) {
- id<CDRExampleReporter> reporter = [[[CDRDefaultReporter alloc] init] autorelease];
- runSpecsWithCustomExampleReporter(NULL, reporter);
- exit([reporter result]);
+ int exitStatus = runAllSpecs();
+
+ UIApplication *application = [UIApplication sharedApplication];
+ if ([application respondsToSelector:@selector(_terminateWithStatus:)]) {
+ [application performSelector:@selector(_terminateWithStatus:)
+ withObject:(id)exitStatus];
+ } else {
+ exit(exitStatus);
+ }
} else {
[self performSelectorInBackground:@selector(startSpecs) withObject:NULL];
}
}
- (void)viewDidUnload {
-
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

0 comments on commit ffc3d45

Please sign in to comment.