PageRenderTime 31ms CodeModel.GetById 21ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/MapView/GTM/GTMNSObject+UnitTesting.h

http://github.com/route-me/route-me
C Header | 427 lines | 83 code | 35 blank | 309 comment | 9 complexity | 870a864b1fa718aa6f60a534a0286846 MD5 | raw file
  1//
  2//  GTMNSObject+UnitTesting.h
  3//
  4//  Utilities for doing advanced unittesting with objects.
  5//
  6//  Copyright 2006-2008 Google Inc.
  7//
  8//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  9//  use this file except in compliance with the License.  You may obtain a copy
 10//  of the License at
 11// 
 12//  http://www.apache.org/licenses/LICENSE-2.0
 13// 
 14//  Unless required by applicable law or agreed to in writing, software
 15//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 16//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 17//  License for the specific language governing permissions and limitations under
 18//  the License.
 19//
 20
 21#import "GTMDefines.h"
 22#import <Foundation/Foundation.h>
 23
 24#if GTM_MACOS_SDK
 25#import <ApplicationServices/ApplicationServices.h>
 26#elif GTM_IPHONE_SDK
 27#import <CoreGraphics/CoreGraphics.h>
 28#endif
 29
 30#import "GTMSenTestCase.h"
 31
 32// Utility functions for GTMAssert* Macros. Don't use them directly
 33// but use the macros below instead
 34BOOL GTMIsObjectImageEqualToImageNamed(id object, 
 35                                       NSString *filename, 
 36                                       NSString **error);
 37BOOL GTMIsObjectStateEqualToStateNamed(id object, 
 38                                       NSString *filename, 
 39                                       NSString **error);
 40
 41// Fails when image of |a1| does not equal image in image file named |a2|
 42//
 43//  Generates a failure when the unittest image of |a1| is not equal to the 
 44//  image stored in the image file named |a2|, or |a2| does not exist in the 
 45//  executable code's bundle.
 46//  If |a2| does not exist in the executable code's bundle, we save a image
 47//  representation of |a1| in the save directory with name |a2|. This can then
 48//  be included in the bundle as the master to test against.
 49//  If |a2| != |a1|, we save a image representation of |a1| in the save 
 50//  directory named |a2|_Failed and a file named |a2|_Failed_Diff showing the 
 51//  diff in red so that we can see what has changed.
 52//  See pathForImageNamed to see how name is searched for.
 53//  The save directory is specified by +gtm_setUnitTestSaveToDirectory, and is
 54//  the desktop by default.
 55//  Implemented as a macro to match the rest of the SenTest macros.
 56//
 57//  Args:
 58//    a1: The object to be checked. Must implement the -createUnitTestImage method.
 59//    a2: The name of the image file to check against.
 60//        Do not include the extension
 61//    description: A format string as in the printf() function. 
 62//        Can be nil or an empty string but must be present. 
 63//    ...: A variable number of arguments to the format string. Can be absent.
 64//
 65#define GTMAssertObjectImageEqualToImageNamed(a1, a2, description, ...) \
 66do { \
 67  id a1Object = (a1); \
 68  NSString* a2String = (a2); \
 69  NSString *failString = nil; \
 70  BOOL isGood = GTMIsObjectImageEqualToImageNamed(a1Object, a2String, &failString); \
 71  if (!isGood) { \
 72    if (description != nil) { \
 73      STFail(@"%@: %@", failString, STComposeString(description, ##__VA_ARGS__)); \
 74    } else { \
 75      STFail(@"%@", failString); \
 76    } \
 77  } \
 78} while(0)
 79
 80// Fails when state of |a1| does not equal state in file |a2|
 81//
 82//  Generates a failure when the unittest state of |a1| is not equal to the 
 83//  state stored in the state file named |a2|, or |a2| does not exist in the 
 84//  executable code's bundle.
 85//  If |a2| does not exist in the executable code's bundle, we save a state
 86//  representation of |a1| in the save directiry with name |a2|. This can then 
 87//  be included in the bundle as the master to test against.
 88//  If |a2| != |a1|, we save a state representation of |a1| in the save 
 89//  directory with name |a2|_Failed so that we can compare the two files to see 
 90//  what has changed.
 91//  The save directory is specified by +gtm_setUnitTestSaveToDirectory, and is
 92//  the desktop by default.
 93//  Implemented as a macro to match the rest of the SenTest macros.
 94//
 95//  Args:
 96//    a1: The object to be checked. Must implement the -createUnitTestImage method.
 97//    a2: The name of the state file to check against.
 98//        Do not include the extension
 99//    description: A format string as in the printf() function. 
100//        Can be nil or an empty string but must be present. 
101//    ...: A variable number of arguments to the format string. Can be absent.
102//
103#define GTMAssertObjectStateEqualToStateNamed(a1, a2, description, ...) \
104do { \
105  id a1Object = (a1); \
106  NSString* a2String = (a2); \
107  NSString *failString = nil; \
108  BOOL isGood = GTMIsObjectStateEqualToStateNamed(a1Object, a2String, &failString); \
109  if (!isGood) { \
110    if (description != nil) { \
111      STFail(@"%@: %@", failString, STComposeString(description, ##__VA_ARGS__)); \
112    } else { \
113      STFail(@"%@", failString); \
114    } \
115  } \
116} while(0);
117
118// test both GTMAssertObjectImageEqualToImageNamed and GTMAssertObjectStateEqualToStateNamed
119//
120// Combines the above two macros into a single ubermacro for comparing
121// both state and image. When only the best will do...
122#define GTMAssertObjectEqualToStateAndImageNamed(a1, a2, description, ...) \
123do { \
124  GTMAssertObjectImageEqualToImageNamed(a1, a2, description, ##__VA_ARGS__); \
125  GTMAssertObjectStateEqualToStateNamed(a1, a2, description, ##__VA_ARGS__); \
126} while (0)
127
128// Create a CGBitmapContextRef appropriate for using in creating a unit test 
129// image. If data is non-NULL, returns the buffer that the bitmap is
130// using for it's underlying storage. You must free this buffer using
131// free. If data is NULL, uses it's own internal storage.
132// Defined as a C function instead of an obj-c method because you have to
133// release the CGContextRef that is returned.
134//
135//  Returns:
136//    an CGContextRef of the object. Caller must release
137
138CGContextRef GTMCreateUnitTestBitmapContextOfSizeWithData(CGSize size,
139                                                          unsigned char **data);
140
141// GTMUnitTestingImaging protocol is for objects which need to save their
142// image for using with the unit testing categories
143@protocol GTMUnitTestingImaging
144// Create a CGImageRef containing a representation suitable for use in 
145// comparing against a master image. 
146//
147//  Returns:
148//    an CGImageRef of the object.
149- (CGImageRef)gtm_unitTestImage;
150@end
151
152// GTMUnitTestingEncoding protocol is for objects which need to save their
153// "state" for using with the unit testing categories
154@protocol GTMUnitTestingEncoding
155//  Encodes the state of an object in a manner suitable for comparing
156//  against a master state file so we can determine whether the
157//  object is in a suitable state. Encode data in the coder in the same
158//  manner that you would encode data in any other Keyed NSCoder subclass.
159//
160//  Arguments:
161//    inCoder - the coder to encode our state into
162- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder;
163@end
164
165// Category for saving and comparing object state and image for unit tests
166//
167//  The GTMUnitTestAdditions category gives object the ability to store their
168//  state for use in unittesting in two different manners.
169// 1) Objects can elect to save their "image" that we can compare at
170// runtime to an image file to make sure that the representation hasn't
171// changed. All views and Windows can save their image. In the case of Windows,
172// they are "bluescreened" so that any transparent areas can be compared between
173// machines.
174// 2) Objects can elect to save their "state". State is the attributes that we
175// want to verify when running unit tests. Applications, Windows, Views,
176// Controls and Cells currently return a variety of state information. If you
177// want to customize the state information that a particular object returns, you
178// can do it via the GTMUnitTestingEncodedObjectNotification. Items that have
179// delegates (Applications/Windows) can also have their delegates return state
180// information if appropriate via the unitTestEncoderDidEncode:inCoder: delegate
181// method.
182// To compare state/image in your unit tests, you can use the three macros above
183// GTMAssertObjectStateEqualToStateNamed, GTMAssertObjectImageEqualToImageNamed and
184// GTMAssertObjectEqualToStateAndImageNamed.
185@interface NSObject (GTMUnitTestingAdditions) <GTMUnitTestingEncoding>
186// Allows you to control where the unit test utilities save any files
187// (image or state) that they create on your behalf. By default they
188// will save to the desktop.
189+ (void)gtm_setUnitTestSaveToDirectory:(NSString*)path;
190+ (NSString *)gtm_getUnitTestSaveToDirectory;
191
192// Checks to see that system settings are valid for doing an image comparison.
193// Most of these are set by our unit test app. See the unit test app main.m
194// for details.
195//
196// Returns:
197//  YES if we can do image comparisons for this object type.
198- (BOOL)gtm_areSystemSettingsValidForDoingImage;
199
200// Return the type of image to work with. Only valid types on the iPhone
201// are kUTTypeJPEG and kUTTypePNG. MacOS supports several more.
202- (CFStringRef)gtm_imageUTI;
203
204// Return the extension to be used for saving unittest images
205//
206// Returns
207//  An extension (e.g. "png")
208- (NSString*)gtm_imageExtension;
209
210// Return image data in the format expected for gtm_imageExtension
211// So for a "png" extension I would expect "png" data
212//
213// Returns
214//  NSData for image
215- (NSData*)gtm_imageDataForImage:(CGImageRef)image;
216
217// Save the unitTestImage to a image file with name 
218// |name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension
219// in the save folder (desktop by default)
220//
221//  Args:
222//    name: The name for the image file you would like saved.
223//
224//  Returns:
225//    YES if the file was successfully saved.
226//
227- (BOOL)gtm_saveToImageNamed:(NSString*)name;
228
229// Save unitTestImage of |self| to an image file at path |path|. 
230// All non-drawn areas will be transparent.
231//
232//  Args:
233//    name: The name for the image file you would like saved.
234//
235//  Returns:
236//    YES if the file was successfully saved.
237//
238- (BOOL)gtm_saveToImageAt:(NSString*)path;
239
240//  Compares unitTestImage of |self| to the image located at |path|
241//
242//  Args:
243//    path: the path to the image file you want to compare against.
244//    If diff is non-nil, it will contain an auto-released diff of the images.
245//
246//  Returns:
247//    YES if they are equal, NO is they are not
248//    If diff is non-nil, it will contain a diff of the images. Must
249//    be released by caller.
250//
251- (BOOL)gtm_compareWithImageAt:(NSString*)path diffImage:(CGImageRef*)diff;
252
253//  Find the path for a image by name in your bundle.
254//  Searches for the following:
255//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.OSVersionBugFix.arch.extension"
256//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.arch.extension"
257//  "name.CompilerSDK.OSVersionMajor.arch.extension"
258//  "name.CompilerSDK.arch.extension"
259//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.OSVersionBugFix.extension"
260//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.extension"
261//  "name.CompilerSDK.OSVersionMajor.extension"
262//  "name.CompilerSDK.extension"
263//  "name.OSVersionMajor.OSVersionMinor.OSVersionBugFix.arch.extension"
264//  "name.OSVersionMajor.OSVersionMinor.arch.extension"
265//  "name.OSVersionMajor.arch.extension"
266//  "name.arch.extension"
267//  "name.OSVersionMajor.OSVersionMinor.OSVersionBugFix.extension"
268//  "name.OSVersionMajor.OSVersionMinor.extension"
269//  "name.OSVersionMajor.extension"
270//  "name.extension"
271//  Do not include the extension on your name.
272//
273//  Args:
274//    name: The name for the image file you would like to find.
275//
276//  Returns:
277//    the path if the image exists in your bundle
278//    or nil if no image to be found
279//
280- (NSString *)gtm_pathForImageNamed:(NSString*)name;
281
282// Generates a CGImageRef from the image at |path|
283// Args:
284//  path: The path to the image.
285//
286// Returns:
287//  An autoreleased CGImageRef own, or nil if no image at path
288- (CGImageRef)gtm_imageWithContentsOfFile:(NSString*)path;
289
290//  Generates a path for a image in the save directory, which is desktop
291//  by default.
292//  Path will be:
293//  SaveDir/|name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension
294//
295//  Args:
296//    name: The name for the image file you would like to generate a path for.
297//
298//  Returns:
299//    the path
300//
301- (NSString *)gtm_saveToPathForImageNamed:(NSString*)name;
302
303//  Gives us a representation of unitTestImage of |self|.
304//
305//  Returns:
306//    a representation if successful
307//    nil if failed
308//
309- (NSData *)gtm_imageRepresentation;
310
311// Return the extension to be used for saving unittest states
312//
313// Returns
314//  An extension (e.g. "gtmUTState")
315- (NSString*)gtm_stateExtension;
316
317// Save the encoded unit test state to a state file with name 
318// |name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension
319// in the save folder (desktop by default)
320//
321//  Args:
322//    name: The name for the state file you would like saved.
323//
324//  Returns:
325//    YES if the file was successfully saved.
326//
327- (BOOL)gtm_saveToStateNamed:(NSString*)name;
328
329//  Save encoded unit test state of |self| to a state file at path |path|.
330//
331//  Args:
332//    name: The name for the state file you would like saved.
333//
334//  Returns:
335//    YES if the file was successfully saved.
336//
337- (BOOL)gtm_saveToStateAt:(NSString*)path;
338
339// Compares encoded unit test state of |self| to the state file located at |path|
340//
341//  Args:
342//    path: the path to the state file you want to compare against.
343//
344//  Returns:
345//    YES if they are equal, NO is they are not
346//
347- (BOOL)gtm_compareWithStateAt:(NSString*)path;
348
349
350// Find the path for a state by name in your bundle.
351//  Searches for:
352//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.OSVersionBugFix.arch.extension"
353//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.arch.extension"
354//  "name.CompilerSDK.OSVersionMajor.arch.extension"
355//  "name.CompilerSDK.arch.extension"
356//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.OSVersionBugFix.extension"
357//  "name.CompilerSDK.OSVersionMajor.OSVersionMinor.extension"
358//  "name.CompilerSDK.OSVersionMajor.extension"
359//  "name.CompilerSDK.extension"
360//  "name.OSVersionMajor.OSVersionMinor.OSVersionBugFix.arch.extension"
361//  "name.OSVersionMajor.OSVersionMinor.arch.extension"
362//  "name.OSVersionMajor.arch.extension"
363//  "name.arch.extension"
364//  "name.OSVersionMajor.OSVersionMinor.OSVersionBugFix.extension"
365//  "name.OSVersionMajor.OSVersionMinor.extension"
366//  "name.OSVersionMajor.extension"
367//  "name.extension"
368//  Do not include the extension on your name.
369//
370//  Args:
371//    name: The name for the state file you would like to find.
372//
373//  Returns:
374//    the path if the state exists in your bundle
375//    or nil if no state to be found
376//
377- (NSString *)gtm_pathForStateNamed:(NSString*)name;
378
379//  Generates a path for a state in the save directory, which is desktop
380//  by default.
381//  Path will be:
382//  SaveDir/|name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension
383//
384//  Args:
385//    name: The name for the state file you would like to generate a path for.
386//
387//  Returns:
388//    the path
389//
390- (NSString *)gtm_saveToPathForStateNamed:(NSString*)name;
391
392//  Gives us the encoded unit test state for |self|
393//
394//  Returns:
395//    the encoded state if successful
396//    nil if failed
397//
398- (NSDictionary *)gtm_stateRepresentation;
399
400//  Encodes the state of an object in a manner suitable for comparing
401//  against a master state file so we can determine whether the
402//  object is in a suitable state. Encode data in the coder in the same
403//  manner that you would encode data in any other Keyed NSCoder subclass.
404//
405//  Arguments:
406//    inCoder - the coder to encode our state into
407- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder;  
408@end
409
410// Informal protocol for delegates that wanst to be able to add state info
411// when state info is collected for their "owned" objects
412@interface NSObject (GTMUnitTestingEncodingAdditions)
413// Delegate function for unit test objects that have delegates. Delegates have
414// the option of encoding more data into the coder to store their state for
415// unittest usage.
416- (void)gtm_unitTestEncoderWillEncode:(id)sender inCoder:(NSCoder*)inCoder;
417@end
418
419// Whenever an object is encoded by the unit test encoder, it send out a
420// notification so that objects who want to add data to the encoded objects unit
421// test state can do so. The Coder will be in the userInfo dictionary for the
422// notification under the GTMUnitTestingEncoderKey key.
423GTM_EXTERN NSString *const GTMUnitTestingEncodedObjectNotification;
424
425// Key for finding the encoder in the userInfo dictionary for
426// GTMUnitTestingEncodedObjectNotification notifications.
427GTM_EXTERN NSString *const GTMUnitTestingEncoderKey;