├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Classes ├── Core │ ├── KWAny.h │ ├── KWAny.m │ ├── KWBlock.h │ ├── KWBlock.m │ ├── KWCallSite.h │ ├── KWCallSite.m │ ├── KWCaptureSpy.h │ ├── KWCaptureSpy.m │ ├── KWCountType.h │ ├── KWDeviceInfo.h │ ├── KWDeviceInfo.m │ ├── KWExample.h │ ├── KWExample.m │ ├── KWExampleDelegate.h │ ├── KWExampleNodeVisitor.h │ ├── KWExampleSuite.h │ ├── KWExampleSuite.m │ ├── KWExampleSuiteBuilder.h │ ├── KWExampleSuiteBuilder.m │ ├── KWExpectationType.h │ ├── KWFailure.h │ ├── KWFailure.m │ ├── KWFormatter.h │ ├── KWFormatter.m │ ├── KWFutureObject.h │ ├── KWFutureObject.m │ ├── KWInvocationCapturer.h │ ├── KWInvocationCapturer.m │ ├── KWLet.h │ ├── KWMatcher.h │ ├── KWMatcher.m │ ├── KWMatcherFactory.h │ ├── KWMatcherFactory.m │ ├── KWMatchers.h │ ├── KWMatchers.m │ ├── KWMatching.h │ ├── KWMessageSpying.h │ ├── KWMessageTracker.h │ ├── KWMessageTracker.m │ ├── KWNull.h │ ├── KWNull.m │ ├── KWObjCUtilities.h │ ├── KWObjCUtilities.m │ ├── KWProbe.h │ ├── KWProbePoller.h │ ├── KWProbePoller.m │ ├── KWReporting.h │ ├── KWSpec.h │ ├── KWSpec.m │ ├── KWStringUtilities.h │ ├── KWStringUtilities.m │ ├── KWSymbolicator.h │ ├── KWSymbolicator.m │ ├── KWValue.h │ ├── KWValue.m │ ├── KWWorkarounds.h │ ├── KWWorkarounds.m │ ├── Kiwi.h │ ├── KiwiBlockMacros.h │ ├── KiwiConfiguration.h │ ├── KiwiMacros.h │ ├── NSInvocation+KiwiAdditions.h │ ├── NSInvocation+KiwiAdditions.m │ ├── NSInvocation+OCMAdditions.h │ ├── NSInvocation+OCMAdditions.m │ ├── NSMethodSignature+KiwiAdditions.h │ ├── NSMethodSignature+KiwiAdditions.m │ ├── NSNumber+KiwiAdditions.h │ ├── NSNumber+KiwiAdditions.m │ ├── NSObject+KiwiSpyAdditions.h │ ├── NSObject+KiwiSpyAdditions.m │ ├── NSObject+KiwiVerifierAdditions.h │ ├── NSObject+KiwiVerifierAdditions.m │ ├── NSProxy+KiwiVerifierAdditions.h │ ├── NSProxy+KiwiVerifierAdditions.m │ ├── NSValue+KiwiAdditions.h │ └── NSValue+KiwiAdditions.m ├── Matchers │ ├── KWBeBetweenMatcher.h │ ├── KWBeBetweenMatcher.m │ ├── KWBeEmptyMatcher.h │ ├── KWBeEmptyMatcher.m │ ├── KWBeIdenticalToMatcher.h │ ├── KWBeIdenticalToMatcher.m │ ├── KWBeKindOfClassMatcher.h │ ├── KWBeKindOfClassMatcher.m │ ├── KWBeMemberOfClassMatcher.h │ ├── KWBeMemberOfClassMatcher.m │ ├── KWBeSubclassOfClassMatcher.h │ ├── KWBeSubclassOfClassMatcher.m │ ├── KWBeTrueMatcher.h │ ├── KWBeTrueMatcher.m │ ├── KWBeWithinMatcher.h │ ├── KWBeWithinMatcher.m │ ├── KWBeZeroMatcher.h │ ├── KWBeZeroMatcher.m │ ├── KWBlockRaiseMatcher.h │ ├── KWBlockRaiseMatcher.m │ ├── KWChangeMatcher.h │ ├── KWChangeMatcher.m │ ├── KWConformToProtocolMatcher.h │ ├── KWConformToProtocolMatcher.m │ ├── KWContainMatcher.h │ ├── KWContainMatcher.m │ ├── KWContainStringMatcher.h │ ├── KWContainStringMatcher.m │ ├── KWEqualMatcher.h │ ├── KWEqualMatcher.m │ ├── KWGenericMatchEvaluator.h │ ├── KWGenericMatchEvaluator.m │ ├── KWGenericMatcher.h │ ├── KWGenericMatcher.m │ ├── KWGenericMatchingAdditions.h │ ├── KWGenericMatchingAdditions.m │ ├── KWHaveMatcher.h │ ├── KWHaveMatcher.m │ ├── KWHaveValueMatcher.h │ ├── KWHaveValueMatcher.m │ ├── KWInequalityMatcher.h │ ├── KWInequalityMatcher.m │ ├── KWNilMatcher.h │ ├── KWNilMatcher.m │ ├── KWNotificationMatcher.h │ ├── KWNotificationMatcher.m │ ├── KWRaiseMatcher.h │ ├── KWRaiseMatcher.m │ ├── KWReceiveMatcher.h │ ├── KWReceiveMatcher.m │ ├── KWRegularExpressionPatternMatcher.h │ ├── KWRegularExpressionPatternMatcher.m │ ├── KWRespondToSelectorMatcher.h │ ├── KWRespondToSelectorMatcher.m │ ├── KWStringContainsMatcher.h │ ├── KWStringContainsMatcher.m │ ├── KWStringPrefixMatcher.h │ ├── KWStringPrefixMatcher.m │ ├── KWUserDefinedMatcher.h │ └── KWUserDefinedMatcher.m ├── Mocking │ ├── KWMock.h │ ├── KWMock.m │ ├── NSObject+KiwiMockAdditions.h │ └── NSObject+KiwiMockAdditions.m ├── Nodes │ ├── KWAfterAllNode.h │ ├── KWAfterAllNode.m │ ├── KWAfterEachNode.h │ ├── KWAfterEachNode.m │ ├── KWBeforeAllNode.h │ ├── KWBeforeAllNode.m │ ├── KWBeforeEachNode.h │ ├── KWBeforeEachNode.m │ ├── KWBlockNode.h │ ├── KWBlockNode.m │ ├── KWContextNode.h │ ├── KWContextNode.m │ ├── KWExampleNode.h │ ├── KWItNode.h │ ├── KWItNode.m │ ├── KWLetNode.h │ ├── KWLetNode.m │ ├── KWPendingNode.h │ ├── KWPendingNode.m │ ├── KWRegisterMatchersNode.h │ └── KWRegisterMatchersNode.m ├── Stubbing │ ├── KWIntercept.h │ ├── KWIntercept.m │ ├── KWStub.h │ ├── KWStub.m │ ├── NSObject+KiwiStubAdditions.h │ └── NSObject+KiwiStubAdditions.m └── Verifiers │ ├── KWAsyncVerifier.h │ ├── KWAsyncVerifier.m │ ├── KWExistVerifier.h │ ├── KWExistVerifier.m │ ├── KWMatchVerifier.h │ ├── KWMatchVerifier.m │ └── KWVerifying.h ├── Kiwi.podspec ├── Kiwi.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── Kiwi-OSX.xcscheme │ ├── Kiwi-XCTest.xcscheme │ ├── Kiwi-iOS.xcscheme │ └── Kiwi.xcscheme ├── KiwiXCTests └── KWXCFunctionalTest.m ├── License.txt ├── Makefile ├── NonARC ├── KWMessagePattern.h └── KWMessagePattern.m ├── Readme.md ├── Release.txt ├── SenTestingKit ├── SenTestSuite+KiwiAdditions.h └── SenTestSuite+KiwiAdditions.m ├── Supporting Files ├── Kiwi-Prefix.pch └── Kiwi-XCTest-Prefix.pch ├── Tests ├── KWBeBetweenMatcherTest.m ├── KWBeEmptyMatcherTest.m ├── KWBeIndenticalToMatcherTest.m ├── KWBeKindOfClassMatcherTest.m ├── KWBeMemberOfClassMatcherTest.m ├── KWBeSubclassOfClassMatcherTest.m ├── KWBeTrueMatcherTest.m ├── KWBeWithinMatcherTest.m ├── KWBeZeroMatcherTest.m ├── KWBlockRaiseMatcherTest.m ├── KWCaptureTest.m ├── KWChangeMatcherTest.m ├── KWConformToProtocolMatcherTest.m ├── KWContainMatcherTest.m ├── KWContainStringMatcherTest.m ├── KWContextNodeTest.m ├── KWDeviceInfoTest.m ├── KWEqualMatcherTest.m ├── KWExampleSuiteBuilderTest.m ├── KWExampleTest.m ├── KWFailureTest.m ├── KWFormatterTest.m ├── KWFunctionalTests.m ├── KWGenericMatcherTest.m ├── KWHaveMatcherTest.m ├── KWHaveValueMatcherTest.m ├── KWInequalityMatcherTest.m ├── KWLetNodeTest.m ├── KWMessagePatternTest.m ├── KWMockTest.m ├── KWNotificationMatcherTest.m ├── KWObjCUtilitiesTest.m ├── KWRaiseMatcherTest.m ├── KWRealObjectSpyTest.m ├── KWRealObjectStubTest.m ├── KWReceiveMatcherTest.m ├── KWRegularExpressionPatternMatcherTest.m ├── KWRespondToSelectorMatcherTest.m ├── KWStringUtilitiesTest.m ├── KWStubTest.m ├── KWUserDefinedMatcherFunctionalTest.m ├── KWUserDefinedMatcherTest.m ├── KWValueTest.m ├── KiwiTestConfiguration.h ├── NSNumber_KiwiAdditionsTests.m └── Test Classes │ ├── Carrier.h │ ├── Carrier.m │ ├── Cruiser.h │ ├── Cruiser.m │ ├── Engine.h │ ├── Engine.m │ ├── Fighter.h │ ├── Fighter.m │ ├── Galaxy.h │ ├── Galaxy.m │ ├── JumpCapable.h │ ├── KiwiAppDelegate.h │ ├── KiwiAppDelegate.m │ ├── KiwiViewController.h │ ├── KiwiViewController.m │ ├── OrbitCapable.h │ ├── Robot.h │ ├── Robot.m │ ├── SpaceShip.h │ ├── SpaceShip.m │ ├── TestClasses.h │ ├── TestReporter.h │ ├── TestReporter.m │ ├── TestSpy.h │ ├── TestSpy.m │ ├── TestVerifier.h │ └── TestVerifier.m └── Xcode Templates ├── Kiwi Spec.xctemplate ├── TemplateInfo.plist └── ___FILEBASENAME___.m ├── install-templates.sh └── uninstall-templates.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .localized 3 | 4 | # Build directory 5 | build/ 6 | 7 | # XCode user specific files 8 | xcuserdata/ 9 | *.xcworkspace/ 10 | *.mode1v3 11 | *.mode2v3 12 | *.perspectivev3 13 | *.pbxuser 14 | output 15 | 16 | # AppCode files 17 | .idea 18 | 19 | # raw logs 20 | xcodebuild.log 21 | xcodebuild_error.log 22 | 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | before_install: 3 | - gem install xcpretty 4 | script: make ci | xcpretty -c && exit ${PIPESTATUS[0]} 5 | 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to Kiwi! 2 | 3 | We're building a BDD library that is exquisitely simple to setup and use, 4 | and we'd love your help! 5 | 6 | ## Reporting Bugs 7 | 8 | Kiwi currently uses two channels for reporting bugs: 9 | 10 | 1. If Kiwi isn't working as you'd expect it to, but you're not sure whether 11 | you're using it correctly, please send a message to the 12 | [Kiwi Google group](https://groups.google.com/forum/#!forum/kiwi-bdd). 13 | 14 | Once your issue has been resolved, please consider contributing to the 15 | [Wiki](https://github.com/allending/Kiwi/wiki) to help people 16 | who might experience similar issues in the future. 17 | 18 | 2. If you're sure that you're using Kiwi correctly, but Kiwi still does not 19 | behave as you'd expect it to, you may have found a bug. If no one 20 | has [already reported the issue](https://github.com/allending/Kiwi/issues?state=open), 21 | please [submit a new issue](https://github.com/allending/Kiwi/issues/new), 22 | and include any and all information maintainers might need to fix the problem. 23 | It's not easy to fix bugs, but detailed reports help! 24 | 25 | ## Pull Requests 26 | 27 | Our work flow is a typical GitHub flow, where contributors fork the 28 | [Kiwi repository](https://github.com/allending/Kiwi), make their changes on branch, 29 | and submit a pull request. 30 | 31 | Please include a description of your changes with your pull request. 32 | All pull requests that involve changes to the source code should include 33 | tests that prove the changes behave as stated in the pull request message. 34 | -------------------------------------------------------------------------------- /Classes/Core/KWAny.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | // KWAny exists to determine arguments in a message pattern that should 10 | // match any value. Used for pointers as well as for scalar values. 11 | @interface KWAny : NSObject 12 | 13 | #pragma mark - Initializing 14 | 15 | + (id)any; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Core/KWAny.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWAny.h" 8 | 9 | @implementation KWAny 10 | 11 | #pragma mark - Initializing 12 | 13 | + (id)any { 14 | static KWAny *sharedAny = nil; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | sharedAny = [self new]; 18 | 19 | }); 20 | return sharedAny; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Core/KWBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface KWBlock : NSObject 10 | 11 | #pragma mark - Initializing 12 | - (id)initWithBlock:(void (^)(void))block; 13 | 14 | + (id)blockWithBlock:(void (^)(void))block; 15 | 16 | #pragma mark - Calling Blocks 17 | 18 | - (void)call; 19 | 20 | @end 21 | 22 | #pragma mark - Creating Blocks 23 | 24 | KWBlock *theBlock(void (^block)(void)); 25 | KWBlock *lambda(void (^block)(void)); 26 | -------------------------------------------------------------------------------- /Classes/Core/KWBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBlock.h" 8 | 9 | @interface KWBlock() 10 | 11 | #pragma mark - Properties 12 | 13 | @property (nonatomic, readonly, copy) void (^block)(void); 14 | 15 | @end 16 | 17 | @implementation KWBlock 18 | 19 | #pragma mark - Initializing 20 | 21 | - (id)initWithBlock:(void (^)(void))block { 22 | self = [super init]; 23 | if (self) { 24 | _block = [block copy]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | + (id)blockWithBlock:(void (^)(void))aBlock { 31 | return [[self alloc] initWithBlock:aBlock]; 32 | } 33 | 34 | #pragma mark - Calling Blocks 35 | 36 | - (void)call { 37 | self.block(); 38 | } 39 | 40 | @end 41 | 42 | #pragma mark - Creating Blocks 43 | 44 | KWBlock *theBlock(void (^block)(void)) { 45 | return lambda(block); 46 | } 47 | 48 | KWBlock *lambda(void (^block)(void)) { 49 | return [KWBlock blockWithBlock:block]; 50 | } 51 | -------------------------------------------------------------------------------- /Classes/Core/KWCallSite.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface KWCallSite : NSObject 10 | 11 | #pragma mark - Initializing 12 | 13 | - (id)initWithFilename:(NSString *)aFilename lineNumber:(NSUInteger)aLineNumber; 14 | 15 | + (id)callSiteWithFilename:(NSString *)aFilename lineNumber:(NSUInteger)aLineNumber; 16 | 17 | #pragma mark - Properties 18 | 19 | @property (nonatomic, readonly, copy) NSString *filename; 20 | @property (nonatomic, readonly) NSUInteger lineNumber; 21 | 22 | #pragma mark - Identifying and Comparing 23 | 24 | - (BOOL)isEqualToCallSite:(KWCallSite *)aCallSite; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Core/KWCallSite.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWCallSite.h" 8 | 9 | @implementation KWCallSite 10 | 11 | #pragma mark - Initializing 12 | 13 | - (id)initWithFilename:(NSString *)aFilename lineNumber:(NSUInteger)aLineNumber { 14 | self = [super init]; 15 | if (self) { 16 | _filename = [aFilename copy]; 17 | _lineNumber = aLineNumber; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | + (id)callSiteWithFilename:(NSString *)aFilename lineNumber:(NSUInteger)aLineNumber { 24 | return [[self alloc] initWithFilename:aFilename lineNumber:aLineNumber]; 25 | } 26 | 27 | #pragma mark - Identifying and Comparing 28 | 29 | - (NSUInteger)hash { 30 | return [[NSString stringWithFormat:@"%@%u", self.filename, (unsigned)self.lineNumber] hash]; 31 | } 32 | 33 | - (BOOL)isEqual:(id)anObject { 34 | if (![anObject isKindOfClass:[KWCallSite class]]) 35 | return NO; 36 | 37 | return [self isEqualToCallSite:anObject]; 38 | } 39 | 40 | - (BOOL)isEqualToCallSite:(KWCallSite *)aCallSite { 41 | return [self.filename isEqualToString:aCallSite.filename] && (self.lineNumber == aCallSite.lineNumber); 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Classes/Core/KWCaptureSpy.h: -------------------------------------------------------------------------------- 1 | #import "KWMessageSpying.h" 2 | 3 | @interface KWCaptureSpy : NSObject 4 | 5 | @property (nonatomic, strong, readonly) id argument; 6 | 7 | - (id)initWithArgumentIndex:(NSUInteger)index; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /Classes/Core/KWCaptureSpy.m: -------------------------------------------------------------------------------- 1 | #import "KWCaptureSpy.h" 2 | 3 | #import "KWObjCUtilities.h" 4 | #import "KWNull.h" 5 | #import "KWValue.h" 6 | #import "NSInvocation+KiwiAdditions.h" 7 | #import "NSMethodSignature+KiwiAdditions.h" 8 | 9 | @interface KWCaptureSpy() 10 | 11 | @property (nonatomic, strong) id argument; 12 | 13 | @end 14 | 15 | @implementation KWCaptureSpy { 16 | NSUInteger _argumentIndex; 17 | } 18 | 19 | - (id)initWithArgumentIndex:(NSUInteger)index { 20 | self = [super init]; 21 | if (self) { 22 | _argumentIndex = index; 23 | } 24 | return self; 25 | } 26 | 27 | - (id)argument { 28 | if (!_argument) { 29 | @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Argument requested has yet to be captured." userInfo:nil]; 30 | } 31 | 32 | if(_argument == [KWNull null]) { 33 | return nil; 34 | } 35 | else { 36 | return _argument; 37 | } 38 | } 39 | 40 | - (void)object:(id)anObject didReceiveInvocation:(NSInvocation *)anInvocation { 41 | if (!_argument) { 42 | NSMethodSignature *signature = [anInvocation methodSignature]; 43 | const char *objCType = [signature messageArgumentTypeAtIndex:_argumentIndex]; 44 | if (KWObjCTypeIsObject(objCType) || KWObjCTypeIsClass(objCType)) { 45 | void* argumentBuffer = NULL; 46 | [anInvocation getMessageArgument:&argumentBuffer atIndex:_argumentIndex]; 47 | id argument = (__bridge id)argumentBuffer; 48 | if (KWObjCTypeIsBlock(objCType)) { 49 | _argument = [argument copy]; 50 | } else { 51 | if(argument == nil) { 52 | _argument = [KWNull null]; 53 | } else { 54 | _argument = argument; 55 | } 56 | } 57 | } else { 58 | NSData *data = [anInvocation messageArgumentDataAtIndex:_argumentIndex]; 59 | _argument = [KWValue valueWithBytes:[data bytes] objCType:objCType]; 60 | } 61 | } 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Classes/Core/KWCountType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | enum { 10 | KWCountTypeExact, 11 | KWCountTypeAtLeast, 12 | KWCountTypeAtMost 13 | }; 14 | 15 | typedef NSUInteger KWCountType; 16 | -------------------------------------------------------------------------------- /Classes/Core/KWDeviceInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface KWDeviceInfo : NSObject 10 | 11 | #pragma mark - Getting the Device Type 12 | 13 | + (BOOL)isSimulator; 14 | + (BOOL)isPhysical; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Core/KWDeviceInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWDeviceInfo.h" 8 | 9 | #if TARGET_IPHONE_SIMULATOR 10 | 11 | #import 12 | 13 | #endif // #if TARGET_IPHONE_SIMULATOR 14 | 15 | @implementation KWDeviceInfo 16 | 17 | #pragma mark - Getting the Device Type 18 | 19 | + (BOOL)isSimulator { 20 | #if TARGET_IPHONE_SIMULATOR 21 | return YES; 22 | #else 23 | return NO; 24 | #endif // #if TARGET_IPHONE_SIMULATOR 25 | } 26 | 27 | + (BOOL)isPhysical { 28 | return ![self isSimulator]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Classes/Core/KWExampleDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWExampleGroupDelegate.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 08/09/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class KWExample; 12 | @class KWFailure; 13 | 14 | @protocol KWExampleDelegate 15 | 16 | - (void)example:(KWExample *)example didFailWithFailure:(KWFailure *)failure; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Core/KWExampleNodeVisitor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @class KWAfterAllNode; 10 | @class KWAfterEachNode; 11 | @class KWBeforeAllNode; 12 | @class KWBeforeEachNode; 13 | @class KWContextNode; 14 | @class KWLetNode; 15 | @class KWItNode; 16 | @class KWPendingNode; 17 | @class KWRegisterMatchersNode; 18 | 19 | @protocol KWExampleNodeVisitor 20 | 21 | #pragma mark - Visiting Nodes 22 | 23 | @optional 24 | 25 | - (void)visitContextNode:(KWContextNode *)aNode; 26 | - (void)visitRegisterMatchersNode:(KWRegisterMatchersNode *)aNode; 27 | - (void)visitBeforeAllNode:(KWBeforeAllNode *)aNode; 28 | - (void)visitAfterAllNode:(KWAfterAllNode *)aNode; 29 | - (void)visitBeforeEachNode:(KWBeforeEachNode *)aNode; 30 | - (void)visitAfterEachNode:(KWAfterEachNode *)aNode; 31 | - (void)visitLetNode:(KWLetNode *)aNode; 32 | - (void)visitItNode:(KWItNode *)aNode; 33 | - (void)visitPendingNode:(KWPendingNode *)aNode; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Classes/Core/KWExampleSuite.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWExampleSuite.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/10/2011. 6 | // Copyright (c) 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWExampleNodeVisitor.h" 11 | 12 | @class KWContextNode; 13 | @class KWExample; 14 | @class SenTestCase; 15 | 16 | @interface KWExampleSuite : NSObject 17 | 18 | - (id)initWithRootNode:(KWContextNode *)contextNode; 19 | - (void)addExample:(KWExample *)example; 20 | - (void)markLastExampleAsLastInContext:(KWContextNode *)context; 21 | - (NSArray *)invocationsForTestCase; 22 | @end 23 | 24 | @interface NSInvocation (KWExampleGroup) 25 | - (void)kw_setExample:(KWExample *)exampleGroup; 26 | - (KWExample *)kw_example; 27 | @end 28 | -------------------------------------------------------------------------------- /Classes/Core/KWExampleSuite.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWExampleSuite.m 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/10/2011. 6 | // Copyright (c) 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWExampleSuite.h" 10 | 11 | #import "KWAfterAllNode.h" 12 | #import "KWBeforeAllNode.h" 13 | #import "KWContextNode.h" 14 | #import "KWExample.h" 15 | #import "KWStringUtilities.h" 16 | #import "NSMethodSignature+KiwiAdditions.h" 17 | #import 18 | 19 | #define kKWINVOCATION_EXAMPLE_GROUP_KEY @"__KWExampleGroupKey" 20 | 21 | @interface KWExampleSuite() 22 | 23 | @property (nonatomic, strong) KWContextNode *rootNode; 24 | @property (nonatomic, strong) NSMutableArray *examples; 25 | 26 | @end 27 | 28 | @implementation KWExampleSuite 29 | 30 | - (id)initWithRootNode:(KWContextNode *)contextNode { 31 | self = [super init]; 32 | if (self) { 33 | _rootNode = contextNode; 34 | _examples = [[NSMutableArray alloc] init]; 35 | } 36 | return self; 37 | } 38 | 39 | 40 | - (void)addExample:(KWExample *)example { 41 | [self.examples addObject:example]; 42 | example.suite = self; 43 | } 44 | 45 | - (void)markLastExampleAsLastInContext:(KWContextNode *)context 46 | { 47 | if ([self.examples count] > 0) { 48 | KWExample *lastExample = (KWExample *)[self.examples lastObject]; 49 | [lastExample.lastInContexts addObject:context]; 50 | } 51 | } 52 | 53 | - (NSArray *)invocationsForTestCase { 54 | NSMutableArray *invocations = [NSMutableArray array]; 55 | 56 | // Add a single dummy invocation for each example group 57 | 58 | for (KWExample *exampleGroup in self.examples) { 59 | NSMethodSignature *methodSignature = [NSMethodSignature signatureWithObjCTypes:[KWEncodingForDefaultMethod() UTF8String]]; 60 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; 61 | [invocations addObject:invocation]; 62 | [invocation kw_setExample:exampleGroup]; 63 | } 64 | 65 | return invocations; 66 | } 67 | 68 | @end 69 | 70 | #pragma mark - 71 | 72 | // because SenTest will modify the invocation target, we'll have to store 73 | // another reference to the example group so we can retrieve it later 74 | 75 | @implementation NSInvocation (KWExampleGroup) 76 | 77 | - (void)kw_setExample:(KWExample *)exampleGroup { 78 | objc_setAssociatedObject(self, kKWINVOCATION_EXAMPLE_GROUP_KEY, exampleGroup, OBJC_ASSOCIATION_RETAIN); 79 | } 80 | 81 | - (KWExample *)kw_example { 82 | return objc_getAssociatedObject(self, kKWINVOCATION_EXAMPLE_GROUP_KEY); 83 | } 84 | 85 | @end 86 | 87 | -------------------------------------------------------------------------------- /Classes/Core/KWExampleSuiteBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWBlock.h" 9 | 10 | @class KWCallSite; 11 | @class KWExample; 12 | @class KWExampleSuite; 13 | @class KWContextNode; 14 | 15 | @interface KWExampleSuiteBuilder : NSObject 16 | 17 | #pragma mark - Initializing 18 | 19 | + (id)sharedExampleSuiteBuilder; 20 | 21 | #pragma mark - Building Example Groups 22 | 23 | @property (nonatomic, readonly) BOOL isBuildingExampleSuite; 24 | @property (nonatomic, strong, readonly) KWExampleSuite *currentExampleSuite; 25 | @property (nonatomic, strong) KWExample *currentExample; 26 | @property (nonatomic, strong) KWCallSite *focusedCallSite; 27 | 28 | //spec file name:line number of callsite 29 | - (void)focusWithURI:(NSString *)nodeUrl; 30 | - (KWExampleSuite *)buildExampleSuite:(void (^)(void))buildingBlock; 31 | 32 | - (void)pushContextNodeWithCallSite:(KWCallSite *)aCallSite description:(NSString *)aDescription; 33 | - (void)popContextNode; 34 | - (void)setRegisterMatchersNodeWithCallSite:(KWCallSite *)aCallSite namespacePrefix:(NSString *)aNamespacePrefix; 35 | - (void)setBeforeAllNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 36 | - (void)setAfterAllNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 37 | - (void)setBeforeEachNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 38 | - (void)setAfterEachNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 39 | - (void)addLetNodeWithCallSite:(KWCallSite *)aCallSite objectRef:(id *)anObjectRef symbolName:(NSString *)aSymbolName block:(id (^)(void))block; 40 | - (void)addItNodeWithCallSite:(KWCallSite *)aCallSite description:(NSString *)aDescription block:(void (^)(void))block; 41 | - (void)addPendingNodeWithCallSite:(KWCallSite *)aCallSite description:(NSString *)aDescription; 42 | 43 | - (BOOL)isFocused; 44 | - (BOOL)foundFocus; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Classes/Core/KWExpectationType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | enum { 10 | KWExpectationTypeShould, 11 | KWExpectationTypeShouldNot, 12 | KWExpectationTypeMaybe 13 | }; 14 | 15 | typedef NSUInteger KWExpectationType; 16 | -------------------------------------------------------------------------------- /Classes/Core/KWFailure.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @class KWCallSite; 10 | 11 | @interface KWFailure : NSObject 12 | 13 | #pragma mark - Initializing 14 | 15 | - (id)initWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage; 16 | - (id)initWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ...; 17 | 18 | + (id)failureWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage; 19 | + (id)failureWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ...; 20 | 21 | #pragma mark - Properties 22 | 23 | @property (nonatomic, readonly) NSString *message; 24 | @property (nonatomic, weak, readonly) KWCallSite *callSite; 25 | 26 | #pragma mark - Getting Exception Representations 27 | 28 | - (NSException *)exceptionValue; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Classes/Core/KWFailure.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWFailure.h" 8 | #import 9 | #import "KWCallSite.h" 10 | 11 | @implementation KWFailure 12 | 13 | #pragma mark - Initializing 14 | 15 | - (id)initWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage { 16 | self = [super init]; 17 | if (self) { 18 | _callSite = aCallSite; 19 | _message = [aMessage copy]; 20 | } 21 | 22 | return self; 23 | } 24 | 25 | - (id)initWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ... { 26 | va_list argumentList; 27 | va_start(argumentList, format); 28 | NSString *aMessage = [[NSString alloc] initWithFormat:format arguments:argumentList]; 29 | return [self initWithCallSite:aCallSite message:aMessage]; 30 | } 31 | 32 | + (id)failureWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage { 33 | return [[self alloc] initWithCallSite:aCallSite message:aMessage]; 34 | } 35 | 36 | + (id)failureWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ... { 37 | va_list argumentList; 38 | va_start(argumentList, format); 39 | NSString *message = [[NSString alloc] initWithFormat:format arguments:argumentList]; 40 | return [self failureWithCallSite:aCallSite message:message]; 41 | } 42 | 43 | #pragma mark - Getting Exception Representations 44 | 45 | - (NSException *)exceptionValue { 46 | NSDictionary *userInfo = nil; 47 | if (self.callSite) { 48 | NSNumber *lineNumber = @(self.callSite.lineNumber); 49 | userInfo = @{ 50 | @"SenTestFilenameKey": self.callSite.filename, 51 | @"SenTestLineNumberKey": lineNumber 52 | }; 53 | } 54 | return [NSException exceptionWithName:@"KWFailureException" reason:self.message userInfo:userInfo]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Classes/Core/KWFormatter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface KWFormatter : NSObject 10 | 11 | #pragma mark - Getting Descriptions 12 | 13 | + (NSString *)formatObject:(id)anObject; 14 | + (NSString *)formatObjectIncludingClass:(id)anObject; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Core/KWFormatter.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWFormatter.h" 8 | 9 | @implementation KWFormatter 10 | 11 | 12 | #pragma mark - Getting Descriptions 13 | 14 | + (NSString *)formatObject:(id)anObject { 15 | if ([anObject isKindOfClass:[NSString class]]) 16 | return [NSString stringWithFormat:@"\"%@\"", anObject]; 17 | 18 | else if ([anObject isKindOfClass:[NSDictionary class]]) 19 | return [anObject description]; // NSDictionary conforms to NSFastEnumeration 20 | 21 | else if ([anObject conformsToProtocol:@protocol(NSFastEnumeration)]) 22 | return [self formattedCollection:anObject]; 23 | 24 | return [anObject description]; 25 | } 26 | 27 | + (NSString *)formatObjectIncludingClass:(id)anObject { 28 | NSString *classString = [[anObject class] description]; 29 | 30 | if ([anObject isKindOfClass:[NSString class]]) 31 | classString = @"NSString"; 32 | 33 | return [NSString stringWithFormat:@"(%@) %@", classString, [self formatObject:anObject]]; 34 | } 35 | 36 | 37 | #pragma mark - Private 38 | 39 | + (NSString *)formattedCollection:(id)collection { 40 | 41 | NSMutableString *description = [[NSMutableString alloc] initWithString:@"("]; 42 | NSUInteger index = 0; 43 | 44 | for (id object in collection) { 45 | if (index == 0) 46 | [description appendFormat:@"%@", [self formatObject:object]]; 47 | else 48 | [description appendFormat:@", %@", [self formatObject:object]]; 49 | 50 | ++index; 51 | } 52 | 53 | [description appendString:@")"]; 54 | return description; 55 | } 56 | 57 | 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Classes/Core/KWFutureObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWFutureObject.h 3 | // iOSFalconCore 4 | // 5 | // Created by Luke Redpath on 13/01/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef id (^KWFutureObjectBlock)(void); 12 | 13 | @interface KWFutureObject : NSObject 14 | 15 | + (id)objectWithObjectPointer:(id *)pointer; 16 | + (id)futureObjectWithBlock:(KWFutureObjectBlock)block; 17 | - (id)initWithBlock:(KWFutureObjectBlock)aBlock; 18 | - (id)object; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Core/KWFutureObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWFutureObject.m 3 | // iOSFalconCore 4 | // 5 | // Created by Luke Redpath on 13/01/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "KWFutureObject.h" 10 | 11 | @interface KWFutureObject() 12 | 13 | @property (nonatomic, strong) KWFutureObjectBlock block; 14 | 15 | @end 16 | 17 | @implementation KWFutureObject 18 | 19 | + (id)objectWithObjectPointer:(id *)pointer { 20 | return [self futureObjectWithBlock:^{ return *pointer; }]; 21 | } 22 | 23 | + (id)futureObjectWithBlock:(KWFutureObjectBlock)block { 24 | return [[self alloc] initWithBlock:block]; 25 | } 26 | 27 | - (id)initWithBlock:(KWFutureObjectBlock)aBlock { 28 | self = [super init]; 29 | if (self) { 30 | _block = [aBlock copy]; 31 | } 32 | return self; 33 | } 34 | 35 | - (id)object; { 36 | return self.block(); 37 | } 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Classes/Core/KWInvocationCapturer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @protocol KWInvocationCapturerDelegate; 10 | 11 | @interface KWInvocationCapturer : NSProxy 12 | 13 | #pragma mark - Initializing 14 | 15 | - (id)initWithDelegate:(id)aDelegate; 16 | - (id)initWithDelegate:(id)aDelegate userInfo:(NSDictionary *)aUserInfo; 17 | 18 | + (id)invocationCapturerWithDelegate:(id)aDelegate; 19 | + (id)invocationCapturerWithDelegate:(id)aDelegate userInfo:(NSDictionary *)aUserInfo; 20 | 21 | #pragma mark - Properties 22 | 23 | @property (nonatomic, weak, readonly) id delegate; 24 | @property (nonatomic, strong, readonly) NSDictionary *userInfo; 25 | 26 | @end 27 | 28 | @protocol KWInvocationCapturerDelegate 29 | 30 | #pragma mark - Capturing Invocations 31 | 32 | - (NSMethodSignature *)invocationCapturer:(KWInvocationCapturer *)anInvocationCapturer methodSignatureForSelector:(SEL)aSelector; 33 | - (void)invocationCapturer:(KWInvocationCapturer *)anInvocationCapturer didCaptureInvocation:(NSInvocation *)anInvocation; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Classes/Core/KWLet.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #if __has_feature(objc_arr) 8 | # define KW_ARC_AUTORELEASE(obj) obj 9 | #else 10 | # define KW_ARC_AUTORELEASE(obj) [obj autorelease] 11 | #endif 12 | 13 | #define KW_LET_REF(var) \ 14 | (__autoreleasing id *) \ 15 | ( (void *(^)(void)) KW_ARC_AUTORELEASE([^{ void *ref = &var; return ref; } copy]) )() 16 | -------------------------------------------------------------------------------- /Classes/Core/KWMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatching.h" 9 | 10 | @interface KWMatcher : NSObject 11 | 12 | #pragma mark - Initializing 13 | 14 | - (id)initWithSubject:(id)anObject; 15 | 16 | + (id)matcherWithSubject:(id)anObject; 17 | 18 | #pragma mark - Properties 19 | 20 | @property (nonatomic, strong) id subject; 21 | 22 | #pragma mark - Getting Matcher Strings 23 | 24 | + (NSArray *)matcherStrings; 25 | 26 | #pragma mark - Getting Matcher Compatability 27 | 28 | + (BOOL)canMatchSubject:(id)anObject; 29 | 30 | #pragma mark - Matching 31 | 32 | - (BOOL)evaluate; 33 | 34 | #pragma mark - Getting Failure Messages 35 | 36 | - (NSString *)failureMessageForShould; 37 | - (NSString *)failureMessageForShouldNot; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/Core/KWMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWMatcher.h" 8 | #import "KWFormatter.h" 9 | #import "KWFutureObject.h" 10 | 11 | @implementation KWMatcher 12 | 13 | #pragma mark - Initializing 14 | 15 | - (id)initWithSubject:(id)anObject { 16 | self = [super init]; 17 | if (self) { 18 | _subject = anObject; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | + (id)matcherWithSubject:(id)anObject { 25 | return [[self alloc] initWithSubject:anObject]; 26 | } 27 | 28 | 29 | #pragma mark - Properties 30 | 31 | - (id)subject 32 | { 33 | if ([_subject isKindOfClass:[KWFutureObject class]]) { 34 | return [(KWFutureObject *)_subject object]; 35 | } 36 | return _subject; 37 | } 38 | 39 | #pragma mark - Getting Matcher Strings 40 | 41 | + (NSArray *)matcherStrings { 42 | return nil; 43 | } 44 | 45 | #pragma mark - Getting Matcher Compatability 46 | 47 | + (BOOL)canMatchSubject:(id)anObject { 48 | return YES; 49 | } 50 | 51 | #pragma mark - Matching 52 | 53 | - (BOOL)evaluate { 54 | [NSException raise:NSInternalInconsistencyException format:@"%@ must override -evaluate", 55 | [KWFormatter formatObject:[self class]]]; 56 | return NO; 57 | } 58 | 59 | #pragma mark - Getting Failure Messages 60 | 61 | - (NSString *)failureMessageForShould { 62 | return @"subject did not meet expectation"; 63 | } 64 | 65 | - (NSString *)failureMessageForShouldNot { 66 | NSString *failureMessageForShould = [self failureMessageForShould]; 67 | NSRange markerRange = [failureMessageForShould rangeOfString:@" to "]; 68 | 69 | if (markerRange.location == NSNotFound) 70 | return @"subject did not meet expectation"; 71 | 72 | NSRange replacementRange = NSMakeRange(0, markerRange.location + markerRange.length); 73 | NSString *message = [failureMessageForShould stringByReplacingOccurrencesOfString:@" to " 74 | withString:@" not to " 75 | options:0 76 | range:replacementRange]; 77 | return message; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /Classes/Core/KWMatcherFactory.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatching.h" 9 | 10 | @class KWFailure; 11 | @class KWMatcher; 12 | @class KWUserDefinedMatcherBuilder; 13 | 14 | @interface KWMatcherFactory : NSObject 15 | 16 | #pragma mark - Initializing 17 | 18 | - (id)init; 19 | 20 | #pragma mark - Properties 21 | 22 | @property (nonatomic, readonly) NSArray *registeredMatcherClasses; 23 | 24 | #pragma mark - Registering Matcher Classes 25 | 26 | - (void)registerMatcherClass:(Class)aClass; 27 | - (void)registerMatcherClassesWithNamespacePrefix:(NSString *)aNamespacePrefix; 28 | 29 | #pragma mark - Getting Method Signatures 30 | 31 | - (NSMethodSignature *)methodSignatureForMatcherSelector:(SEL)aSelector; 32 | 33 | #pragma mark - Getting Matchers 34 | 35 | - (KWMatcher *)matcherFromInvocation:(NSInvocation *)anInvocation subject:(id)subject; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Classes/Core/KWMatchers.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWMatchers.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/06/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class KWUserDefinedMatcherBuilder; 12 | 13 | typedef void (^KWMatchersBuildingBlock)(KWUserDefinedMatcherBuilder *matcherBuilder); 14 | 15 | @class KWUserDefinedMatcher; 16 | 17 | @interface KWMatchers : NSObject 18 | 19 | + (id)matchers; 20 | 21 | #pragma mark - Defining Matchers 22 | 23 | + (void)defineMatcher:(NSString *)selectorString as:(KWMatchersBuildingBlock)block; 24 | - (void)defineMatcher:(NSString *)selectorString as:(KWMatchersBuildingBlock)block; 25 | - (void)addUserDefinedMatcherBuilder:(KWUserDefinedMatcherBuilder *)builder; 26 | 27 | #pragma mark - Building Matchers 28 | 29 | - (KWUserDefinedMatcher *)matcherForSelector:(SEL)selector subject:(id)subject; 30 | @end 31 | 32 | void KWDefineMatchers(NSString *selectorString, KWMatchersBuildingBlock block); 33 | -------------------------------------------------------------------------------- /Classes/Core/KWMatchers.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWMatchers.m 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/06/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWMatchers.h" 10 | #import "KWUserDefinedMatcher.h" 11 | 12 | @interface KWMatchers() { 13 | NSMutableDictionary *userDefinedMatchers; 14 | } 15 | @end 16 | 17 | @implementation KWMatchers 18 | 19 | #pragma mark - Singleton implementation 20 | 21 | static id sharedMatchers = nil; 22 | 23 | + (void)initialize { 24 | if (self == [KWMatchers class]) { 25 | sharedMatchers = [[self alloc] init]; 26 | } 27 | } 28 | 29 | + (id)matchers { 30 | return sharedMatchers; 31 | } 32 | 33 | - (id)init { 34 | self = [super init]; 35 | if (self) { 36 | userDefinedMatchers = [[NSMutableDictionary alloc] init]; 37 | } 38 | return self; 39 | } 40 | 41 | #pragma mark - Defining Matchers 42 | 43 | + (void)defineMatcher:(NSString *)selectorString as:(KWMatchersBuildingBlock)block { 44 | [[self matchers] defineMatcher:selectorString as:block]; 45 | } 46 | 47 | - (void)defineMatcher:(NSString *)selectorString as:(KWMatchersBuildingBlock)block { 48 | KWUserDefinedMatcherBuilder *builder = [KWUserDefinedMatcherBuilder builderForSelector:NSSelectorFromString(selectorString)]; 49 | block(builder); 50 | userDefinedMatchers[builder.key] = builder; 51 | } 52 | 53 | - (void)addUserDefinedMatcherBuilder:(KWUserDefinedMatcherBuilder *)builder { 54 | userDefinedMatchers[builder.key] = builder; 55 | } 56 | 57 | #pragma mark - Building Matchers 58 | 59 | - (KWUserDefinedMatcher *)matcherForSelector:(SEL)selector subject:(id)subject { 60 | KWUserDefinedMatcherBuilder *builder = userDefinedMatchers[NSStringFromSelector(selector)]; 61 | 62 | if (builder == nil) 63 | return nil; 64 | 65 | return [builder buildMatcherWithSubject:subject]; 66 | } 67 | 68 | 69 | @end 70 | 71 | void KWDefineMatchers(NSString *selectorString, KWMatchersBuildingBlock block) 72 | { 73 | [KWMatchers defineMatcher:selectorString as:block]; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Classes/Core/KWMatching.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @protocol KWMatching 10 | 11 | #pragma mark - Initializing 12 | 13 | - (id)initWithSubject:(id)anObject; 14 | 15 | #pragma mark - Getting Matcher Strings 16 | 17 | + (NSArray *)matcherStrings; 18 | 19 | #pragma mark - Getting Matcher Compatability 20 | 21 | + (BOOL)canMatchSubject:(id)anObject; 22 | 23 | #pragma mark - Matching 24 | 25 | @optional 26 | 27 | - (BOOL)isNilMatcher; 28 | - (BOOL)shouldBeEvaluatedAtEndOfExample; 29 | - (BOOL)willEvaluateMultipleTimes; 30 | - (void)setWillEvaluateMultipleTimes:(BOOL)shouldEvaluateMultipleTimes; 31 | - (void)setWillEvaluateAgainstNegativeExpectation:(BOOL)willEvaluateAgainstNegativeExpectation; 32 | 33 | @required 34 | 35 | - (BOOL)evaluate; 36 | 37 | #pragma mark - Getting Failure Messages 38 | 39 | - (NSString *)failureMessageForShould; 40 | - (NSString *)failureMessageForShouldNot; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Classes/Core/KWMessageSpying.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @protocol KWMessageSpying 10 | 11 | #pragma mark - Spying on Messages 12 | 13 | - (void)object:(id)anObject didReceiveInvocation:(NSInvocation *)anInvocation; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Core/KWMessageTracker.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWCountType.h" 9 | #import "KWMessageSpying.h" 10 | 11 | @class KWMessagePattern; 12 | 13 | @interface KWMessageTracker : NSObject 14 | 15 | #pragma mark - Initializing 16 | 17 | - (id)initWithSubject:(id)anObject messagePattern:(KWMessagePattern *)aMessagePattern countType:(KWCountType)aCountType count:(NSUInteger)aCount; 18 | 19 | + (id)messageTrackerWithSubject:(id)anObject messagePattern:(KWMessagePattern *)aMessagePattern countType:(KWCountType)aCountType count:(NSUInteger)aCount; 20 | 21 | #pragma mark - Properties 22 | 23 | @property (nonatomic, readonly) id subject; 24 | @property (nonatomic, readonly) KWMessagePattern *messagePattern; 25 | @property (nonatomic, readonly) KWCountType countType; 26 | @property (nonatomic, readonly) NSUInteger count; 27 | 28 | #pragma mark - Stopping Tracking 29 | 30 | - (void)stopTracking; 31 | 32 | #pragma mark - Getting Message Tracker Status 33 | 34 | - (BOOL)succeeded; 35 | 36 | #pragma mark - Getting Phrases 37 | 38 | - (NSString *)expectedCountPhrase; 39 | - (NSString *)receivedCountPhrase; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Classes/Core/KWNull.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | // KWNull exists to represent the same thing as NSNull, except that Kiwi needs 10 | // to distinguish between null singletons used internally and those a user 11 | // is using as an object parameter. 12 | @interface KWNull : NSObject 13 | 14 | #pragma mark - Initializing 15 | 16 | + (id)null; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Core/KWNull.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWNull.h" 8 | 9 | @implementation KWNull 10 | 11 | #pragma mark - Initializing 12 | 13 | 14 | + (id)null { 15 | static KWNull *sharedNull = nil; 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | sharedNull = [self new]; 19 | 20 | }); 21 | 22 | return sharedNull; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/Core/KWObjCUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | #pragma mark - Objective-C Type Utilities 10 | 11 | BOOL KWObjCTypeEqualToObjCType(const char *firstObjCType, const char *secondObjCType); 12 | BOOL KWObjCTypeIsNumeric(const char *objCType); 13 | BOOL KWObjCTypeIsFloatingPoint(const char *objCType); 14 | BOOL KWObjCTypeIsIntegral(const char *objCType); 15 | BOOL KWObjCTypeIsSignedIntegral(const char *objCType); 16 | BOOL KWObjCTypeIsUnsignedIntegral(const char *objCType); 17 | BOOL KWObjCTypeIsBoolean(const char *objCType); 18 | BOOL KWObjCTypeIsObject(const char *objCType); 19 | BOOL KWObjCTypeIsCharString(const char *objCType); 20 | BOOL KWObjCTypeIsClass(const char *objCType); 21 | BOOL KWObjCTypeIsSelector(const char *objCType); 22 | BOOL KWObjCTypeIsPointerToType(const char *objCType); 23 | BOOL KWObjCTypeIsPointerLike(const char *objCType); 24 | BOOL KWObjCTypeIsUnknown(const char *objCType); 25 | BOOL KWObjCTypeIsBlock(const char *objCType); 26 | 27 | NSUInteger KWObjCTypeLength(const char *objCType); 28 | 29 | #pragma mark - Selector Utlities 30 | 31 | NSUInteger KWSelectorParameterCount(SEL selector); 32 | -------------------------------------------------------------------------------- /Classes/Core/KWProbe.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWProbe.h 3 | // iOSFalconCore 4 | // 5 | // Created by Luke Redpath on 13/01/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol KWProbe 12 | - (BOOL)isSatisfied; 13 | - (void)sample; 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/Core/KWProbePoller.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWProbePoller.h 3 | // iOSFalconCore 4 | // 5 | // Created by Luke Redpath on 13/01/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWProbe.h" 11 | 12 | #define kKW_DEFAULT_PROBE_DELAY 0.1 13 | 14 | @interface KWProbePoller : NSObject 15 | 16 | - (id)initWithTimeout:(NSTimeInterval)theTimeout delay:(NSTimeInterval)theDelay shouldWait:(BOOL)wait; 17 | - (BOOL)check:(id)probe; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Core/KWProbePoller.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWProbePoller.m 3 | // iOSFalconCore 4 | // 5 | // Created by Luke Redpath on 13/01/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "KWProbePoller.h" 10 | 11 | @interface KWTimeout : NSObject 12 | 13 | @property (nonatomic) CFTimeInterval timeoutDateStamp; 14 | 15 | @end 16 | 17 | @implementation KWTimeout 18 | 19 | - (id)initWithTimeout:(NSTimeInterval)timeout 20 | { 21 | self = [super init]; 22 | if (self) { 23 | _timeoutDateStamp = CFAbsoluteTimeGetCurrent() + timeout; 24 | } 25 | return self; 26 | } 27 | 28 | 29 | - (BOOL)hasTimedOut { 30 | return (_timeoutDateStamp - CFAbsoluteTimeGetCurrent()) < 0; 31 | } 32 | 33 | @end 34 | 35 | 36 | @interface KWProbePoller() 37 | 38 | @property (nonatomic, assign) NSTimeInterval timeoutInterval; 39 | @property (nonatomic, assign) NSTimeInterval delayInterval; 40 | @property (nonatomic, assign) BOOL shouldWait; 41 | 42 | @end 43 | 44 | @implementation KWProbePoller 45 | 46 | - (id)initWithTimeout:(NSTimeInterval)theTimeout 47 | delay:(NSTimeInterval)theDelay 48 | shouldWait:(BOOL)wait { 49 | self = [super init]; 50 | if (self) { 51 | _timeoutInterval = theTimeout; 52 | _delayInterval = theDelay; 53 | _shouldWait = wait; 54 | } 55 | return self; 56 | } 57 | 58 | - (BOOL)check:(id)probe; { 59 | KWTimeout *timeout = [[KWTimeout alloc] initWithTimeout:self.timeoutInterval]; 60 | 61 | while (self.shouldWait || ![probe isSatisfied]) { 62 | if ([timeout hasTimedOut]) { 63 | return [probe isSatisfied]; 64 | } 65 | CFRunLoopRunInMode(kCFRunLoopDefaultMode, _delayInterval, false); 66 | [probe sample]; 67 | } 68 | 69 | return YES; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /Classes/Core/KWReporting.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @class KWFailure; 10 | 11 | @protocol KWReporting 12 | 13 | #pragma mark - Reporting Failures 14 | 15 | - (void)reportFailure:(KWFailure *)failure; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Core/KWSpec.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import 9 | #import "KWExpectationType.h" 10 | #import "KWVerifying.h" 11 | #import "KWExampleDelegate.h" 12 | 13 | 14 | @class KWCallSite; 15 | 16 | #ifdef XCT_EXPORT 17 | @interface KWSpec : XCTestCase 18 | #else 19 | @interface KWSpec : SenTestCase 20 | #endif 21 | 22 | #pragma mark - Adding Verifiers 23 | 24 | + (id)addVerifier:(id)aVerifier; 25 | + (id)addExistVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite; 26 | + (id)addMatchVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite; 27 | + (id)addAsyncVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite timeout:(NSTimeInterval)timeout shouldWait:(BOOL)shouldWait; 28 | 29 | #pragma mark - Building Example Groups 30 | 31 | + (NSString *)file; 32 | + (void)buildExampleGroups; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Core/KWStringUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | #pragma mark - Checking for Case Separated Words 10 | 11 | BOOL KWStringHasWordPrefix(NSString *string, NSString *prefix); 12 | BOOL KWStringHasStrictWordPrefix(NSString *string, NSString *prefix); 13 | BOOL KWStringHasWord(NSString *string, NSString *word); 14 | 15 | #pragma mark - Getting Type Encodings 16 | 17 | NSString *KWEncodingWithObjCTypes(const char *firstType, ...) NS_REQUIRES_NIL_TERMINATION; 18 | NSString *KWEncodingForVoidMethod(void); 19 | NSString *KWEncodingForDefaultMethod(void); 20 | -------------------------------------------------------------------------------- /Classes/Core/KWSymbolicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWSymbolicator.h 3 | // Kiwi 4 | // 5 | // Created by Jerry Marino on 4/28/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | long kwCallerAddress(void); 12 | 13 | @interface NSString (KWShellCommand) 14 | 15 | + (NSString *)stringWithShellCommand:(NSString *)command arguments:(NSArray *)arguments; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Core/KWSymbolicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWSymbolicator.m 3 | // Kiwi 4 | // 5 | // Created by Jerry Marino on 4/28/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWSymbolicator.h" 10 | #import 11 | #import 12 | 13 | long kwCallerAddress (void){ 14 | #if !__arm__ 15 | unw_cursor_t cursor; unw_context_t uc; 16 | unw_word_t ip; 17 | 18 | unw_getcontext(&uc); 19 | unw_init_local(&cursor, &uc); 20 | 21 | int pos = 2; 22 | while (unw_step(&cursor) && pos--){ 23 | unw_get_reg (&cursor, UNW_REG_IP, &ip); 24 | if(pos == 0) return (NSUInteger)(ip - 4); 25 | } 26 | #endif 27 | return 0; 28 | } 29 | 30 | // Used to suppress compiler warnings by 31 | // casting receivers to this protocol 32 | @protocol NSTask_KWWarningSuppressor 33 | 34 | - (void)setLaunchPath:(NSString *)path; 35 | - (void)setArguments:(NSArray *)arguments; 36 | - (void)setEnvironment:(NSDictionary *)dict; 37 | - (void)setStandardOutput:(id)output; 38 | - (void)launch; 39 | - (void)waitUntilExit; 40 | 41 | @end 42 | 43 | @implementation NSString (KWShellCommand) 44 | 45 | + (NSString *)stringWithShellCommand:(NSString *)command arguments:(NSArray *)arguments { 46 | id task = [[NSClassFromString(@"NSTask") alloc] init]; 47 | [task setEnvironment:[NSDictionary dictionary]]; 48 | [task setLaunchPath:command]; 49 | [task setArguments:arguments]; 50 | 51 | NSPipe *pipe = [NSPipe pipe]; 52 | [task setStandardOutput:pipe]; 53 | [task launch]; 54 | 55 | [task waitUntilExit]; 56 | 57 | NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile]; 58 | NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 59 | return string; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Classes/Core/KWWorkarounds.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG 10 | 11 | #pragma mark - Invocation Exception Bug Workaround 12 | 13 | // See KiwiConfiguration.h for notes. 14 | void KWSetExceptionFromAcrossInvocationBoundary(NSException *anException); 15 | NSException *KWGetAndClearExceptionFromAcrossInvocationBoundary(void); 16 | 17 | #endif // #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG 18 | -------------------------------------------------------------------------------- /Classes/Core/KWWorkarounds.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWWorkarounds.h" 8 | 9 | #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG 10 | 11 | static NSException *KWExceptionAcrossInvokeBoundary = nil; 12 | 13 | void KWSetExceptionFromAcrossInvocationBoundary(NSException *anException) { 14 | if (KWExceptionAcrossInvokeBoundary != nil) 15 | return; 16 | 17 | KWExceptionAcrossInvokeBoundary = anException; 18 | } 19 | 20 | NSException *KWGetAndClearExceptionFromAcrossInvocationBoundary(void) { 21 | NSException *exception = KWExceptionAcrossInvokeBoundary; 22 | KWExceptionAcrossInvokeBoundary = nil; 23 | return exception; 24 | } 25 | 26 | #endif // #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG 27 | -------------------------------------------------------------------------------- /Classes/Core/KiwiBlockMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // KiwiBlockMacros.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 11/07/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | // user defined matchers 10 | #define registerMatcher(name) \ 11 | \ 12 | @interface NSObject (KWUserDefinedMatchersDefinitions) \ 13 | - (void)name; \ 14 | @end \ 15 | 16 | #define defineMatcher(...) KWDefineMatchers(__VA_ARGS__) 17 | -------------------------------------------------------------------------------- /Classes/Core/KiwiConfiguration.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | // As of iPhone SDK 4 GM, exceptions thrown across an NSInvocation -invoke or 8 | // forwardInvocation: boundary in the simulator will terminate the app instead 9 | // of being caught in @catch blocks from the caller side of the -invoke. Kiwi 10 | // tries to handle this by storing the first exception that it would have 11 | // otherwise thrown in a nasty global that callers can look for and handle. 12 | // (Buggy termination is less desirable than global variables). 13 | // 14 | // Obviously, this can only handles cases where Kiwi itself would have raised 15 | // an exception. 16 | #if TARGET_IPHONE_SIMULATOR 17 | #define KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG 1 18 | #endif 19 | -------------------------------------------------------------------------------- /Classes/Core/NSInvocation+KiwiAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface NSInvocation(KiwiAdditions) 10 | 11 | #pragma mark - Creating NSInvocation Objects 12 | 13 | + (NSInvocation *)invocationWithTarget:(id)anObject selector:(SEL)aSelector; 14 | + (NSInvocation *)invocationWithTarget:(id)anObject selector:(SEL)aSelector messageArguments:(const void *)firstBytes, ...; 15 | 16 | #pragma mark - Accessing Message Arguments 17 | 18 | // Message arguments are invocation arguments that begin after the target and selector arguments. These methods provide 19 | // convenient ways to access them. 20 | 21 | - (NSData *)messageArgumentDataAtIndex:(NSUInteger)anIndex; 22 | - (void)getMessageArgument:(void *)buffer atIndex:(NSUInteger)anIndex; 23 | - (void)setMessageArgument:(const void *)bytes atIndex:(NSUInteger)anIndex; 24 | - (void)setMessageArguments:(const void *)firstBytes, ...; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Core/NSInvocation+OCMAdditions.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // $Id$ 3 | // Copyright (c) 2006-2009 by Mulle Kybernetik. See License file for details. 4 | //--------------------------------------------------------------------------------------- 5 | 6 | #import 7 | 8 | @interface NSInvocation(OCMAdditions) 9 | 10 | - (id)getArgumentAtIndexAsObject:(int)argIndex; 11 | 12 | - (NSString *)invocationDescription; 13 | 14 | - (NSString *)argumentDescriptionAtIndex:(int)argIndex; 15 | 16 | - (NSString *)objectDescriptionAtIndex:(int)anInt; 17 | - (NSString *)charDescriptionAtIndex:(int)anInt; 18 | - (NSString *)unsignedCharDescriptionAtIndex:(int)anInt; 19 | - (NSString *)intDescriptionAtIndex:(int)anInt; 20 | - (NSString *)unsignedIntDescriptionAtIndex:(int)anInt; 21 | - (NSString *)shortDescriptionAtIndex:(int)anInt; 22 | - (NSString *)unsignedShortDescriptionAtIndex:(int)anInt; 23 | - (NSString *)longDescriptionAtIndex:(int)anInt; 24 | - (NSString *)unsignedLongDescriptionAtIndex:(int)anInt; 25 | - (NSString *)longLongDescriptionAtIndex:(int)anInt; 26 | - (NSString *)unsignedLongLongDescriptionAtIndex:(int)anInt; 27 | - (NSString *)doubleDescriptionAtIndex:(int)anInt; 28 | - (NSString *)floatDescriptionAtIndex:(int)anInt; 29 | - (NSString *)structDescriptionAtIndex:(int)anInt; 30 | - (NSString *)pointerDescriptionAtIndex:(int)anInt; 31 | - (NSString *)cStringDescriptionAtIndex:(int)anInt; 32 | - (NSString *)selectorDescriptionAtIndex:(int)anInt; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Core/NSMethodSignature+KiwiAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface NSMethodSignature(KiwiAdditions) 10 | 11 | #pragma mark - Getting Information on Message Arguments 12 | 13 | - (NSUInteger)numberOfMessageArguments; 14 | - (const char *)messageArgumentTypeAtIndex:(NSUInteger)anIndex; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Core/NSMethodSignature+KiwiAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "NSMethodSignature+KiwiAdditions.h" 8 | 9 | @implementation NSMethodSignature(KiwiAdditions) 10 | 11 | #pragma mark - Getting Information on Message Arguments 12 | 13 | - (NSUInteger)numberOfMessageArguments { 14 | return [self numberOfArguments] - 2; 15 | } 16 | 17 | - (const char *)messageArgumentTypeAtIndex:(NSUInteger)anIndex { 18 | return [self getArgumentTypeAtIndex:anIndex + 2]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/Core/NSNumber+KiwiAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface NSNumber(KiwiAdditions) 10 | 11 | #pragma mark - Creating Numbers 12 | 13 | + (id)numberWithBytes:(const void *)bytes objCType:(const char *)anObjCType; 14 | + (id)numberWithBoolBytes:(const void *)bytes; 15 | + (id)numberWithStdBoolBytes:(const void *)bytes; 16 | + (id)numberWithCharBytes:(const void *)bytes; 17 | + (id)numberWithDoubleBytes:(const void *)bytes; 18 | + (id)numberWithFloatBytes:(const void *)bytes; 19 | + (id)numberWithIntBytes:(const void *)bytes; 20 | + (id)numberWithIntegerBytes:(const void *)bytes; 21 | + (id)numberWithLongBytes:(const void *)bytes; 22 | + (id)numberWithLongLongBytes:(const void *)bytes; 23 | + (id)numberWithShortBytes:(const void *)bytes; 24 | + (id)numberWithUnsignedCharBytes:(const void *)bytes; 25 | + (id)numberWithUnsignedIntBytes:(const void *)bytes; 26 | + (id)numberWithUnsignedIntegerBytes:(const void *)bytes; 27 | + (id)numberWithUnsignedLongBytes:(const void *)bytes; 28 | + (id)numberWithUnsignedLongLongBytes:(const void *)bytes; 29 | + (id)numberWithUnsignedShortBytes:(const void *)bytes; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Classes/Core/NSObject+KiwiSpyAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @class KWCaptureSpy; 10 | 11 | @protocol KiwiSpyAdditions 12 | 13 | - (KWCaptureSpy *)captureArgument:(SEL)selector atIndex:(NSUInteger)index; 14 | + (KWCaptureSpy *)captureArgument:(SEL)selector atIndex:(NSUInteger)index; 15 | 16 | @end 17 | 18 | @interface NSObject (KiwiSpyAdditions) 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Core/NSObject+KiwiSpyAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "NSObject+KiwiSpyAdditions.h" 8 | 9 | #import "KWCaptureSpy.h" 10 | #import "KWMessagePattern.h" 11 | #import "NSObject+KiwiStubAdditions.h" 12 | 13 | @implementation NSObject (KiwiSpyAdditions) 14 | 15 | - (KWCaptureSpy *)captureArgument:(SEL)selector atIndex:(NSUInteger)index { 16 | KWCaptureSpy *spy = [[KWCaptureSpy alloc] initWithArgumentIndex:index]; 17 | KWMessagePattern *pattern = [[KWMessagePattern alloc] initWithSelector:selector]; 18 | [self addMessageSpy:spy forMessagePattern:pattern]; 19 | return spy; 20 | } 21 | 22 | + (KWCaptureSpy *)captureArgument:(SEL)selector atIndex:(NSUInteger)index { 23 | KWCaptureSpy *spy = [[KWCaptureSpy alloc] initWithArgumentIndex:index]; 24 | KWMessagePattern *pattern = [[KWMessagePattern alloc] initWithSelector:selector]; 25 | [self addMessageSpy:spy forMessagePattern:pattern]; 26 | return spy; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Classes/Core/NSObject+KiwiVerifierAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @protocol KWVerifying; 10 | 11 | @interface NSObject(KiwiVerifierAdditions) 12 | 13 | #pragma mark - Attaching to Verifiers 14 | 15 | - (id)attachToVerifier:(id)aVerifier; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Core/NSObject+KiwiVerifierAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "NSObject+KiwiVerifierAdditions.h" 8 | #import "KWVerifying.h" 9 | 10 | @implementation NSObject(KiwiVerifierAdditions) 11 | 12 | #pragma mark - Attaching to Verifiers 13 | 14 | - (id)attachToVerifier:(id)aVerifier { 15 | [aVerifier setSubject:self]; 16 | return aVerifier; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Core/NSProxy+KiwiVerifierAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2013 Allen Ding. All rights reserved. 5 | // 6 | // Contributed by https://github.com/dwlnetnl 7 | // 8 | 9 | #import "KiwiConfiguration.h" 10 | 11 | @protocol KWVerifying; 12 | 13 | @interface NSProxy (KiwiVerifierAdditions) 14 | 15 | #pragma mark - Attaching to Verifiers 16 | 17 | - (id)attachToVerifier:(id)aVerifier; 18 | - (id)attachToVerifier:(id)firstVerifier verifier:(id)secondVerifier; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Core/NSProxy+KiwiVerifierAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2013 Allen Ding. All rights reserved. 5 | // 6 | // Contributed by https://github.com/dwlnetnl 7 | // 8 | 9 | #import "NSProxy+KiwiVerifierAdditions.h" 10 | #import "KWVerifying.h" 11 | 12 | @implementation NSProxy (KiwiVerifierAdditions) 13 | 14 | #pragma mark - Attaching to Verifiers 15 | 16 | - (id)attachToVerifier:(id)aVerifier { 17 | [aVerifier setSubject:self]; 18 | return aVerifier; 19 | } 20 | 21 | - (id)attachToVerifier:(id)firstVerifier verifier:(id)secondVerifier { 22 | [firstVerifier setSubject:self]; 23 | [secondVerifier setSubject:self]; 24 | return firstVerifier; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Classes/Core/NSValue+KiwiAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface NSValue(KiwiAdditions) 10 | 11 | #pragma mark - Accessing Data 12 | 13 | - (NSData *)dataValue; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Core/NSValue+KiwiAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "NSValue+KiwiAdditions.h" 8 | #import "KWObjCUtilities.h" 9 | 10 | @implementation NSValue(KiwiAdditions) 11 | 12 | #pragma mark - Accessing Data 13 | 14 | - (NSData *)dataValue { 15 | NSUInteger length = KWObjCTypeLength([self objCType]); 16 | void *buffer = malloc(length); 17 | [self getValue:buffer]; 18 | NSData *data = [NSData dataWithBytes:buffer length:length]; 19 | free(buffer); 20 | return data; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeBetweenMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeBetweenMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | // TODO: 'and' below is a reserved word in C++ 15 | - (void)beBetween:(id)aLowerEndpoint and:(id)anUpperEndpoint; 16 | - (void)beInTheIntervalFrom:(id)aLowerEndpoint to:(id)anUpperEndpoint; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeBetweenMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeBetweenMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWBeBetweenMatcher() 11 | 12 | #pragma mark - Properties 13 | 14 | @property (nonatomic, strong) id lowerEndpoint; 15 | @property (nonatomic, strong) id upperEndpoint; 16 | 17 | @end 18 | 19 | @implementation KWBeBetweenMatcher 20 | 21 | #pragma mark - Getting Matcher Strings 22 | 23 | + (NSArray *)matcherStrings { 24 | return @[@"beBetween:and:", @"beInTheIntervalFrom:to:"]; 25 | } 26 | 27 | #pragma mark - Matching 28 | 29 | - (BOOL)evaluate { 30 | if (![self.subject respondsToSelector:@selector(compare:)]) 31 | [NSException raise:@"KWMatcherException" format:@"subject does not respond to -compare:"]; 32 | 33 | NSComparisonResult lowerResult = [self.subject compare:self.lowerEndpoint]; 34 | NSComparisonResult upperResult = [self.subject compare:self.upperEndpoint]; 35 | return (lowerResult == NSOrderedDescending || lowerResult == NSOrderedSame) && 36 | (upperResult == NSOrderedAscending || upperResult == NSOrderedSame); 37 | } 38 | 39 | #pragma mark - Getting Failure Messages 40 | 41 | - (NSString *)failureMessageForShould { 42 | return [NSString stringWithFormat:@"expected subject to be in the interval [%@, %@], got %@", 43 | [KWFormatter formatObject:self.lowerEndpoint], 44 | [KWFormatter formatObject:self.upperEndpoint], 45 | [KWFormatter formatObject:self.subject]]; 46 | } 47 | 48 | - (NSString *)description { 49 | return [NSString stringWithFormat:@"be between %@ and %@", self.lowerEndpoint, self.upperEndpoint]; 50 | } 51 | 52 | #pragma mark - Configuring Matchers 53 | 54 | - (void)beBetween:(id)aLowerEndpoint and:(id)anUpperEndpoint { 55 | [self beInTheIntervalFrom:aLowerEndpoint to:anUpperEndpoint]; 56 | } 57 | 58 | - (void)beInTheIntervalFrom:(id)aLowerEndpoint to:(id)anUpperEndpoint { 59 | self.lowerEndpoint = aLowerEndpoint; 60 | self.upperEndpoint = anUpperEndpoint; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeEmptyMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeEmptyMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beEmpty; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeEmptyMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeEmptyMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWBeEmptyMatcher() 11 | 12 | #pragma mark - Properties 13 | 14 | @property (nonatomic, readwrite) NSUInteger count; 15 | 16 | @end 17 | 18 | @implementation KWBeEmptyMatcher 19 | 20 | #pragma mark - Getting Matcher Strings 21 | 22 | + (NSArray *)matcherStrings { 23 | return @[@"beEmpty"]; 24 | } 25 | 26 | #pragma mark - Matching 27 | 28 | - (BOOL)evaluate { 29 | if ([self.subject respondsToSelector:@selector(count)]) { 30 | self.count = [self.subject count]; 31 | return self.count == 0; 32 | } 33 | else if ([self.subject respondsToSelector:@selector(length)]) { 34 | self.count = [self.subject length]; 35 | return self.count == 0; 36 | } 37 | 38 | [NSException raise:@"KWMatcherException" format:@"subject does not respond to -count or -length"]; 39 | return NO; 40 | } 41 | 42 | #pragma mark - Getting Failure Messages 43 | 44 | - (NSString *)countPhrase { 45 | if (self.count == 1) 46 | return @"1 item"; 47 | else 48 | return [NSString stringWithFormat:@"%u items", (unsigned)self.count]; 49 | } 50 | 51 | - (NSString *)failureMessageForShould { 52 | return [NSString stringWithFormat:@"expected subject to be empty, got %@", [self countPhrase]]; 53 | } 54 | 55 | - (NSString *)failureMessageForShouldNot { 56 | return @"expected subject not to be empty"; 57 | } 58 | 59 | - (NSString *)description { 60 | return @"be empty"; 61 | } 62 | 63 | #pragma mark - Configuring Matchers 64 | 65 | - (void)beEmpty { 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeIdenticalToMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeIdenticalToMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beIdenticalTo:(id)anObject; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeIdenticalToMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeIdenticalToMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWBeIdenticalToMatcher() 11 | 12 | #pragma mark - Properties 13 | 14 | @property (nonatomic, readwrite, strong) id otherSubject; 15 | 16 | @end 17 | 18 | @implementation KWBeIdenticalToMatcher 19 | 20 | #pragma mark - Getting Matcher Strings 21 | 22 | + (NSArray *)matcherStrings { 23 | return @[@"beIdenticalTo:"]; 24 | } 25 | 26 | #pragma mark - Matching 27 | 28 | - (BOOL)evaluate { 29 | return self.subject == self.otherSubject; 30 | } 31 | 32 | #pragma mark - Getting Failure Messages 33 | 34 | - (NSString *)failureMessageForShould { 35 | return [NSString stringWithFormat:@"expected subject to be identical to %@ (%p), got %@ (%p)", 36 | [KWFormatter formatObject:self.otherSubject], 37 | self.otherSubject, 38 | [KWFormatter formatObject:self.subject], 39 | self.subject]; 40 | } 41 | 42 | - (NSString *)failureMessageForShouldNot { 43 | return [NSString stringWithFormat:@"expected subject not to be identical to %@ (%p)", 44 | [KWFormatter formatObject:self.otherSubject], 45 | self.otherSubject]; 46 | } 47 | 48 | - (NSString *)description { 49 | return [NSString stringWithFormat:@"be identical to %@", self.otherSubject]; 50 | } 51 | 52 | #pragma mark - Configuring Matchers 53 | 54 | - (void)beIdenticalTo:(id)anObject { 55 | self.otherSubject = anObject; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeKindOfClassMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeKindOfClassMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beKindOfClass:(Class)aClass; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeKindOfClassMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeKindOfClassMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWBeKindOfClassMatcher() 11 | 12 | @property (nonatomic, assign) Class targetClass; 13 | 14 | @end 15 | 16 | @implementation KWBeKindOfClassMatcher 17 | 18 | #pragma mark - Getting Matcher Strings 19 | 20 | + (NSArray *)matcherStrings { 21 | return @[@"beKindOfClass:"]; 22 | } 23 | 24 | #pragma mark - Matching 25 | 26 | - (BOOL)evaluate { 27 | return [self.subject isKindOfClass:self.targetClass]; 28 | } 29 | 30 | #pragma mark - Getting Failure Messages 31 | 32 | - (NSString *)failureMessageForShould { 33 | return [NSString stringWithFormat:@"expected subject to be kind of %@, got %@", 34 | NSStringFromClass(self.targetClass), 35 | NSStringFromClass([self.subject class])]; 36 | } 37 | 38 | - (NSString *)description { 39 | return [NSString stringWithFormat:@"be kind of %@", NSStringFromClass(self.targetClass)]; 40 | } 41 | 42 | #pragma mark - Configuring Matchers 43 | 44 | - (void)beKindOfClass:(Class)aClass { 45 | self.targetClass = aClass; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeMemberOfClassMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeMemberOfClassMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beMemberOfClass:(Class)aClass; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeMemberOfClassMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeMemberOfClassMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWBeMemberOfClassMatcher() 11 | 12 | @property (nonatomic, assign) Class targetClass; 13 | 14 | @end 15 | 16 | @implementation KWBeMemberOfClassMatcher 17 | 18 | #pragma mark - Getting Matcher Strings 19 | 20 | + (NSArray *)matcherStrings { 21 | return @[@"beMemberOfClass:"]; 22 | } 23 | 24 | #pragma mark - Matching 25 | 26 | - (BOOL)evaluate { 27 | return [self.subject isMemberOfClass:self.targetClass]; 28 | } 29 | 30 | #pragma mark - Getting Failure Messages 31 | 32 | - (NSString *)failureMessageForShould { 33 | return [NSString stringWithFormat:@"expected subject to be member of %@, got %@", 34 | NSStringFromClass(self.targetClass), 35 | NSStringFromClass([self.subject class])]; 36 | } 37 | 38 | - (NSString *)description { 39 | return [NSString stringWithFormat:@"be member of %@", 40 | NSStringFromClass(self.targetClass)]; 41 | } 42 | 43 | #pragma mark - Configuring Matchers 44 | 45 | - (void)beMemberOfClass:(Class)aClass { 46 | self.targetClass = aClass; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeSubclassOfClassMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeSubclassOfClassMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beSubclassOfClass:(Class)aClass; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeSubclassOfClassMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeSubclassOfClassMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWBeSubclassOfClassMatcher() 11 | 12 | #pragma mark - Properties 13 | 14 | @property (nonatomic, assign) Class targetClass; 15 | 16 | @end 17 | 18 | @implementation KWBeSubclassOfClassMatcher 19 | 20 | #pragma mark - Getting Matcher Strings 21 | 22 | + (NSArray *)matcherStrings { 23 | return @[@"beSubclassOfClass:"]; 24 | } 25 | 26 | #pragma mark - Matching 27 | 28 | - (BOOL)evaluate { 29 | return [self.subject isSubclassOfClass:self.targetClass]; 30 | } 31 | 32 | #pragma mark - Getting Failure Messages 33 | 34 | - (NSString *)failureMessageForShould { 35 | return [NSString stringWithFormat:@"expected subject to be subclass of %@, got %@", 36 | NSStringFromClass(self.targetClass), 37 | NSStringFromClass([self.subject class])]; 38 | } 39 | 40 | - (NSString *)description { 41 | return [NSString stringWithFormat:@"be subclass of %@", 42 | NSStringFromClass(self.targetClass)]; 43 | } 44 | 45 | #pragma mark - Configuring Matchers 46 | 47 | - (void)beSubclassOfClass:(Class)aClass { 48 | self.targetClass = aClass; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeTrueMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeTrueMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beTrue; 15 | - (void)beFalse; 16 | - (void)beYes; 17 | - (void)beNo; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeTrueMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeTrueMatcher.h" 8 | 9 | @interface KWBeTrueMatcher() 10 | 11 | @property (nonatomic, readwrite) BOOL expectedValue; 12 | 13 | @end 14 | 15 | @implementation KWBeTrueMatcher 16 | 17 | #pragma mark - Getting Matcher Strings 18 | 19 | + (NSArray *)matcherStrings { 20 | return @[@"beTrue", @"beFalse", @"beYes", @"beNo"]; 21 | } 22 | 23 | #pragma mark - Matching 24 | 25 | - (BOOL)evaluate { 26 | if (![self.subject respondsToSelector:@selector(boolValue)]) 27 | [NSException raise:@"KWMatcherException" format:@"subject does not respond to -boolValue"]; 28 | 29 | return [self.subject boolValue] == self.expectedValue; 30 | } 31 | 32 | #pragma mark - Getting Failure Messages 33 | 34 | - (NSString *)failureMessageForShould { 35 | return [NSString stringWithFormat:@"expected subject to be %@", 36 | self.expectedValue ? @"true" : @"false"]; 37 | } 38 | 39 | - (NSString *)description { 40 | if (self.expectedValue == YES) { 41 | return @"be true"; 42 | } 43 | return @"be false"; 44 | } 45 | 46 | #pragma mark - Configuring Matchers 47 | 48 | - (void)beTrue { 49 | self.expectedValue = YES; 50 | } 51 | 52 | - (void)beFalse { 53 | self.expectedValue = NO; 54 | } 55 | 56 | - (void)beYes { 57 | self.expectedValue = YES; 58 | } 59 | 60 | - (void)beNo { 61 | self.expectedValue = NO; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeWithinMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeWithinMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beWithin:(id)aDistance of:(id)aValue; 15 | - (void)equal:(double)aValue withDelta:(double)aDelta; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeZeroMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBeZeroMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beZero; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBeZeroMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeZeroMatcher.h" 8 | #import "KWFormatter.h" 9 | #import "KWValue.h" 10 | 11 | @implementation KWBeZeroMatcher 12 | 13 | #pragma mark - Getting Matcher Strings 14 | 15 | + (NSArray *)matcherStrings { 16 | return @[@"beZero"]; 17 | } 18 | 19 | #pragma mark - Matching 20 | 21 | - (BOOL)evaluate { 22 | if ([self.subject isKindOfClass:[NSNumber class]]) { 23 | return [self.subject isEqualToNumber:@0]; 24 | } 25 | 26 | if ([self.subject respondsToSelector:@selector(numberValue)]) { 27 | return [[self.subject numberValue] isEqualToNumber:@0]; 28 | } 29 | 30 | return NO; 31 | } 32 | 33 | #pragma mark - Getting Failure Messages 34 | 35 | - (NSString *)failureMessageForShould { 36 | return [NSString stringWithFormat:@"expected subject to be zero, got %@", 37 | [KWFormatter formatObject:self.subject]]; 38 | } 39 | 40 | - (NSString *)failureMessageForShouldNot { 41 | return [NSString stringWithFormat:@"expected subject not to be zero"]; 42 | } 43 | 44 | - (NSString *)description { 45 | return @"be zero"; 46 | } 47 | 48 | #pragma mark - Configuring Matchers 49 | 50 | - (void)beZero { 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Classes/Matchers/KWBlockRaiseMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWBlockRaiseMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)raise; 15 | - (void)raiseWithName:(NSString *)aName; 16 | - (void)raiseWithReason:(NSString *)aReason; 17 | - (void)raiseWithName:(NSString *)aName reason:(NSString *)aReason; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Matchers/KWChangeMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWChangeMatcher.h 3 | // Kiwi 4 | // 5 | // Copyright (c) 2013 Eloy Durán . 6 | // All rights reserved. 7 | // 8 | 9 | #import "KWMatcher.h" 10 | 11 | typedef NSInteger (^KWChangeMatcherCountBlock)(); 12 | 13 | @interface KWChangeMatcher : KWMatcher 14 | 15 | // Expect _any_ change. 16 | - (void)change:(KWChangeMatcherCountBlock)countBlock; 17 | 18 | // Expect changes by a specific amount. 19 | - (void)change:(KWChangeMatcherCountBlock)countBlock by:(NSInteger)expectedDifference; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/Matchers/KWChangeMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWChangeMatcher.m 3 | // Kiwi 4 | // 5 | // Copyright (c) 2013 Eloy Durán . 6 | // All rights reserved. 7 | // 8 | 9 | #import "KWChangeMatcher.h" 10 | #import "KWBlock.h" 11 | 12 | @interface KWChangeMatcher () 13 | @property (nonatomic, copy) KWChangeMatcherCountBlock countBlock; 14 | @property (nonatomic, assign) BOOL anyChange; 15 | @property (nonatomic, assign) NSInteger expectedDifference, expectedTotal, actualTotal; 16 | @end 17 | 18 | @implementation KWChangeMatcher 19 | 20 | + (NSArray *)matcherStrings { 21 | return @[@"change:by:", @"change:"]; 22 | } 23 | 24 | - (NSString *)failureMessageForShould { 25 | if (self.anyChange) { 26 | return @"expected subject to change the count"; 27 | } else { 28 | return [NSString stringWithFormat:@"expected subject to change the count to %d, got %d", (int)self.expectedTotal, (int)self.actualTotal]; 29 | } 30 | } 31 | 32 | - (NSString *)failureMessageForShouldNot { 33 | if (self.anyChange) { 34 | return @"expected subject to not change the count"; 35 | } else { 36 | return [NSString stringWithFormat:@"expected subject not to change the count to %d", (int)self.actualTotal]; 37 | } 38 | } 39 | 40 | - (NSString *)description { 41 | if (self.anyChange) { 42 | return @"change count"; 43 | } else { 44 | return [NSString stringWithFormat:@"change count by %d", (int)self.expectedDifference]; 45 | } 46 | } 47 | 48 | - (BOOL)evaluate { 49 | NSInteger before = self.countBlock(); 50 | // Perform actual work, which is expected to change the result of countBlock. 51 | [self.subject call]; 52 | self.actualTotal = self.countBlock(); 53 | 54 | if (self.anyChange) { 55 | return before != self.actualTotal; 56 | } else { 57 | self.expectedTotal = before + self.expectedDifference; 58 | return self.expectedTotal == self.actualTotal; 59 | } 60 | } 61 | 62 | - (void)change:(KWChangeMatcherCountBlock)countBlock by:(NSInteger)expectedDifference { 63 | self.anyChange = NO; 64 | self.expectedDifference = expectedDifference; 65 | self.countBlock = countBlock; 66 | } 67 | 68 | - (void)change:(KWChangeMatcherCountBlock)countBlock { 69 | self.anyChange = YES; 70 | self.countBlock = countBlock; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Classes/Matchers/KWConformToProtocolMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWConformToProtocolMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)conformToProtocol:(Protocol *)aProtocol; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWConformToProtocolMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWConformToProtocolMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWConformToProtocolMatcher() 11 | 12 | @property (nonatomic, assign) Protocol *protocol; 13 | 14 | @end 15 | 16 | @implementation KWConformToProtocolMatcher 17 | 18 | #pragma mark - Getting Matcher Strings 19 | 20 | + (NSArray *)matcherStrings { 21 | return @[@"conformToProtocol:"]; 22 | } 23 | 24 | #pragma mark - Matching 25 | 26 | - (BOOL)evaluate { 27 | return [self.subject conformsToProtocol:self.protocol]; 28 | } 29 | 30 | #pragma mark - Getting Failure Messages 31 | 32 | - (NSString *)failureMessageForShould { 33 | return [NSString stringWithFormat:@"expected subject to conform to %@ protocol", 34 | NSStringFromProtocol(self.protocol)]; 35 | } 36 | 37 | - (NSString *)description { 38 | return [NSString stringWithFormat:@"conform to %@ protocol", NSStringFromProtocol(self.protocol)]; 39 | } 40 | 41 | #pragma mark - Configuring Matchers 42 | 43 | - (void)conformToProtocol:(Protocol *)aProtocol { 44 | self.protocol = aProtocol; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Classes/Matchers/KWContainMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | #import "KWMatchVerifier.h" 10 | 11 | @interface KWContainMatcher : KWMatcher 12 | 13 | #pragma mark - Configuring Matchers 14 | 15 | - (void)contain:(id)anObject; 16 | - (void)containObjectsInArray:(NSArray *)anArray; 17 | 18 | @end 19 | 20 | @interface KWMatchVerifier(KWContainMatcherAdditions) 21 | 22 | #pragma mark - Verifying 23 | 24 | - (void)containObjects:(id)firstObject, ... NS_REQUIRES_NIL_TERMINATION; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Matchers/KWContainMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWContainMatcher.h" 8 | #import "KWFormatter.h" 9 | #import "KWGenericMatchingAdditions.h" 10 | 11 | @interface KWContainMatcher() 12 | 13 | @property (nonatomic, readwrite, strong) id objects; 14 | 15 | @end 16 | 17 | @implementation KWContainMatcher 18 | 19 | #pragma mark - Getting Matcher Strings 20 | 21 | + (NSArray *)matcherStrings { 22 | return @[@"contain:", @"containObjectsInArray:"]; 23 | } 24 | 25 | #pragma mark - Matching 26 | 27 | - (BOOL)evaluate { 28 | if (![self.subject respondsToSelector:@selector(containsObjectEqualToOrMatching:)]) 29 | [NSException raise:@"KWMatcherException" format:@"subject does not respond to -containsObjectEqualToOrMatching:"]; 30 | 31 | for (id object in self.objects) { 32 | if (![self.subject containsObjectEqualToOrMatching:object]) 33 | return NO; 34 | } 35 | 36 | return YES; 37 | } 38 | 39 | #pragma mark - Getting Failure Messages 40 | 41 | - (NSString *)objectsPhrase { 42 | if ([self.objects count] == 1) 43 | return [KWFormatter formatObject:(self.objects)[0]]; 44 | 45 | return [NSString stringWithFormat:@"all of %@", [KWFormatter formatObject:self.objects]]; 46 | } 47 | 48 | - (NSString *)failureMessageForShould { 49 | return [NSString stringWithFormat:@"expected subject to contain %@", [self objectsPhrase]]; 50 | } 51 | 52 | - (NSString *)description { 53 | return [NSString stringWithFormat:@"contain %@", [self objectsPhrase]]; 54 | } 55 | 56 | #pragma mark - Configuring Matchers 57 | 58 | - (void)contain:(id)anObject { 59 | self.objects = @[anObject]; 60 | } 61 | 62 | - (void)containObjectsInArray:(NSArray *)anArray { 63 | self.objects = anArray; 64 | } 65 | 66 | @end 67 | 68 | @implementation KWMatchVerifier(KWContainMatcherAdditions) 69 | 70 | #pragma mark - Verifying 71 | 72 | - (void)containObjects:(id)firstObject, ... { 73 | NSMutableArray *objects = [NSMutableArray array]; 74 | 75 | va_list argumentList; 76 | va_start(argumentList, firstObject); 77 | id object = firstObject; 78 | 79 | while (object != nil) { 80 | [objects addObject:object]; 81 | object = va_arg(argumentList, id); 82 | } 83 | 84 | va_end(argumentList); 85 | [(id)self containObjectsInArray:objects]; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Classes/Matchers/KWContainStringMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWContainStringMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Kristopher Johnson on 4/28/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KiwiConfiguration.h" 10 | #import "KWMatcher.h" 11 | 12 | // Kiwi matcher for determining whether a string contains an expected substring 13 | // 14 | // Examples: 15 | // 16 | // [[@"Hello, world!" should] containString:@"world"]; 17 | // [[@"Hello, world!" shouldNot] containString:@"xyzzy"]; 18 | // 19 | // [[@"Hello, world!" should] containString:@"WORLD" 20 | // options:NSCaseInsensitiveSearch]; 21 | // 22 | // [[@"Hello, world!" should] startWithString:@"Hello,"]; 23 | // [[@"Hello, world!" should] endWithString:@"world!"]; 24 | 25 | @interface KWContainStringMatcher : KWMatcher 26 | 27 | // Match if subject contains specified substring 28 | - (void)containString:(NSString *)string; 29 | 30 | // Match if subject contains specified substring, using specified comparison options 31 | - (void)containString:(NSString *)string options:(NSStringCompareOptions)options; 32 | 33 | // Match if subject starts with the specified prefix 34 | - (void)startWithString:(NSString *)prefix; 35 | 36 | // Match if subject ends with the specified prefix 37 | - (void)endWithString:(NSString *)suffix; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/Matchers/KWContainStringMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWContainStringMatcher.m 3 | // Kiwi 4 | // 5 | // Created by Kristopher Johnson on 4/28/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWContainStringMatcher.h" 10 | #import "KWFormatter.h" 11 | 12 | @interface KWContainStringMatcher () 13 | 14 | @property (nonatomic, copy) NSString *substring; 15 | @property (nonatomic) NSStringCompareOptions options; 16 | 17 | @end 18 | 19 | 20 | @implementation KWContainStringMatcher 21 | 22 | #pragma mark - Getting Matcher Strings 23 | 24 | + (NSArray *)matcherStrings { 25 | return @[@"containString:", 26 | @"containString:options:", 27 | @"startWithString:", 28 | @"endWithString:"]; 29 | } 30 | 31 | #pragma mark - Matching 32 | 33 | - (BOOL)evaluate { 34 | NSString *subjectString = (NSString *)self.subject; 35 | if (![subjectString isKindOfClass:[NSString class]]) { 36 | [NSException raise:@"KWMatcherException" format:@"subject is not a string"]; 37 | return NO; 38 | } 39 | 40 | NSRange range = [subjectString rangeOfString:self.substring options:self.options]; 41 | return (range.location != NSNotFound); 42 | } 43 | 44 | #pragma mark - Getting Failure Messages 45 | 46 | - (NSString *)failureMessageForShould { 47 | return [NSString stringWithFormat:@"%@ did not contain string \"%@\"", 48 | [KWFormatter formatObject:self.subject], 49 | self.substring]; 50 | } 51 | 52 | - (NSString *)failureMessageForShouldNot { 53 | return [NSString stringWithFormat:@"expected subject not to contain string \"%@\"", 54 | self.substring]; 55 | } 56 | 57 | - (NSString *)description { 58 | return [NSString stringWithFormat:@"contain substring \"%@\"", self.substring]; 59 | } 60 | 61 | #pragma mark - Configuring matchers 62 | 63 | - (void)containString:(NSString *)substring { 64 | self.substring = substring; 65 | self.options = 0; 66 | } 67 | 68 | - (void)containString:(NSString *)substring options:(NSStringCompareOptions)options { 69 | self.substring = substring; 70 | self.options = options; 71 | } 72 | 73 | - (void)startWithString:(NSString *)prefix { 74 | self.substring = prefix; 75 | self.options = NSAnchoredSearch; 76 | } 77 | 78 | - (void)endWithString:(NSString *)suffix { 79 | self.substring = suffix; 80 | self.options = NSAnchoredSearch | NSBackwardsSearch; 81 | } 82 | 83 | @end 84 | 85 | 86 | -------------------------------------------------------------------------------- /Classes/Matchers/KWEqualMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWEqualMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)equal:(id)anObject; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWEqualMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWEqualMatcher.h" 8 | #import "KWFormatter.h" 9 | #import "KWValue.h" 10 | 11 | @interface KWEqualMatcher() 12 | 13 | #pragma mark - Properties 14 | 15 | @property (nonatomic, readwrite, strong) id otherSubject; 16 | 17 | @end 18 | 19 | @implementation KWEqualMatcher 20 | 21 | #pragma mark - Initializing 22 | 23 | 24 | #pragma mark - Properties 25 | 26 | @synthesize otherSubject; 27 | 28 | #pragma mark - Getting Matcher Strings 29 | 30 | + (NSArray *)matcherStrings { 31 | return @[@"equal:"]; 32 | } 33 | 34 | #pragma mark - Matching 35 | 36 | - (BOOL)evaluate { 37 | /** handle this as a special case; KWValue supports NSNumber equality but not vice-versa **/ 38 | if ([self.subject isKindOfClass:[NSNumber class]] && [self.otherSubject isKindOfClass:[KWValue class]]) { 39 | return [self.otherSubject isEqual:self.subject]; 40 | } 41 | return [self.subject isEqual:self.otherSubject]; 42 | } 43 | 44 | #pragma mark - Getting Failure Messages 45 | 46 | - (NSString *)failureMessageForShould { 47 | return [NSString stringWithFormat:@"expected subject to equal %@, got %@", 48 | [KWFormatter formatObjectIncludingClass:self.otherSubject], 49 | [KWFormatter formatObjectIncludingClass:self.subject]]; 50 | } 51 | 52 | - (NSString *)failureMessageForShouldNot { 53 | return [NSString stringWithFormat:@"expected subject not to equal %@", 54 | [KWFormatter formatObjectIncludingClass:self.otherSubject]]; 55 | } 56 | 57 | - (NSString *)description 58 | { 59 | return [NSString stringWithFormat:@"equal %@", [KWFormatter formatObjectIncludingClass:self.otherSubject]]; 60 | } 61 | 62 | #pragma mark - Configuring Matchers 63 | 64 | - (void)equal:(id)anObject { 65 | self.otherSubject = anObject; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Classes/Matchers/KWGenericMatchEvaluator.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWGenericMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Allen Ding on 1/31/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KWGenericMatchEvaluator : NSObject 12 | 13 | + (BOOL)isGenericMatcher:(id)object; 14 | 15 | + (BOOL)genericMatcher:(id)matcher matches:(id)object; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Matchers/KWGenericMatchEvaluator.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWGenericMatcher.m 3 | // Kiwi 4 | // 5 | // Created by Allen Ding on 1/31/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWGenericMatchEvaluator.h" 10 | #import "KWStringUtilities.h" 11 | #import "KWObjCUtilities.h" 12 | #import 13 | #import "KWGenericMatcher.h" 14 | 15 | @implementation KWGenericMatchEvaluator 16 | 17 | // Returns true only if the object has a method with the signature "- (BOOL)matches:(id)object" 18 | + (BOOL)isGenericMatcher:(id)object { 19 | Class theClass = object_getClass(object); 20 | 21 | if (theClass == NULL) { 22 | return NO; 23 | } 24 | Method method = class_getInstanceMethod(theClass, @selector(matches:)); 25 | 26 | if (method == NULL) { 27 | return NO; 28 | } 29 | 30 | const char *cEncoding = method_getTypeEncoding(method); 31 | 32 | if (cEncoding == NULL) { 33 | return NO; 34 | } 35 | 36 | NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:cEncoding]; 37 | 38 | if (!KWObjCTypeEqualToObjCType(@encode(BOOL), [signature methodReturnType])) { 39 | return NO; 40 | } 41 | 42 | if ([signature numberOfArguments] != 3) { 43 | return NO; 44 | } 45 | 46 | if (!KWObjCTypeEqualToObjCType(@encode(id), [signature getArgumentTypeAtIndex:2])) { 47 | return NO; 48 | } 49 | 50 | return YES; 51 | } 52 | 53 | + (BOOL)genericMatcher:(id)matcher matches:(id)object { 54 | NSString *targetEncoding = KWEncodingWithObjCTypes(@encode(BOOL), @encode(id), @encode(SEL), @encode(id), nil); 55 | NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:[targetEncoding UTF8String]]; 56 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 57 | [invocation setSelector:@selector(matches:)]; 58 | [invocation setArgument:&object atIndex:2]; 59 | [invocation invokeWithTarget:matcher]; 60 | BOOL result = NO; 61 | [invocation getReturnValue:&result]; 62 | return result; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Classes/Matchers/KWGenericMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWGenericMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 24/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWMatcher.h" 11 | 12 | @protocol KWGenericMatching 13 | 14 | - (BOOL)matches:(id)object; 15 | 16 | @end 17 | 18 | @interface KWGenericMatcher : KWMatcher 19 | 20 | #pragma mark - Configuring Matchers 21 | 22 | - (void)match:(id)aMatcher; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Matchers/KWGenericMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWGenericMatcher.m 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 24/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWGenericMatcher.h" 10 | #import "KWGenericMatchEvaluator.h" 11 | 12 | @interface KWGenericMatcher () 13 | 14 | @property (nonatomic, strong) id matcher; 15 | 16 | @end 17 | 18 | @implementation KWGenericMatcher 19 | 20 | #pragma mark - Matching 21 | 22 | - (BOOL)evaluate { 23 | return [KWGenericMatchEvaluator genericMatcher:self.matcher matches:self.subject]; 24 | } 25 | 26 | - (NSString *)failureMessageForShould { 27 | return [NSString stringWithFormat:@"expected subject to match %@", self.matcher]; 28 | } 29 | 30 | - (NSString *)description 31 | { 32 | return [NSString stringWithFormat:@"match %@", [self.matcher description]]; 33 | } 34 | 35 | #pragma mark - Getting Matcher Strings 36 | 37 | + (NSArray *)matcherStrings { 38 | return @[@"match:"]; 39 | } 40 | 41 | #pragma mark - Configuring Matchers 42 | 43 | - (void)match:(id)aMatcher; 44 | { 45 | self.matcher = aMatcher; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Classes/Matchers/KWGenericMatchingAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+KiwiAdditions.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 24/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (KiwiGenericMatchingAdditions) 12 | 13 | - (BOOL)isEqualOrMatches:(id)object DEPRECATED_ATTRIBUTE; 14 | 15 | @end 16 | 17 | @interface NSArray (KiwiGenericMatchingAdditions) 18 | 19 | - (BOOL)containsObjectEqualToOrMatching:(id)object DEPRECATED_ATTRIBUTE; 20 | - (BOOL)containsObjectMatching:(id)matcher DEPRECATED_ATTRIBUTE; 21 | 22 | @end 23 | 24 | @interface NSSet (KiwiGenericMatchingAdditions) 25 | 26 | - (BOOL)containsObjectEqualToOrMatching:(id)object DEPRECATED_ATTRIBUTE; 27 | 28 | @end 29 | 30 | @interface NSOrderedSet (KiwiGenericMatchingAdditions) 31 | 32 | - (BOOL)containsObjectEqualToOrMatching:(id)object DEPRECATED_ATTRIBUTE; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Matchers/KWGenericMatchingAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+KiwiAdditions.m 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 24/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWGenericMatchingAdditions.h" 10 | #import "KWGenericMatcher.h" 11 | #import "KWGenericMatchEvaluator.h" 12 | 13 | @implementation NSObject (KiwiGenericMatchingAdditions) 14 | 15 | - (BOOL)isEqualOrMatches:(id)object { 16 | if ([KWGenericMatchEvaluator isGenericMatcher:self]) { 17 | return [KWGenericMatchEvaluator genericMatcher:self matches:object]; 18 | } 19 | return [self isEqual:object]; 20 | } 21 | 22 | @end 23 | 24 | @implementation NSArray (KiwiGenericMatchingAdditions) 25 | 26 | - (BOOL)containsObjectEqualToOrMatching:(id)object { 27 | if ([KWGenericMatchEvaluator isGenericMatcher:object]) { 28 | return [self containsObjectMatching:object]; 29 | } 30 | return [self containsObject:object]; 31 | } 32 | 33 | - (BOOL)containsObjectMatching:(id)matcher { 34 | NSIndexSet *indexSet = [self indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) { 35 | BOOL matches = [KWGenericMatchEvaluator genericMatcher:matcher matches:obj]; 36 | if (matches) { 37 | *stop = YES; 38 | } 39 | return matches; 40 | }]; 41 | 42 | return (indexSet.count > 0); 43 | } 44 | 45 | @end 46 | 47 | @implementation NSSet (KiwiGenericMatchingAdditions) 48 | 49 | - (BOOL)containsObjectEqualToOrMatching:(id)object { 50 | if ([KWGenericMatchEvaluator isGenericMatcher:object]) { 51 | return [[self allObjects] containsObjectMatching:object]; 52 | } 53 | return [self containsObject:object]; 54 | } 55 | 56 | @end 57 | 58 | @implementation NSOrderedSet (KiwiGenericMatchingAdditions) 59 | 60 | - (BOOL)containsObjectEqualToOrMatching:(id)object { 61 | if ([KWGenericMatchEvaluator isGenericMatcher:object]) { 62 | return [[self array] containsObjectMatching:object]; 63 | } 64 | return [self containsObject:object]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Classes/Matchers/KWHaveMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWCountType.h" 9 | #import "KWMatcher.h" 10 | #import "KWMatchVerifier.h" 11 | 12 | @interface KWHaveMatcher : KWMatcher 13 | 14 | #pragma mark - Configuring Matchers 15 | 16 | - (void)haveCountOf:(NSUInteger)aCount; 17 | - (void)haveCountOfAtLeast:(NSUInteger)aCount; 18 | - (void)haveCountOfAtMost:(NSUInteger)aCount; 19 | - (void)haveLengthOf:(NSUInteger)aCount; 20 | - (void)haveLengthOfAtLeast:(NSUInteger)aCount; 21 | - (void)haveLengthOfAtMost:(NSUInteger)aCount; 22 | - (void)have:(NSUInteger)aCount itemsForInvocation:(NSInvocation *)anInvocation; 23 | - (void)haveAtLeast:(NSUInteger)aCount itemsForInvocation:(NSInvocation *)anInvocation; 24 | - (void)haveAtMost:(NSUInteger)aCount itemsForInvocation:(NSInvocation *)anInvocation; 25 | 26 | @end 27 | 28 | @protocol KWContainmentCountMatcherTerminals 29 | 30 | #pragma mark - Terminals 31 | 32 | - (id)objects; 33 | - (id)items; 34 | - (id)elements; 35 | 36 | @end 37 | 38 | #pragma mark - Verifying 39 | 40 | @interface KWMatchVerifier(KWHaveMatcherAdditions) 41 | 42 | #pragma mark - Invocation Capturing Methods 43 | 44 | - (id)have:(NSUInteger)aCount; 45 | - (id)haveAtLeast:(NSUInteger)aCount; 46 | - (id)haveAtMost:(NSUInteger)aCount; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Classes/Matchers/KWHaveValueMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWHaveValueMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 24/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWMatcher.h" 11 | 12 | @interface KWHaveValueMatcher : KWMatcher 13 | 14 | #pragma mark - Configuring Matchers 15 | 16 | - (void)haveValue:(id)value forKey:(NSString *)key; 17 | - (void)haveValue:(id)value forKeyPath:(NSString *)keyPath; 18 | - (void)haveValueForKey:(NSString *)key; 19 | - (void)haveValueForKeyPath:(NSString *)keyPath; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/Matchers/KWInequalityMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWInequalityMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)beLessThan:(id)aValue; 15 | - (void)beLessThanOrEqualTo:(id)aValue; 16 | - (void)beGreaterThan:(id)aValue; 17 | - (void)beGreaterThanOrEqualTo:(id)aValue; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Matchers/KWNilMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWBeNilMatcher.h 3 | // iOSFalconCore 4 | // 5 | // Created by Luke Redpath on 14/01/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWMatcher.h" 11 | 12 | @interface KWNilMatcher : KWMatcher 13 | 14 | - (void)beNil; 15 | - (void)beNonNil; 16 | 17 | - (void)beNil:(BOOL)workaroundArgument; 18 | - (void)beNonNil:(BOOL)workaroundArgument; 19 | 20 | + (BOOL)verifyNilSubject; 21 | + (BOOL)verifyNonNilSubject; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Matchers/KWNotificationMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWNotificationMatcher.h 3 | // 4 | // Created by Paul Zabelin on 7/12/12. 5 | // Copyright (c) 2012 Blazing Cloud, Inc. All rights reserved. 6 | // 7 | 8 | #import "KWMatcher.h" 9 | 10 | typedef void (^PostedNotificationBlock)(NSNotification* note); 11 | 12 | @interface KWNotificationMatcher : KWMatcher 13 | 14 | - (void)bePosted; 15 | - (void)bePostedWithObject:(id)object; 16 | - (void)bePostedWithUserInfo:(NSDictionary *)userInfo; 17 | - (void)bePostedWithObject:(id)object andUserInfo:(NSDictionary *)userInfo; 18 | - (void)bePostedEvaluatingBlock:(PostedNotificationBlock)block; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Matchers/KWRaiseMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWRaiseMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)raiseWhenSent:(SEL)aSelector DEPRECATED_ATTRIBUTE; 15 | - (void)raiseWithName:(NSString *)aName whenSent:(SEL)aSelector DEPRECATED_ATTRIBUTE; 16 | - (void)raiseWithReason:(NSString *)aReason whenSent:(SEL)aSelector DEPRECATED_ATTRIBUTE; 17 | - (void)raiseWithName:(NSString *)aName reason:(NSString *)aReason whenSent:(SEL)aSelector DEPRECATED_ATTRIBUTE; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Matchers/KWRegularExpressionPatternMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWRegularExpressionPatternMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Kristopher Johnson on 4/11/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KiwiConfiguration.h" 10 | #import "KWMatcher.h" 11 | 12 | @interface KWRegularExpressionPatternMatcher : KWMatcher 13 | 14 | - (void)matchPattern:(NSString *)pattern; 15 | 16 | - (void)matchPattern:(NSString *)pattern options:(NSRegularExpressionOptions)options; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Matchers/KWRespondToSelectorMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWMatcher.h" 9 | 10 | @interface KWRespondToSelectorMatcher : KWMatcher 11 | 12 | #pragma mark - Configuring Matchers 13 | 14 | - (void)respondToSelector:(SEL)aSelector; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Matchers/KWRespondToSelectorMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWRespondToSelectorMatcher.h" 8 | #import "KWFormatter.h" 9 | 10 | @interface KWRespondToSelectorMatcher() 11 | 12 | #pragma mark - Properties 13 | 14 | @property (nonatomic, assign) SEL selector; 15 | 16 | @end 17 | 18 | @implementation KWRespondToSelectorMatcher 19 | 20 | #pragma mark - Getting Matcher Strings 21 | 22 | + (NSArray *)matcherStrings { 23 | return @[@"respondToSelector:"]; 24 | } 25 | 26 | #pragma mark - Matching 27 | 28 | - (BOOL)evaluate { 29 | return [self.subject respondsToSelector:self.selector]; 30 | } 31 | 32 | #pragma mark - Getting Failure Messages 33 | 34 | - (NSString *)failureMessageForShould { 35 | return [NSString stringWithFormat:@"expected subject to respond to -%@", 36 | NSStringFromSelector(self.selector)]; 37 | } 38 | 39 | - (NSString *)description { 40 | return [NSString stringWithFormat:@"respond to -%@", NSStringFromSelector(self.selector)]; 41 | } 42 | 43 | #pragma mark - Configuring Matchers 44 | 45 | - (void)respondToSelector:(SEL)aSelector { 46 | self.selector = aSelector; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Classes/Matchers/KWStringContainsMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWStringContainsMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Stewart Gleadow on 7/06/12. 6 | // Copyright (c) 2012 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWGenericMatcher.h" 11 | 12 | @interface KWStringContainsMatcher : NSObject 13 | 14 | + (id)matcherWithSubstring:(NSString *)aSubstring DEPRECATED_ATTRIBUTE; 15 | - (id)initWithSubstring:(NSString *)aSubstring DEPRECATED_ATTRIBUTE; 16 | 17 | @end 18 | 19 | #define hasSubstring(substring) [KWStringContainsMatcher matcherWithSubstring:substring] 20 | -------------------------------------------------------------------------------- /Classes/Matchers/KWStringContainsMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // StringContainsMatcher.m 3 | // Kiwi 4 | // 5 | // Created by Stewart Gleadow on 7/06/12. 6 | // Copyright (c) 2012 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWStringContainsMatcher.h" 10 | 11 | @interface KWStringContainsMatcher(){} 12 | @property (nonatomic, copy) NSString *substring; 13 | @end 14 | 15 | @implementation KWStringContainsMatcher 16 | 17 | + (id)matcherWithSubstring:(NSString *)aSubstring { 18 | return [[self alloc] initWithSubstring:aSubstring]; 19 | } 20 | 21 | - (id)initWithSubstring:(NSString *)aSubstring { 22 | self = [super init]; 23 | if (self) { 24 | _substring = [aSubstring copy]; 25 | } 26 | return self; 27 | } 28 | 29 | 30 | - (BOOL)matches:(id)item { 31 | if (![item respondsToSelector:@selector(rangeOfString:)]) { 32 | return NO; 33 | } 34 | 35 | return [item rangeOfString:self.substring].location != NSNotFound; 36 | } 37 | 38 | - (NSString *)description { 39 | return [NSString stringWithFormat:@"a string with substring '%@'", self.substring]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Classes/Matchers/KWStringPrefixMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // StringPrefixMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KWStringPrefixMatcher : NSObject 12 | 13 | + (id)matcherWithPrefix:(NSString *)aPrefix; 14 | - (id)initWithPrefix:(NSString *)aPrefix; 15 | 16 | @end 17 | 18 | #define hasPrefix(prefix) [KWStringPrefixMatcher matcherWithPrefix:prefix] 19 | -------------------------------------------------------------------------------- /Classes/Matchers/KWStringPrefixMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // StringPrefixMatcher.m 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KWStringPrefixMatcher.h" 10 | 11 | @interface KWStringPrefixMatcher(){} 12 | @property (nonatomic, copy) NSString *prefix; 13 | @end 14 | 15 | @implementation KWStringPrefixMatcher 16 | 17 | + (id)matcherWithPrefix:(NSString *)aPrefix { 18 | return [[self alloc] initWithPrefix:aPrefix]; 19 | } 20 | 21 | - (id)initWithPrefix:(NSString *)aPrefix { 22 | self = [super init]; 23 | if (self) { 24 | _prefix = [aPrefix copy]; 25 | } 26 | return self; 27 | } 28 | 29 | 30 | - (BOOL)matches:(id)item { 31 | if (![item respondsToSelector:@selector(hasPrefix:)]) 32 | return NO; 33 | 34 | return [item hasPrefix:self.prefix]; 35 | } 36 | 37 | - (NSString *)description { 38 | return [NSString stringWithFormat:@"a string with prefix '%@'", self.prefix]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Classes/Matchers/KWUserDefinedMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWUserDefinedMatcher.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 16/06/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWMatcher.h" 11 | 12 | typedef BOOL (^KWUserDefinedMatcherBlock)(); 13 | 14 | @interface KWUserDefinedMatcher : KWMatcher 15 | 16 | @property (nonatomic, assign) SEL selector; 17 | @property (nonatomic, copy) NSString *failureMessageForShould; 18 | @property (nonatomic, copy) NSString *failureMessageForShouldNot; 19 | @property (nonatomic, copy) KWUserDefinedMatcherBlock matcherBlock; 20 | @property (nonatomic, copy) NSString *description; 21 | 22 | + (id)matcherWithSubject:(id)aSubject block:(KWUserDefinedMatcherBlock)aBlock; 23 | - (id)initWithSubject:(id)aSubject block:(KWUserDefinedMatcherBlock)aBlock; 24 | @end 25 | 26 | #pragma mark - 27 | 28 | typedef NSString * (^KWUserDefinedMatcherMessageBlock)(id); 29 | 30 | @interface KWUserDefinedMatcherBuilder : NSObject 31 | { 32 | KWUserDefinedMatcher *matcher; 33 | KWUserDefinedMatcherMessageBlock failureMessageForShouldBlock; 34 | KWUserDefinedMatcherMessageBlock failureMessageForShouldNotBlock; 35 | NSString *description; 36 | } 37 | @property (nonatomic, copy, readonly) NSString *key; 38 | 39 | + (id)builder; 40 | + (id)builderForSelector:(SEL)aSelector; 41 | - (id)initWithSelector:(SEL)aSelector; 42 | 43 | #pragma mark - Configuring The Matcher 44 | 45 | - (void)match:(KWUserDefinedMatcherBlock)block; 46 | - (void)failureMessageForShould:(KWUserDefinedMatcherMessageBlock)block; 47 | - (void)failureMessageForShouldNot:(KWUserDefinedMatcherMessageBlock)block; 48 | - (void)description:(NSString *)description; 49 | 50 | #pragma mark - Buiding The Matcher 51 | 52 | - (KWUserDefinedMatcher *)buildMatcherWithSubject:(id)subject; 53 | @end 54 | -------------------------------------------------------------------------------- /Classes/Mocking/NSObject+KiwiMockAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @protocol KiwiMockAdditions 10 | 11 | #pragma mark - Creating Mocks 12 | 13 | + (id)mock; 14 | + (id)mockWithName:(NSString *)aName; 15 | 16 | + (id)nullMock; 17 | + (id)nullMockWithName:(NSString *)aName; 18 | 19 | @end 20 | 21 | @interface NSObject(KiwiMockAdditions) 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Mocking/NSObject+KiwiMockAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "NSObject+KiwiMockAdditions.h" 8 | #import "KWMock.h" 9 | 10 | @implementation NSObject(KiwiMockAdditions) 11 | 12 | #pragma mark - Creating Mocks 13 | 14 | + (id)mock { 15 | return [KWMock mockForClass:[self class]]; 16 | } 17 | 18 | + (id)mockWithName:(NSString *)aName { 19 | return [KWMock mockWithName:aName forClass:[self class]]; 20 | } 21 | 22 | + (id)nullMock { 23 | return [KWMock nullMockForClass:[self class]]; 24 | } 25 | 26 | + (id)nullMockWithName:(NSString *)aName { 27 | return [KWMock nullMockWithName:aName forClass:[self class]]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Classes/Nodes/KWAfterAllNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWBlockNode.h" 9 | #import "KWExampleNode.h" 10 | 11 | @interface KWAfterAllNode : KWBlockNode 12 | 13 | #pragma mark - Initializing 14 | 15 | + (id)afterAllNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Nodes/KWAfterAllNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWAfterAllNode.h" 8 | #import "KWExampleNodeVisitor.h" 9 | 10 | @implementation KWAfterAllNode 11 | 12 | #pragma mark - Initializing 13 | 14 | + (id)afterAllNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block { 15 | return [[self alloc] initWithCallSite:aCallSite description:nil block:block]; 16 | } 17 | 18 | #pragma mark - Accepting Visitors 19 | 20 | - (void)acceptExampleNodeVisitor:(id)aVisitor { 21 | [aVisitor visitAfterAllNode:self]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Nodes/KWAfterEachNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWBlockNode.h" 9 | #import "KWExampleNode.h" 10 | 11 | @interface KWAfterEachNode : KWBlockNode 12 | 13 | #pragma mark - Initializing 14 | 15 | + (id)afterEachNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Nodes/KWAfterEachNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWAfterEachNode.h" 8 | #import "KWExampleNodeVisitor.h" 9 | 10 | @implementation KWAfterEachNode 11 | 12 | #pragma mark - Initializing 13 | 14 | + (id)afterEachNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block { 15 | return [[self alloc] initWithCallSite:aCallSite description:nil block:block]; 16 | } 17 | 18 | #pragma mark - Accepting Visitors 19 | 20 | - (void)acceptExampleNodeVisitor:(id)aVisitor { 21 | [aVisitor visitAfterEachNode:self]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Nodes/KWBeforeAllNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWBlockNode.h" 9 | #import "KWExampleNode.h" 10 | 11 | @interface KWBeforeAllNode : KWBlockNode 12 | 13 | #pragma mark - Initializing 14 | 15 | + (id)beforeAllNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Nodes/KWBeforeAllNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeforeAllNode.h" 8 | #import "KWExampleNodeVisitor.h" 9 | 10 | @implementation KWBeforeAllNode 11 | 12 | #pragma mark - Initializing 13 | 14 | + (id)beforeAllNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block { 15 | return [[self alloc] initWithCallSite:aCallSite description:nil block:block]; 16 | } 17 | 18 | #pragma mark - Accepting Visitors 19 | 20 | - (void)acceptExampleNodeVisitor:(id)aVisitor { 21 | [aVisitor visitBeforeAllNode:self]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Nodes/KWBeforeEachNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWBlockNode.h" 9 | #import "KWExampleNode.h" 10 | 11 | @interface KWBeforeEachNode : KWBlockNode 12 | 13 | #pragma mark - Initializing 14 | 15 | + (id)beforeEachNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Nodes/KWBeforeEachNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBeforeEachNode.h" 8 | #import "KWExampleNodeVisitor.h" 9 | 10 | @implementation KWBeforeEachNode 11 | 12 | #pragma mark - Initializing 13 | 14 | + (id)beforeEachNodeWithCallSite:(KWCallSite *)aCallSite block:(void (^)(void))block { 15 | return [[self alloc] initWithCallSite:aCallSite description:nil block:block]; 16 | } 17 | 18 | #pragma mark - Accepting Visitors 19 | 20 | - (void)acceptExampleNodeVisitor:(id)aVisitor { 21 | [aVisitor visitBeforeEachNode:self]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Nodes/KWBlockNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWBlock.h" 9 | 10 | @class KWCallSite; 11 | 12 | @interface KWBlockNode : NSObject 13 | 14 | #pragma mark - Initializing 15 | 16 | - (id)initWithCallSite:(KWCallSite *)aCallSite description:(NSString *)aDescription block:(void (^)(void))block; 17 | 18 | #pragma mark - Getting Call Sites 19 | 20 | @property (nonatomic, strong, readonly) KWCallSite *callSite; 21 | 22 | #pragma mark - Getting Descriptions 23 | 24 | @property (nonatomic, copy) NSString *description; 25 | 26 | #pragma mark - Getting Blocks 27 | 28 | @property (nonatomic, copy, readonly) void (^block)(void); 29 | 30 | #pragma mark - Performing blocks 31 | 32 | - (void)performBlock; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Nodes/KWBlockNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWBlockNode.h" 8 | 9 | @implementation KWBlockNode 10 | 11 | #pragma mark - Initializing 12 | 13 | - (id)initWithCallSite:(KWCallSite *)aCallSite description:(NSString *)aDescription block:(void (^)(void))block { 14 | self = [super init]; 15 | if (self) { 16 | _callSite = aCallSite; 17 | _description = aDescription; 18 | _block = [block copy]; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | - (void)performBlock { 25 | if (self.block != nil) { self.block(); } 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/Nodes/KWContextNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWExampleNode.h" 9 | 10 | @class KWAfterAllNode; 11 | @class KWAfterEachNode; 12 | @class KWBeforeAllNode; 13 | @class KWBeforeEachNode; 14 | @class KWCallSite; 15 | @class KWLetNode; 16 | @class KWItNode; 17 | @class KWPendingNode; 18 | @class KWRegisterMatchersNode; 19 | @class KWExample; 20 | 21 | @interface KWContextNode : NSObject 22 | 23 | #pragma mark - Initializing 24 | 25 | - (id)initWithCallSite:(KWCallSite *)aCallSite parentContext:(KWContextNode *)node description:(NSString *)aDescription; 26 | 27 | + (id)contextNodeWithCallSite:(KWCallSite *)aCallSite parentContext:(KWContextNode *)contextNode description:(NSString *)aDescription; 28 | 29 | #pragma mark - Getting Call Sites 30 | 31 | @property (nonatomic, weak, readonly) KWCallSite *callSite; 32 | 33 | #pragma mark - Getting Descriptions 34 | 35 | @property (nonatomic, readonly) NSString *description; 36 | 37 | #pragma mark - Managing Nodes 38 | 39 | @property (nonatomic, strong) KWBeforeAllNode *beforeAllNode; 40 | @property (nonatomic, strong) KWAfterAllNode *afterAllNode; 41 | @property (nonatomic, strong) KWBeforeEachNode *beforeEachNode; 42 | @property (nonatomic, strong) KWAfterEachNode *afterEachNode; 43 | @property (nonatomic, readonly) NSArray *nodes; 44 | @property (nonatomic, readonly) NSArray *registerMatchersNodes; 45 | @property (nonatomic, readonly) NSArray *letNodes; 46 | 47 | @property (nonatomic, readonly) KWContextNode *parentContext; 48 | 49 | @property (nonatomic, assign) BOOL isFocused; 50 | 51 | - (void)addContextNode:(KWContextNode *)aNode; 52 | - (void)addLetNode:(KWLetNode *)aNode; 53 | - (void)addRegisterMatchersNode:(KWRegisterMatchersNode *)aNode; 54 | - (void)addItNode:(KWItNode *)aNode; 55 | - (void)addPendingNode:(KWPendingNode *)aNode; 56 | 57 | - (KWLetNode *)letNodeTree; 58 | 59 | - (void)performExample:(KWExample *)example withBlock:(void (^)(void))exampleBlock; 60 | 61 | #pragma mark - Accepting Visitors 62 | 63 | - (void)acceptExampleNodeVisitor:(id)aVisitor; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Classes/Nodes/KWExampleNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @class KWContextNode; 10 | @protocol KWExampleNodeVisitor; 11 | 12 | @protocol KWExampleNode 13 | 14 | #pragma mark - Accepting Visitors 15 | 16 | - (void)acceptExampleNodeVisitor:(id)aVisitor; 17 | 18 | @optional 19 | 20 | - (NSArray *)contextStack; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Classes/Nodes/KWItNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWBlockNode.h" 9 | #import "KWExampleNode.h" 10 | 11 | @class KWPendingNode; 12 | @class KWExample; 13 | @class KWContextNode; 14 | 15 | @interface KWItNode : KWBlockNode 16 | 17 | @property (nonatomic, strong) KWExample *example; 18 | @property (nonatomic, weak, readonly) KWContextNode *context; 19 | 20 | #pragma mark - Initializing 21 | 22 | + (id)itNodeWithCallSite:(KWCallSite *)aCallSite 23 | description:(NSString *)aDescription 24 | context:(KWContextNode *)context 25 | block:(void (^)(void))block; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Classes/Nodes/KWItNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWItNode.h" 8 | #import "KWExampleNodeVisitor.h" 9 | #import "KWExample.h" 10 | #import "KWVerifying.h" 11 | #import "KWContextNode.h" 12 | 13 | @interface KWItNode () 14 | 15 | @property (nonatomic, weak) KWContextNode *context; 16 | 17 | @end 18 | 19 | @implementation KWItNode 20 | 21 | #pragma mark - Initializing 22 | 23 | + (id)itNodeWithCallSite:(KWCallSite *)aCallSite 24 | description:(NSString *)aDescription 25 | context:(KWContextNode *)context 26 | block:(void (^)(void))block { 27 | KWItNode *itNode = [[self alloc] initWithCallSite:aCallSite description:aDescription block:block]; 28 | itNode.context = context; 29 | return itNode; 30 | } 31 | 32 | #pragma mark - Accepting Visitors 33 | 34 | - (void)acceptExampleNodeVisitor:(id)aVisitor { 35 | [aVisitor visitItNode:self]; 36 | } 37 | 38 | #pragma mark - Runtime Description support 39 | 40 | - (NSString *)description { 41 | NSString *description = [super description]; 42 | if (description == nil) { 43 | description = [self.example generateDescriptionForAnonymousItNode]; 44 | } 45 | return description; 46 | } 47 | 48 | #pragma mark - Accessing the context stack 49 | 50 | - (NSArray *)contextStack { 51 | NSMutableArray *contextStack = [NSMutableArray array]; 52 | 53 | KWContextNode *currentContext = _context; 54 | 55 | while (currentContext) { 56 | [contextStack addObject:currentContext]; 57 | currentContext = currentContext.parentContext; 58 | } 59 | return contextStack; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Classes/Nodes/KWLetNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWExampleNode.h" 9 | 10 | @interface KWLetNode : NSObject 11 | 12 | - (instancetype)initWithSymbolName:(NSString *)aSymbolName objectRef:(id *)anObjectRef block:(id (^)(void))block; 13 | + (instancetype)letNodeWithSymbolName:(NSString *)aSymbolName objectRef:(id *)anObjectRef block:(id (^)(void))block; 14 | 15 | @property (nonatomic, copy) NSString *symbolName; 16 | @property (nonatomic, copy) id (^block)(void); 17 | @property (nonatomic, readonly) __autoreleasing id *objectRef; 18 | 19 | - (id)evaluate; 20 | - (void)evaluateTree; 21 | 22 | - (void)addLetNode:(KWLetNode *)aNode; 23 | - (void)unlink; 24 | 25 | // The parent/child relationship describes let nodes declared in nested 26 | // contexts -- evaluating a node returns the value of the deepest 27 | // evaluated child. 28 | @property (nonatomic, readonly, weak) KWLetNode *parent; 29 | @property (nonatomic, readonly, strong) KWLetNode *child; 30 | 31 | // The next/previous relationship describes the order in which nodes 32 | // of different symbols were declared. 33 | @property (nonatomic, readonly, strong) KWLetNode *next; 34 | @property (nonatomic, readonly, weak) KWLetNode *previous; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/Nodes/KWPendingNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWExampleNode.h" 9 | 10 | @class KWContextNode; 11 | @class KWCallSite; 12 | 13 | @interface KWPendingNode : NSObject 14 | 15 | @property (nonatomic, readonly, strong) KWContextNode *context; 16 | 17 | #pragma mark - Initializing 18 | 19 | - (id)initWithCallSite:(KWCallSite *)aCallSite context:(KWContextNode *)context description:(NSString *)aDescription; 20 | 21 | + (id)pendingNodeWithCallSite:(KWCallSite *)aCallSite context:(KWContextNode *)context description:(NSString *)aDescription; 22 | 23 | #pragma mark - Getting Call Sites 24 | 25 | @property (nonatomic, readonly) KWCallSite *callSite; 26 | 27 | #pragma mark - Getting Descriptions 28 | 29 | @property (nonatomic, readonly) NSString *description; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Classes/Nodes/KWPendingNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWPendingNode.h" 8 | 9 | #import "KWCallSite.h" 10 | #import "KWContextNode.h" 11 | #import "KWExampleNodeVisitor.h" 12 | 13 | @implementation KWPendingNode 14 | 15 | #pragma mark - Initializing 16 | 17 | - (id)initWithCallSite:(KWCallSite *)aCallSite context:(KWContextNode *)context description:(NSString *)aDescription { 18 | self = [super init]; 19 | if (self) { 20 | _callSite = aCallSite; 21 | _description = [aDescription copy]; 22 | _context = context; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | + (id)pendingNodeWithCallSite:(KWCallSite *)aCallSite context:(KWContextNode *)context description:(NSString *)aDescription { 29 | return [[self alloc] initWithCallSite:aCallSite context:context description:aDescription]; 30 | } 31 | 32 | #pragma mark - Accepting Visitors 33 | 34 | - (void)acceptExampleNodeVisitor:(id)aVisitor { 35 | [aVisitor visitPendingNode:self]; 36 | } 37 | 38 | #pragma mark - Accessing the context stack 39 | 40 | - (NSArray *)contextStack 41 | { 42 | NSMutableArray *contextStack = [NSMutableArray array]; 43 | 44 | KWContextNode *currentContext = _context; 45 | 46 | while (currentContext) { 47 | [contextStack addObject:currentContext]; 48 | currentContext = currentContext.parentContext; 49 | } 50 | return contextStack; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Classes/Nodes/KWRegisterMatchersNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWExampleNode.h" 9 | 10 | @class KWCallSite; 11 | 12 | @interface KWRegisterMatchersNode : NSObject 13 | 14 | #pragma mark - Initializing 15 | 16 | - (id)initWithCallSite:(KWCallSite *)aCallSite namespacePrefix:(NSString *)aNamespacePrefix; 17 | 18 | + (id)registerMatchersNodeWithCallSite:(KWCallSite *)aCallSite namespacePrefix:(NSString *)aNamespacePrefix; 19 | 20 | #pragma mark - Getting Call Sites 21 | 22 | @property (nonatomic, readonly) KWCallSite *callSite; 23 | 24 | #pragma mark - Getting Namespace Prefixes 25 | 26 | @property (nonatomic, readonly) NSString *namespacePrefix; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/Nodes/KWRegisterMatchersNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWRegisterMatchersNode.h" 8 | 9 | #import "KWCallSite.h" 10 | #import "KWExampleNodeVisitor.h" 11 | 12 | @implementation KWRegisterMatchersNode 13 | 14 | #pragma mark - Initializing 15 | 16 | - (id)initWithCallSite:(KWCallSite *)aCallSite namespacePrefix:(NSString *)aNamespacePrefix { 17 | self = [super init]; 18 | if (self) { 19 | _callSite = aCallSite; 20 | _namespacePrefix = [aNamespacePrefix copy]; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | + (id)registerMatchersNodeWithCallSite:(KWCallSite *)aCallSite namespacePrefix:(NSString *)aNamespacePrefix { 27 | return [[self alloc] initWithCallSite:aCallSite namespacePrefix:aNamespacePrefix]; 28 | } 29 | 30 | #pragma mark - Accepting Visitors 31 | 32 | - (void)acceptExampleNodeVisitor:(id)aVisitor { 33 | [aVisitor visitRegisterMatchersNode:self]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/Stubbing/KWIntercept.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import 9 | 10 | @class KWMessagePattern; 11 | @class KWStub; 12 | 13 | #pragma mark - Getting Forwarding Implementations 14 | 15 | IMP KWRegularForwardingImplementation(void); 16 | IMP KWStretForwardingImplementation(void); 17 | IMP KWForwardingImplementationForMethodEncoding(const char* encoding); 18 | 19 | #pragma mark - Getting Intercept Class Information 20 | 21 | BOOL KWObjectIsClass(id anObject); 22 | BOOL KWClassIsInterceptClass(Class aClass); 23 | NSString *KWInterceptClassNameForClass(Class aClass); 24 | Class KWInterceptClassForCanonicalClass(Class canonicalClass); 25 | Class KWRealClassForClass(Class aClass); 26 | 27 | #pragma mark - Enabling Intercepting 28 | 29 | Class KWSetupObjectInterceptSupport(id anObject); 30 | void KWSetupMethodInterceptSupport(Class interceptClass, SEL aSelector); 31 | 32 | #pragma mark - Managing Stubs & Spies 33 | void KWClearStubsAndSpies(void); 34 | 35 | #pragma mark - Managing Objects Stubs 36 | 37 | void KWAssociateObjectStub(id anObject, KWStub *aStub, BOOL overrideExisting); 38 | void KWClearObjectStubs(id anObject); 39 | void KWClearAllObjectStubs(void); 40 | 41 | #pragma mark - Managing Message Spies 42 | 43 | void KWAssociateMessageSpy(id anObject, id aSpy, KWMessagePattern *aMessagePattern); 44 | void KWClearObjectSpy(id anObject, id aSpy, KWMessagePattern *aMessagePattern); 45 | void KWClearAllMessageSpies(void); 46 | -------------------------------------------------------------------------------- /Classes/Stubbing/KWStub.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @class KWMessagePattern; 10 | 11 | @interface KWStub : NSObject 12 | 13 | #pragma mark - Initializing 14 | 15 | - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern; 16 | - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue; 17 | - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern block:(id (^)(NSArray *params))aBlock; 18 | - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue times:(id)times afterThatReturn:(id)aSecondValue; 19 | 20 | + (id)stubWithMessagePattern:(KWMessagePattern *)aMessagePattern; 21 | + (id)stubWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue; 22 | + (id)stubWithMessagePattern:(KWMessagePattern *)aMessagePattern block:(id (^)(NSArray *params))aBlock; 23 | + (id)stubWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue times:(id)times afterThatReturn:(id)aSecondValue; 24 | 25 | #pragma mark - Properties 26 | 27 | @property (nonatomic, readonly) KWMessagePattern *messagePattern; 28 | @property (nonatomic, readonly) id value; 29 | @property (nonatomic, readonly) id returnValueTimes; 30 | @property (nonatomic, readonly) int returnedValueTimes; 31 | @property (nonatomic, readonly) id secondValue; 32 | 33 | #pragma mark - Processing Invocations 34 | 35 | - (BOOL)processInvocation:(NSInvocation *)anInvocation; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Classes/Verifiers/KWAsyncVerifier.h: -------------------------------------------------------------------------------- 1 | // 2 | // KWAsyncVerifier.h 3 | // iOSFalconCore 4 | // 5 | // Created by Luke Redpath on 13/01/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KWMatchVerifier.h" 11 | #import "KWProbe.h" 12 | 13 | #define kKW_DEFAULT_PROBE_TIMEOUT 1.0 14 | 15 | @class KWAsyncMatcherProbe; 16 | 17 | 18 | @interface KWAsyncVerifier : KWMatchVerifier 19 | 20 | @property (nonatomic, assign) NSTimeInterval timeout; 21 | @property (nonatomic, assign) BOOL shouldWait; 22 | 23 | + (id)asyncVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter probeTimeout:(NSTimeInterval)probeTimeout shouldWait:(BOOL)shouldWait; 24 | - (void)verifyWithProbe:(KWAsyncMatcherProbe *)aProbe; 25 | 26 | @end 27 | 28 | 29 | @interface KWAsyncMatcherProbe : NSObject 30 | 31 | @property (nonatomic, assign) BOOL matchResult; 32 | @property (nonatomic, readonly) id matcher; 33 | 34 | - (id)initWithMatcher:(id)aMatcher; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/Verifiers/KWExistVerifier.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWExpectationType.h" 9 | #import "KWVerifying.h" 10 | 11 | @class KWCallSite; 12 | 13 | @protocol KWReporting; 14 | 15 | @interface KWExistVerifier : NSObject 16 | 17 | #pragma mark - Initializing 18 | 19 | - (id)initWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite reporter:(id)aReporter; 20 | 21 | + (id)existVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite reporter:(id)aReporter; 22 | 23 | #pragma mark - Properties 24 | 25 | @property (nonatomic, strong) id subject; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Classes/Verifiers/KWExistVerifier.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KWExistVerifier.h" 8 | 9 | #import "KWCallSite.h" 10 | #import "KWFailure.h" 11 | #import "KWFormatter.h" 12 | #import "KWReporting.h" 13 | 14 | @interface KWExistVerifier() 15 | 16 | @property (nonatomic, readonly) KWExpectationType expectationType; 17 | @property (nonatomic, readonly) id reporter; 18 | 19 | @property (nonatomic, strong) KWCallSite *callSite; 20 | 21 | @end 22 | 23 | @implementation KWExistVerifier 24 | 25 | #pragma mark - Initializing 26 | 27 | - (id)initWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite reporter:(id)aReporter { 28 | self = [super init]; 29 | if (self) { 30 | _expectationType = anExpectationType; 31 | _callSite = aCallSite; 32 | _reporter = aReporter; 33 | } 34 | 35 | return self; 36 | } 37 | 38 | + (id)existVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite reporter:(id)aReporter { 39 | return [[self alloc] initWithExpectationType:anExpectationType callSite:aCallSite reporter:aReporter]; 40 | } 41 | 42 | 43 | - (NSString *)descriptionForAnonymousItNode { 44 | if (self.expectationType == KWExpectationTypeShould) { 45 | return @"should exist"; 46 | } 47 | return @"should not exist"; 48 | } 49 | 50 | #pragma mark - Ending Examples 51 | 52 | - (void)exampleWillEnd { 53 | if (self.expectationType == KWExpectationTypeShould && self.subject == nil) { 54 | KWFailure *failure = [KWFailure failureWithCallSite:self.callSite message:@"expected subject not to be nil"]; 55 | [self.reporter reportFailure:failure]; 56 | } else if (self.expectationType == KWExpectationTypeShouldNot && self.subject != nil) { 57 | KWFailure *failure = [KWFailure failureWithCallSite:self.callSite format:@"expected subject to be nil, got %@", 58 | [KWFormatter formatObject:self.subject]]; 59 | [self.reporter reportFailure:failure]; 60 | } 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Classes/Verifiers/KWMatchVerifier.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | #import "KWExpectationType.h" 9 | #import "KWVerifying.h" 10 | 11 | @class KWCallSite; 12 | @class KWMatcherFactory; 13 | 14 | @protocol KWMatching; 15 | @protocol KWReporting; 16 | 17 | @interface KWMatchVerifier : NSObject 18 | 19 | #pragma mark - Properties 20 | 21 | @property (nonatomic, readonly) KWExpectationType expectationType; 22 | 23 | @property (nonatomic, readonly) KWMatcherFactory *matcherFactory; 24 | @property (nonatomic, readonly) id reporter; 25 | 26 | @property (nonatomic, strong) id subject; 27 | 28 | 29 | #pragma mark - Initializing 30 | 31 | - (id)initForShouldWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; 32 | - (id)initForShouldNotWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; 33 | - (id)initWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; 34 | 35 | + (id)matchVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; 36 | 37 | - (void)verifyWithMatcher:(id)aMatcher; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/Verifiers/KWVerifying.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @class KWCallSite; 10 | 11 | @protocol KWVerifying 12 | 13 | @property (nonatomic, readonly) KWCallSite *callSite; 14 | 15 | - (NSString *)descriptionForAnonymousItNode; 16 | 17 | #pragma mark - Subjects 18 | 19 | @property (nonatomic, strong) id subject; 20 | 21 | #pragma mark - Ending Examples 22 | 23 | - (void)exampleWillEnd; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Kiwi.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'Kiwi' 3 | s.version = '2.2.4' 4 | s.summary = 'A Behavior Driven Development library for iOS and OS X.' 5 | s.homepage = 'https://github.com/allending/Kiwi' 6 | s.authors = { 'Allen Ding' => 'alding@gmail.com', 'Luke Redpath' => 'luke@lukeredpath.co.uk', 'Marin Usalj' => 'mneorr@gmail.com', 'Stepan Hruda' => 'stepan.hruda@gmail.com' } 7 | s.license = { :type => 'MIT', :file => 'License.txt' } 8 | s.source = { :git => 'https://github.com/allending/Kiwi.git', :tag => s.version.to_s } 9 | s.ios.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SDKROOT)/Developer/Library/Frameworks" "$(DEVELOPER_LIBRARY_DIR)/Frameworks"' } 10 | s.osx.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(DEVELOPER_LIBRARY_DIR)/Frameworks"' } 11 | s.ios.deployment_target = '5.0' 12 | s.osx.deployment_target = '10.7' 13 | s.default_subspec = 'SenTestingKit' 14 | 15 | s.subspec 'SenTestingKit' do |sentest| 16 | sentest.framework = 'SenTestingKit' 17 | sentest.dependency 'Kiwi/ARC' 18 | sentest.dependency 'Kiwi/NonARC' 19 | sentest.source_files = 'SenTestingKit/**/*.{h,m}' 20 | sentest.prefix_header_contents = <<-EOS 21 | #import 22 | EOS 23 | end 24 | 25 | s.subspec 'XCTest' do |xctest| 26 | xctest.framework = 'XCTest' 27 | xctest.dependency 'Kiwi/ARC' 28 | xctest.dependency 'Kiwi/NonARC' 29 | xctest.prefix_header_contents = <<-EOS 30 | #import 31 | EOS 32 | end 33 | 34 | s.subspec 'ARC' do |arc| 35 | arc.source_files = 'Classes/**/*.{h,m}' 36 | arc.requires_arc = true 37 | end 38 | 39 | s.subspec 'NonARC' do |nonarc| 40 | nonarc.source_files = 'NonARC/**/*.{h,m}' 41 | nonarc.compiler_flags = '-fno-objc-arc' 42 | end 43 | 44 | end 45 | 46 | -------------------------------------------------------------------------------- /Kiwi.xcodeproj/xcshareddata/xcschemes/Kiwi-OSX.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 44 | 45 | 51 | 52 | 54 | 55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Kiwi.xcodeproj/xcshareddata/xcschemes/Kiwi-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 44 | 45 | 51 | 52 | 54 | 55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /KiwiXCTests/KWXCFunctionalTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWXCFunctionalTest.m 3 | // KiwiXCTests 4 | // 5 | // Created by Brian Ivan Gesiak on 9/13/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "Kiwi.h" 10 | 11 | SPEC_BEGIN(XCFunctionalTest) 12 | 13 | NSMutableArray *calls = [@[ 14 | @"it", 15 | @"describe-beforeAll", 16 | @"describe-beforeEach", 17 | @"describe-afterEach", 18 | @"describe-afterAll", 19 | @"describe-it", 20 | @"describe-context-beforeAll", 21 | @"describe-context-beforeEach", 22 | @"describe-context-afterEach", 23 | @"describe-context-afterAll", 24 | @"describe-context-it" 25 | ] mutableCopy]; 26 | 27 | it(@"is a top-level it block", ^{ 28 | [calls removeObject:@"it"]; 29 | [[theValue([calls count]) should] equal:theValue(10)]; 30 | }); 31 | 32 | describe(@"within a describe block", ^{ 33 | beforeAll(^{ [calls removeObject:@"describe-beforeAll"]; }); 34 | beforeEach(^{ [calls removeObject:@"describe-beforeEach"]; }); 35 | 36 | it(@"is a nested it block", ^{ 37 | [calls removeObject:@"describe-it"]; 38 | [[theValue([calls count]) should] equal:theValue(7)]; 39 | }); 40 | 41 | context(@"within a nested context block", ^{ 42 | beforeAll(^{ [calls removeObject:@"describe-context-beforeAll"]; }); 43 | beforeEach(^{ [calls removeObject:@"describe-context-beforeEach"]; }); 44 | 45 | it(@"is a nested it block", ^{ 46 | [calls removeObject:@"describe-context-it"]; 47 | [[theValue([calls count]) should] equal:theValue(3)]; 48 | }); 49 | 50 | afterEach(^{ [calls removeObject:@"describe-context-afterEach"]; }); 51 | afterAll(^{ [calls removeObject:@"describe-context-afterAll"]; }); 52 | }); 53 | 54 | afterEach(^{ [calls removeObject:@"describe-afterEach"]; }); 55 | afterAll(^{ 56 | [calls removeObject:@"describe-afterAll"]; 57 | if ([calls count] > 0) { 58 | [NSException raise:NSInternalInconsistencyException 59 | format:@"Not all XCFunctionalTest spec blocks were run."]; 60 | } 61 | }); 62 | }); 63 | 64 | SPEC_END 65 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Allen Ding 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of Allen Ding nor the names of any contributors may be 15 | used to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: clean ios 2 | 3 | clean: 4 | xcodebuild clean 5 | rm -rf output 6 | 7 | ios: 8 | xcodebuild -project Kiwi.xcodeproj -scheme Kiwi-iOS build 9 | 10 | install: 11 | xcodebuild -project Kiwi.xcodeproj -scheme Kiwi-iOS install 12 | 13 | test: 14 | xcodebuild -project Kiwi.xcodeproj -scheme Kiwi -sdk iphonesimulator test 15 | 16 | ci: test 17 | 18 | -------------------------------------------------------------------------------- /NonARC/KWMessagePattern.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiConfiguration.h" 8 | 9 | @interface KWMessagePattern : NSObject 10 | 11 | #pragma mark - Initializing 12 | 13 | - (id)initWithSelector:(SEL)aSelector; 14 | - (id)initWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray; 15 | - (id)initWithSelector:(SEL)aSelector firstArgumentFilter:(id)firstArgumentFilter argumentList:(va_list)argumentList; 16 | 17 | + (id)messagePatternWithSelector:(SEL)aSelector; 18 | + (id)messagePatternWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray; 19 | + (id)messagePatternWithSelector:(SEL)aSelector firstArgumentFilter:(id)firstArgumentFilter argumentList:(va_list)argumentList; 20 | 21 | + (id)messagePatternFromInvocation:(NSInvocation *)anInvocation; 22 | 23 | #pragma mark - Properties 24 | 25 | @property (nonatomic, readonly) SEL selector; 26 | @property (nonatomic, readonly) NSArray *argumentFilters; 27 | 28 | #pragma mark - Matching Invocations 29 | 30 | - (BOOL)matchesInvocation:(NSInvocation *)anInvocation; 31 | 32 | #pragma mark - Comparing Message Patterns 33 | 34 | - (BOOL)isEqualToMessagePattern:(KWMessagePattern *)aMessagePattern; 35 | 36 | #pragma mark - Retrieving String Representations 37 | 38 | - (NSString *)stringValue; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Simple BDD for iOS # 2 | 3 | ## Kiwi has moved to the kiwi-bdd organization here: (https://github.com/kiwi-bdd/Kiwi). Please go there. allending/Kiwi is now a personal fork used to submit PRs. 4 | 5 | [![Build Status](https://travis-ci.org/kiwi-bdd/Kiwi.svg?branch=master)](https://travis-ci.org/kiwi-bdd/Kiwi) 6 | 7 | Kiwi is a Behavior Driven Development library for iOS development. 8 | The goal is to provide a BDD library that is exquisitely simple to setup and use. 9 | 10 | ## Why? 11 | The idea behind Kiwi is to have tests that are more readable than what is possible with the bundled test framework. 12 | 13 | Tests (or rather specs) are written in Objective-C and run within the comfort of Xcode to provide a test environment that is as unobtrusive and seamless as possible in terms of running tests and error reporting. 14 | 15 | Specs look like this: 16 | 17 | ```objective-c 18 | describe(@"Team", ^{ 19 | context(@"when newly created", ^{ 20 | it(@"should have a name", ^{ 21 | id team = [Team team]; 22 | [[team.name should] equal:@"Black Hawks"]; 23 | }); 24 | 25 | it(@"should have 11 players", ^{ 26 | id team = [Team team]; 27 | [[[team should] have:11] players]; 28 | }); 29 | }); 30 | }); 31 | ``` 32 | 33 | ## Documentation 34 | The [Kiwi Wiki](https://github.com/kiwi-bdd/Kiwi/wiki) is the official documentation source. 35 | 36 | ## Getting it 37 | The best way to get Kiwi is by using [CocoaPods](https://github.com/cocoapods/cocoapods). 38 | For all the installation details, check out the [Wiki](https://github.com/kiwi-bdd/Kiwi/wiki) 39 | 40 | ## Support 41 | For all the questions / suggestions you have, that aren't bug reports please use our [Google Group](https://groups.google.com/forum/#!forum/kiwi-bdd) 42 | 43 | -------------------------------------------------------------------------------- /SenTestingKit/SenTestSuite+KiwiAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // SenTestSuite+KiwiAdditions.h 3 | // Kiwi 4 | // 5 | // Created by Jerry Marino on 5/17/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SenTestSuite (KiwiAdditions) 12 | 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Supporting Files/Kiwi-Prefix.pch: -------------------------------------------------------------------------------- 1 | #import 2 | -------------------------------------------------------------------------------- /Supporting Files/Kiwi-XCTest-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Kiwi-XCTest-Prefix.pch 3 | // Kiwi 4 | // 5 | // Created by Brian Ivan Gesiak on 9/13/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #ifndef Kiwi_Kiwi_XCTest_Prefix_pch 10 | #define Kiwi_Kiwi_XCTest_Prefix_pch 11 | 12 | #import 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /Tests/KWBeBetweenMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWBeBetweenMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWBeBetweenMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeBetweenMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beBetween:and:", @"beInTheIntervalFrom:to:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchIncludedElements { 28 | id subject = [KWValue valueWithInt:42]; 29 | id matcher = [KWBeBetweenMatcher matcherWithSubject:subject]; 30 | [matcher beBetween:[KWValue valueWithInt:40] and:[KWValue valueWithInt:50]]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchIncludedElements { 35 | id subject = [KWValue valueWithInt:42]; 36 | id matcher = [KWBeBetweenMatcher matcherWithSubject:subject]; 37 | [matcher beBetween:[KWValue valueWithInt:50] and:[KWValue valueWithInt:60]]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | - (void)testItShouldHaveHumanReadableDescription 42 | { 43 | id matcher = [KWBeBetweenMatcher matcherWithSubject:[KWValue valueWithInt:0]]; 44 | [matcher beBetween:[KWValue valueWithInt:10] and:[KWValue valueWithInt:20]]; 45 | STAssertEqualObjects([matcher description], @"be between 10 and 20", @"expected description to match"); 46 | } 47 | 48 | @end 49 | 50 | #endif // #if KW_TESTS_ENABLED 51 | -------------------------------------------------------------------------------- /Tests/KWBeEmptyMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWEmptyCollectionMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWEmptyCollectionMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeEmptyMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beEmpty"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchEmptyCollections { 28 | id subject = @{}; 29 | id matcher = [KWBeEmptyMatcher matcherWithSubject:subject]; 30 | [matcher beEmpty]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchNonEmptyCollections { 35 | id subject = @{@"foo": @"bar"}; 36 | id matcher = [KWBeEmptyMatcher matcherWithSubject:subject]; 37 | [matcher beEmpty]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | 42 | - (void)testItShouldHaveHumanReadableDescription 43 | { 44 | id matcher = [KWBeEmptyMatcher matcherWithSubject:nil]; 45 | STAssertEqualObjects(@"be empty", [matcher description], @"description should match"); 46 | } 47 | 48 | @end 49 | 50 | #endif // #if KW_TESTS_ENABLED 51 | -------------------------------------------------------------------------------- /Tests/KWBeIndenticalToMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWBeIdenticalToMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWBeIdenticalToMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeIdenticalToMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beIdenticalTo:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchIdenticalObjects { 28 | id subject = [Cruiser cruiser]; 29 | id matcher = [KWBeIdenticalToMatcher matcherWithSubject:subject]; 30 | [matcher beIdenticalTo:subject]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchDifferentObjects { 35 | id subject = [Cruiser cruiser]; 36 | id otherSubject = [Cruiser cruiser]; 37 | id matcher = [KWBeIdenticalToMatcher matcherWithSubject:subject]; 38 | [matcher beIdenticalTo:otherSubject]; 39 | STAssertFalse([matcher evaluate], @"expected negative match"); 40 | } 41 | 42 | - (void)testItShouldHaveHumanReadableDescription 43 | { 44 | id matcher = [KWBeIdenticalToMatcher matcherWithSubject:nil]; 45 | [matcher beIdenticalTo:@"foo"]; 46 | STAssertEqualObjects(@"be identical to foo", [matcher description], @"description should match"); 47 | } 48 | 49 | @end 50 | 51 | #endif // #if KW_TESTS_ENABLED 52 | -------------------------------------------------------------------------------- /Tests/KWBeKindOfClassMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWBeKindOfClassMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWBeKindOfClassMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeKindOfClassMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beKindOfClass:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchKindOfClass { 28 | id subject = [Cruiser cruiser]; 29 | id matcher = [KWBeKindOfClassMatcher matcherWithSubject:subject]; 30 | [matcher beKindOfClass:[SpaceShip class]]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchNonKindOfClass { 35 | id subject = [Cruiser cruiser]; 36 | id matcher = [KWBeKindOfClassMatcher matcherWithSubject:subject]; 37 | [matcher beKindOfClass:[Fighter class]]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | - (void)testItShouldHaveHumanReadableDescription 42 | { 43 | id matcher = [KWBeKindOfClassMatcher matcherWithSubject:nil]; 44 | [matcher beKindOfClass:[Fighter class]]; 45 | STAssertEqualObjects(@"be kind of Fighter", [matcher description], @"description should match"); 46 | } 47 | 48 | - (void)testItShouldHaveInformativeFailureMessageForShould 49 | { 50 | id subject = [Cruiser cruiser]; 51 | id matcher = [KWBeKindOfClassMatcher matcherWithSubject:subject]; 52 | [matcher beKindOfClass:[Fighter class]]; 53 | STAssertEqualObjects([matcher failureMessageForShould], @"expected subject to be kind of Fighter, got Cruiser", @"failure message should match"); 54 | } 55 | 56 | - (void)testItShouldHaveInformativeFailureMessageForShouldNot 57 | { 58 | id subject = [Cruiser cruiser]; 59 | id matcher = [KWBeKindOfClassMatcher matcherWithSubject:subject]; 60 | [matcher beKindOfClass:[Fighter class]]; 61 | STAssertEqualObjects([matcher failureMessageForShouldNot], @"expected subject not to be kind of Fighter, got Cruiser", @"failure message should match"); 62 | } 63 | 64 | @end 65 | 66 | #endif // #if KW_TESTS_ENABLED 67 | -------------------------------------------------------------------------------- /Tests/KWBeMemberOfClassMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWBeMemberOfClassMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWBeMemberOfClassMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeMemberOfClassMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beMemberOfClass:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchMembersOfAClass { 28 | id subject = [Cruiser cruiser]; 29 | id matcher = [KWBeMemberOfClassMatcher matcherWithSubject:subject]; 30 | [matcher beMemberOfClass:[Cruiser class]]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchNonMembersOfAClass { 35 | id subject = [Cruiser cruiser]; 36 | id matcher = [KWBeMemberOfClassMatcher matcherWithSubject:subject]; 37 | [matcher beMemberOfClass:[Fighter class]]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | - (void)testItShouldHaveHumanReadableDescription 42 | { 43 | id matcher = [KWBeMemberOfClassMatcher matcherWithSubject:nil]; 44 | [matcher beMemberOfClass:[Cruiser class]]; 45 | STAssertEqualObjects(@"be member of Cruiser", [matcher description], @"description should match"); 46 | } 47 | 48 | - (void)testItShouldHaveInformativeFailureMessageForShould 49 | { 50 | id subject = [Cruiser cruiser]; 51 | id matcher = [KWBeMemberOfClassMatcher matcherWithSubject:subject]; 52 | [matcher beMemberOfClass:[Fighter class]]; 53 | STAssertEqualObjects([matcher failureMessageForShould], @"expected subject to be member of Fighter, got Cruiser", @"failure message should match"); 54 | } 55 | 56 | - (void)testItShouldHaveInformativeFailureMessageForShouldNot 57 | { 58 | id subject = [Cruiser cruiser]; 59 | id matcher = [KWBeMemberOfClassMatcher matcherWithSubject:subject]; 60 | [matcher beMemberOfClass:[Fighter class]]; 61 | STAssertEqualObjects([matcher failureMessageForShouldNot], @"expected subject not to be member of Fighter, got Cruiser", @"failure message should match"); 62 | } 63 | 64 | @end 65 | 66 | #endif // #if KW_TESTS_ENABLED 67 | -------------------------------------------------------------------------------- /Tests/KWBeSubclassOfClassMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWBeSubclassOfClassMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWBeSubclassOfClassMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeSubclassOfClassMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beSubclassOfClass:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchSubclassesOfAClass { 28 | id subject = [Cruiser class]; 29 | id matcher = [KWBeSubclassOfClassMatcher matcherWithSubject:subject]; 30 | [matcher beSubclassOfClass:[Cruiser class]]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchNonSubclassesOfAClass { 35 | id subject = [Cruiser class]; 36 | id matcher = [KWBeSubclassOfClassMatcher matcherWithSubject:subject]; 37 | [matcher beSubclassOfClass:[Fighter class]]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | - (void)testItShouldHaveHumanReadableDescription 42 | { 43 | id matcher = [KWBeSubclassOfClassMatcher matcherWithSubject:nil]; 44 | [matcher beSubclassOfClass:[Cruiser class]]; 45 | STAssertEqualObjects(@"be subclass of Cruiser", [matcher description], @"description should match"); 46 | } 47 | 48 | - (void)testItShouldHaveInformativeFailureMessageForShould 49 | { 50 | id subject = [Cruiser cruiser]; 51 | id matcher = [KWBeSubclassOfClassMatcher matcherWithSubject:subject]; 52 | [matcher beSubclassOfClass:[Fighter class]]; 53 | STAssertEqualObjects([matcher failureMessageForShould], @"expected subject to be subclass of Fighter, got Cruiser", @"failure message should match"); 54 | } 55 | 56 | - (void)testItShouldHaveInformativeFailureMessageForShouldNot 57 | { 58 | id subject = [Cruiser cruiser]; 59 | id matcher = [KWBeSubclassOfClassMatcher matcherWithSubject:subject]; 60 | [matcher beSubclassOfClass:[Fighter class]]; 61 | STAssertEqualObjects([matcher failureMessageForShouldNot], @"expected subject not to be subclass of Fighter, got Cruiser", @"failure message should match"); 62 | } 63 | 64 | @end 65 | 66 | #endif // #if KW_TESTS_ENABLED 67 | -------------------------------------------------------------------------------- /Tests/KWBeWithinMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWBeWithinMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWBeWithinMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeWithinMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beWithin:of:", @"equal:withDelta:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchCloseObjects { 28 | id subject = [KWValue valueWithInt:42]; 29 | id matcher = [KWBeWithinMatcher matcherWithSubject:subject]; 30 | [matcher beWithin:[KWValue valueWithInt:2] of:[KWValue valueWithInt:40]]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchNonCloseObjects { 35 | id subject = [KWValue valueWithInt:42]; 36 | id matcher = [KWBeWithinMatcher matcherWithSubject:subject]; 37 | [matcher beWithin:[KWValue valueWithInt:1] of:[KWValue valueWithInt:40]]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | - (void)testItShouldHaveHumanReadableDescription 42 | { 43 | id matcher = [KWBeWithinMatcher matcherWithSubject:nil]; 44 | [matcher beWithin:[KWValue valueWithInt:1] of:[KWValue valueWithInt:40]]; 45 | STAssertEqualObjects(@"be within 1 of 40", [matcher description], @"description should match"); 46 | } 47 | 48 | @end 49 | 50 | #endif // #if KW_TESTS_ENABLED 51 | -------------------------------------------------------------------------------- /Tests/KWBeZeroMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Created by Stewart Gleadow on 12/02/14. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWBeZeroMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWBeZeroMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWBeZeroMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"beZero"]; 22 | STAssertEqualObjects(matcherStrings, expectedStrings, @"expected beZero in the matcher strings"); 23 | } 24 | 25 | - (void)testItShouldNotMatchNil { 26 | id matcher = [KWBeZeroMatcher matcherWithSubject:nil]; 27 | [matcher beZero]; 28 | STAssertFalse([matcher evaluate], @"expected negative match for nil subject"); 29 | } 30 | 31 | - (void)testItShouldMatchZeroAsAPrimitive { 32 | id subject = [KWValue valueWithInt:0]; 33 | id matcher = [KWBeZeroMatcher matcherWithSubject:subject]; 34 | [matcher beZero]; 35 | STAssertTrue([matcher evaluate], @"expected positive match for zero as a value"); 36 | } 37 | 38 | - (void)testItShouldNotMatchNonZeroPrimitiveValues { 39 | id subject = [KWValue valueWithInt:42]; 40 | id matcher = [KWBeZeroMatcher matcherWithSubject:subject]; 41 | [matcher beZero]; 42 | STAssertFalse([matcher evaluate], @"expected negative match for primitive non-zero value"); 43 | } 44 | 45 | - (void)testItShouldMatchZeroAsAnNSNumber { 46 | id subject = @0; 47 | id matcher = [KWBeZeroMatcher matcherWithSubject:subject]; 48 | [matcher beZero]; 49 | STAssertTrue([matcher evaluate], @"expected positive match for zero as an NSNumber"); 50 | } 51 | 52 | - (void)testItShouldNotMatchNonZeroNSNumberValues { 53 | id subject = @42; 54 | id matcher = [KWBeZeroMatcher matcherWithSubject:subject]; 55 | [matcher beZero]; 56 | STAssertFalse([matcher evaluate], @"expected negative match for non-zero NSNumber values"); 57 | } 58 | 59 | - (void)testItShouldHaveHumanReadableDescription { 60 | id matcher = [KWBeZeroMatcher matcherWithSubject:nil]; 61 | STAssertEqualObjects(@"be zero", [matcher description], @"description should match"); 62 | } 63 | 64 | @end 65 | 66 | #endif // #if KW_TESTS_ENABLED 67 | -------------------------------------------------------------------------------- /Tests/KWConformToProtocolMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWConformToProtocolMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWConformToProtocolMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWConformToProtocolMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"conformToProtocol:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchConformingObjects { 28 | id subject = [Cruiser cruiser]; 29 | id matcher = [KWConformToProtocolMatcher matcherWithSubject:subject]; 30 | [matcher conformToProtocol:@protocol(JumpCapable)]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchNonConformingObjects { 35 | id subject = [Fighter fighter]; 36 | id matcher = [KWConformToProtocolMatcher matcherWithSubject:subject]; 37 | [matcher conformToProtocol:@protocol(JumpCapable)]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | - (void)testItShouldHaveHumanReadableDescription 42 | { 43 | id matcher = [KWConformToProtocolMatcher matcherWithSubject:nil]; 44 | [matcher conformToProtocol:@protocol(JumpCapable)]; 45 | STAssertEqualObjects(@"conform to JumpCapable protocol", [matcher description], @"description should match"); 46 | } 47 | 48 | @end 49 | 50 | #endif // #if KW_TESTS_ENABLED 51 | -------------------------------------------------------------------------------- /Tests/KWDeviceInfoTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | 10 | #if KW_TESTS_ENABLED 11 | 12 | @interface KWDeviceInfoTest : SenTestCase 13 | 14 | @end 15 | 16 | @implementation KWDeviceInfoTest 17 | 18 | - (void)testItShouldDetectWhenRunningOnSimulator { 19 | #if TARGET_IPHONE_SIMULATOR 20 | BOOL isSimulator = [KWDeviceInfo isSimulator]; 21 | STAssertTrue(isSimulator, @"expected simulator device to be positive"); 22 | #else 23 | BOOL isSimulator = [KWDeviceInfo isSimulator]; 24 | STAssertFalse(isSimulator, @"expected simulator device to be negative"); 25 | #endif // #if TARGET_IPHONE_SIMULATOR 26 | } 27 | 28 | - (void)testItShouldDetectWhenRunningOnDevice { 29 | #if TARGET_IPHONE_SIMULATOR 30 | BOOL isPhysical = [KWDeviceInfo isPhysical]; 31 | STAssertFalse(isPhysical, @"expected physical device to be negative"); 32 | #else 33 | BOOL isPhysical = [KWDeviceInfo isPhysical]; 34 | STAssertTrue(isPhysical, @"expected physical device to be positive"); 35 | #endif // #if TARGET_IPHONE_SIMULATOR 36 | } 37 | 38 | @end 39 | 40 | #endif // #if KW_TESTS_ENABLED 41 | -------------------------------------------------------------------------------- /Tests/KWExampleSuiteBuilderTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWExampleSuiteBuilderTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWExampleSuiteBuilderTest 18 | 19 | - (void)testItShouldBuildExampleSuite { 20 | id exampleSuite = [[KWExampleSuiteBuilder sharedExampleSuiteBuilder] buildExampleSuite:^{}]; 21 | STAssertNotNil(exampleSuite, @"expected example suite to be created"); 22 | STAssertFalse([[KWExampleSuiteBuilder sharedExampleSuiteBuilder] isBuildingExampleSuite], @"example suite builder must be clean for other tests to run cleanly"); 23 | } 24 | 25 | - (void)testItShouldRaiseWhenPopContextUnmatched { 26 | [[KWExampleSuiteBuilder sharedExampleSuiteBuilder] buildExampleSuite:^{ 27 | STAssertThrows([[KWExampleSuiteBuilder sharedExampleSuiteBuilder] popContextNode], @"expected raised exception"); 28 | }]; 29 | STAssertFalse([[KWExampleSuiteBuilder sharedExampleSuiteBuilder] isBuildingExampleSuite], @"example suite builder must be clean for other tests to run cleanly"); 30 | } 31 | 32 | @end 33 | 34 | #endif // #if KW_TESTS_ENABLED 35 | -------------------------------------------------------------------------------- /Tests/KWExampleTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | 10 | #if KW_TESTS_ENABLED 11 | 12 | @interface KWExampleTest : SenTestCase 13 | 14 | @end 15 | 16 | @implementation KWExampleTest 17 | 18 | - (void)testItDoesntThrowExceptionWhenMakingExpectationsOnNilSubject { 19 | KWExample *example = [[KWExample alloc] initWithExampleNode:nil]; 20 | void (^itNodeImitation)() = ^{ 21 | [[(id)nil attachToVerifier:[example addMatchVerifierWithExpectationType:KWExpectationTypeShould callSite:nil]] equal:@"foo"]; 22 | [[(id)nil attachToVerifier:[example addMatchVerifierWithExpectationType:KWExpectationTypeShouldNot callSite:nil]] containString:@"bar"]; 23 | }; 24 | STAssertNoThrow(itNodeImitation(), @"expected no exception"); 25 | } 26 | 27 | @end 28 | 29 | #endif // #if KW_TESTS_ENABLED 30 | -------------------------------------------------------------------------------- /Tests/KWFailureTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWFailureTest.m 3 | // Kiwi 4 | // 5 | // Created by Andrew J Wagner on 2/20/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "KiwiTestConfiguration.h" 10 | #import "TestClasses.h" 11 | #import "KWFailure.h" 12 | 13 | @interface KWFailureTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWFailureTest 18 | 19 | - (void)testExceptionValue { 20 | KWFailure *failure = [KWFailure failureWithCallSite:nil message:@"a message"]; 21 | STAssertNil([failure exceptionValue].userInfo, @"userInfo should be nil since there was no callSite"); 22 | STAssertEquals([failure exceptionValue].reason, @"a message", @"the reason of the exception should be the same as the one used to create the failure"); 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Tests/KWFormatterTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWFormatterTest.m 3 | // Kiwi 4 | // 5 | // Created by Marin Usalj on 3/23/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "Kiwi.h" 10 | #import "KiwiTestConfiguration.h" 11 | 12 | #if KW_TESTS_ENABLED 13 | 14 | @interface KWFormatterTest : SenTestCase 15 | 16 | @end 17 | 18 | @implementation KWFormatterTest 19 | 20 | - (void)testFormatsStringsWithQuotes { 21 | NSString *sampleString = @"sample"; 22 | STAssertEqualObjects(@"\"sample\"", [KWFormatter formatObject:sampleString], @"String should be surrounded with quotes"); 23 | } 24 | 25 | - (void)testFormatsEnumerableCollectionsInline { 26 | NSArray *sampleArray = @[@1, @2, @3]; 27 | STAssertEqualObjects(@"(1, 2, 3)", [KWFormatter formatObject:sampleArray], @"Array objects should be formatted inline"); 28 | } 29 | 30 | - (void)testFormatsDictionariesWithKeysAndValuesMultiline { 31 | NSDictionary *sampleDict = @{ @"foo" : @"bar", @"baz" : @"bang" }; 32 | STAssertEqualObjects([sampleDict description], [KWFormatter formatObject:sampleDict], @"Dictionaries should be not treated as NSEnumerable"); 33 | } 34 | 35 | @end 36 | 37 | #endif // #if KW_TESTS_ENABLED 38 | -------------------------------------------------------------------------------- /Tests/KWGenericMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWGenericMatcherTest.m 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 24/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "Kiwi.h" 10 | #import "KiwiTestConfiguration.h" 11 | #import "TestClasses.h" 12 | 13 | #if KW_TESTS_ENABLED 14 | 15 | @interface KWGenericMatcherTest : SenTestCase 16 | 17 | @end 18 | 19 | @implementation KWGenericMatcherTest 20 | 21 | - (void)testItShouldMatchObjectsThatMatchGenericMatchers 22 | { 23 | id matcher = [KWGenericMatcher matcherWithSubject:@"Alpha Bravo"]; 24 | [matcher match:hasPrefix(@"Alpha")]; 25 | STAssertTrue([matcher evaluate], @"expected positive match"); 26 | } 27 | 28 | - (void)testItShouldNotMatchObjectsThatMatchGenericMatchers 29 | { 30 | id matcher = [KWGenericMatcher matcherWithSubject:@"Charlie Bravo"]; 31 | [matcher match:hasPrefix(@"Alpha")]; 32 | STAssertFalse([matcher evaluate], @"expected negative match"); 33 | } 34 | 35 | - (void)testItShouldHaveHumanReadableDescription 36 | { 37 | id matcher = [KWGenericMatcher matcherWithSubject:nil]; 38 | [matcher match:hasPrefix(@"Alpha")]; 39 | STAssertEqualObjects(@"match a string with prefix 'Alpha'", [matcher description], @"description should match"); 40 | } 41 | 42 | @end 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /Tests/KWObjCUtilitiesTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // KWObjCUtilitiesTest.m 3 | // Kiwi 4 | // 5 | // Created by Brian Ivan Gesiak on 9/16/13. 6 | // Copyright (c) 2013 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "Kiwi.h" 10 | #import "KiwiTestConfiguration.h" 11 | 12 | #if KW_TESTS_ENABLED 13 | 14 | @interface KWObjCUtilitiesTest : SenTestCase 15 | 16 | @end 17 | 18 | @implementation KWObjCUtilitiesTest 19 | 20 | #pragma mark KWObjCTypeIsBoolean 21 | 22 | - (void)testBOOLIsABoolean { 23 | STAssertTrue(KWObjCTypeIsBoolean(@encode(BOOL)), 24 | @"Expected BOOL to be evaluated as a boolean."); 25 | } 26 | 27 | - (void)testStdBoolIsABoolean { 28 | STAssertTrue(KWObjCTypeIsBoolean(@encode(bool)), 29 | @"Expected bool to be evaluated as a boolean."); 30 | } 31 | 32 | - (void)testIntIsNotABoolean { 33 | STAssertFalse(KWObjCTypeIsBoolean(@encode(int)), 34 | @"Did not expect int type to be evaluated as a boolean."); 35 | } 36 | 37 | #pragma mark KWSelectorParameterCount 38 | 39 | - (void)testNumberOfParametersInMethodThatTakesNoParametersIsZero { 40 | STAssertEquals(KWSelectorParameterCount(@selector(description)), (NSUInteger)0, 41 | @"Expected -description to have a parameter count of 0."); 42 | } 43 | 44 | - (void)testNumberOfParametersInMethodThatTakesTwoParametersIsTwo { 45 | STAssertEquals(KWSelectorParameterCount(@selector(performSelector:withObject:)), (NSUInteger)2, 46 | @"Expected -performSelector:withObject: to have a parameter count of 2."); 47 | } 48 | 49 | @end 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /Tests/KWRealObjectSpyTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | #import "KWIntercept.h" 11 | 12 | #if KW_TESTS_ENABLED 13 | 14 | @interface KWRealObjectSpyTest : SenTestCase 15 | 16 | @end 17 | 18 | @implementation KWRealObjectSpyTest 19 | 20 | - (void)tearDown { 21 | KWClearStubsAndSpies(); 22 | } 23 | 24 | - (void)testItShouldNotifySpies { 25 | Cruiser *cruiser = [Cruiser cruiser]; 26 | TestSpy *spy = [TestSpy testSpy]; 27 | [cruiser addMessageSpy:spy forMessagePattern:[KWMessagePattern messagePatternWithSelector:@selector(raiseShields)]]; 28 | [cruiser raiseShields]; 29 | STAssertTrue(spy.wasNotified, @"expected object to notify spies"); 30 | } 31 | 32 | - (void)testItShouldRemoveSpies { 33 | Cruiser *cruiser = [Cruiser cruiser]; 34 | TestSpy *spy = [TestSpy testSpy]; 35 | KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:@selector(raiseShields)]; 36 | [cruiser addMessageSpy:spy forMessagePattern:messagePattern]; 37 | [cruiser removeMessageSpy:spy forMessagePattern:messagePattern]; 38 | [cruiser raiseShields]; 39 | STAssertFalse(spy.wasNotified, @"expected object to remove spies"); 40 | } 41 | 42 | - (void)testItShouldNotifyMultipleSpiesWithDifferentMessagePatterns { 43 | Cruiser *cruiser = [Cruiser cruiser]; 44 | TestSpy *spy1 = [TestSpy testSpy]; 45 | TestSpy *spy2 = [TestSpy testSpy]; 46 | KWMessagePattern *messagePattern1 = [KWMessagePattern messagePatternWithSelector:@selector(energyLevelInWarpCore:)]; 47 | NSArray *argumentFilters = @[[KWValue valueWithUnsignedInt:2]]; 48 | KWMessagePattern *messagePattern2 = [KWMessagePattern messagePatternWithSelector:@selector(energyLevelInWarpCore:) argumentFilters:argumentFilters]; 49 | 50 | [cruiser addMessageSpy:spy1 forMessagePattern:messagePattern1]; 51 | [cruiser addMessageSpy:spy2 forMessagePattern:messagePattern2]; 52 | [cruiser energyLevelInWarpCore:2]; 53 | 54 | STAssertTrue(spy1.wasNotified, @"expected object to notify spies"); 55 | STAssertTrue(spy2.wasNotified, @"expected object to notify spies"); 56 | } 57 | 58 | @end 59 | 60 | #endif // #if KW_TESTS_ENABLED 61 | -------------------------------------------------------------------------------- /Tests/KWRespondToSelectorMatcherTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "TestClasses.h" 10 | 11 | #if KW_TESTS_ENABLED 12 | 13 | @interface KWRespondToSelectorMatcherTest : SenTestCase 14 | 15 | @end 16 | 17 | @implementation KWRespondToSelectorMatcherTest 18 | 19 | - (void)testItShouldHaveTheRightMatcherStrings { 20 | NSArray *matcherStrings = [KWRespondToSelectorMatcher matcherStrings]; 21 | NSArray *expectedStrings = @[@"respondToSelector:"]; 22 | STAssertEqualObjects([matcherStrings sortedArrayUsingSelector:@selector(compare:)], 23 | [expectedStrings sortedArrayUsingSelector:@selector(compare:)], 24 | @"expected specific matcher strings"); 25 | } 26 | 27 | - (void)testItShouldMatchObjectsThatRespondToSelector { 28 | id subject = [Cruiser cruiser]; 29 | id matcher = [KWRespondToSelectorMatcher matcherWithSubject:subject]; 30 | [matcher respondToSelector:@selector(raiseShields)]; 31 | STAssertTrue([matcher evaluate], @"expected positive match"); 32 | } 33 | 34 | - (void)testItShouldNotMatchObjectsThatRespondToSelector { 35 | id subject = [Cruiser cruiser]; 36 | id matcher = [KWRespondToSelectorMatcher matcherWithSubject:subject]; 37 | [matcher respondToSelector:@selector(setObject:forKey:)]; 38 | STAssertFalse([matcher evaluate], @"expected negative match"); 39 | } 40 | 41 | - (void)testItShouldHaveHumanReadableDescription 42 | { 43 | id matcher = [KWRespondToSelectorMatcher matcherWithSubject:theValue(123)]; 44 | [matcher respondToSelector:@selector(setObject:forKey:)]; 45 | STAssertEqualObjects(@"respond to -setObject:forKey:", [matcher description], @"description should match"); 46 | } 47 | 48 | @end 49 | 50 | #endif // #if KW_TESTS_ENABLED 51 | -------------------------------------------------------------------------------- /Tests/KWStringUtilitiesTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | 10 | #if KW_TESTS_ENABLED 11 | 12 | @interface KWStringUtilitiesTest : SenTestCase 13 | 14 | @end 15 | 16 | @implementation KWStringUtilitiesTest 17 | 18 | - (void)testItShouldDetectStringsWithStrictWordPrefixes { 19 | NSString *string = @"KWEqualMatcher"; 20 | NSString *prefix = @"KW"; 21 | STAssertTrue(KWStringHasStrictWordPrefix(string, prefix), @"expected string to pass test"); 22 | 23 | string = @"KWarElephant"; 24 | STAssertFalse(KWStringHasStrictWordPrefix(string, prefix), @"expected string to fail test"); 25 | 26 | string = @"itShouldOpenDoors"; 27 | prefix = @"it"; 28 | STAssertTrue(KWStringHasStrictWordPrefix(string, prefix), @"expected string to pass test"); 29 | 30 | string = @"itsyBitsy"; 31 | STAssertFalse(KWStringHasStrictWordPrefix(string, prefix), @"expected string to fail test"); 32 | } 33 | 34 | - (void)testItShouldDetectStringsWithWords { 35 | STAssertTrue(KWStringHasWord(@"copy", @"copy"), @"expected string to pass test"); 36 | STAssertTrue(KWStringHasWord(@"mutableCopy", @"Copy"), @"expected string to pass test"); 37 | STAssertTrue(KWStringHasWord(@"mutableCopyWithAccoutrement", @"Copy"), @"expected string to pass test"); 38 | STAssertFalse(KWStringHasWord(@"copyright", @"copy"), @"expected string to pass test"); 39 | STAssertFalse(KWStringHasWord(@"rightcopy", @"copy"), @"expected string to pass test"); 40 | STAssertFalse(KWStringHasWord(@"copyright", @"copy"), @"expected string to pass test"); 41 | } 42 | 43 | @end 44 | 45 | #endif // #if KW_TESTS_ENABLED 46 | -------------------------------------------------------------------------------- /Tests/KWUserDefinedMatcherFunctionalTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2014 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "Cruiser.h" 9 | 10 | #pragma mark - Custom Matcher Implementations 11 | 12 | @interface HALTHyperdriveLevelMatcher : KWMatcher 13 | @property (nonatomic, assign) NSInteger hyperdriveFuelLevel; 14 | @end 15 | 16 | @implementation HALTHyperdriveLevelMatcher 17 | 18 | + (NSArray *)matcherStrings { 19 | return @[@"haveHyperdriveFuelLevelGreaterThan:"]; 20 | } 21 | 22 | - (BOOL)evaluate { 23 | return ((Cruiser *)self.subject).hyperdriveFuelLevel > self.hyperdriveFuelLevel; 24 | } 25 | 26 | - (void)haveHyperdriveFuelLevelGreaterThan:(NSInteger)hyperdriveFuelLevel { 27 | self.hyperdriveFuelLevel = hyperdriveFuelLevel; 28 | } 29 | 30 | @end 31 | 32 | @interface FLOWCrewComplementMatcher : KWMatcher 33 | @property (nonatomic, assign) NSInteger crewComplement; 34 | @end 35 | 36 | @implementation FLOWCrewComplementMatcher 37 | 38 | + (NSArray *)matcherStrings { 39 | return @[@"haveCrewComplementLessThan:"]; 40 | } 41 | 42 | - (BOOL)evaluate { 43 | return ((Cruiser *)self.subject).crewComplement < self.crewComplement; 44 | } 45 | 46 | - (void)haveCrewComplementLessThan:(NSInteger)crewComplement { 47 | self.crewComplement = crewComplement; 48 | } 49 | 50 | @end 51 | 52 | #pragma mark - Tests 53 | 54 | SPEC_BEGIN(KWUserDefinedMatcherFunctionalTest) 55 | 56 | registerMatchers(@"HALT"); 57 | registerMatchers(@"FLOW"); 58 | 59 | describe(@"Cruiser", ^{ 60 | let(cruiser, ^id{ return [Cruiser new]; }); 61 | 62 | it(@"has a hyperdrive fuel level above 50", ^{ 63 | [[cruiser should] haveHyperdriveFuelLevelGreaterThan:50]; 64 | }); 65 | 66 | it(@"has a crew complement below 5000", ^{ 67 | [[cruiser should] haveCrewComplementLessThan:5000]; 68 | }); 69 | }); 70 | 71 | SPEC_END 72 | -------------------------------------------------------------------------------- /Tests/KiwiTestConfiguration.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | // Set this to 0 to turn off all internal Kiwi tests. Useful when needing to 8 | // focus on a single issue that could be affected by other tests, especially 9 | // when dealing with Class method stubs, alloc/init stubs, etc. 10 | #define KW_TESTS_ENABLED 1 11 | -------------------------------------------------------------------------------- /Tests/NSNumber_KiwiAdditionsTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2014 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | #import "KiwiTestConfiguration.h" 9 | #import "NSNumber+KiwiAdditions.h" 10 | 11 | @interface NSNumber_KiwiAdditionsTests : SenTestCase 12 | 13 | @end 14 | 15 | @implementation NSNumber_KiwiAdditionsTests 16 | 17 | #pragma mark numberWithBoolBytes 18 | 19 | - (void)testNumberWithBoolBytesReturnsANumberFromBoolBytes { 20 | BOOL value = YES; 21 | NSNumber *number = [NSNumber numberWithBoolBytes:&value]; 22 | STAssertEqualObjects(number, @1, @"Expected +numberWithBoolBytes: to convert YES to @1."); 23 | } 24 | 25 | #pragma mark numberWithStdBoolBytes 26 | 27 | - (void)testNumberWithStdBoolBytesReturnsANumberFromStdBoolBytes { 28 | bool value = true; 29 | NSNumber *number = [NSNumber numberWithStdBoolBytes:&value]; 30 | STAssertEqualObjects(number, @1, @"Expected +numberWithStdBoolBytes: to convert true to @1."); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Tests/Test Classes/Carrier.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Cruiser.h" 8 | 9 | @interface Carrier : Cruiser 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Tests/Test Classes/Carrier.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Carrier.h" 8 | 9 | @implementation Carrier 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Tests/Test Classes/Cruiser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | #import "JumpCapable.h" 9 | #import "SpaceShip.h" 10 | 11 | @class Engine; 12 | @class Fighter; 13 | 14 | @interface Cruiser : SpaceShip { 15 | @private 16 | NSString *callsign; 17 | Engine *engine; 18 | NSArray *fighters; 19 | } 20 | #pragma mark - 21 | #pragma mark Initializing 22 | 23 | - (id)initWithCallsign:(NSString *)aCallsign; 24 | 25 | + (id)cruiser; 26 | + (id)cruiserWithCallsign:(NSString *)aCallsign; 27 | 28 | #pragma mark - 29 | #pragma mark Properties 30 | 31 | @property (nonatomic, readonly) NSString *callsign; 32 | @property (nonatomic, retain) Engine *engine; 33 | @property (nonatomic, readonly) NSString *classification; 34 | 35 | + (NSString *)classification; 36 | - (NSUInteger)crewComplement; 37 | 38 | #pragma mark - 39 | #pragma mark Managing Fighters 40 | 41 | @property (nonatomic, readwrite, retain) NSArray *fighters; 42 | 43 | - (Fighter *)fighterWithCallsign:(NSString *)aCallsign; 44 | - (Fighter *)fighterWithCallsignUTF8CString:(const char *)aCallsign; 45 | - (NSArray *)fightersInSquadron:(NSString *)aSquadron; 46 | 47 | #pragma mark - 48 | #pragma mark Managing Systems 49 | 50 | - (BOOL)raiseShields; 51 | - (float)energyLevelInWarpCore:(NSUInteger)anIndex; 52 | 53 | #pragma mark - 54 | #pragma mark Getting Navigation Information 55 | 56 | // starHash => key/2 + key/4 + key/8 + ... 1 57 | - (NSUInteger)computeStarHashForKey:(NSUInteger)aKey; 58 | 59 | #pragma mark - 60 | #pragma mark Orbiting 61 | 62 | - (void)orbitPlanet:(id)aPlanet; 63 | - (float)orbitPeriodForMass:(float)aMass; 64 | 65 | #pragma mark - 66 | #pragma mark Jumping 67 | 68 | - (void)computeParsecs; 69 | - (void)engageHyperdrive; 70 | - (NSUInteger)hyperdriveFuelLevel; 71 | 72 | #pragma mark - 73 | #pragma mark Raising 74 | 75 | - (void)raise; 76 | - (void)raiseWithName:(NSString *)aName description:(NSString *)aDescription; 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Tests/Test Classes/Engine.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | 9 | @interface Engine : NSObject 10 | @property (nonatomic, copy) NSString *model; 11 | 12 | + (id)engineWithModel:(NSString *)modelName; 13 | @end 14 | -------------------------------------------------------------------------------- /Tests/Test Classes/Engine.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Engine.h" 8 | 9 | @implementation Engine 10 | 11 | @synthesize model; 12 | 13 | + (id)engineWithModel:(NSString *)modelName; 14 | { 15 | Engine *engine = [[[self class] alloc] init]; 16 | engine.model = modelName; 17 | return [engine autorelease]; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Tests/Test Classes/Fighter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | #import "SpaceShip.h" 9 | 10 | @class Engine; 11 | 12 | @interface Fighter : SpaceShip { 13 | @private 14 | NSString *callsign; 15 | Engine *engine; 16 | } 17 | 18 | #pragma mark - 19 | #pragma mark Initializing 20 | 21 | - (id)initWithCallsign:(NSString *)aCallsign; 22 | 23 | + (id)fighter; 24 | + (id)fighterWithCallsign:(NSString *)aCallsign; 25 | 26 | #pragma mark - 27 | #pragma mark Properties 28 | 29 | @property (nonatomic, readonly) NSString *callsign; 30 | @property (nonatomic, readonly) Engine *engine; 31 | 32 | + (NSString *)classification; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Tests/Test Classes/Fighter.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Fighter.h" 8 | #import "Engine.h" 9 | 10 | @implementation Fighter 11 | 12 | #pragma mark - 13 | #pragma mark Initializing 14 | 15 | - (id)initWithCallsign:(NSString *)aCallsign { 16 | if ((self = [super init])) { 17 | callsign = [aCallsign copy]; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | + (id)fighter { 24 | return [self fighterWithCallsign:nil]; 25 | } 26 | 27 | + (id)fighterWithCallsign:(NSString *)aCallsign { 28 | return [[[self alloc] initWithCallsign:aCallsign] autorelease]; 29 | } 30 | 31 | - (void)dealloc { 32 | [callsign release]; 33 | [super dealloc]; 34 | } 35 | 36 | #pragma mark - 37 | #pragma mark Properties 38 | 39 | @synthesize callsign; 40 | @synthesize engine; 41 | 42 | + (NSString *)classification { 43 | return @"Starfighter"; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Tests/Test Classes/Galaxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Galaxy.h 3 | // Kiwi 4 | // 5 | // Created by Nathan Heagy on 12-03-22. 6 | // Copyright (c) 2012 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Galaxy : NSObject 12 | 13 | + (id)sharedGalaxy; 14 | - (void)notifyPlanet:(int)planet; 15 | - (void)notifyEarth; 16 | - (NSString *)name; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Tests/Test Classes/Galaxy.m: -------------------------------------------------------------------------------- 1 | // 2 | // Galaxy.m 3 | // Kiwi 4 | // 5 | // Created by Nathan Heagy on 12-03-22. 6 | // Copyright (c) 2012 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "Galaxy.h" 10 | 11 | @implementation Galaxy 12 | 13 | + (id)sharedGalaxy 14 | { 15 | static Galaxy *instance; 16 | 17 | static dispatch_once_t predicate; 18 | dispatch_once(&predicate, ^{ 19 | instance = [[Galaxy alloc] init]; 20 | }); 21 | 22 | return instance; 23 | } 24 | 25 | - (void)notifyPlanet:(int)planet { 26 | NSLog(@"Planet %d was notified", planet); 27 | } 28 | - (void)notifyEarth { 29 | [self notifyPlanet:1]; 30 | } 31 | 32 | - (NSString *)name 33 | { 34 | return @"Milky Way"; 35 | } 36 | @end 37 | -------------------------------------------------------------------------------- /Tests/Test Classes/JumpCapable.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "OrbitCapable.h" 8 | 9 | @protocol JumpCapable 10 | 11 | #pragma mark - 12 | #pragma mark Jumping 13 | 14 | - (void)computeParsecs; 15 | - (void)engageHyperdrive; 16 | - (NSUInteger)hyperdriveFuelLevel; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Tests/Test Classes/KiwiAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | 9 | @class KiwiViewController; 10 | 11 | @interface KiwiAppDelegate : NSObject { 12 | UIWindow *window; 13 | KiwiViewController *viewController; 14 | } 15 | 16 | @property (nonatomic, retain) IBOutlet UIWindow *window; 17 | @property (nonatomic, retain) IBOutlet KiwiViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Tests/Test Classes/KiwiAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiAppDelegate.h" 8 | #import "KiwiViewController.h" 9 | 10 | @implementation KiwiAppDelegate 11 | 12 | @synthesize window; 13 | @synthesize viewController; 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 16 | // Override point for customization after app launch 17 | [window addSubview:viewController.view]; 18 | [window makeKeyAndVisible]; 19 | return YES; 20 | } 21 | 22 | - (void)dealloc { 23 | [viewController release]; 24 | [window release]; 25 | [super dealloc]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Tests/Test Classes/KiwiViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | 9 | @interface KiwiViewController : UIViewController 10 | 11 | @end 12 | 13 | -------------------------------------------------------------------------------- /Tests/Test Classes/KiwiViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "KiwiViewController.h" 8 | 9 | @implementation KiwiViewController 10 | 11 | /* 12 | // The designated initializer. Override to perform setup that is required before the view is loaded. 13 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 14 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 15 | // Custom initialization 16 | } 17 | return self; 18 | } 19 | */ 20 | 21 | /* 22 | // Implement loadView to create a view hierarchy programmatically, without using a nib. 23 | - (void)loadView { 24 | } 25 | */ 26 | 27 | 28 | /* 29 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | } 33 | */ 34 | 35 | 36 | /* 37 | // Override to allow orientations other than the default portrait orientation. 38 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 39 | // Return YES for supported orientations 40 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 41 | } 42 | */ 43 | 44 | - (void)didReceiveMemoryWarning { 45 | // Releases the view if it doesn't have a superview. 46 | [super didReceiveMemoryWarning]; 47 | 48 | // Release any cached data, images, etc that aren't in use. 49 | } 50 | 51 | - (void)viewDidUnload { 52 | // Release any retained subviews of the main view. 53 | // e.g. self.myOutlet = nil; 54 | } 55 | 56 | 57 | - (void)dealloc { 58 | [super dealloc]; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Tests/Test Classes/OrbitCapable.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | 9 | @protocol OrbitCapable 10 | 11 | #pragma mark - 12 | #pragma mark Orbiting 13 | 14 | - (void)orbitPlanet:(id)aPlanet; 15 | - (float)orbitPeriodForMass:(float)aMass; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Tests/Test Classes/Robot.h: -------------------------------------------------------------------------------- 1 | // 2 | // Robot.h 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface Robot : NSObject { 13 | 14 | } 15 | + (id)robot; 16 | - (void)speak:(NSString *)message; 17 | - (void)speak:(id)message ofType:(Class)messageType; 18 | - (void)speak:(NSString *)message afterDelay:(NSTimeInterval)delay whenDone:(void(^)(void))handler; 19 | @end 20 | -------------------------------------------------------------------------------- /Tests/Test Classes/Robot.m: -------------------------------------------------------------------------------- 1 | // 2 | // Robot.m 3 | // Kiwi 4 | // 5 | // Created by Luke Redpath on 17/01/2011. 6 | // Copyright 2011 Allen Ding. All rights reserved. 7 | // 8 | 9 | #import "Robot.h" 10 | 11 | 12 | @implementation Robot 13 | 14 | + (id)robot; 15 | { 16 | return [[[self alloc] init] autorelease]; 17 | } 18 | 19 | - (void)speak:(NSString *)message 20 | { 21 | NSLog(@"Robot says %@", message); 22 | } 23 | 24 | - (void)speak:(id)message ofType:(Class)messageType { 25 | NSLog(@"Robot says %@ [Message Type:%@]", message, messageType); 26 | } 27 | 28 | - (void)speak:(NSString *)message afterDelay:(NSTimeInterval)delay whenDone:(void(^)(void))handler 29 | { 30 | NSLog(@"Robot will say %@ after a %f second delay", message, delay); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Tests/Test Classes/SpaceShip.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | 9 | @interface SpaceShip : NSObject 10 | 11 | #pragma mark - 12 | #pragma mark Managing Shields 13 | 14 | - (BOOL)raiseShields; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Tests/Test Classes/SpaceShip.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "SpaceShip.h" 8 | 9 | @implementation SpaceShip 10 | 11 | #pragma mark - 12 | #pragma mark Managing Shields 13 | 14 | - (BOOL)raiseShields { 15 | return YES; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Tests/Test Classes/TestClasses.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Carrier.h" 8 | #import "Cruiser.h" 9 | #import "Engine.h" 10 | #import "Fighter.h" 11 | #import "JumpCapable.h" 12 | #import "OrbitCapable.h" 13 | #import "SpaceShip.h" 14 | #import "TestReporter.h" 15 | #import "TestSpy.h" 16 | #import "TestVerifier.h" 17 | #import "Robot.h" 18 | #import "Galaxy.h" 19 | -------------------------------------------------------------------------------- /Tests/Test Classes/TestReporter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import 8 | #import "KWReporting.h" 9 | 10 | @class KWFailure; 11 | 12 | @interface TestReporter : NSObject { 13 | @private 14 | BOOL hasUnmetExpectations; 15 | NSMutableArray *failures; 16 | } 17 | 18 | #pragma mark - 19 | #pragma mark Initializing 20 | 21 | + (id)testReporter; 22 | 23 | #pragma mark - 24 | #pragma mark Properties 25 | 26 | @property (nonatomic, readonly) BOOL hasUnmetExpectations; 27 | @property (nonatomic, readonly) NSArray* failures; 28 | 29 | #pragma mark - 30 | #pragma mark Reporting Failures 31 | 32 | - (void)reportFailure:(KWFailure *)aFailure; 33 | 34 | #pragma mark - 35 | #pragma mark Getting Failure Information 36 | 37 | - (BOOL)hasNoFailure; 38 | - (BOOL)hasOneFailure; 39 | - (KWFailure *)onlyFailure; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Tests/Test Classes/TestReporter.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "TestReporter.h" 8 | #import "KWFailure.h" 9 | 10 | @interface TestReporter() 11 | 12 | #pragma mark - 13 | #pragma mark Properties 14 | 15 | @property (nonatomic, readwrite) BOOL hasUnmetExpectations; 16 | 17 | @end 18 | 19 | @implementation TestReporter 20 | 21 | #pragma mark - 22 | #pragma mark Initializing 23 | 24 | - (id)init { 25 | self = [super init]; 26 | if (self) { 27 | failures = [[NSMutableArray alloc] init]; 28 | } 29 | 30 | return self; 31 | } 32 | 33 | + (id)testReporter { 34 | return [[[self alloc] init] autorelease]; 35 | } 36 | 37 | - (void)dealloc { 38 | [failures release]; 39 | [super dealloc]; 40 | } 41 | 42 | #pragma mark - 43 | #pragma mark Properties 44 | 45 | @synthesize hasUnmetExpectations; 46 | @synthesize failures; 47 | 48 | #pragma mark - 49 | #pragma mark Reporting Failures 50 | 51 | - (void)reportFailure:(KWFailure *)aFailure { 52 | if (aFailure == nil) 53 | return; 54 | 55 | self.hasUnmetExpectations = YES; 56 | [failures addObject:aFailure]; 57 | } 58 | 59 | #pragma mark - 60 | #pragma mark Getting Failure Information 61 | 62 | - (BOOL)hasNoFailure { 63 | return [self.failures count] == 0; 64 | } 65 | 66 | - (BOOL)hasOneFailure { 67 | return [self.failures count] == 1; 68 | } 69 | 70 | - (KWFailure *)onlyFailure { 71 | return (self.failures)[0]; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Tests/Test Classes/TestSpy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | 9 | @interface TestSpy : NSObject { 10 | @private 11 | BOOL wasNotified; 12 | } 13 | 14 | #pragma mark - 15 | #pragma mark Initializing 16 | 17 | + (id)testSpy; 18 | 19 | #pragma mark - 20 | #pragma mark Checking Notifications 21 | 22 | @property (nonatomic, readonly) BOOL wasNotified; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Tests/Test Classes/TestSpy.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "TestSpy.h" 8 | 9 | @implementation TestSpy 10 | 11 | #pragma mark - 12 | #pragma mark Initializing 13 | 14 | + (id)testSpy { 15 | return [[[self alloc] init] autorelease]; 16 | } 17 | 18 | #pragma mark - 19 | #pragma mark Checking Notifications 20 | 21 | @synthesize wasNotified; 22 | 23 | - (void)object:(id)anObject didReceiveInvocation:(NSInvocation *)anInvocation { 24 | wasNotified = YES; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Tests/Test Classes/TestVerifier.h: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "Kiwi.h" 8 | 9 | @interface TestVerifier : NSObject 10 | 11 | #pragma mark - Properties 12 | 13 | @property (nonatomic, readonly) BOOL notifiedOfEndOfExample; 14 | 15 | #pragma mark - Verifying 16 | 17 | - (void)exampleWillEnd; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Tests/Test Classes/TestVerifier.m: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed under the terms in License.txt 3 | // 4 | // Copyright 2010 Allen Ding. All rights reserved. 5 | // 6 | 7 | #import "TestVerifier.h" 8 | 9 | @interface TestVerifier() 10 | 11 | @property (nonatomic, readwrite) BOOL notifiedOfEndOfExample; 12 | 13 | @end 14 | 15 | @implementation TestVerifier 16 | 17 | #pragma mark - Properties 18 | 19 | @synthesize notifiedOfEndOfExample; 20 | 21 | #pragma mark - Setting Subjects 22 | 23 | - (void)setSubject:(id)anObject { 24 | } 25 | 26 | #pragma mark - Verifying 27 | 28 | - (void)exampleWillEnd { 29 | self.notifiedOfEndOfExample = YES; 30 | } 31 | 32 | - (NSString *)descriptionForAnonymousItNode 33 | { 34 | return @""; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Xcode Templates/Kiwi Spec.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AllowedTypes 6 | 7 | public.objective-c-source 8 | 9 | Platforms 10 | 11 | com.apple.platform.iphoneos 12 | 13 | DefaultCompletionName 14 | NewKiwiSpec 15 | Description 16 | Kiwi spec file 17 | Kind 18 | Xcode.IDEKit.TextSubstitutionFileTemplateKind 19 | MainTemplateFile 20 | ___FILEBASENAME___.m 21 | SortOrder 22 | 1 23 | Options 24 | 25 | 26 | Default 27 | 28 | Description 29 | What would you like to test? 30 | Identifier 31 | testedClass 32 | Name 33 | Spec for 34 | Required 35 | 36 | NotPersisted 37 | 38 | Type 39 | text 40 | 41 | 42 | Default 43 | ___VARIABLE_testedClass___Spec 44 | Identifier 45 | productName 46 | Type 47 | static 48 | 49 | 50 | Summary 51 | Spec class of Kiwi BDD framework 52 | 53 | 54 | -------------------------------------------------------------------------------- /Xcode Templates/Kiwi Spec.xctemplate/___FILEBASENAME___.m: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PROJECTNAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "___VARIABLE_testedClass___.h" 11 | 12 | 13 | SPEC_BEGIN(___FILEBASENAMEASIDENTIFIER___) 14 | 15 | describe(@"___VARIABLE_testedClass___", ^{ 16 | 17 | }); 18 | 19 | SPEC_END 20 | -------------------------------------------------------------------------------- /Xcode Templates/install-templates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | SOURCE_DIR=$(dirname "$0") 4 | TEMPLATES_DIR="$HOME/Library/Developer/Xcode/Templates" 5 | FILE_TEMPLATES_DIR="$TEMPLATES_DIR/File Templates" 6 | KIWI_TEMPLATES_DIR="$FILE_TEMPLATES_DIR/Kiwi" 7 | 8 | echo "Installing templates to $KIWI_TEMPLATES_DIR" 9 | mkdir -p "$KIWI_TEMPLATES_DIR" 10 | cp -R "$SOURCE_DIR/Kiwi Spec.xctemplate" "$KIWI_TEMPLATES_DIR" 11 | echo "Finished" 12 | -------------------------------------------------------------------------------- /Xcode Templates/uninstall-templates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | TEMPLATES_DIR="$HOME/Library/Developer/Xcode/Templates" 4 | FILE_TEMPLATES_DIR="$TEMPLATES_DIR/File Templates" 5 | KIWI_TEMPLATES_DIR="$FILE_TEMPLATES_DIR/Kiwi" 6 | KIWI_SPEC_TEMPLATE="$KIWI_TEMPLATES_DIR/Kiwi Spec.xctemplate" 7 | echo "Removing $KIWI_SPEC_TEMPLATE" 8 | rm -rf "$KIWI_TEMPLATES_DIR/Kiwi Spec.xctemplate" 9 | echo "Finished" 10 | --------------------------------------------------------------------------------