2015-02-26 23 views
7

Sto scrivendo unit test per i miei ViewControllers. Qual è la migliore pratica per metodi come viewDidAppear :, viewWillAppear:, ecc.Unit Testing ViewController's Lifecycle

Sto utilizzando [vc view] che chiama viewDidLoad. Ma oltre a viewDidLoad, come posso testare unitamente altri metodi del ciclo di vita. È comune averli testati? Ha senso chiamarli direttamente? come:

[vc viewWillAppear:NO]; 
[vc viewDidAppear:NO]; 

Grazie

+1

Che cosa stai cercando di testare? Quale valore fornirebbe un test unitario in questo scenario? –

+1

Quindi con UIView * v = [vista vc] Controllo se la vista è caricata e non è nulla, XCTAssertNotNil (v, @ "Dovrebbe essere caricata") ... ma per gli altri metodi del ciclo di vita sto cercando di istruirmi è una pratica di test unitaria comune. Intendo anche aumentare la copertura del codice. – ramo

+0

@ramo Non penso che ci sia molto valore nel testare la capacità del framework UIKit di caricare la vista, a meno che tu non sia preoccupato di non riuscire a creare le connessioni corrette in uno .xib o storyboard. –

risposta

4

Hai appena sentito una grande con dei ViewControllers iOS: fanno schifo a testability.

Un altro grosso problema con MVC è che scoraggia gli sviluppatori dai test delle unità di scrittura . Poiché i controller di visualizzazione combinano la logica di manipolazione della vista con la logica aziendale, la separazione di tali componenti per il test dell'unità diventa un'attività di tipo erculeo. Un compito che molti ignorano nel favore di ... semplicemente non testare nulla.

source

Non testare UIKit! Dovresti testare la tua logica. Mettere la logica nel tuo VC rende molto difficile testare. Prova a metterlo da qualche altra parte e l'unità testarlo separatamente. La risposta è: dovresti evitare i test chiamando i metodi UIKit, specialmente se questi metodi non sono stati progettati per essere chiamati direttamente!

Se si ottiene tutta la logica dal ViewController, diventerà davvero una visualizzazione: una classe stupida che mostra qualcosa sullo schermo. Non ci dovrebbe essere nulla da testare lì.

Forse dovresti pensare a utilizzare MVVM/MVP/VIPER. Si prega di leggere il link fornito, spiegherà tutto.

4

Ci sono molti sviluppatori che evitano o non credono di poter testare UIViewControllers. Apples poor testing doco non aiuta neanche questo.

UIViewControllers sono abbastanza testabili con un numero di approcci che è possibile adottare.

In primo luogo, come chiunque altro vi dirà, cercate di mantenere la logica aziendale fuori dal vostro controller di visualizzazione. Prova a farlo solo per caricare la vista e il meno possibile. Passare dall'architettura MVC a qualcos'altro può aiutare con questo. A seconda di ciò che si sta creando, si può anche prendere in considerazione l'utilizzo di classi di UIView personalizzate per aiutare pure.

test di unità/logica pura

mi avete a che fare con quello che Apple chiamata 'test Logica', vale a dire un bersaglio di prova senza eseguibile assegnato. Puoi ancora testare molto. I metodi che contengono un semplice codice di gestione delle viste possono essere testati impostando manualmente una vista, oppure usando il codice di prova per caricare manualmente un file xib, ecc. Strutture di simulazione come OCMock possono essere molto utili.

Spesso, tuttavia, in questi tipi di test, è necessario eseguire manualmente vari metodi del ciclo di vita per eseguire il codice che si desidera testare.Ad esempio, se si vogliono testare un metodo viewDidLoad:

id mockView = OCMClassMock([UIView class]); 
// Setup mock expectations. 
myViewController.view = mockView; 
[myViewController viewDidLoad]; 

test applicativi

Se si utilizza un obiettivo di prova in cui è stata impostata l'applicazione, quindi si può effettivamente fare alcuni test da un unit test senza provare a navigare l'app. Questo è un po 'un trucco, ma a volte l'ho trovato abbastanza utile.

UIView *myView = // ... load the view manually or simply [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)] 
myViewController.view = myView; 
[[UIApplication sharedApplication].keyWindow addSubview:myView]; 

Assicurarsi di rimuovere la vista nel teardown se si utilizza questo approccio. Il vantaggio di questo è che tutti i metodi del ciclo di vita intorno a ottenere una vista sullo schermo vengono automaticamente chiamati per te.

Principalmente l'ho trovato utile per i test in relazione ai controller di visualizzazione e alle viste personalizzate relative a viste che sono parti di layout di schermo più grandi. Non tanto i controller di visualizzazione di livello superiore.

test UI

Infine v'è il nuovo framework di test di interfaccia utente che Apple ha fornito. Ho usato framework Ruby di terze parti come Frank e Calabash in passato. A quanto pare, il test dell'interfaccia utente di Apple è abbastanza buono e abbastanza simile a questi strumenti.

Il trucco con esso è usarlo per costruire una libreria di metodi che hanno senso e aiutano a descrivere (usando una DSL) vari aspetti della tua app.

Lo svantaggio di questo approccio è che non è possibile caricare solo la vista che si desidera testare. Devi effettivamente eseguire l'app e navigare verso di essa. L'altro aspetto negativo di questo è che si basa molto sulla vista basata sull'accessibilità esterna della tua app. È quasi impossibile raggiungere le parti interne in modo che i test si basino sul comportamento delle schermate delle app piuttosto che sulle classi interne.

Finora non ho esplorato l'idea di mescolare questa forma di test e caricare manualmente le viste sulla finestra, ma non riesco a capire perché non funzionerebbe.

+0

Nel mixare il test dell'interfaccia utente e manipolare manualmente la gerarchia della vista della finestra - non penso sia possibile, dal momento che i test dell'interfaccia utente vengono eseguiti in un processo separato e hanno accesso solo tramite le varie classi proxy fornite per l'ispezione dell'interfaccia utente (principalmente tramite le proprietà di accessibilità, come hai notato). –

+1

Ancora non riesci a entrare in 'viewDidLayoutSubviews:': / – Kuba