5 // Created by Wincent Colaiuta on 12 October 2004.
7 // Copyright 2004-2007 Wincent Colaiuta.
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #import <Foundation/Foundation.h>
24 @interface WOTest : NSObject {
28 unsigned classesWithTests;
29 unsigned classesWithoutTests;
30 unsigned methodsWithTests;
34 unsigned uncaughtExceptions;
36 //! test sense inversion: should only be used during WOTest self-testing
37 unsigned testsFailedExpected;
38 unsigned testsPassedUnexpected;
41 //! low-level exception handling inversion: should only be used during WOTest self-testing
42 unsigned lowLevelExceptionsExpected;
43 unsigned lowLevelExceptionsUnexpected;
44 BOOL expectLowLevelExceptions;
46 //! Optionally refrain from handling low level exceptions
47 BOOL handlesLowLevelExceptions;
49 //! Internal use only: used for keeping track of whether low-level exception handlers have been installed or not
50 //! Necessary because tested methods may change the low-level-exception-catching status mid-test
51 BOOL lowLevelExceptionHandlerInstalled;
53 //! 0 = mostly silent operation; 1 = verbose; 2 = very verbose
56 //! Optionally trim leading path components when printing path names to console.
57 unsigned trimInitialPathComponents;
59 //! Cache last reported path and last reported line number for use when printing warnings and errors which don't include file and line information
60 NSString *lastReportedFile;
64 BOOL warnsAboutSignComparisons;
68 #pragma mark Singleton pattern enforcement methods
70 /*! \name Singleton pattern enforcement methods
73 + (WOTest *)sharedInstance;
78 #pragma mark Utility methods
80 /*! \name Utility methods
83 /*! Returns an NSString based on sending the "description" selector to anObject, compressing whitespace and truncating if necessary at index and appending an ellipsis. Returns nil if anObject is nil. Optionally returns YES or NO indirectyl via /p didTruncate to indicate whether truncation actually occurred. Pass \p index of 0 to return an untruncated, uncompressed description. */
84 - (NSString *)description:(id)anObject truncatedAt:(unsigned)index didTruncate:(BOOL *)didTruncate;
86 /*! Seed the random number generator with current system time, in effect causing the random number generator to produce a different sequence of numbers on each run. The random value generator methods will output values that are equal to WO_TEST_VALUE (or WO_BIG_TEST_VALUE or WO_SMALL_TEST_VALUE) plus or minus a random offset up to WO_RANDOMIZATION_RANGE. If you do not explicitly seed the random number generator, the same seed will be used on each run. */
87 - (void)seedRandomNumberGenerator;
89 /*! Seed the random number generator with the value passed as seed. Pass 1 to generate a repeatable sequence of numbers on each run (see the random (3) man page for more information. */
90 - (void)seedRandomNumberGenerator:(unsigned long)seed;
95 #pragma mark Test-running methods
97 /*! \name Test-running test methods
100 /*! Runs all tests currently visible in the runtime. Returns YES if all tests pass, NO if any test fails. */
103 /*! Returns YES if all tests pass, NO if any test fails. Raises an exception if className is nil. */
104 - (BOOL)runTestsForClassName:(NSString *)className;
106 /*! Returns YES if all tests pass, NO if any test fails. Raises an exception if aClass is nil. */
107 - (BOOL)runTestsForClass:(Class)aClass;
109 /*! Returns a list of class names (NSStrings) corresponding to all classes known to the runtime that conform to the WOTest protocol. */
110 - (NSArray *)testableClasses;
112 /*! Like the allTestableClasses method, returns a list of class names (NSStrings) corresponding to all classes known to the runtime that conform to the WOTest protocol, with the additional limitation that only classes belonging to the specified bundle are included. */
113 - (NSArray *)testableClassesFrom:(NSBundle *)aBundle;
115 /*! Given a class that conforms to the WOTest protocol, returns a list of method names (NSStrings) in that class that correspond to testable methods (in other words, method names that begin with the string "test"). */
116 - (NSArray *)testableMethodsFrom:(Class)aClass;
118 - (void)printTestResultsSummary;
120 //! Returns YES if there were no failures.
121 - (BOOL)testsWereSuccessful;
126 #pragma mark Growl support
128 - (void)growlNotifyTitle:(NSString *)title message:(NSString *)message isWarning:(BOOL)isWarning sticky:(BOOL)sticky;
131 #pragma mark Logging methods
133 //! \name Logging methods
136 //! Keep track of last known file and line number
137 - (void)cacheFile:(char *)path line:(int)line;
139 - (void)writeLastKnownLocation;
141 - (void)writePassed:(BOOL)passed inFile:(char *)path atLine:(int)line message:(NSString *)message, ...;
143 - (void)writeErrorInFile:(char *)path atLine:(int)line message:(NSString *)message, ...;
145 - (void)writeWarningInFile:(char *)path atLine:(int)line message:(NSString *)message, ...;
147 - (void)writeUncaughtException:(NSString *)info inFile:(char *)path atLine:(int)line;
149 - (void)writeStatusInFile:(char *)path atLine:(int)line message:(NSString *)message, ...;
151 - (void)writeStatus:(NSString *)message, ...;
153 - (void)writeWarning:(NSString *)message, ...;
155 - (void)writeError:(NSString *)message, ...;
160 #pragma mark Empty (do-nothing) test methods
162 /*! \name Empty (do-nothing) test methods
165 /*! An empty test which always passes. */
166 - (void)passTestInFile:(char *)path atLine:(int)line;
168 /*! An empty test which always fails. */
169 - (void)failTestInFile:(char *)path atLine:(int)line;
174 #pragma mark Boolean test methods
176 /*! \name Boolean test methods
179 - (void)testTrue:(BOOL)expr inFile:(char *)path atLine:(int)line;
181 - (void)testFalse:(BOOL)expr inFile:(char *)path atLine:(int)line;
186 #pragma mark NSValue-based tests
188 /*! \name NSValue-based tests
191 - (void)testValue:(NSValue *)actual isEqualTo:(NSValue *)expected inFile:(char *)path atLine:(int)line;
193 - (void)testValue:(NSValue *)actual isNotEqualTo:(NSValue *)expected inFile:(char *)path atLine:(int)line;
195 - (void)testValue:(NSValue *)actual greaterThan:(NSValue *)expected inFile:(char *)path atLine:(int)line;
197 - (void)testValue:(NSValue *)actual notGreaterThan:(NSValue *)expected inFile:(char *)path atLine:(int)line;
199 - (void)testValue:(NSValue *)actual lessThan:(NSValue *)expected inFile:(char *)path atLine:(int)line;
201 - (void)testValue:(NSValue *)actual notLessThan:(NSValue *)expected inFile:(char *)path atLine:(int)line;
206 #pragma mark Pointer to void test methods
208 /*! \name Pointer to void test methods
211 - (void)testNil:(void *)pointer inFile:(char *)path atLine:(int)line;
213 - (void)testNotNil:(void *)pointer inFile:(char *)path atLine:(int)line;
215 - (void)testPointer:(void *)actual isEqualTo:(void *)expected inFile:(char *)path atLine:(int)line;
217 - (void)testPointer:(void *)actual isNotEqualTo:(void *)expected inFile:(char *)path atLine:(int)line;
222 #pragma mark int test methods
224 /*! \name int test methods
227 /*! The WO_TEST_IS_INT macro uses \@encode(typeof()) to pass a string encoding of the type. */
228 - (void)testIsInt:(char *)type inFile:(char *)path atLine:(int)line;
230 /*! The WO_TEST_IS_NOT_INT macro uses \@encode(typeof()) to pass a string encoding of the type. */
231 - (void)testIsNotInt:(char *)type inFile:(char *)path atLine:(int)line;
233 - (void)testIntPositive:(int)aInt inFile:(char *)path atLine:(int)line;
235 - (void)testIntNegative:(int)aInt inFile:(char *)path atLine:(int)line;
237 - (void)testIntZero:(int)aInt inFile:(char *)path atLine:(int)line;
239 - (void)testIntNotZero:(int)aInt inFile:(char *)path atLine:(int)line;
241 - (void)testInt:(int)actual isEqualTo:(int)expected inFile:(char *)path atLine:(int)line;
243 - (void)testInt:(int)actual isNotEqualTo:(int)expected inFile:(char *)path atLine:(int)line;
245 - (void)testInt:(int)actual greaterThan:(int)expected inFile:(char *)path atLine:(int)line;
247 - (void)testInt:(int)actual notGreaterThan:(int)expected inFile:(char *)path atLine:(int)line;
249 - (void)testInt:(int)actual lessThan:(int)expected inFile:(char *)path atLine:(int)line;
251 - (void)testInt:(int)actual notLessThan:(int)expected inFile:(char *)path atLine:(int)line;
256 #pragma mark unsigned test methods
258 /*! \name unsigned test methods
261 /*! The WO_TEST_IS_UNSIGNED macro uses \@encode(typeof()) to pass a string encoding of the type. */
262 - (void)testIsUnsigned:(char *)type inFile:(char *)path atLine:(int)line;
264 /*! The WO_TEST_IS_NOT_UNSIGNED macro uses \@encode(typeof()) to pass a string encoding of the type. */
265 - (void)testIsNotUnsigned:(char *)type inFile:(char *)path atLine:(int)line;
267 - (void)testUnsignedZero:(unsigned)aUnsigned inFile:(char *)path atLine:(int)line;
269 - (void)testUnsignedNotZero:(unsigned)aUnsigned inFile:(char *)path atLine:(int)line;
271 - (void)testUnsigned:(unsigned)actual isEqualTo:(unsigned)expected inFile:(char *)path atLine:(int)line;
273 - (void)testUnsigned:(unsigned)actual isNotEqualTo:(unsigned)expected inFile:(char *)path atLine:(int)line;
275 - (void)testUnsigned:(unsigned)actual greaterThan:(unsigned)expected inFile:(char *)path atLine:(int)line;
277 - (void)testUnsigned:(unsigned)actual notGreaterThan:(unsigned)expected inFile:(char *)path atLine:(int)line;
279 - (void)testUnsigned:(unsigned)actual lessThan:(unsigned)expected inFile:(char *)path atLine:(int)line;
281 - (void)testUnsigned:(unsigned)actual notLessThan:(unsigned)expected inFile:(char *)path atLine:(int)line;
286 #pragma mark float test methods without error margins
288 /*! \name float test methods without error margins
291 /*! The WO_TEST_IS_FLOAT macro uses \@encode(typeof()) to pass a string encoding of the type. */
292 - (void)testIsFloat:(char *)type inFile:(char *)path atLine:(int)line;
294 /*! The WO_TEST_IS_NOT_FLOAT macro uses \@encode(typeof()) to pass a string encoding of the type. */
295 - (void)testIsNotFloat:(char *)type inFile:(char *)path atLine:(int)line;
297 - (void)testFloatPositive:(float)aFloat inFile:(char *)path atLine:(int)line;
299 - (void)testFloatNegative:(float)aFloat inFile:(char *)path atLine:(int)line;
301 - (void)testFloatZero:(float)aFloat inFile:(char *)path atLine:(int)line;
303 - (void)testFloatNotZero:(float)aFloat inFile:(char *)path atLine:(int)line;
305 - (void)testFloat:(float)actual isEqualTo:(float)expected inFile:(char *)path atLine:(int)line;
307 - (void)testFloat:(float)actual isNotEqualTo:(float)expected inFile:(char *)path atLine:(int)line;
309 - (void)testFloat:(float)actual greaterThan:(float)expected inFile:(char *)path atLine:(int)line;
311 - (void)testFloat:(float)actual notGreaterThan:(float)expected inFile:(char *)path atLine:(int)line;
313 - (void)testFloat:(float)actual lessThan:(float)expected inFile:(char *)path atLine:(int)line;
315 - (void)testFloat:(float)actual notLessThan:(float)expected inFile:(char *)path atLine:(int)line;
320 #pragma mark float test methods with error margins
322 /*! \name float test methods with error margins
325 - (void)testFloatPositive:(float)aFloat withinError:(float)error inFile:(char *)path atLine:(int)line;
327 - (void)testFloatNegative:(float)aFloat withinError:(float)error inFile:(char *)path atLine:(int)line;
329 - (void)testFloatZero:(float)aFloat withinError:(float)error inFile:(char *)path atLine:(int)line;
331 - (void)testFloatNotZero:(float)aFloat withinError:(float)error inFile:(char *)path atLine:(int)line;
333 - (void)testFloat:(float)actual isEqualTo:(float)expected withinError:(float)error inFile:(char *)path atLine:(int)line;
335 - (void)testFloat:(float)actual isNotEqualTo:(float)expected withinError:(float)error inFile:(char *)path atLine:(int)line;
337 - (void)testFloat:(float)actual greaterThan:(float)expected withinError:(float)error inFile:(char *)path atLine:(int)line;
339 - (void)testFloat:(float)actual notGreaterThan:(float)expected withinError:(float)error inFile:(char *)path atLine:(int)line;
341 - (void)testFloat:(float)actual lessThan:(float)expected withinError:(float)error inFile:(char *)path atLine:(int)line;
343 - (void)testFloat:(float)actual notLessThan:(float)expected withinError:(float)error inFile:(char *)path atLine:(int)line;
348 #pragma mark double test methods without error margins
350 /*! \name double test methods without error margins
353 /*! The WO_TEST_IS_DOUBLE macro uses \@encode(typeof()) to pass a string encoding of the type. */
354 - (void)testIsDouble:(char *)type inFile:(char *)path atLine:(int)line;
356 /*! The WO_TEST_IS_NOT_DOUBLE macro uses \@encode(typeof()) to pass a string encoding of the type. */
357 - (void)testIsNotDouble:(char *)type inFile:(char *)path atLine:(int)line;
359 - (void)testDoublePositive:(double)aDouble inFile:(char *)path atLine:(int)line;
361 - (void)testDoubleNegative:(double)aDouble inFile:(char *)path atLine:(int)line;
363 - (void)testDoubleZero:(double)aDouble inFile:(char *)path atLine:(int)line;
365 - (void)testDoubleNotZero:(double)aDouble inFile:(char *)path atLine:(int)line;
367 - (void)testDouble:(double)actual isEqualTo:(double)expected inFile:(char *)path atLine:(int)line;
369 - (void)testDouble:(double)actual isNotEqualTo:(double)expected inFile:(char *)path atLine:(int)line;
371 - (void)testDouble:(double)actual greaterThan:(double)expected inFile:(char *)path atLine:(int)line;
373 - (void)testDouble:(double)actual notGreaterThan:(double)expected inFile:(char *)path atLine:(int)line;
375 - (void)testDouble:(double)actual lessThan:(double)expected inFile:(char *)path atLine:(int)line;
377 - (void)testDouble:(double)actual notLessThan:(double)expected inFile:(char *)path atLine:(int)line;
382 #pragma mark double test methods with error margins
384 /*! \name double test methods with error margins
387 - (void)testDoublePositive:(double)aDouble withinError:(double)error inFile:(char *)path atLine:(int)line;
389 - (void)testDoubleNegative:(double)aDouble withinError:(double)error inFile:(char *)path atLine:(int)line;
391 - (void)testDoubleZero:(double)aDouble withinError:(double)error inFile:(char *)path atLine:(int)line;
393 - (void)testDoubleNotZero:(double)aDouble withinError:(double)error inFile:(char *)path atLine:(int)line;
395 - (void)testDouble:(double)actual isEqualTo:(double)expected withinError:(double)error inFile:(char *)path atLine:(int)line;
397 - (void)testDouble:(double)actual isNotEqualTo:(double)expected withinError:(double)error inFile:(char *)path atLine:(int)line;
399 - (void)testDouble:(double)actual greaterThan:(double)expected withinError:(double)error inFile:(char *)path atLine:(int)line;
401 - (void)testDouble:(double)actual notGreaterThan:(double)expected withinError:(double)error inFile:(char *)path atLine:(int)line;
403 - (void)testDouble:(double)actual lessThan:(double)expected withinError:(double)error inFile:(char *)path atLine:(int)line;
405 - (void)testDouble:(double)actual notLessThan:(double)expected withinError:(float)error inFile:(char *)path atLine:(int)line;
410 #pragma mark Object test methods
412 /*! \name Object test methods
415 - (void)testObject:(id)actual isEqualTo:(id)expected inFile:(char *)path atLine:(int)line;
417 - (void)testObject:(id)actual isNotEqualTo:(id)expected inFile:(char *)path atLine:(int)line;
422 #pragma mark NSString test methods
424 /*! \name NSString test methods
427 - (void)testString:(NSString *)actual isEqualTo:(NSString *)expected inFile:(char *)path atLine:(int)line;
429 - (void)testString:(NSString *)actual isNotEqualTo:(NSString *)expected inFile:(char *)path atLine:(int)line;
431 - (void)testString:(NSString *)actual hasPrefix:(NSString *)expected inFile:(char *)path atLine:(int)line;
433 - (void)testString:(NSString *)actual doesNotHavePrefix:(NSString *)expected inFile:(char *)path atLine:(int)line;
435 - (void)testString:(NSString *)actual hasSuffix:(NSString *)expected inFile:(char *)path atLine:(int)line;
437 - (void)testString:(NSString *)actual doesNotHaveSuffix:(NSString *)expected inFile:(char *)path atLine:(int)line;
439 - (void)testString:(NSString *)actual contains:(NSString *)expected inFile:(char *)path atLine:(int)line;
441 - (void)testString:(NSString *)actual doesNotContain:(NSString *)expected inFile:(char *)path atLine:(int)line;
446 #pragma mark NSArray test methods
448 /*! \name NSArray test methods
451 - (void)testArray:(NSArray *)actual isEqualTo:(NSArray *)expected inFile:(char *)path atLine:(int)line;
453 - (void)testArray:(NSArray *)actual isNotEqualTo:(NSArray *)expected inFile:(char *)path atLine:(int)line;
458 #pragma mark NSDictionary test methods
460 /*! \name NSDictionary test methods
463 - (void)testDictionary:(NSDictionary *)actual isEqualTo:(NSDictionary *)expected inFile:(char *)path atLine:(int)line;
465 - (void)testDictionary:(NSDictionary *)actual isNotEqualTo:(NSDictionary *)expected inFile:(char *)path atLine:(int)line;
470 #pragma mark Exception test methods
472 /*! \name Exception test methods
475 - (void)testThrowsException:(id)exception inFile:(char *)path atLine:(int)line;
477 - (void)testDoesNotThrowException:(id)exception inFile:(char *)path atLine:(int)line;
479 - (void)testThrowsException:(id)exception named:(NSString *)name inFile:(char *)path atLine:(int)line;
481 - (void)testDoesNotThrowException:(id)exception named:(NSString *)name inFile:(char *)path atLine:(int)line;
486 #pragma mark Random value generator methods
488 /*! \name Random value generator methods
497 - (int)aBigPositiveInt;
498 - (int)aBigNegativeInt;
500 - (int)aSmallPositiveInt;
501 - (int)aSmallNegativeInt;
503 - (unsigned)anUnsigned;
504 - (unsigned)aZeroUnsigned;
505 - (unsigned)aBigUnsigned;
506 - (unsigned)aSmallUnsigned;
509 - (float)aPositiveFloat;
510 - (float)aNegativeFloat;
513 - (float)aBigPositiveFloat;
514 - (float)aBigNegativeFloat;
515 - (float)aSmallFloat;
516 - (float)aSmallPositiveFloat;
517 - (float)aSmallNegativeFloat;
520 - (double)aPositiveDouble;
521 - (double)aNegativeDouble;
522 - (double)aZeroDouble;
523 - (double)aBigDouble;
524 - (double)aBigPositiveDouble;
525 - (double)aBigNegativeDouble;
526 - (double)aSmallDouble;
527 - (double)aSmallPositiveDouble;
528 - (double)aSmallNegativeDouble;
533 #pragma mark Accessors
538 - (NSDate *)startDate;
539 - (unsigned)classesWithTests;
540 - (unsigned)classesWithoutTests;
541 - (unsigned)methodsWithTests;
542 - (unsigned)testsRun;
543 - (unsigned)testsPassed;
544 - (unsigned)testsFailed;
546 // TODO: need sense inversion here as well (for uncaught exceptions) for self-testing purposes
547 - (unsigned)uncaughtExceptions;
549 - (unsigned)testsFailedExpected;
550 - (unsigned)testsPassedUnexpected;
551 - (BOOL)expectFailures;
552 - (void)setExpectFailures:(BOOL)aValue;
554 - (unsigned)lowLevelExceptionsExpected;
555 - (unsigned)lowLevelExceptionsUnexpected;
556 - (BOOL)expectLowLevelExceptions;
557 - (void)setExpectLowLevelExceptions:(BOOL)aValue;
559 - (BOOL)handlesLowLevelExceptions;
560 - (void)setHandlesLowLevelExceptions:(BOOL)aValue;
562 - (unsigned)verbosity;
563 - (void)setVerbosity:(unsigned)aVerbosity;
565 - (unsigned)trimInitialPathComponents;
566 - (void)setTrimInitialPathComponents:(unsigned)aTrimInitialPathComponents;
568 - (NSString *)lastReportedFile;
569 - (void)setLastReportedFile:(NSString *)aLastReportedFile;
571 - (BOOL)warnsAboutSignComparisons;
572 - (void)setWarnsAboutSignComparisons:(BOOL)aWarnsAboutSignComparisons;