Browse files

Functions for running specs with custom spec runner classes; optional…

… spec runner protocol delegate method called when specs start; beginnings of a view controller for displaying run status on the device or simulator; example of internal compiler error when using blocks in C++ files.
  • Loading branch information...
1 parent f6194b5 commit 7c1bef14cf3492d31edeb58ecbaca309ded27f12 Adam Milligan committed Jun 6, 2010
View
52 Cedar.xcodeproj/project.pbxproj
@@ -8,6 +8,11 @@
/* Begin PBXBuildFile section */
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+ AE16DC7B11BB514300270D0B /* CppSpecSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE16DC7A11BB514300270D0B /* CppSpecSpec.mm */; };
+ AE16DC9E11BB52B100270D0B /* ActualValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AE16DC9C11BB52B100270D0B /* ActualValue.h */; };
+ AE16DC9F11BB52B100270D0B /* ActualValue.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE16DC9D11BB52B100270D0B /* ActualValue.mm */; };
+ AE16DD3211BC874F00270D0B /* CDRExampleRunnerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = AE16DD3111BC874F00270D0B /* CDRExampleRunnerViewController.h */; };
+ AE16DD6B11BC93F600270D0B /* CDRExampleRunnerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AE16DD6A11BC93F600270D0B /* CDRExampleRunnerViewController.m */; };
AE603C7E118CC85100D312FC /* CDRDefaultRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = AE603C79118CC85100D312FC /* CDRDefaultRunner.m */; };
AE603C7F118CC85100D312FC /* CDRExample.m in Sources */ = {isa = PBXBuildFile; fileRef = AE603C7A118CC85100D312FC /* CDRExample.m */; };
AE603C80118CC85100D312FC /* CDRExampleBase.m in Sources */ = {isa = PBXBuildFile; fileRef = AE603C7B118CC85100D312FC /* CDRExampleBase.m */; };
@@ -72,6 +77,11 @@
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* Cedar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cedar.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ AE16DC7A11BB514300270D0B /* CppSpecSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CppSpecSpec.mm; sourceTree = "<group>"; };
+ AE16DC9C11BB52B100270D0B /* ActualValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActualValue.h; sourceTree = "<group>"; };
+ AE16DC9D11BB52B100270D0B /* ActualValue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ActualValue.mm; sourceTree = "<group>"; };
+ AE16DD3111BC874F00270D0B /* CDRExampleRunnerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDRExampleRunnerViewController.h; sourceTree = "<group>"; };
+ AE16DD6A11BC93F600270D0B /* CDRExampleRunnerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDRExampleRunnerViewController.m; sourceTree = "<group>"; };
AE17ECE211B6F00B004C4DC0 /* MACROS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MACROS; sourceTree = "<group>"; };
AE4E524911B357F5001E36F3 /* README.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.markdown; sourceTree = "<group>"; };
AE603C79118CC85100D312FC /* CDRDefaultRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDRDefaultRunner.m; sourceTree = "<group>"; };
@@ -168,24 +178,55 @@
name = Resources;
sourceTree = "<group>";
};
+ AE16DC9911BB524000270D0B /* Matchers */ = {
+ isa = PBXGroup;
+ children = (
+ AE16DC9C11BB52B100270D0B /* ActualValue.h */,
+ AE16DC9D11BB52B100270D0B /* ActualValue.mm */,
+ );
+ name = Matchers;
+ path = ../../cedar/Source/Matchers;
+ sourceTree = "<group>";
+ };
+ AE16DD2011BC868900270D0B /* iPhone */ = {
+ isa = PBXGroup;
+ children = (
+ AEBAB0C311B9D8120085EC6E /* CedarApplicationDelegate.m */,
+ AE16DD6A11BC93F600270D0B /* CDRExampleRunnerViewController.m */,
+ );
+ path = iPhone;
+ sourceTree = "<group>";
+ };
+ AE16DD2111BC868E00270D0B /* iPhone */ = {
+ isa = PBXGroup;
+ children = (
+ AEBAB0C111B9D2380085EC6E /* CedarApplicationDelegate.h */,
+ AE16DD3111BC874F00270D0B /* CDRExampleRunnerViewController.h */,
+ );
+ path = iPhone;
+ sourceTree = "<group>";
+ };
AE603C76118CC81500D312FC /* Source */ = {
isa = PBXGroup;
children = (
+ AE16DD2011BC868900270D0B /* iPhone */,
+ AE16DC9911BB524000270D0B /* Matchers */,
AE603C78118CC81D00D312FC /* Headers */,
AE603C79118CC85100D312FC /* CDRDefaultRunner.m */,
AE603C7A118CC85100D312FC /* CDRExample.m */,
AE603C7B118CC85100D312FC /* CDRExampleBase.m */,
AE603C7C118CC85100D312FC /* CDRExampleGroup.m */,
AE603C7D118CC85100D312FC /* CDRSpec.m */,
AE603CA9118CC94100D312FC /* Cedar.m */,
- AEBAB0C311B9D8120085EC6E /* CedarApplicationDelegate.m */,
);
- path = Source;
+ name = Source;
+ path = ../cedar/Source;
sourceTree = "<group>";
};
AE603C78118CC81D00D312FC /* Headers */ = {
isa = PBXGroup;
children = (
+ AE16DD2111BC868E00270D0B /* iPhone */,
AE603D69118CCB6000D312FC /* Cedar.h */,
AE603D6A118CCB6000D312FC /* CDRDefaultRunner.h */,
AE603D6B118CCB6000D312FC /* CDRExample.h */,
@@ -194,7 +235,6 @@
AE603D6E118CCB6000D312FC /* CDRExampleRunner.h */,
AE603D6F118CCB6000D312FC /* CDRSpec.h */,
AE603D70118CCB6000D312FC /* SpecHelper.h */,
- AEBAB0C111B9D2380085EC6E /* CedarApplicationDelegate.h */,
);
path = Headers;
sourceTree = "<group>";
@@ -205,6 +245,7 @@
AE603D81118CCBBF00D312FC /* SpecSpec.m */,
AE603D82118CCBBF00D312FC /* SpecSpec2.m */,
AE603E14118CCE1F00D312FC /* main.m */,
+ AE16DC7A11BB514300270D0B /* CppSpecSpec.mm */,
);
path = Spec;
sourceTree = "<group>";
@@ -220,6 +261,7 @@
AE603D78118CCB6000D312FC /* SpecHelper.h in Headers */,
AED41F9411B871BC006DBB00 /* CDRSpec.h in Headers */,
AED41F9511B871C1006DBB00 /* CDRExampleBase.h in Headers */,
+ AE16DC9E11BB52B100270D0B /* ActualValue.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -236,6 +278,7 @@
AED41F3E11B86A53006DBB00 /* CDRSpec.h in Headers */,
AED41F3F11B86A53006DBB00 /* SpecHelper.h in Headers */,
AEBAB0C211B9D2380085EC6E /* CedarApplicationDelegate.h in Headers */,
+ AE16DD3211BC874F00270D0B /* CDRExampleRunnerViewController.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -338,6 +381,7 @@
AE603C81118CC85100D312FC /* CDRExampleGroup.m in Sources */,
AE603C82118CC85100D312FC /* CDRSpec.m in Sources */,
AE603CAB118CC94100D312FC /* Cedar.m in Sources */,
+ AE16DC9F11BB52B100270D0B /* ActualValue.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -348,6 +392,7 @@
AE603DCA118CCCBE00D312FC /* SpecSpec.m in Sources */,
AE603DCB118CCCC700D312FC /* SpecSpec2.m in Sources */,
AE603E15118CCE1F00D312FC /* main.m in Sources */,
+ AE16DC7B11BB514300270D0B /* CppSpecSpec.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -362,6 +407,7 @@
AED41F3611B86A44006DBB00 /* CDRSpec.m in Sources */,
AED41F3711B86A44006DBB00 /* Cedar.m in Sources */,
AEBAB0C411B9D8120085EC6E /* CedarApplicationDelegate.m in Sources */,
+ AE16DD6B11BC93F600270D0B /* CDRExampleRunnerViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
1 Source/CDRSpec.m
@@ -4,7 +4,6 @@
#import "CDRExampleRunner.h"
static CDRSpec *currentSpec;
-extern CDRSpecBlock PENDING;
void describe(NSString *text, CDRSpecBlock block) {
CDRExampleGroup *parentGroup = currentSpec.currentGroup;
View
44 Source/Cedar.m
@@ -5,7 +5,7 @@
#import "CDRExampleRunner.h"
#import "CDRDefaultRunner.h"
-BOOL isASpecClass(Class class) {
+BOOL CDRIsASpecClass(Class class) {
if (strcmp("CDRSpec", class_getName(class))) {
while (class) {
if (class_conformsToProtocol(class, NSProtocolFromString(@"CDRSpec"))) {
@@ -14,44 +14,60 @@ BOOL isASpecClass(Class class) {
class = class_getSuperclass(class);
}
}
-
+
return NO;
}
-NSArray *enumerateSpecClasses() {
+NSArray *CDREnumerateSpecClasses() {
unsigned int numberOfClasses = objc_getClassList(NULL, 0);
Class classes[numberOfClasses];
numberOfClasses = objc_getClassList(classes, numberOfClasses);
-
+
NSMutableArray *specClasses = [NSMutableArray array];
for (unsigned int i = 0; i < numberOfClasses; ++i) {
Class class = classes[i];
- if (isASpecClass(class)) {
+ if (CDRIsASpecClass(class)) {
[specClasses addObject:class];
}
}
-
return specClasses;
}
-int runSpecs(NSArray *specClasses) {
- id<CDRExampleRunner> runner = [[[CDRDefaultRunner alloc] init] autorelease];
-
+NSArray *CDRCreateSpecsFromSpecClasses(NSArray *specClasses) {
+ NSMutableArray *specs = [[NSMutableArray alloc] initWithCapacity:[specClasses count]];
for (Class class in specClasses) {
CDRSpec *spec = [[class alloc] init];
[spec defineBehaviors];
- [spec runWithRunner:runner];
+ [specs addObject:spec];
[spec release];
}
-
+ return specs;
+}
+
+int runSpecsWithCustomExampleRunner(NSArray *specClasses, id<CDRExampleRunner> runner) {
+ NSArray *specs = CDRCreateSpecsFromSpecClasses(specClasses);
+
+ if ([runner respondsToSelector:@selector(runWillStartWithSpecs:)]) {
+ [runner runWillStartWithSpecs:specs];
+ }
+
+ for (CDRSpec *spec in specs) {
+ [spec runWithRunner:runner];
+ }
+
+ [specs release];
return [runner result];
}
int runAllSpecs() {
+ return runAllSpecsWithCustomExampleRunner([[[CDRDefaultRunner alloc] init] autorelease]);
+}
+
+int runAllSpecsWithCustomExampleRunner(id<CDRExampleRunner> runner) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- int result = runSpecs(enumerateSpecClasses());
-
+
+ int result = runSpecsWithCustomExampleRunner(CDREnumerateSpecClasses(), runner);
+
[pool drain];
return result;
}
View
11 Source/CedarApplicationDelegate.m
@@ -1,11 +0,0 @@
-#import "CedarApplicationDelegate.h"
-#import "Cedar.h"
-
-@implementation CedarApplicationDelegate
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- runAllSpecs();
- return NO;
-}
-
-@end
View
4 Source/Headers/CDRExampleRunner.h
@@ -4,11 +4,15 @@
@protocol CDRExampleRunner <NSObject>
+@required
- (void)exampleSucceeded:(CDRExample *)example;
- (void)example:(CDRExample *)example failedWithMessage:(NSString *)message;
- (void)example:(CDRExample *)example threwException:(NSException *)exception;
- (void)exampleThrewError:(CDRExample *)example;
- (void)examplePending:(CDRExample *)example;
- (int)result;
+@optional
+- (void)runWillStartWithSpecs:(NSArray *)specs;
+
@end
View
7 Source/Headers/Cedar.h
@@ -1,4 +1,7 @@
#import <Foundation/Foundation.h>
-int runSpecs(NSArray *specClasses);
-int runAllSpecs();
+@protocol CDRExampleRunner;
+
+int runSpecsWithCustomExampleRunner(NSArray *specClasses, id<CDRExampleRunner> runner);
+int runAllSpecs();
+int runAllSpecsWithCustomExampleRunner(id<CDRExampleRunner> runner);
View
5 Source/Headers/CedarApplicationDelegate.h
@@ -1,5 +0,0 @@
-#import <UIKit/UIKit.h>
-
-@interface CedarApplicationDelegate : NSObject <UIApplicationDelegate>
-
-@end
View
10 Source/Headers/iPhone/CDRExampleRunnerViewController.h
@@ -0,0 +1,10 @@
+#import <UIKit/UIKit.h>
+#import "CDRExampleRunner.h"
+#import "CDRDefaultRunner.h"
+
+@interface CDRExampleRunnerViewController : UITableViewController /*<CDRExampleRunner>*/ {
+ // TODO create a real runner here.
+ CDRDefaultRunner *stubRunner_;
+}
+
+@end
View
10 Source/Headers/iPhone/CedarApplicationDelegate.h
@@ -0,0 +1,10 @@
+#import <UIKit/UIKit.h>
+
+@class CDRExampleRunnerViewController;
+
+@interface CedarApplicationDelegate : NSObject <UIApplicationDelegate> {
+ UIWindow *window_;
+ CDRExampleRunnerViewController *viewController_;
+}
+
+@end
View
59 Source/Matchers/ActualValue.h
@@ -0,0 +1,59 @@
+#import <Foundation/Foundation.h>
+#import "CDRExampleBase.h"
+
+#include <iostream>
+#include <sstream>
+
+namespace Cedar {
+namespace Matchers {
+
+void fail(const NSString * failureMessage);
+
+template<typename T>
+class ActualValue {
+private:
+ template<typename U>
+ ActualValue(const ActualValue<U> &);
+ template<typename U>
+ ActualValue & operator=(const ActualValue<U> &);
+
+public:
+ ActualValue(const T &);
+
+ template<typename U>
+ void toEqual(const U &) const;
+
+ inline void foo(int i) const { std::cout << "int foo" << std::endl; }
+ inline void foo(NSObject * i) const { std::cout << "NSObject foo" << std::endl; };
+
+ template<typename U>
+ inline void bar(U i) const { std::cout << "template bar" << std::endl; }
+
+private:
+ const T value_;
+};
+
+#pragma mark It's 2010 and linkers still can't handle templates in implementation files?
+
+template<typename T>
+const ActualValue<T> expect(const T & value) {
+ return ActualValue<T>(value);
+}
+
+template<typename T>
+ActualValue<T>::ActualValue(const T & value) : value_(value) {
+}
+
+#pragma mark toEqual
+template<typename T> template<typename U>
+void ActualValue<T>::toEqual(const U & expectedValue) const {
+ if (expectedValue != value_) {
+ std::stringstream message;
+ message << "Expected <" << value_ << "> to equal <" << expectedValue << ">";
+
+ [[CDRSpecFailure specFailureWithReason:[NSString stringWithCString:message.str().c_str() encoding:NSUTF8StringEncoding]] raise];
+ }
+}
+
+}
+}
View
11 Source/Matchers/ActualValue.mm
@@ -0,0 +1,11 @@
+#import "ActualValue.h"
+
+namespace Cedar {
+namespace Matchers {
+
+void fail(const NSString *failureMessage) {
+ [[CDRSpecFailure specFailureWithReason:[NSString stringWithFormat:@"Failure: %@", failureMessage]] raise];
+}
+
+}
+}
View
91 Source/iPhone/CDRExampleRunnerViewController.m
@@ -0,0 +1,91 @@
+#import "CDRExampleRunnerViewController.h"
+#import "Cedar.h"
+
+@implementation CDRExampleRunnerViewController
+
+#pragma mark Initialization
+- (id)initWithStyle:(UITableViewStyle)style {
+ if ((self = [super initWithStyle:style])) {
+ stubRunner_ = [[CDRDefaultRunner alloc] init];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [stubRunner_ release];
+ [super dealloc];
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ runAllSpecsWithCustomExampleRunner(stubRunner_);
+}
+
+- (void)viewDidUnload {
+
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ return YES;
+}
+
+#pragma mark Table view data source
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ // !!! Number of spec classes?
+ return 1;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ // !!!
+ return 0;
+}
+
+
+// Customize the appearance of table view cells.
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ static NSString *CellIdentifier = @"CedarExampleCell";
+
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+ if (!cell) {
+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
+ }
+
+ return cell;
+}
+
+#pragma mark -
+#pragma mark Table view delegate
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ // Navigation logic may go here. Create and push another view controller.
+ /*
+ <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
+ // ...
+ // Pass the selected object to the new view controller.
+ [self.navigationController pushViewController:detailViewController animated:YES];
+ [detailViewController release];
+ */
+}
+
+//#pragma mark CDRExampleRunner
+//- (void)exampleSucceeded:(CDRExample *)example {
+//}
+//
+//- (void)example:(CDRExample *)example failedWithMessage:(NSString *)message {
+//}
+//
+//- (void)example:(CDRExample *)example threwException:(NSException *)exception {
+//}
+//
+//- (void)exampleThrewError:(CDRExample *)example {
+//}
+//
+//- (void)examplePending:(CDRExample *)example {
+//}
+//
+//- (int)result {
+// return 0;
+//}
+
+@end
+
View
16 Source/iPhone/CedarApplicationDelegate.m
@@ -0,0 +1,16 @@
+#import "CedarApplicationDelegate.h"
+#import "CDRExampleRunnerViewController.h"
+
+@implementation CedarApplicationDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+
+ viewController_ = [[CDRExampleRunnerViewController alloc] init];
+ [window_ addSubview:viewController_.view];
+ [window_ makeKeyAndVisible];
+
+ return NO;
+}
+
+@end
View
24 Spec/CppSpecSpec.mm
@@ -0,0 +1,24 @@
+#import <Cedar/SpecHelper.h>
+
+#define HC_SHORTHAND
+#import <OCHamcrest/OCHamcrest.h>
+
+SPEC_BEGIN(CppSpecSpec)
+
+describe(@"CppSpec", ^{
+ describe(@"Expectations", ^{
+ describe(@"with built-in types", ^{
+ __block int expectedValue;
+
+ beforeEach(^ {
+// expectedValue = 1;
+ });
+
+ it(@"should run", ^{
+// assertThatInt(1, equalToInt(expectedValue));
+ });
+ });
+ });
+});
+
+SPEC_END
View
3 Spec/SpecSpec2.m
@@ -1,7 +1,8 @@
#import "SpecHelper.h"
+
SPEC_BEGIN(SpecSpec2)
-describe(@"A second spec file in the same target", ^ {
+describe(@"A second spec file in the same target", ^ {
it(@"should run", ^ {
// NSLog(@"=====================> Spec 2");
});

0 comments on commit 7c1bef1

Please sign in to comment.