iOS - Test unitari per codici KVO / delegato

3

Ho intenzione di progettare un pattern MVC. Potrebbe essere progettato come modello delegato o Key-Value-Observing (KVO), per notificare al controller i cambiamenti dei modelli. Il progetto richiede alcune procedure di controllo della qualità per conformarsi a tali documenti di verifica.

Le mie domande:

  1. Il modello delegato si adatta meglio ai test unitari rispetto a KVO?

  2. Se KVO si adatta meglio, la prego di suggerire alcuni codici di esempio?

posta ZhangChn 04.09.2012 - 09:43
fonte

3 risposte

3

Penso che questa sia la domanda sbagliata. Delegati, KVO e notifiche possono essere tutti testati unitamente. Questo non dovrebbe essere il problema principale quando scegli come interagire gli oggetti tra loro.

Scegli il modello appropriato per il problema che stai cercando di risolvere. Ad esempio, Apple utilizza i delegati per consentire a UITableView di estrarre informazioni da un controller. Questo sembra appropriato. La vista tabella sa di quali informazioni ha bisogno e estrae le informazioni dai suoi delegati.

Apple avrebbe potuto scegliere di inviare notifiche UITableView. Non vi è alcun motivo tecnico per cui una vista tabella non invii un UITableViewCellForRowAtIndexPathNotification e si aspetti che un sottoscrittore imposti la cella in un percorso dell'indice incluso nelle informazioni utente. Non l'hanno fatto perché non è appropriato.

In generale, i delegati sono appropriati per estrarre informazioni da una fonte di verità. Le viste lo usano per raccogliere i dettagli necessari per la visualizzazione. La notifica e la KVO sono appropriate per spingere le informazioni fuori da una fonte di verità. I modelli lo usano per annunciare le modifiche di cui il resto del sistema potrebbe aver bisogno di sapere.

Aggiorna

Dopo aver letto di nuovo la tua domanda, sembra che tu voglia usare KVO. Per quanto riguarda il codice di un test unitario, ecco un codice per dimostrare come questo può essere fatto.

Presumo che stai cercando di testare un controller che sta osservando una modifica a una proprietà di un modello. Quando si osserva la modifica, il controller cambia il testo di una vista. Il controller avrà proprietà denominate model e textView. Il modello avrà un nome di proprietà prop. TextView avrà una proprietà denominata testo. Il controller esegue KVO chiamando [self addObserver:self forKeyPath:@"model.prop" options:0 context:NULL] .

FakeModel *fakeModel = [[FakeModel alloc] init]; // FakeModel stubs out the needed functionality of Model.
FakeTextView *fakeTextView = [[FakeTextView alloc] init]; // FakeTextView stubs out the needed functionality of TextView.

Controller *controller = [storyboard instantiateViewControllerWithIdentifier:@"controller"]; // Or however you create your controller.
controller.textView = fakeTextView;
controller.model = fakeModel;

fakeModel.prop = @"new value"; // Change model.prop to kick off the KVO and change textview.text.

STAssertEqualObjects(fakeTextView.text, @"expected new text", @"Text should have matched");

Ovviamente, puoi usare OCMock per questo, se lo hai nel tuo progetto.

Spero che ti aiuti.

    
risposta data 18.12.2012 - 17:35
fonte
1

L'approccio delegato è più semplice da testare in quanto il delegato può essere deriso e usato come mock senza dover cambiare (o prestazioni eroiche) nel codice originale.

    
risposta data 18.12.2012 - 07:55
fonte
1

Nessuno dei tuoi approcci suggeriti "si adatta meglio ai test unitari". Potresti usare un delegato, KVO, un blocco di callback, notifiche o qualche altro schema: ognuna di queste cose potrebbe essere testata.

La chiave per scrivere codice testabile nella mia esperienza è scrivere i test prima, come con Sviluppo basato sui test e il suo mantra red-green-refactor. In questo modo, sei vincolato a scrivere codice che può essere (facilmente) testato dal fatto che il test esiste già e devi scrivere codice che si integra con esso.

Se scrivi il codice per primo, quindi prova a testarlo, hai lo stesso problema di qualsiasi tentativo di integrare il codice esistente, anche se su piccola scala. Devi capire dove il tuo test ha bisogno di interfacciarsi con la classe, se la classe fornisce quell'interfaccia, se la classe si aspetta che l'interfaccia sia usata in quel modo ... un aspetto importante di TDD è che scrivi le interfacce di cui hai bisogno < em> quando ti servono, piuttosto che provare ad aggiornarli.

    
risposta data 19.12.2012 - 09:44
fonte

Leggi altre domande sui tag