kiwi-bdd / Kiwi

Simple BDD for iOS
BSD 3-Clause "New" or "Revised" License
4.14k stars 512 forks source link

Added block beEvaluated family of matchers to Kiwi. #673

Open trimmurrti opened 8 years ago

trimmurrti commented 8 years ago

This PR adds beEvaluated family of verifiers to the latest version of Kiwi (2.3.1).

beEvaluated allows developers to intercept the messages sent to block in order to verifyif, the block was called and which arguments are being used. See the functional tests in Tests/Functional/KWMessagePatternFunctionalTests.m for sample usage.

Adresses issue #183.

Implementation Details

KWSelectorMessagePattern was previously KWMessagePattern KWBlockMessagePattern is a subclass of KWMessagePattern. In order to make the unintrusive implementation, block message pattern works the same way, as an ordinary message pattern, but doesn't rely on selectors, selector getter always returns NULL. KWMessagePattern is an abstract superclass for both message pattern types, it has class cluster methods for creating subclasses. KWBlockSignature is NSMethodSignature subclass, it is used specifically for blocks, who only have 1 hidden argument (self), unlike objective-c methods, which have 2 (self and _cmd). It also implements methods from NSMethodSignature+KiwiAdditions to account for that. KWBlockInvocation is an NSInvocation subclass, which takes into account specifics of block invocations (they have KWBlockSignatures) and only one hidden argument. It also implements methods from NSInvocation+KiwiAdditions to account for that. KWMessageTrackerMatcher is a parent class for the classes using message trackers (e.g. KWReceiveMatcher) in order to avoid code duplication. KWReceiveMatcher was refactored to use KWMessageTrackerMatcher. KWBeEvaluatedMatcher is the new matcher, which implements the block call verification with or without parameter matching. KWBlockLayout is a set of C runtime methods and data structures derived from the libclosure. KWProxyBlock is a an object wrapper around block, which imitates the block in runtime according to the current libclosure implementation. It intercepts the block calls by redirecting block call to _objc_msgForward_stret / _objc_msgForward depending on the block contents. Additional logic was added for listening to the block message patterns. As of now, KWProxyBlock returns the result originally implemented by the block and doesn't support stubbing the block. theBlockProxy, lambdaProxy - creates the KWProxyBlock

Sample Usage

describe(@"block message patterns", ^{

    it(@"can match a call with a specific single argument", ^{
        id argument = [NSObject new];
        id block = theBlockProxy(^(id object) { [object description]; });

        [[block should] beEvaluatedWithArguments:argument];

        ((KWTestBlock)block)(argument);
    });

});
trimmurrti commented 8 years ago

It seems, like travis is using outdated build environment, as the tests are passing fine on my local environment. Could you pelase specify, which environment are you using for tests, so that I could fix the appropriate tests, that are failing?

trimmurrti commented 8 years ago

Hi, I see, that there are merge conflicts now. Should I resolve them on my end and then update the pull - request to simplify matters for you?

ecaselles commented 4 years ago

Hello @trimmurrti, I am preparing a new version of Kiwi and reviewing the old open PRs for potential features to add, I believe this one would be a helpful one. Would you be interested in resurrecting it?

trimmurrti commented 4 years ago

@ecaselles, I would be glad to. I'll start the next weekend.

trimmurrti commented 4 years ago

@ecaselles, lets see how tests roll. It's compilable and tests are working under xcode 11.3

trimmurrti commented 4 years ago

@ecaselles , pull request updated and works. Feel free to merge at your convenience or ping me, if you need some guidance, fixes or updates.

ecaselles commented 4 years ago

Great @trimmurrti! I will review it and let you know if I have any questions but it looks good. It’s a cool feature 👌

trimmurrti commented 4 years ago

@ecaselles, awesome.