Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

First release.

  • Loading branch information...
commit 4f0c6270207cafacf4c1d5508351c72a361ee894 0 parents
@allending authored
Showing with 13,422 additions and 0 deletions.
  1. +10 −0 .gitignore
  2. +11 −0 Classes/Carrier.h
  3. +11 −0 Classes/Carrier.m
  4. +78 −0 Classes/Cruiser.h
  5. +136 −0 Classes/Cruiser.m
  6. +11 −0 Classes/Engine.h
  7. +11 −0 Classes/Engine.m
  8. +34 −0 Classes/Fighter.h
  9. +46 −0 Classes/Fighter.m
  10. +18 −0 Classes/JumpCapable.h
  11. +19 −0 Classes/KiwiAppDelegate.h
  12. +28 −0 Classes/KiwiAppDelegate.m
  13. +12 −0 Classes/KiwiViewController.h
  14. +61 −0 Classes/KiwiViewController.m
  15. +17 −0 Classes/OrbitCapable.h
  16. +16 −0 Classes/SpaceShip.h
  17. +18 −0 Classes/SpaceShip.m
  18. +16 −0 Classes/TestClasses.h
  19. +41 −0 Classes/TestReporter.h
  20. +73 −0 Classes/TestReporter.m
  21. +24 −0 Classes/TestSpy.h
  22. +27 −0 Classes/TestSpy.m
  23. +24 −0 Classes/TestVerifier.h
  24. +38 −0 Classes/TestVerifier.m
  25. +61 −0 Examples/ExampleSpec.m
  26. +224 −0 Examples/ExampleTestCase.m
  27. +38 −0 Examples/SimpleSpec.m
  28. +1,362 −0 Kiwi.xcodeproj/project.pbxproj
  29. +22 −0 Kiwi/KWAfterAllNode.h
  30. +30 −0 Kiwi/KWAfterAllNode.m
  31. +22 −0 Kiwi/KWAfterEachNode.h
  32. +30 −0 Kiwi/KWAfterEachNode.m
  33. +23 −0 Kiwi/KWBeBetweenMatcher.h
  34. +79 −0 Kiwi/KWBeBetweenMatcher.m
  35. +20 −0 Kiwi/KWBeEmptyMatcher.h
  36. +74 −0 Kiwi/KWBeEmptyMatcher.m
  37. +20 −0 Kiwi/KWBeIdenticalToMatcher.h
  38. +72 −0 Kiwi/KWBeIdenticalToMatcher.m
  39. +20 −0 Kiwi/KWBeKindOfClassMatcher.h
  40. +55 −0 Kiwi/KWBeKindOfClassMatcher.m
  41. +20 −0 Kiwi/KWBeMemberOfClassMatcher.h
  42. +55 −0 Kiwi/KWBeMemberOfClassMatcher.m
  43. +23 −0 Kiwi/KWBeTrueMatcher.h
  44. +69 −0 Kiwi/KWBeTrueMatcher.m
  45. +22 −0 Kiwi/KWBeWithinMatcher.h
  46. +109 −0 Kiwi/KWBeWithinMatcher.m
  47. +17 −0 Kiwi/KWBeZeroMatcher.h
  48. +48 −0 Kiwi/KWBeZeroMatcher.m
  49. +22 −0 Kiwi/KWBeforeAllNode.h
  50. +30 −0 Kiwi/KWBeforeAllNode.m
  51. +22 −0 Kiwi/KWBeforeEachNode.h
  52. +30 −0 Kiwi/KWBeforeEachNode.m
  53. +37 −0 Kiwi/KWBlock.h
  54. +67 −0 Kiwi/KWBlock.m
  55. +43 −0 Kiwi/KWBlockNode.h
  56. +55 −0 Kiwi/KWBlockNode.m
  57. +28 −0 Kiwi/KWBlockRaiseMatcher.h
  58. +125 −0 Kiwi/KWBlockRaiseMatcher.m
  59. +33 −0 Kiwi/KWCallSite.h
  60. +56 −0 Kiwi/KWCallSite.m
  61. +20 −0 Kiwi/KWConformToProtocolMatcher.h
  62. +55 −0 Kiwi/KWConformToProtocolMatcher.m
  63. +31 −0 Kiwi/KWContainMatcher.h
  64. +104 −0 Kiwi/KWContainMatcher.m
  65. +71 −0 Kiwi/KWContextNode.h
  66. +105 −0 Kiwi/KWContextNode.m
  67. +15 −0 Kiwi/KWCountType.h
  68. +17 −0 Kiwi/KWDeviceInfo.h
  69. +33 −0 Kiwi/KWDeviceInfo.m
  70. +20 −0 Kiwi/KWEqualMatcher.h
  71. +69 −0 Kiwi/KWEqualMatcher.m
  72. +37 −0 Kiwi/KWExampleGroup.h
  73. +89 −0 Kiwi/KWExampleGroup.m
  74. +44 −0 Kiwi/KWExampleGroupBuilder.h
  75. +187 −0 Kiwi/KWExampleGroupBuilder.m
  76. +22 −0 Kiwi/KWExampleNode.h
  77. +36 −0 Kiwi/KWExampleNodeVisitor.h
  78. +35 −0 Kiwi/KWExistVerifier.h
  79. +70 −0 Kiwi/KWExistVerifier.m
  80. +14 −0 Kiwi/KWExpectationType.h
  81. +37 −0 Kiwi/KWFailure.h
  82. +65 −0 Kiwi/KWFailure.m
  83. +16 −0 Kiwi/KWFormatter.h
  84. +38 −0 Kiwi/KWFormatter.m
  85. +54 −0 Kiwi/KWHaveMatcher.h
  86. +254 −0 Kiwi/KWHaveMatcher.m
  87. +33 −0 Kiwi/KWInequalityMatcher.h
  88. +117 −0 Kiwi/KWInequalityMatcher.m
  89. +47 −0 Kiwi/KWIntercept.h
  90. +276 −0 Kiwi/KWIntercept.m
  91. +42 −0 Kiwi/KWInvocationCapturer.h
  92. +97 −0 Kiwi/KWInvocationCapturer.m
  93. +24 −0 Kiwi/KWItNode.h
  94. +30 −0 Kiwi/KWItNode.m
  95. +45 −0 Kiwi/KWMatchVerifier.h
  96. +164 −0 Kiwi/KWMatchVerifier.m
  97. +48 −0 Kiwi/KWMatcher.h
  98. +82 −0 Kiwi/KWMatcher.m
  99. +42 −0 Kiwi/KWMatcherFactory.h
  100. +122 −0 Kiwi/KWMatcherFactory.m
  101. +43 −0 Kiwi/KWMatching.h
  102. +49 −0 Kiwi/KWMessagePattern.h
  103. +223 −0 Kiwi/KWMessagePattern.m
  104. +16 −0 Kiwi/KWMessageSpying.h
  105. +53 −0 Kiwi/KWMessageTracker.h
  106. +151 −0 Kiwi/KWMessageTracker.m
  107. +88 −0 Kiwi/KWMock.h
  108. +556 −0 Kiwi/KWMock.m
  109. +19 −0 Kiwi/KWNull.h
  110. +47 −0 Kiwi/KWNull.m
  111. +31 −0 Kiwi/KWObjCUtilities.h
  112. +97 −0 Kiwi/KWObjCUtilities.m
  113. +39 −0 Kiwi/KWPendingNode.h
  114. +55 −0 Kiwi/KWPendingNode.m
  115. +25 −0 Kiwi/KWRaiseMatcher.h
  116. +121 −0 Kiwi/KWRaiseMatcher.m
  117. +61 −0 Kiwi/KWReceiveMatcher.h
  118. +308 −0 Kiwi/KWReceiveMatcher.m
  119. +39 −0 Kiwi/KWRegisterMatchersNode.h
  120. +55 −0 Kiwi/KWRegisterMatchersNode.m
  121. +18 −0 Kiwi/KWReporting.h
  122. +20 −0 Kiwi/KWRespondToSelectorMatcher.h
  123. +55 −0 Kiwi/KWRespondToSelectorMatcher.m
  124. +49 −0 Kiwi/KWSpec.h
  125. +321 −0 Kiwi/KWSpec.m
  126. +20 −0 Kiwi/KWStringUtilities.h
  127. +90 −0 Kiwi/KWStringUtilities.m
  128. +37 −0 Kiwi/KWStub.h
  129. +131 −0 Kiwi/KWStub.m
  130. +44 −0 Kiwi/KWTestCase.h
  131. +185 −0 Kiwi/KWTestCase.m
  132. +96 −0 Kiwi/KWValue.h
  133. +352 −0 Kiwi/KWValue.m
  134. +21 −0 Kiwi/KWVerifying.h
  135. +18 −0 Kiwi/KWWorkarounds.h
  136. +26 −0 Kiwi/KWWorkarounds.m
  137. +73 −0 Kiwi/Kiwi.h
  138. +28 −0 Kiwi/KiwiConfiguration.h
  139. +67 −0 Kiwi/KiwiMacros.h
  140. +28 −0 Kiwi/NSInvocation+KiwiAdditions.h
  141. +93 −0 Kiwi/NSInvocation+KiwiAdditions.m
  142. +17 −0 Kiwi/NSMethodSignature+KiwiAdditions.h
  143. +22 −0 Kiwi/NSMethodSignature+KiwiAdditions.m
  144. +31 −0 Kiwi/NSNumber+KiwiAdditions.h
  145. +111 −0 Kiwi/NSNumber+KiwiAdditions.m
  146. +20 −0 Kiwi/NSObject+KiwiMockAdditions.h
  147. +31 −0 Kiwi/NSObject+KiwiMockAdditions.m
  148. +36 −0 Kiwi/NSObject+KiwiStubAdditions.h
  149. +108 −0 Kiwi/NSObject+KiwiStubAdditions.m
  150. +19 −0 Kiwi/NSObject+KiwiVerifierAdditions.h
  151. +26 −0 Kiwi/NSObject+KiwiVerifierAdditions.m
  152. +16 −0 Kiwi/NSValue+KiwiAdditions.h
  153. +24 −0 Kiwi/NSValue+KiwiAdditions.m
  154. +27 −0 License.txt
  155. +13 −0 Other Sources/Kiwi_Prefix.pch
  156. +14 −0 Other Sources/main.m
  157. +15 −0 Readme.txt
  158. BIN  Resources/Icon.png
  159. +30 −0 Resources/KiwiDriver-Info.plist
  160. +20 −0 Resources/KiwiTests-Info.plist
  161. +156 −0 Resources/KiwiViewController.xib
  162. +227 −0 Resources/MainWindow.xib
  163. +43 −0 Tests/KWBeBetweenMatcherTest.m
  164. +43 −0 Tests/KWBeEmptyMatcherTest.m
  165. +44 −0 Tests/KWBeIndenticalToMatcherTest.m
  166. +43 −0 Tests/KWBeKindOfClassMatcherTest.m
  167. +43 −0 Tests/KWBeMemberOfClassMatcherTest.m
  168. +64 −0 Tests/KWBeTrueMatcherTest.m
  169. +43 −0 Tests/KWBeWithinMatcherTest.m
  170. +48 −0 Tests/KWBlockRaiseMatcherTest.m
  171. +43 −0 Tests/KWConformToProtocolMatcherTest.m
  172. +66 −0 Tests/KWContainMatcherTest.m
  173. +37 −0 Tests/KWContextNodeTest.m
  174. +40 −0 Tests/KWDeviceInfoTest.m
  175. +45 −0 Tests/KWEqualMatcherTest.m
  176. +62 −0 Tests/KWExampleGroupBuilderTest.m
  177. +112 −0 Tests/KWHaveMatcherTest.m
  178. +84 −0 Tests/KWInequalityMatcherTest.m
  179. +77 −0 Tests/KWMessagePatternTest.m
  180. +269 −0 Tests/KWMockTest.m
  181. +74 −0 Tests/KWRaiseMatcherTest.m
  182. +61 −0 Tests/KWRealObjectSpyTest.m
  183. +147 −0 Tests/KWRealObjectStubTest.m
  184. +129 −0 Tests/KWReceiveMatcherTest.m
  185. +43 −0 Tests/KWRespondToSelectorMatcherTest.m
  186. +45 −0 Tests/KWStringUtilitiesTest.m
  187. +110 −0 Tests/KWStubTest.m
  188. +42 −0 Tests/KWTestCaseTest.m
  189. +194 −0 Tests/KWValueTest.m
  190. +10 −0 Tests/KiwiTestConfiguration.h
10 .gitignore
@@ -0,0 +1,10 @@
+*.DS_Store
+
+# Build directory
+build/
+
+# XCode user specific files
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+*.pbxuser
11 Classes/Carrier.h
@@ -0,0 +1,11 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Cruiser.h"
+
+@interface Carrier : Cruiser
+
+@end
11 Classes/Carrier.m
@@ -0,0 +1,11 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Carrier.h"
+
+@implementation Carrier
+
+@end
78 Classes/Cruiser.h
@@ -0,0 +1,78 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "JumpCapable.h"
+#import "SpaceShip.h"
+
+@class Engine;
+@class Fighter;
+
+@interface Cruiser : SpaceShip<JumpCapable> {
+@private
+ NSString *callsign;
+ Engine *engine;
+ NSArray *fighters;
+}
+
+#pragma mark -
+#pragma mark Initializing
+
+- (id)initWithCallsign:(NSString *)aCallsign;
+
++ (id)cruiser;
++ (id)cruiserWithCallsign:(NSString *)aCallsign;
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readonly) NSString *callsign;
+@property (nonatomic, readonly) Engine *engine;
+
++ (NSString *)classification;
+
+- (NSUInteger)crewComplement;
+
+#pragma mark -
+#pragma mark Managing Fighters
+
+@property (nonatomic, readwrite, retain) NSArray *fighters;
+
+- (Fighter *)fighterWithCallsign:(NSString *)aCallsign;
+- (NSArray *)fightersInSquadron:(NSString *)aSquadron;
+
+#pragma mark -
+#pragma mark Managing Systems
+
+- (BOOL)raiseShields;
+- (float)energyLevelInWarpCore:(NSUInteger)anIndex;
+
+#pragma mark -
+#pragma mark Getting Navigation Information
+
+// starHash => key/2 + key/4 + key/8 + ... 1
+- (NSUInteger)computeStarHashForKey:(NSUInteger)aKey;
+
+#pragma mark -
+#pragma mark Orbiting
+
+- (void)orbitPlanet:(id)aPlanet;
+- (float)orbitPeriodForMass:(float)aMass;
+
+#pragma mark -
+#pragma mark Jumping
+
+- (void)computeParsecs;
+- (void)engageHyperdrive;
+- (NSUInteger)hyperdriveFuelLevel;
+
+#pragma mark -
+#pragma mark Raising
+
+- (void)raise;
+- (void)raiseWithName:(NSString *)aName description:(NSString *)aDescription;
+
+@end
136 Classes/Cruiser.m
@@ -0,0 +1,136 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Cruiser.h"
+#import "Engine.h"
+#import "Fighter.h"
+
+@implementation Cruiser
+
+#pragma mark -
+#pragma mark Initializing
+
+- (id)initWithCallsign:(NSString *)aCallsign {
+ if ((self = [super init])) {
+ callsign = [aCallsign copy];
+ }
+
+ return self;
+}
+
++ (id)cruiser {
+ return [self cruiserWithCallsign:nil];
+}
+
++ (id)cruiserWithCallsign:(NSString *)aCallsign {
+ return [[[self alloc] initWithCallsign:aCallsign] autorelease];
+}
+
+- (void)dealloc {
+ [callsign release];
+ [engine release];
+ [fighters release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize callsign;
+@synthesize engine;
+
++ (NSString *)classification {
+ return @"Capital Ship";
+}
+
+- (NSUInteger)crewComplement {
+ return 1010;
+}
+
+#pragma mark -
+#pragma mark Managing Fighters
+
+@synthesize fighters;
+
+- (Fighter *)fighterWithCallsign:(NSString *)aCallsign {
+ for (Fighter *fighter in self.fighters) {
+ if ([fighter.callsign isEqualToString:aCallsign])
+ return fighter;
+ }
+
+ return nil;
+}
+
+- (NSArray *)fightersInSquadron:(NSString *)aSquadron {
+ NSMutableArray *fightersInSquadron = [[[NSMutableArray alloc] init] autorelease];
+
+ for (Fighter *fighter in self.fighters) {
+ if ([fighter.callsign hasPrefix:aSquadron])
+ [fightersInSquadron addObject:fighter];
+ }
+
+ return fightersInSquadron;
+}
+
+#pragma mark -
+#pragma mark Managing Systems
+
+- (BOOL)raiseShields {
+ return [super raiseShields];
+}
+
+- (float)energyLevelInWarpCore:(NSUInteger)anIndex {
+ return 42.0f * (float)anIndex;
+}
+
+#pragma mark -
+#pragma mark Getting Navigation Information
+
+- (NSUInteger)computeStarHashForKey:(NSUInteger)aKey {
+ if (aKey == 0)
+ return 0;
+
+ return aKey + [self computeStarHashForKey:aKey/2];
+}
+
+#pragma mark -
+#pragma mark Orbiting
+
+- (void)orbitPlanet:(id)aPlanet {
+ NSLog(@"orbiting planet ...");
+}
+
+- (float)orbitPeriodForMass:(float)aMass {
+ return aMass * 9.8f;
+}
+
+#pragma mark -
+#pragma mark Jumping
+
+- (void)computeParsecs {
+ NSLog(@"computing parsecs ...");
+}
+
+- (void)engageHyperdrive {
+ NSLog(@"engaging hyperdrive ...");
+}
+
+- (NSUInteger)hyperdriveFuelLevel {
+ return 77;
+}
+
+#pragma mark -
+#pragma mark Raising
+
+- (void)raise {
+ [NSException raise:@"CruiserException" format:@"-[Cruiser raise]"];
+}
+
+- (void)raiseWithName:(NSString *)aName description:(NSString *)aDescription {
+ [NSException raise:aName format:@"%@", aDescription];
+}
+
+@end
11 Classes/Engine.h
@@ -0,0 +1,11 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface Engine : NSObject
+
+@end
11 Classes/Engine.m
@@ -0,0 +1,11 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Engine.h"
+
+@implementation Engine
+
+@end
34 Classes/Fighter.h
@@ -0,0 +1,34 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "SpaceShip.h"
+
+@class Engine;
+
+@interface Fighter : SpaceShip {
+@private
+ NSString *callsign;
+ Engine *engine;
+}
+
+#pragma mark -
+#pragma mark Initializing
+
+- (id)initWithCallsign:(NSString *)aCallsign;
+
++ (id)fighter;
++ (id)fighterWithCallsign:(NSString *)aCallsign;
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readonly) NSString *callsign;
+@property (nonatomic, readonly) Engine *engine;
+
++ (NSString *)classification;
+
+@end
46 Classes/Fighter.m
@@ -0,0 +1,46 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Fighter.h"
+#import "Engine.h"
+
+@implementation Fighter
+
+#pragma mark -
+#pragma mark Initializing
+
+- (id)initWithCallsign:(NSString *)aCallsign {
+ if ((self = [super init])) {
+ callsign = [aCallsign copy];
+ }
+
+ return self;
+}
+
++ (id)fighter {
+ return [self fighterWithCallsign:nil];
+}
+
++ (id)fighterWithCallsign:(NSString *)aCallsign {
+ return [[[self alloc] initWithCallsign:aCallsign] autorelease];
+}
+
+- (void)dealloc {
+ [callsign release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize callsign;
+@synthesize engine;
+
++ (NSString *)classification {
+ return @"Starfighter";
+}
+
+@end
18 Classes/JumpCapable.h
@@ -0,0 +1,18 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "OrbitCapable.h"
+
+@protocol JumpCapable<OrbitCapable>
+
+#pragma mark -
+#pragma mark Jumping
+
+- (void)computeParsecs;
+- (void)engageHyperdrive;
+- (NSUInteger)hyperdriveFuelLevel;
+
+@end
19 Classes/KiwiAppDelegate.h
@@ -0,0 +1,19 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@class KiwiViewController;
+
+@interface KiwiAppDelegate : NSObject <UIApplicationDelegate> {
+ UIWindow *window;
+ KiwiViewController *viewController;
+}
+
+@property (nonatomic, retain) IBOutlet UIWindow *window;
+@property (nonatomic, retain) IBOutlet KiwiViewController *viewController;
+
+@end
28 Classes/KiwiAppDelegate.m
@@ -0,0 +1,28 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiAppDelegate.h"
+#import "KiwiViewController.h"
+
+@implementation KiwiAppDelegate
+
+@synthesize window;
+@synthesize viewController;
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Override point for customization after app launch
+ [window addSubview:viewController.view];
+ [window makeKeyAndVisible];
+ return YES;
+}
+
+- (void)dealloc {
+ [viewController release];
+ [window release];
+ [super dealloc];
+}
+
+@end
12 Classes/KiwiViewController.h
@@ -0,0 +1,12 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface KiwiViewController : UIViewController
+
+@end
+
61 Classes/KiwiViewController.m
@@ -0,0 +1,61 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiViewController.h"
+
+@implementation KiwiViewController
+
+/*
+// The designated initializer. Override to perform setup that is required before the view is loaded.
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
+ // Custom initialization
+ }
+ return self;
+}
+*/
+
+/*
+// Implement loadView to create a view hierarchy programmatically, without using a nib.
+- (void)loadView {
+}
+*/
+
+
+/*
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void)viewDidLoad {
+ [super viewDidLoad];
+}
+*/
+
+
+/*
+// Override to allow orientations other than the default portrait orientation.
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ // Return YES for supported orientations
+ return (interfaceOrientation == UIInterfaceOrientationPortrait);
+}
+*/
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+@end
17 Classes/OrbitCapable.h
@@ -0,0 +1,17 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@protocol OrbitCapable<NSObject>
+
+#pragma mark -
+#pragma mark Orbiting
+
+- (void)orbitPlanet:(id)aPlanet;
+- (float)orbitPeriodForMass:(float)aMass;
+
+@end
16 Classes/SpaceShip.h
@@ -0,0 +1,16 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface SpaceShip : NSObject
+
+#pragma mark -
+#pragma mark Managing Shields
+
+- (BOOL)raiseShields;
+
+@end
18 Classes/SpaceShip.m
@@ -0,0 +1,18 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "SpaceShip.h"
+
+@implementation SpaceShip
+
+#pragma mark -
+#pragma mark Managing Shields
+
+- (BOOL)raiseShields {
+ return YES;
+}
+
+@end
16 Classes/TestClasses.h
@@ -0,0 +1,16 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Carrier.h"
+#import "Cruiser.h"
+#import "Engine.h"
+#import "Fighter.h"
+#import "JumpCapable.h"
+#import "OrbitCapable.h"
+#import "SpaceShip.h"
+#import "TestReporter.h"
+#import "TestSpy.h"
+#import "TestVerifier.h"
41 Classes/TestReporter.h
@@ -0,0 +1,41 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "KWReporting.h"
+
+@class KWFailure;
+
+@interface TestReporter : NSObject<KWReporting> {
+@private
+ BOOL hasUnmetExpectations;
+ NSMutableArray *failures;
+}
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)testReporter;
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readonly) BOOL hasUnmetExpectations;
+@property (nonatomic, readonly) NSArray* failures;
+
+#pragma mark -
+#pragma mark Reporting Failures
+
+- (void)reportFailure:(KWFailure *)aFailure;
+
+#pragma mark -
+#pragma mark Getting Failure Information
+
+- (BOOL)hasNoFailure;
+- (BOOL)hasOneFailure;
+- (KWFailure *)onlyFailure;
+
+@end
73 Classes/TestReporter.m
@@ -0,0 +1,73 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "TestReporter.h"
+#import "KWFailure.h"
+
+@interface TestReporter()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite) BOOL hasUnmetExpectations;
+
+@end
+
+@implementation TestReporter
+
+#pragma mark -
+#pragma mark Initializing
+
+- (id)init {
+ if ((self = [super init])) {
+ failures = [[NSMutableArray alloc] init];
+ }
+
+ return self;
+}
+
++ (id)testReporter {
+ return [[[self alloc] init] autorelease];
+}
+
+- (void)dealloc {
+ [failures release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize hasUnmetExpectations;
+@synthesize failures;
+
+#pragma mark -
+#pragma mark Reporting Failures
+
+- (void)reportFailure:(KWFailure *)aFailure {
+ if (aFailure == nil)
+ return;
+
+ self.hasUnmetExpectations = YES;
+ [failures addObject:aFailure];
+}
+
+#pragma mark -
+#pragma mark Getting Failure Information
+
+- (BOOL)hasNoFailure {
+ return [self.failures count] == 0;
+}
+
+- (BOOL)hasOneFailure {
+ return [self.failures count] == 1;
+}
+
+- (KWFailure *)onlyFailure {
+ return [self.failures objectAtIndex:0];
+}
+
+@end
24 Classes/TestSpy.h
@@ -0,0 +1,24 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Kiwi.h"
+
+@interface TestSpy : NSObject<KWMessageSpying> {
+@private
+ BOOL wasNotified;
+}
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)testSpy;
+
+#pragma mark -
+#pragma mark Checking Notifications
+
+@property (nonatomic, readonly) BOOL wasNotified;
+
+@end
27 Classes/TestSpy.m
@@ -0,0 +1,27 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "TestSpy.h"
+
+@implementation TestSpy
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)testSpy {
+ return [[[self alloc] init] autorelease];
+}
+
+#pragma mark -
+#pragma mark Checking Notifications
+
+@synthesize wasNotified;
+
+- (void)object:(id)anObject didReceiveInvocation:(NSInvocation *)anInvocation {
+ wasNotified = YES;
+}
+
+@end
24 Classes/TestVerifier.h
@@ -0,0 +1,24 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Kiwi.h"
+
+@interface TestVerifier : NSObject<KWVerifying> {
+@private
+ BOOL notifiedOfEndOfExample;
+}
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readonly) BOOL notifiedOfEndOfExample;
+
+#pragma mark -
+#pragma mark Verifying
+
+- (void)exampleWillEnd;
+
+@end
38 Classes/TestVerifier.m
@@ -0,0 +1,38 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "TestVerifier.h"
+
+@interface TestVerifier()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite) BOOL notifiedOfEndOfExample;
+
+@end
+
+@implementation TestVerifier
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize notifiedOfEndOfExample;
+
+#pragma mark -
+#pragma mark Setting Subjects
+
+- (void)setSubject:(id)anObject {
+}
+
+#pragma mark -
+#pragma mark Verifying
+
+- (void)exampleWillEnd {
+ self.notifiedOfEndOfExample = YES;
+}
+
+@end
61 Examples/ExampleSpec.m
@@ -0,0 +1,61 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiTestConfiguration.h"
+#import "TestClasses.h"
+#import "Kiwi.h"
+
+#if KW_TESTS_ENABLED && KW_BLOCKS_ENABLED
+
+SPEC_BEGIN(ExampleSpec)
+
+describe(@"Cruiser", ^{
+ registerMatchers(@"KWT");
+
+ context(@"with fighters set", ^{
+ __block Cruiser *cruiser = nil;
+
+ beforeAll(^{
+ });
+
+ afterAll(^{
+ });
+
+ beforeEach(^{
+ cruiser = [Cruiser cruiser];
+ [cruiser stub:@selector(raiseShields) andReturn:theValue(NO)];
+ [cruiser setFighters:[NSArray arrayWithObjects:[Fighter fighterWithCallsign:@"Viper 1"],
+ [Fighter fighterWithCallsign:@"Viper 2"],
+ [Fighter fighterWithCallsign:@"Viper 3"], nil]];
+ });
+
+ pending(@"should be really big", nil);
+
+ it(@"should have fighters", ^{
+ [[[cruiser should] have:3] fighters];
+ [[cruiser.fighters shouldNot] beEmpty];
+ [Cruiser stub:@selector(classification) andReturn:@"Animal"];
+ });
+
+ it(@"should raise shields", ^{
+ [[[Cruiser classification] should] equal:@"Capital Ship"];
+ [[theValue([cruiser raiseShields]) should] beFalse];
+ [[cruiser should] receive:@selector(fighterWithCallsign:)];
+ [cruiser fighterWithCallsign:@"Apollo"];
+ });
+
+ it(@"should raise if asked", ^{
+ [[[Cruiser classification] should] equal:@"Capital Ship"];
+ [[lambda(^{
+ [cruiser raiseWithName:@"FooException" description:@"Foo"];
+ }) should] raiseWithName:@"FooException"];
+ });
+ });
+});
+
+SPEC_END
+
+#endif // #if KW_TESTS_ENABLED && KW_BLOCKS_ENABLED
224 Examples/ExampleTestCase.m
@@ -0,0 +1,224 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Kiwi.h"
+#import "KiwiTestConfiguration.h"
+#import "TestClasses.h"
+
+#if KW_TESTS_ENABLED
+
+@interface ExampleTestCase : KWTestCase
+
+@end
+
+@implementation ExampleTestCase
+
+- (void)itShouldVerifyExistence {
+ id subject = [Cruiser cruiser];
+ [subject shouldNotBeNil];
+}
+
+- (void)itShouldVerifyCloseness {
+ id subject = theValue(42);
+ [[subject should] beWithin:theValue(2) of:theValue(40)];
+
+ subject = theValue(42.00001);
+ [[subject should] equal:42.0 withDelta:0.1];
+}
+
+- (void)itShouldVerifyEquality {
+ id subject = @"foo";
+ id otherSubject = @"foo";
+ [[subject should] equal:otherSubject];
+
+ otherSubject = @"bar";
+ [[subject shouldNot] equal:otherSubject];
+}
+
+- (void)itShouldVerifyGreaterValues {
+ id subject = theValue(42);
+ [[subject should] beGreaterThan:theValue(41)];
+ [[subject should] beGreaterThanOrEqualTo:theValue(42)];
+}
+
+- (void)itShouldVerifyLesserValues {
+ id subject = theValue(42);
+ [[subject should] beLessThan:theValue(43)];
+ [[subject should] beLessThanOrEqualTo:theValue(43)];
+}
+
+- (void)itShouldVerifyIdentity {
+ id subject = [Cruiser cruiser];
+ [[subject should] beIdenticalTo:subject];
+}
+
+- (void)itShouldVerifyIntervalMembership {
+ id subject = theValue(42);
+ [[subject should] beBetween:theValue(40) and:theValue(43)];
+}
+
+- (void)itShouldVerifyTruthValues {
+ id subject = theValue(YES);
+ [[subject should] beTrue];
+
+ subject = theValue(NO);
+ [[subject should] beFalse];
+}
+
+- (void)itShouldVerifyZero {
+ id subject = theValue(0);
+ [[subject should] beZero];
+}
+
+- (void)itShouldVerifyProtocolConformance {
+ id subject = [Cruiser cruiser];
+ [[subject should] conformToProtocol:@protocol(JumpCapable)];
+}
+
+- (void)itShouldVerifyKindsOfClasses {
+ id subject = [Cruiser cruiser];
+ [[subject should] beKindOfClass:[SpaceShip class]];
+}
+
+- (void)itShouldVerifyClassMembership {
+ id subject = [Cruiser cruiser];
+ [[subject should] beMemberOfClass:[Cruiser class]];
+}
+
+- (void)itShouldVerifyEmptyCollections {
+ id subject = [NSArray arrayWithObjects:@"foot", @"ball", nil];
+ [[subject shouldNot] beEmpty];
+}
+
+- (void)itShouldVerifyElementContainment {
+ id subject = [NSArray arrayWithObjects:@"dog", @"cat", @"tiger", @"liger", nil];
+ [[subject should] contain:@"liger"];
+ [[subject should] containObjects:@"liger", @"tiger", nil];
+}
+
+- (void)itShouldVerifyCollectionCounts {
+ id subject = [NSArray arrayWithObjects:@"dog", @"cat", @"tiger", @"liger", nil];
+ [[subject should] haveCountOf:4];
+ [[subject should] haveCountOfAtLeast:3];
+ [[subject should] haveCountOfAtMost:5];
+}
+
+- (void)itShouldVerifyCollectionCountsWithInvocationKeys {
+ id subject = [Cruiser cruiser];
+ [subject setFighters:[NSArray arrayWithObjects:[Fighter fighterWithCallsign:@"Viper 1"],
+ [Fighter fighterWithCallsign:@"Viper 2"],
+ [Fighter fighterWithCallsign:@"Mamba 1"], nil]];
+ [[[subject should] have:2] fightersInSquadron:@"Viper"];
+}
+
+- (void)itShouldVerifyRespondsToSelector {
+ id subject = [Cruiser cruiser];
+ [[subject should] respondToSelector:@selector(raiseShields)];
+}
+
+- (void)itShouldVerifyRaisedExceptions {
+ id subject = [Cruiser cruiser];
+ [[subject should] raiseWhenSent:@selector(raise)];
+ [[subject should] raiseWithName:@"CruiserException" whenSent:@selector(raise)];
+ [[subject should] raiseWithReason:@"-[Cruiser raise]" whenSent:@selector(raise)];
+ [[subject should] raiseWithName:@"CruiserException" reason:@"-[Cruiser raise]" whenSent:@selector(raise)];
+}
+
+#if KW_BLOCKS_ENABLED
+
+- (void)itShouldVerifyBlockRaisedExceptions {
+ id subject = [Cruiser cruiser];
+ [[theBlock(^{ [subject raise]; }) should] raise];
+ [[theBlock(^{ [subject raise]; }) should] raiseWithName:@"CruiserException"];
+ [[theBlock(^{ [subject raise]; }) should] raiseWithReason:@"-[Cruiser raise]"];
+ [[theBlock(^{ [subject raise]; }) should] raiseWithName:@"CruiserException" reason:@"-[Cruiser raise]"];
+
+ NSArray *foo = [NSArray array];
+ [[theBlock(^{ [foo objectAtIndex:0]; }) should] raiseWithName:NSRangeException];
+}
+
+#endif // #if KW_BLOCKS_ENABLED
+
+- (void)itShouldVerifyReceivedMessages {
+ id subject = [Cruiser cruiser];
+ [[subject should] receive:@selector(raiseShields) withCountAtLeast:1];
+ [subject raiseShields];
+
+ subject = [Cruiser cruiser];
+ [[[subject should] receiveAndReturn:theValue(42) withCountAtLeast:2] crewComplement];
+ [subject crewComplement];
+ NSUInteger complement = [subject crewComplement];
+ [[theValue(complement) should] equal:theValue(42)];
+
+ subject = [Cruiser cruiser];
+ [[subject should] receive:@selector(energyLevelInWarpCore:) andReturn:theValue(1.01f) withCount:2 arguments:theValue(2)];
+ [subject energyLevelInWarpCore:2];
+ float energyLevel = [subject energyLevelInWarpCore:2];
+ [[theValue(energyLevel) should] equal:theValue(1.01f)];
+}
+
+- (void)itShouldMakeStubbedInstanceObjectsTransparent {
+ id subject = [Cruiser cruiser];
+ [subject stub:@selector(raiseShields) andReturn:theValue(YES)];
+ [[[subject class] should] beIdenticalTo:[Cruiser class]];
+ [[[subject superclass] should] beIdenticalTo:[Cruiser superclass]];
+}
+
+- (void)itShouldMakeStubbedClassObjectsTransparent {
+ id subject = [Cruiser class];
+ [subject stub:@selector(classification) andReturn:@"Animal"];
+ [[[subject class] should] beIdenticalTo:[Cruiser class]];
+ [[[subject superclass] should] beIdenticalTo:[Cruiser superclass]];
+}
+
+- (void)itShouldHandleAMixOfReceiveAndEqualExpectations {
+ id subject = [Cruiser mock];
+ //id subject = [Cruiser cruiser];
+ [[subject should] receive:@selector(raiseShields) andReturn:theValue(NO)];
+ [[subject should] receive:@selector(isEqual:) andReturn:theValue(YES)];
+ [subject raiseShields];
+ [[subject should] equal:@"terry"];
+}
+
+- (void)itShouldHandleStubbedAllocAndInitInMocks {
+ id subject = [Cruiser mock];
+ id otherSubject = [Cruiser mock];
+ [Cruiser stub:@selector(alloc) andReturn:subject];
+ [subject stub:@selector(init) andReturn:otherSubject];
+ id actual = [[[Cruiser alloc] init] autorelease];
+ [[actual should] beIdenticalTo:otherSubject];
+}
+
+- (void)itShouldHandleStubbedAllocAndInitInPartialMocks {
+ id subject = [Cruiser cruiser];
+ id otherSubject = [Cruiser cruiser];
+ [Cruiser stub:@selector(alloc) andReturn:subject];
+ [subject stub:@selector(init) andReturn:otherSubject];
+ id actual = [[[Cruiser alloc] init] autorelease];
+ [[actual should] beIdenticalTo:otherSubject];
+}
+
+- (void)itShouldHandleStubbedAllocAndCustomInitInMocks {
+ id subject = [Cruiser mock];
+ id otherSubject = [Cruiser mock];
+ [Cruiser stub:@selector(alloc) andReturn:subject];
+ [subject stub:@selector(initWithCallsign:) andReturn:otherSubject];
+ id actual = [[[Cruiser alloc] initWithCallsign:@"foo"] autorelease];
+ [[actual should] beIdenticalTo:otherSubject];
+}
+
+- (void)itShouldHandleStubbedAllocAndCustomInitInPartialMocks {
+ id subject = [Cruiser cruiser];
+ id otherSubject = [Cruiser cruiser];
+ [Cruiser stub:@selector(alloc) andReturn:subject];
+ [subject stub:@selector(initWithCallsign:) andReturn:otherSubject];
+ id actual = [[[Cruiser alloc] initWithCallsign:@"foo"] autorelease];
+ [[actual should] beIdenticalTo:otherSubject];
+}
+
+@end
+
+#endif // #if KW_TESTS_ENABLED
38 Examples/SimpleSpec.m
@@ -0,0 +1,38 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "Kiwi.h"
+
+SPEC_BEGIN(SimpleSpec)
+
+describe(@"stack", ^{
+ __block NSMutableArray *arr = nil;
+
+ context(@"new", ^{
+ beforeEach(^{
+ arr = [NSMutableArray array];
+ [arr addObject:@"shark"];
+ });
+
+ context(@"with 2 items", ^{
+ beforeEach(^{
+ [arr addObject:@"dolphin"];
+ });
+
+ it(@"has 2 items", ^{
+ [[arr should] contain:@"dolphin"];
+ arr = nil;
+ });
+
+ it(@"has 2 items", ^{
+ [[arr should] contain:@"dolphin"];
+ arr = nil;
+ });
+ });
+ });
+});
+
+SPEC_END
1,362 Kiwi.xcodeproj/project.pbxproj
1,362 additions, 0 deletions not shown
22 Kiwi/KWAfterAllNode.h
@@ -0,0 +1,22 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWBlockNode.h"
+#import "KWExampleNode.h"
+
+#if KW_BLOCKS_ENABLED
+
+@interface KWAfterAllNode : KWBlockNode<KWExampleNode>
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)afterAllNodeWithCallSite:(KWCallSite *)aCallSite block:(KWVoidBlock)aBlock;
+
+@end
+
+#endif // #if KW_BLOCKS_ENABLED
30 Kiwi/KWAfterAllNode.m
@@ -0,0 +1,30 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWAfterAllNode.h"
+#import "KWExampleNodeVisitor.h"
+
+#if KW_BLOCKS_ENABLED
+
+@implementation KWAfterAllNode
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)afterAllNodeWithCallSite:(KWCallSite *)aCallSite block:(KWVoidBlock)aBlock {
+ return [[[self alloc] initWithCallSite:aCallSite description:nil block:aBlock] autorelease];
+}
+
+#pragma mark -
+#pragma mark Accepting Visitors
+
+- (void)acceptExampleNodeVisitor:(id<KWExampleNodeVisitor>)aVisitor {
+ [aVisitor visitAfterAllNode:self];
+}
+
+@end
+
+#endif // #if KW_BLOCKS_ENABLED
22 Kiwi/KWAfterEachNode.h
@@ -0,0 +1,22 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWBlockNode.h"
+#import "KWExampleNode.h"
+
+#if KW_BLOCKS_ENABLED
+
+@interface KWAfterEachNode : KWBlockNode<KWExampleNode>
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)afterEachNodeWithCallSite:(KWCallSite *)aCallSite block:(KWVoidBlock)aBlock;
+
+@end
+
+#endif // #if KW_BLOCKS_ENABLED
30 Kiwi/KWAfterEachNode.m
@@ -0,0 +1,30 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWAfterEachNode.h"
+#import "KWExampleNodeVisitor.h"
+
+#if KW_BLOCKS_ENABLED
+
+@implementation KWAfterEachNode
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)afterEachNodeWithCallSite:(KWCallSite *)aCallSite block:(KWVoidBlock)aBlock {
+ return [[[self alloc] initWithCallSite:aCallSite description:nil block:aBlock] autorelease];
+}
+
+#pragma mark -
+#pragma mark Accepting Visitors
+
+- (void)acceptExampleNodeVisitor:(id<KWExampleNodeVisitor>)aVisitor {
+ [aVisitor visitAfterEachNode:self];
+}
+
+@end
+
+#endif // #if KW_BLOCKS_ENABLED
23 Kiwi/KWBeBetweenMatcher.h
@@ -0,0 +1,23 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeBetweenMatcher : KWMatcher {
+@private
+ id lowerEndpoint;
+ id upperEndpoint;
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+// TODO: 'and' below is a reserved word in C++
+- (void)beBetween:(id)aLowerEndpoint and:(id)anUpperEndpoint;
+- (void)beInTheIntervalFrom:(id)aLowerEndpoint to:(id)anUpperEndpoint;
+
+@end
79 Kiwi/KWBeBetweenMatcher.m
@@ -0,0 +1,79 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeBetweenMatcher.h"
+#import "KWFormatter.h"
+
+@interface KWBeBetweenMatcher()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite, retain) id lowerEndpoint;
+@property (nonatomic, readwrite, retain) id upperEndpoint;
+
+@end
+
+@implementation KWBeBetweenMatcher
+
+#pragma mark -
+#pragma mark Initializing
+
+- (void)dealloc {
+ [lowerEndpoint release];
+ [upperEndpoint release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize lowerEndpoint;
+@synthesize upperEndpoint;
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObjects:@"beBetween:and:", @"beInTheIntervalFrom:to:", nil];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+- (BOOL)evaluate {
+ if (![self.subject respondsToSelector:@selector(compare:)])
+ [NSException raise:@"KWMatcherException" format:@"subject does not respond to -compare:"];
+
+ NSComparisonResult lowerResult = [self.subject compare:self.lowerEndpoint];
+ NSComparisonResult upperResult = [self.subject compare:self.upperEndpoint];
+ return (lowerResult == NSOrderedDescending || lowerResult == NSOrderedSame) &&
+ (upperResult == NSOrderedAscending || upperResult == NSOrderedSame);
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be in the interval [%@, %@], got %@",
+ [KWFormatter formatObject:self.lowerEndpoint],
+ [KWFormatter formatObject:self.upperEndpoint],
+ [KWFormatter formatObject:self.subject]];
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beBetween:(id)aLowerEndpoint and:(id)anUpperEndpoint {
+ [self beInTheIntervalFrom:aLowerEndpoint to:anUpperEndpoint];
+}
+
+- (void)beInTheIntervalFrom:(id)aLowerEndpoint to:(id)anUpperEndpoint {
+ self.lowerEndpoint = aLowerEndpoint;
+ self.upperEndpoint = anUpperEndpoint;
+}
+
+@end
20 Kiwi/KWBeEmptyMatcher.h
@@ -0,0 +1,20 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeEmptyMatcher : KWMatcher {
+@private
+ NSUInteger count;
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beEmpty;
+
+@end
74 Kiwi/KWBeEmptyMatcher.m
@@ -0,0 +1,74 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeEmptyMatcher.h"
+#import "KWFormatter.h"
+
+@interface KWBeEmptyMatcher()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite) NSUInteger count;
+
+@end
+
+@implementation KWBeEmptyMatcher
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize count;
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObject:@"beEmpty"];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+- (BOOL)evaluate {
+ if ([self.subject respondsToSelector:@selector(count)]) {
+ self.count = [self.subject count];
+ return self.count == 0;
+ }
+ else if ([self.subject respondsToSelector:@selector(length)]) {
+ self.count = [self.subject length];
+ return self.count == 0;
+ }
+
+ [NSException raise:@"KWMatcherException" format:@"subject does not respond to -count or -length"];
+ return NO;
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)countPhrase {
+ if (self.count == 1)
+ return @"1 item";
+ else
+ return [NSString stringWithFormat:@"%u items", self.count];
+}
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be empty, got %@", [self countPhrase]];
+}
+
+- (NSString *)failureMessageForShouldNot {
+ return @"expected subject not to be empty";
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beEmpty {
+}
+
+@end
20 Kiwi/KWBeIdenticalToMatcher.h
@@ -0,0 +1,20 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeIdenticalToMatcher : KWMatcher {
+@private
+ id otherSubject;
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beIdenticalTo:(id)anObject;
+
+@end
72 Kiwi/KWBeIdenticalToMatcher.m
@@ -0,0 +1,72 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeIdenticalToMatcher.h"
+#import "KWFormatter.h"
+
+@interface KWBeIdenticalToMatcher()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite, retain) id otherSubject;
+
+@end
+
+@implementation KWBeIdenticalToMatcher
+
+#pragma mark -
+#pragma mark Initializing
+
+- (void)dealloc {
+ [otherSubject release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize otherSubject;
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObject:@"beIdenticalTo:"];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+- (BOOL)evaluate {
+ return self.subject == self.otherSubject;
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be identical to %@ (%p), got %@ (%p)",
+ [KWFormatter formatObject:self.otherSubject],
+ self.otherSubject,
+ [KWFormatter formatObject:self.subject],
+ self.subject];
+}
+
+- (NSString *)failureMessageForShouldNot {
+ return [NSString stringWithFormat:@"expected subject not to be identical to %@ (%p)",
+ [KWFormatter formatObject:self.otherSubject],
+ self.otherSubject];
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beIdenticalTo:(id)anObject {
+ self.otherSubject = anObject;
+}
+
+@end
20 Kiwi/KWBeKindOfClassMatcher.h
@@ -0,0 +1,20 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeKindOfClassMatcher : KWMatcher {
+@private
+ Class targetClass;
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beKindOfClass:(Class)aClass;
+
+@end
55 Kiwi/KWBeKindOfClassMatcher.m
@@ -0,0 +1,55 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeKindOfClassMatcher.h"
+#import "KWFormatter.h"
+
+@interface KWBeKindOfClassMatcher()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite) Class targetClass;
+
+@end
+
+@implementation KWBeKindOfClassMatcher
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize targetClass;
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObject:@"beKindOfClass:"];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+- (BOOL)evaluate {
+ return [self.subject isKindOfClass:self.targetClass];
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be kind of %@",
+ NSStringFromClass(self.targetClass)];
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beKindOfClass:(Class)aClass {
+ self.targetClass = aClass;
+}
+
+@end
20 Kiwi/KWBeMemberOfClassMatcher.h
@@ -0,0 +1,20 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeMemberOfClassMatcher : KWMatcher {
+@private
+ Class targetClass;
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beMemberOfClass:(Class)aClass;
+
+@end
55 Kiwi/KWBeMemberOfClassMatcher.m
@@ -0,0 +1,55 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeMemberOfClassMatcher.h"
+#import "KWFormatter.h"
+
+@interface KWBeMemberOfClassMatcher()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite) Class targetClass;
+
+@end
+
+@implementation KWBeMemberOfClassMatcher
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize targetClass;
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObject:@"beMemberOfClass:"];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+- (BOOL)evaluate {
+ return [self.subject isMemberOfClass:self.targetClass];
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be member of %@",
+ NSStringFromClass(self.targetClass)];
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beMemberOfClass:(Class)aClass {
+ self.targetClass = aClass;
+}
+
+@end
23 Kiwi/KWBeTrueMatcher.h
@@ -0,0 +1,23 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeTrueMatcher : KWMatcher {
+@private
+ BOOL expectedValue;
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beTrue;
+- (void)beFalse;
+- (void)beYes;
+- (void)beNo;
+
+@end
69 Kiwi/KWBeTrueMatcher.m
@@ -0,0 +1,69 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeTrueMatcher.h"
+
+@interface KWBeTrueMatcher()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite) BOOL expectedValue;
+
+@end
+
+@implementation KWBeTrueMatcher
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize expectedValue;
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObjects:@"beTrue", @"beFalse", @"beYes", @"beNo", nil];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+- (BOOL)evaluate {
+ if (![self.subject respondsToSelector:@selector(boolValue)])
+ [NSException raise:@"KWMatcherException" format:@"subject does not respond to -boolValue"];
+
+ return [self.subject boolValue] == self.expectedValue;
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be %@",
+ expectedValue ? @"true" : @"false"];
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beTrue {
+ self.expectedValue = YES;
+}
+
+- (void)beFalse {
+ self.expectedValue = NO;
+}
+
+- (void)beYes {
+ self.expectedValue = YES;
+}
+
+- (void)beNo {
+ self.expectedValue = NO;
+}
+
+@end
22 Kiwi/KWBeWithinMatcher.h
@@ -0,0 +1,22 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeWithinMatcher : KWMatcher {
+@private
+ id distance;
+ id otherValue;
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beWithin:(id)aDistance of:(id)aValue;
+- (void)equal:(double)aValue withDelta:(double)aDelta;
+
+@end
109 Kiwi/KWBeWithinMatcher.m
@@ -0,0 +1,109 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeWithinMatcher.h"
+#import "KWFormatter.h"
+#import "KWObjCUtilities.h"
+#import "KWValue.h"
+
+@interface KWBeWithinMatcher()
+
+#pragma mark -
+#pragma mark Properties
+
+@property (nonatomic, readwrite, retain) id distance;
+@property (nonatomic, readwrite, retain) id otherValue;
+
+@end
+
+@implementation KWBeWithinMatcher
+
+#pragma mark -
+#pragma mark Initializing
+
+- (void)dealloc {
+ [distance release];
+ [otherValue release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Properties
+
+@synthesize distance;
+@synthesize otherValue;
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObjects:@"beWithin:of:", @"equal:withDelta:", nil];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+// Evaluation is done by getting the underlying values as the widest data
+// types available.
+
+- (BOOL)evaluateForFloatingPoint {
+ double firstValue = [self.subject doubleValue];
+ double secondValue = [self.otherValue doubleValue];
+ double theDistance = [self.distance doubleValue];
+ double absoluteDifference = firstValue > secondValue ? firstValue - secondValue : secondValue - firstValue;
+ return absoluteDifference <= theDistance;
+}
+
+- (BOOL)evaluateForUnsignedIntegral {
+ unsigned long long firstValue = [self.subject unsignedLongLongValue];
+ unsigned long long secondValue = [self.otherValue unsignedLongLongValue];
+ unsigned long long theDistance = [self.distance unsignedLongLongValue];
+ unsigned long long absoluteDifference = firstValue > secondValue ? firstValue - secondValue : secondValue - firstValue;
+ return absoluteDifference <= theDistance;
+}
+
+- (BOOL)evaluateForSignedIntegral {
+ long long firstValue = [self.subject longLongValue];
+ long long secondValue = [self.otherValue longLongValue];
+ long long theDistance = [self.distance longLongValue];
+ long long absoluteDifference = firstValue > secondValue ? firstValue - secondValue : secondValue - firstValue;
+ return absoluteDifference <= theDistance;
+}
+
+- (BOOL)evaluate {
+ const char *objCType = [self.subject objCType];
+
+ if (KWObjCTypeIsFloatingPoint(objCType))
+ return [self evaluateForFloatingPoint];
+ else if (KWObjCTypeIsUnsignedIntegral(objCType))
+ return [self evaluateForUnsignedIntegral];
+ else
+ return [self evaluateForSignedIntegral];
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be within %@ of %@, got %@",
+ [KWFormatter formatObject:self.distance],
+ [KWFormatter formatObject:self.otherValue],
+ [KWFormatter formatObject:self.subject]];
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beWithin:(id)aDistance of:(id)aValue {
+ self.distance = aDistance;
+ self.otherValue = aValue;
+}
+
+- (void)equal:(double)aValue withDelta:(double)aDelta {
+ [self beWithin:[KWValue valueWithDouble:aDelta] of:[KWValue valueWithDouble:aValue]];
+}
+
+@end
17 Kiwi/KWBeZeroMatcher.h
@@ -0,0 +1,17 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWMatcher.h"
+
+@interface KWBeZeroMatcher : KWMatcher
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beZero;
+
+@end
48 Kiwi/KWBeZeroMatcher.m
@@ -0,0 +1,48 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeZeroMatcher.h"
+#import "KWFormatter.h"
+#import "KWValue.h"
+
+@implementation KWBeZeroMatcher
+
+#pragma mark -
+#pragma mark Getting Matcher Strings
+
++ (NSArray *)matcherStrings {
+ return [NSArray arrayWithObject:@"beZero"];
+}
+
+#pragma mark -
+#pragma mark Matching
+
+- (BOOL)evaluate {
+ if (![self.subject respondsToSelector:@selector(boolValue)])
+ [NSException raise:@"KWMatcherException" format:@"subject does not respond to -numberValue"];
+
+ return [[self.subject numberValue] isEqualToNumber:[NSNumber numberWithInt:0]];
+}
+
+#pragma mark -
+#pragma mark Getting Failure Messages
+
+- (NSString *)failureMessageForShould {
+ return [NSString stringWithFormat:@"expected subject to be zero, got %@",
+ [KWFormatter formatObject:self.subject]];
+}
+
+- (NSString *)failureMessageForShouldNot {
+ return [NSString stringWithFormat:@"expected subject not to be zero"];
+}
+
+#pragma mark -
+#pragma mark Configuring Matchers
+
+- (void)beZero {
+}
+
+@end
22 Kiwi/KWBeforeAllNode.h
@@ -0,0 +1,22 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWBlockNode.h"
+#import "KWExampleNode.h"
+
+#if KW_BLOCKS_ENABLED
+
+@interface KWBeforeAllNode : KWBlockNode<KWExampleNode>
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)beforeAllNodeWithCallSite:(KWCallSite *)aCallSite block:(KWVoidBlock)aBlock;
+
+@end
+
+#endif // #if KW_BLOCKS_ENABLED
30 Kiwi/KWBeforeAllNode.m
@@ -0,0 +1,30 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeforeAllNode.h"
+#import "KWExampleNodeVisitor.h"
+
+#if KW_BLOCKS_ENABLED
+
+@implementation KWBeforeAllNode
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)beforeAllNodeWithCallSite:(KWCallSite *)aCallSite block:(KWVoidBlock)aBlock {
+ return [[[self alloc] initWithCallSite:aCallSite description:nil block:aBlock] autorelease];
+}
+
+#pragma mark -
+#pragma mark Accepting Visitors
+
+- (void)acceptExampleNodeVisitor:(id<KWExampleNodeVisitor>)aVisitor {
+ [aVisitor visitBeforeAllNode:self];
+}
+
+@end
+
+#endif // #if KW_BLOCKS_ENABLED
22 Kiwi/KWBeforeEachNode.h
@@ -0,0 +1,22 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KiwiConfiguration.h"
+#import "KWBlockNode.h"
+#import "KWExampleNode.h"
+
+#if KW_BLOCKS_ENABLED
+
+@interface KWBeforeEachNode : KWBlockNode<KWExampleNode>
+
+#pragma mark -
+#pragma mark Initializing
+
++ (id)beforeEachNodeWithCallSite:(KWCallSite *)aCallSite block:(KWVoidBlock)aBlock;
+
+@end
+
+#endif // #if KW_BLOCKS_ENABLED
30 Kiwi/KWBeforeEachNode.m
@@ -0,0 +1,30 @@
+//
+// Licensed under the terms in License.txt
+//
+// Copyright 2010 Allen Ding. All rights reserved.
+//
+
+#import "KWBeforeEachNode.h"
+#import "KWExa