main
1//
2// Licensed under the terms in License.txt
3//
4// Copyright 2010 Allen Ding. All rights reserved.
5//
6
7#import "KWSpec.h"
8#import <objc/runtime.h>
9#import "KWExample.h"
10#import "KWExampleGroupBuilder.h"
11#import "KWIntercept.h"
12#import "KWObjCUtilities.h"
13#import "KWStringUtilities.h"
14#import "NSMethodSignature+KiwiAdditions.h"
15#import "KWFailure.h"
16#import "KWExampleSuite.h"
17
18
19@interface KWSpec()
20
21#pragma mark -
22#pragma mark Properties
23
24@property (nonatomic, retain) KWExample *example;
25
26@end
27
28@implementation KWSpec
29
30@synthesize example;
31
32- (void)dealloc
33{
34 [example release];
35 [super dealloc];
36}
37
38/* This method is only implemented by sub-classes */
39
40+ (void)buildExampleGroups {}
41
42/* Reported by XCode SenTestingKit Runner before and after invocation of the test
43 Use camel case to make method friendly names from example description
44 */
45
46- (NSString *)description
47{
48 KWExample *currentExample = self.example ? self.example : [[self invocation] kw_example];
49 NSString *name = [currentExample descriptionWithContext];
50
51 // CamelCase the string
52 NSArray *words = [name componentsSeparatedByString:@" "];
53 name = @"";
54 for (NSString *word in words) {
55 if ([word length] < 1)
56 {
57 continue;
58 }
59 name = [name stringByAppendingString:[[word substringToIndex:1] uppercaseString]];
60 name = [name stringByAppendingString:[word substringFromIndex:1]];
61 }
62
63 // Replace the commas with underscores to separate the levels of context
64 name = [name stringByReplacingOccurrencesOfString:@"," withString:@"_"];
65
66 // Strip out characters not legal in function names
67 NSError *error = nil;
68 NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^a-zA-Z0-9_]*" options:0 error:&error];
69 name = [regex stringByReplacingMatchesInString:name options:0 range:NSMakeRange(0, name.length) withTemplate:@""];
70
71 return [NSString stringWithFormat:@"-[%@ %@]", NSStringFromClass([self class]), name];
72}
73
74#pragma mark -
75#pragma mark Getting Invocations
76
77/* Called by the SenTestingKit test suite to get an array of invocations that
78 should be run on instances of test cases. */
79
80+ (NSArray *)testInvocations
81{
82 SEL selector = @selector(buildExampleGroups);
83
84 // Only return invocation if the receiver is a concrete spec that has overridden -buildExampleGroups.
85 if ([self methodForSelector:selector] == [KWSpec methodForSelector:selector])
86 return nil;
87
88 KWExampleSuite *exampleSuite = [[KWExampleGroupBuilder sharedExampleGroupBuilder] buildExampleGroups:^{
89 [self buildExampleGroups];
90 }];
91
92 return [exampleSuite invocationsForTestCase];
93}
94
95#pragma mark -
96#pragma mark Running Specs
97
98- (void)invokeTest
99{
100 self.example = [[self invocation] kw_example];
101
102 NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init];
103
104 @try {
105 [self.example runWithDelegate:self];
106 } @catch (NSException *exception) {
107 [self failWithException:exception];
108 }
109
110 [[self invocation] kw_setExample:nil];
111
112 [subPool release];
113}
114
115#pragma mark - KWExampleGroupDelegate methods
116
117- (void)example:(KWExample *)example didFailWithFailure:(KWFailure *)failure
118{
119 [self failWithException:[failure exceptionValue]];
120}
121
122#pragma mark -
123#pragma mark Verification proxies
124
125+ (id)addVerifier:(id<KWVerifying>)aVerifier
126{
127 return [[[KWExampleGroupBuilder sharedExampleGroupBuilder] currentExample] addVerifier:aVerifier];
128}
129
130+ (id)addExistVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite
131{
132 return [[[KWExampleGroupBuilder sharedExampleGroupBuilder] currentExample] addExistVerifierWithExpectationType:anExpectationType callSite:aCallSite];
133}
134
135+ (id)addMatchVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite
136{
137 return [[[KWExampleGroupBuilder sharedExampleGroupBuilder] currentExample] addMatchVerifierWithExpectationType:anExpectationType callSite:aCallSite];
138}
139
140+ (id)addAsyncVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite timeout:(NSInteger)timeout
141{
142 return [[[KWExampleGroupBuilder sharedExampleGroupBuilder] currentExample] addAsyncVerifierWithExpectationType:anExpectationType callSite:aCallSite timeout:timeout];
143}
144
145@end