Last Updated: February 25, 2016
·
2.159K
· javierg

Cocoa Unit testing CGContext transformations

Test coverage in cocoa usually is divided on Unit and Application testing.

Sometimes unit testing will involve asserting transformations on a CGContext. I know you might want to wrap CoreGraphics calls into "mockable" methods to keep your code testable; but just in case you want to test if a transformation actually occurs this is something that worked for me in a recent developed project.

TestView.h

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@interface ABTestView : UIView
@property (nonatomic) CGContextRef drawingContext;
@end

TestView.m

#import "ABTestView.h"

@implementation ABTestView

- (void)drawRect:(CGRect)rect
{
    self.drawingContext = UIGraphicsGetCurrentContext();
}

@end

Once you have this you can add it to the rootViewController on the app, in kiwi should be something like:

#import "MyView.h"
#import "ABTestView.h"
#import "ABAppDelegate.h"

SPEC_BEGIN(MyViewSpec)

__block UIView *testView;
__block UIView *myView;
__block CGContextRef graphicsContext;
__block CGAffineTransform transformMatrix;

beforeEach(^{
    // first we get the app delegate
    app *appDelegate = [[UIApplication sharedApplication] delegate];

    // we init our testView
    CGRect aFrame = CGRectMake(0,0,100,100);
    testView = [TestView.alloc initWithFrame:aFrame];

    //add it to the rootViewController
    [app.window.rootViewController.view addSubview:testView];

    // this is a little weird. If we don't add this the context 
    // won't be available. I bet there is better ways to wait for it.
    [[theValue(testView.drawingContext) shouldEventually] beNonNil];

    // Now we have a context to test
    graphicsContext = testView.drawingContext;

    // Init our view with some transformations
    // or call the methods that transforms the ContextMatrix
    myView = [MyView.alloc initWithFrame:aFrame flipped:YES];
    [testView addSubview:myView];

   // We now capture the Transformation Matrix
    transformMatrix = CGContextGetCTM(graphicsContext);
});

afterEach(^{
    // don't forget to clean after you.
    CGContextRelease(graphicsContext);
    testView = nil;
    myView = nil;
    transformMatrix = nil;
});

it(@"should transform the context matrix", ^{
    // And now we can assert warever transformations we applied
    // to the Affine Transformation Matrix.
    [[theValue(transformMatrix.a) should] equal:theValue(-1)];
});

SPEC_END

This method works only for Context Matrix Transformations, but it allow us to test some logic that is very important for our app. This is not for UI testing, but for testing logic on methods that otherwise will go untested.

1 Response
Add your response

Way to contribute!

over 1 year ago ·