EzDevInfo.com

expecta

A Matcher Framework for Objective-C/Cocoa

How to unit test a UIViewController - TDD/BDD

Unit testing is just something I never seem to be able to get my head around but I can see why its important and can be a huge time saver (if you know what you're doing). I am hoping that someone can point me in the right direction.

I have the following UIViewController

QBElectricityBaseVC.h

@interface QBElectricityBaseVC : QBStateVC

@property (nonatomic, strong) QBElectricityUsage *electricityUsage;
@property (nonatomic, assign) CGFloat tabBarHeight;

- (void)updateElectricityUsage;

@end

QBElectricityBaseVC.m

@implementation QBElectricityBaseVC

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"electricity_title", nil) image:nil tag:0];
    }
    return self;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.notificationCenter addObserver:self selector:@selector(updateElectricityUsage)
                                                 name:kUpdatedElectricityUsageKey object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [self.notificationCenter removeObserver:self];
}

- (void)updateElectricityUsage
{
    self.electricityUsage = [self.stateManager electricityUsage];
}

- (CGFloat)tabBarHeight
{
    return self.tabBarController.tabBar.frame.size.height;
}

@end

What should I test?

  • An observer for kUpdatedElectricityUsageKey is added
  • self.electricityUsage becomes an instance of QBElectricityUsage
  • A tabBarHeight is returned
  • An observer for kUpdatedElectricityUsageKey is removed

Am I missing anything I should test or testing something I really shouldn't?

How do I test?

So I am trying to do this using Specta and Expexta. If I need to mock anything I would be using OCMockito.

I really don't know how to test the observer is added/removed. I see the following in the Expexta documentation but not sure if its relevant/how to use it:

expect(^{ /* code */ }).to.notify(@"NotificationName"); passes if a given block of code generates an NSNotification named NotificationName.

expect(^{ /* code */ }).to.notify(notification); passes if a given block of code generates an NSNotification equal to the passed notification.

To test that self.electricityUsage becomes an instance of QBElectricityUsage I could create a category that has a method that just pretends the notification fired and calls the updateElectricityUsage method but is this the best way?

And as for the tabBarHeight, should I just test that it returns a valid CGFloat and not worry what the value is?


UPDATE

I changed my viewWillAppear method to look like below:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self addNotificationObservers];
}

- (void)addNotificationObservers
{
    [self.notificationCenter addObserver:self selector:@selector(updateElectricityUsage)
                                    name:kUpdatedElectricityUsageKey object:nil];
}

And then I created the following test:

#import "Specs.h"

#import "QBElectricityBaseVC.h"
#import "ElectricityConstants.h"

SpecBegin(QBElectricityBaseVCSpec)

    describe(@"QBElectricityBaseVC", ^{
        __block QBElectricityBaseVC *electricityBaseVC;
        __block NSNotificationCenter *mockNotificationCenter;

        beforeEach(^{
            electricityBaseVC = [QBElectricityBaseVC new];
            mockNotificationCenter = mock([NSNotificationCenter class]);
            electricityBaseVC.notificationCenter = mockNotificationCenter;
        });

        afterEach(^{
            electricityBaseVC = nil;
            mockNotificationCenter = nil;
        });

        it(@"should have a notification observer for updated electricity usage", ^{
            [electricityBaseVC addNotificationObservers];
            [verify(mockNotificationCenter) addObserver:electricityBaseVC selector:@selector(updateElectricityUsage)
                                               name:kUpdatedElectricityUsageKey object:nil];
        });
    });

SpecEnd

That test now passes but is this the correct/best way to test this?


Source: (StackOverflow)

iOS/Mac OS fluent matching framework that works with Swift?

Is there a fluent matching API that works for Swift code? The leading Objective-C matcher candidates seem to be OCHamcrest and Expecta, both of which rely on complex macros that (as per the docs) aren't available to Swift code, e.g.

#define HC_assertThat(actual, matcher)  \
    HC_assertThatWithLocation(self, actual, matcher, __FILE__, __LINE__)

(OCHamcrest)

#define EXP_expect(actual) _EXP_expect(self, __LINE__, __FILE__, ^id{ return EXPObjectify((actual)); })

(Expecta)

Is there another alternative that does work with Swift, or some way to wrap one or the other of these so they can be used with Swift?


ETA: For future readers -- I looked at SwiftHamcrest (per Jon Reid's answer) but for the time being I've settled on Quick/Nimble.


Source: (StackOverflow)

Advertisements

Xcode: Disable watch simulator when running app

I recently updated Xcode and now the watch simulator keeps starting every time I run my app on the regular simulator. How do I disable this?


Source: (StackOverflow)

How can I test asynchronous delegate methods using Expecta/OCMockito?

I'm currently using Kiwi to write tests, but I'm interested in trying out Specta/Expecta/OCMockito (or another mocking library, if necessary).

One thing I use Kiwi for is testing that delegate methods are called after some asynchronous work. For example, this Kiwi spec stubs an HTTP request response (which is performed in a background queue), and tests that eventually the delegate is informed of a response from the request:

it(@"Sends a callback", ^{
    [OHHTTPStubs stubRequestContainingString:@"start" withJSON:@{}];

    id starterMock = [KWMock mockForProtocol:@protocol(HZMediationStarting)];
    HZMediationStarter *starter = [[HZMediationStarter alloc] initWithStartingDelegate:starterMock];

    [starter start];
    [[starterMock shouldEventually] receive:@selector(startWithDictionary:fromCache:)];
});

Is there a way to achieve this with Expecta/OCMockito (or potentially another mocking library?). I can see that Expecta supports asynchronous expectations, but I'm not sure how to combine that with a mocking library like OCMockito.


Source: (StackOverflow)