ios - How to unit test a UIViewController - TDD/BDD -


unit testing never seem able head around can see why important , can huge time saver (if know you're doing). hoping can point me in right direction.

i have 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 test?

  • an observer kupdatedelectricityusagekey added
  • self.electricityusage becomes instance of qbelectricityusage
  • a tabbarheight returned
  • an observer kupdatedelectricityusagekey removed

am missing should test or testing shouldn't?

how test?

so trying using specta , expexta. if need mock using ocmockito.

i don't know how test observer added/removed. see following in expexta documentation not sure if relevant/how use it:

expect(^{ /* code */ }).to.notify(@"notificationname"); passes if given block of code generates nsnotification named notificationname.  expect(^{ /* code */ }).to.notify(notification); passes if given block of code generates nsnotification equal passed notification. 

to test self.electricityusage becomes instance of qbelectricityusage create category has method pretends notification fired , calls updateelectricityusage method best way?

and tabbarheight, should test returns valid cgfloat , not worry value is?


update

i changed viewwillappear method below:

- (void)viewwillappear:(bool)animated {     [super viewwillappear:animated];     [self addnotificationobservers]; }  - (void)addnotificationobservers {     [self.notificationcenter addobserver:self selector:@selector(updateelectricityusage)                                     name:kupdatedelectricityusagekey object:nil]; } 

and created 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 notification observer updated electricity usage", ^{             [electricitybasevc addnotificationobservers];             [verify(mocknotificationcenter) addobserver:electricitybasevc selector:@selector(updateelectricityusage)                                                name:kupdatedelectricityusagekey object:nil];         });     });  specend 

that test passes correct/best way test this?

you've felt 1 big con of ios viewcontrollers: they suck @ testability.

  • viewcontrollers mix logic of managing view , model

another big problem mvc discourages developers writing unit tests. since view controllers mix view manipulation logic business logic, separating out components sake of unit testing becomes herculean task. task many ignore in favour of… not testing anything.

article - source

maybe should think using mvvm instead. great article explaining difference of ios mvc , mvvm.

the great thing using mvvm can use databinding using reactive cocoa. here's tutorial explain data binding mvvm , reactive programming in ios.


Comments

Popular posts from this blog

matlab - "Contour not rendered for non-finite ZData" -

delphi - Indy UDP Read Contents of Adata -

javascript - Any ideas when Firefox is likely to implement lengthAdjust and textLength? -