cedarbdd / cedar

BDD-style testing using Objective-C
http://groups.google.com/group/cedar-discuss
1.19k stars 140 forks source link

should equal throws exception when comparing const pointer to a non-const pointer #401

Closed markcarl closed 7 years ago

markcarl commented 7 years ago

My team has hundreds of Cedar tests for our app that work correctly when I run them within xCode 8 as long as I run them in an iOS 8 simulator. If I attempt to run the Cedar tests on an iOS9 or greater simulator I get hundreds of exceptions like this:

EXCEPTION SFShadowOverTabBar #drawRect: show shadow (happy path) sets the shadow color Invalid return value type 'struct CGPath ' instead of 'const struct CGPath ' for (null)

for tests like this:

    it(@"sets the shadow color", ^{
        view.layer.shadowColor should equal([UIColor blackColor].CGColor);
    });

In this case, it looks like an exception is thrown when should equal compares a const pointer to a non-const pointer. There are other failures too but this is the most obvious one.

Is anyone maintaining Cedar? Does Cedar officially support iOS 10x, iOS 9x and xCode 8x? If not, are there plans to add support? I hope the answer is yes as my team has invested a lot of effort in these tests and we'd like to be able to keep using them.

akitchen commented 7 years ago

Hi there -

Thanks for opening an issue! Yes, Cedar supports the latest iOS and Xcode, is maintained and happily accepting pull requests.

Cedar is very mature and stable however, so we do rely on issues like this coming in from real projects. Thanks for letting us know.

We have noticed some subtle changes here and there in some of the underlying types in the UIColor class cluster in recent iOSes, so this is to be expected to a certain degree.

Your example code references a CGColor, but the error seems to refer to a struct CGPath * -- Are you sure these are from the same test? It's also worth looking into whether the types you wish to compare have their own equality functions, and either use those directly or wrap them in a template specialization within the Equal matcher class

I hope that helps - Thanks!

On Wed, Feb 22, 2017 at 9:44 AM, markcarl notifications@github.com wrote:

My team has hundreds of Cedar tests for our app that work correctly when I run them within xCode 8 as long as I run them in an iOS 8 simulator. If I attempt to run the Cedar tests on an iOS9 or greater simulator I get hundreds of exceptions like this:

EXCEPTION SFShadowOverTabBar #drawRect: show shadow (happy path) sets the shadow color Invalid return value type 'struct CGPath ' instead of 'const struct CGPath ' for (null)

for tests like this:

it(@"sets the shadow color", ^{
    view.layer.shadowColor should equal([UIColor blackColor].CGColor);
});

In this case, it looks like an exception is thrown when should equal compares a const pointer to a non-const pointer. There are other failures too but this is the most obvious one.

Is anyone maintaining Cedar? Does Cedar officially support iOS 10x, iOS 9x and xCode 8x? If not, are there plans to add support? I hope the answer is yes as my team has invested a lot of effort in these tests and we'd like to be able to keep using them.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/pivotal/cedar/issues/401, or mute the thread https://github.com/notifications/unsubscribe-auth/AAXHGEEGNUvSXYizXUe3jEXqKUZczF9gks5rfHP8gaJpZM4MI94f .

markcarl commented 7 years ago

Thanks for your message!

I looked further and see that the exception for the test example I referenced is in the beforeEach block for the test. The exception occurs when the bold line below is executed:

    describe(@"#drawRect2:", ^{
        __block UIBezierPath *fakePath;
        __block CGRect passedRect;
        __block Swizzlean *bezierSwizz;
        __block struct CGPath *path;

        beforeEach(^{
            fakePath = nice_fake_for([UIBezierPath class]);

            bezierSwizz = [[Swizzlean alloc] initWithClassToSwizzle:[UIBezierPath class]];
            [bezierSwizz swizzleClassMethod:@selector(bezierPathWithRect:) withReplacementImplementation:^(id self, CGRect rect) {
                passedRect = rect;
                return [fakePath retain];
            }];

            path = CGPathCreateMutable();
            fakePath stub_method(@selector(CGPath)).and_return(path);

            view.bounds = CGRectMake(0,0,200,200);
            [view drawRect:CGRectZero];
        });

        afterEach(^{
            [bezierSwizz resetSwizzledClassMethod];
        });

        fit(@"sets the shadow color", ^{
            view.layer.shadowColor should equal([UIColor blackColor].CGColor);
        });

    });

If I add a const specifier to the declaration for path, the exception goes away.

__block const struct CGPath *path;

Thanks again for your help!

tjarratt commented 7 years ago

The invalid return type message sounds really similar to the error messages for Cedar's fakes.

My guess is that you have a fake that returns a CGPath * but the UIKit api now returns a const CGPath *.

What's happening under the hood is that Cedar's fakes try to verify that your stubbed values are correct - it wants to catch errors about mismatched return types early, so that you aren't surprised when your tests are wrong. Perhaps as part of building up your subview, or the label, there's a fake somewhere that's providing a CGPath?

That's all just my intuition, but if I'm wrong, I'd try tracking down the "invalid return value type" message, set the appropriate breakpoint in Cedar and try to walk back up the call stack and understand how that happened.

tjarratt commented 7 years ago

Oh sorry @markcarl I didn't see your response, I'm glad you got it to work again. Just a few thoughts and kind words of advice:

Only mentioning that because I've been bit by that a dozen times before personally, and it's always a tough issue to troubleshoot.

tjarratt commented 7 years ago

Closing now as resolved, but feel free to re-open if you'd like to discuss it more. Always happy to talk to Cedar users :)