Cum să testați folosind date false pe iOS

Pentru a oferi software de înaltă calitate și pentru a evita regresia, punerea în aplicare a testării unității este o necesitate pentru fiecare aplicație iOS.
Mocking Objects este o tehnică în testarea unităților care creează obiecte false folosind aceleași API-uri ca cele reale.
Acest articol este conceput pentru a vă oferi cele mai bune practici privind utilizarea de date false și scrierea testelor de unități pentru cele mai apărute scenarii din aplicațiile iOS.

Atunci când scriem teste de unitate, ar trebui să evităm întotdeauna modificarea datelor reale ale țintei aplicației și să utilizăm în schimb date false doar în scopuri de testare.

Următoarele părți vor discuta despre modul de scriere a testelor folosind date false pentru API-urile iOS utilizate în mod obișnuit.

Valorile implicite ale utilizatorului

În dezvoltarea de software, este întotdeauna o bună practică de a reduce dependențele obiectelor. În cel mai bun caz, dependențele trebuie injectate în clasele care le utilizează.

Dar dacă verificăm scenariile de dezvoltare iOS din viața reală, aproape fiecare proiect folosește UserDefaults apelând la API-ul direct pentru stocarea sau preluarea oricăror date.

Prin urmare, vom încerca să oferim o soluție practică pentru testarea UserDefaultsrather decât abstractizarea API-ului său cu protocoale.

Putem crea două funcții noi pe UserDefaults

Este întotdeauna o bună practică să nu modificăm datele aplicației din ținta de testare a unității, de aceea ar trebui să creăm un alt loc de salvare a datelor utilizatorului pentru ținta noastră de testare.

În acest caz, inițializăm un nou obiect al UserDefaults cu suiteName - testDefaults că este complet independent de UserDefaults standard.

Să încercăm să scriem un test simplu care folosește UserDefaults

Deoarece aceste date sunt utilizate în principiu doar pentru testare, ar trebui să evităm să lăsăm acele date atârnate în fișierele noastre de aplicații, prin urmare, creăm o funcție responsabilă de renunțarea la această stocare după ce am terminat testul.

Cel mai bun loc pentru curățarea acestor date va fi, desigur, funcția tearDown din clasa noastră de testare a unității.

Obiecte Singelton

Obiectele Singletons sunt foarte utilizate pe iOS pe multe API-uri, le putem găsi pe NSFileManager, NSApplication, UIApplication și în multe alte locuri.

Știind cum să testați singletons este un lucru util de știut pentru dezvoltatorii iOS.

În exemplul nostru, vom folosi cadrul iAd al mărului. Vom crea un fișier pentru a obține un răspuns local JSON în loc de date reale la solicitarea detaliilor privind atribuirea anunțurilor.

O caracteristică plăcută în iOS este că extensiile în rapid ne permit nu numai să adăugăm noi funcții pentru o API predefinită, ci și să le facem conforme cu propriile protocoale personalizate.

Să definim un protocol AdvertisementClient

După aceea, ne conformăm acestui protocol atât prin ADClient implicit, cât și prin clientul nostru fals de reclame, cum ar fi următoarele

Modificăm apoi dependența

private var adClient: AdvertisementClient = ADClient.shared ()

sau

private var adClient: AdvertisementClient = MockAdClient ()

și folosiți-o după cum urmează

În acest fel, putem decide cu ușurință când să folosim date reale și când testează, în funcție de testarea unității sau de apelare a API-ului de la aplicația noastră directă.

Date de bază

Datele de bază sunt încă foarte utilizate în iOS pentru a memora în cache date. Testarea entităților de date de bază poate fi dificilă. Mai jos vom explica o bună practică atât a organizării serviciilor de date de bază cât și a datelor de falsificare.

În general, în majoritatea cazurilor este întotdeauna un lucru bun să creezi o clasă de servicii care să fie responsabilă cu preluarea și scrierea datelor specifice în baza de date, mai degrabă decât folosirea codului de date de bază pe tot proiectul.

Aceasta are în principal două avantaje:

  • Te decuplează de la baza de date care este folosită, dacă vrei să înlocuiești datele de bază cu orice altă bază de date în viitor, va trebui să faci modificări doar într-o singură clasă.
  • Făcând acest lucru, putem decide cu ușurință ce CoreDataStack se va obișnui sau orice altă configurație de care am avea nevoie într-un alt cadru.

Vom crea un protocol CoreDataStack și după aceea, două CoreDataStacksthat se conformează acestui protocol, unul MainCoreDataStack și unul MockCoreDataStack.

Serviciul nostru de baze de date poate fi inițializat de oricare dintre ei, în funcție de dacă îl utilizăm pe ținta aplicației noastre sau pe ținta noastră de testare a unității.

Principala noastră stivă de date va avea o configurație implicită, după cum urmează

Atunci când testăm unitatea întotdeauna, ar trebui să evităm schimbarea stării obiectelor „reale” actuale când le testăm.

Așadar, atunci când dorim să creăm entități de date false de bază, ar trebui să avem un magazin persistent separat și să utilizăm configurația de tip stocare în memorie, astfel încât modificările aduse nu vor fi salvate pe disc și vor fi complet separate de datele persistente în prezent.

Acum vom putea crea serviciul nostru de baze de date care este inițializat în mod implicit cu MainCoreDataStack.

Și în clasa noastră de testare, o putem inițializa cu stiva de date false

Acum putem scrie câteva teste simple după cum urmează:

Folosind această abordare, putem testa cu ușurință serviciul nostru de baze de date fără a afecta niciuna dintre datele stocate de ținta aplicației.

Cereri de rețea

Atunci când testăm rețeaua de rețea, putem folosi abordarea orientată către protocol pentru a crea un protocol și a se conforma atât de către NetworkService real, cât și de MockNetworkService și, după aceea, injectăm dependențe, fie folosind un serviciu real sau batjocorit.

În acest articol, deși vom folosi o bibliotecă open-source cu adevărat drăguță, numită OHHTTPStubs, care va face față și batjocorirea și încăpățânarea.

Lucrul bun despre această bibliotecă este că funcționează excelent cu celebra bibliotecă de rețele iOS Alamofire.

Încărcarea cererii de rețea este foarte ușoară cu OHHTTPStubs puteți înlocui orice răspuns pentru o anumită cale sau gazdă, dând un răspuns personalizat cu un dicționar.

După aceasta, fiecare cerere care trece de la aplicație la următoarea adresă URL va returna răspunsul nostru personalizat.

permiteți taskURL = URL (șir: „https://jsonplaceholder.typicode.com/todos”)!

De asemenea, ceea ce este interesant în ceea ce privește răspunsurile personalizate este faptul că puteți testa cu ușurință dacă problemele de eroare și margini sunt gestionate corect, pur și simplu returnând o eroare în răspuns.

Construirea manuală a dicționarului pentru răspuns este o caracteristică excelentă, dar atunci când dorim să returnăm date JSON mari, cu o mulțime de proprietăți, poate deveni dezordonat și greu de întreținut în clasele noastre de testare.

În aceste cazuri, putem folosi un fișier JSON pentru a înăbuși răspunsul ca în cele ce urmează.

Acum, de fiecare dată când aplicația noastră trimite solicitarea, vom primi răspunsul din fișierul myResponse.json pe care l-am salvat în fișierele noastre.

Ar trebui să ne amintim, însă, pentru a evita salvarea informațiilor sensibile în aceste fișiere JSON, deoarece dacă livrăm aceste fișiere împreună cu aplicația, acestea pot fi vizualizate cu ușurință.

Puteți consulta articolul meu pe subiectul de securitate pentru mai multe.

In concluzie

Unitatea de testare a aplicației noastre este o necesitate dacă dorim să evităm cât mai mult regresul și să încercăm să furnizăm o aplicație fără cusur.

În acest articol, am discutat despre cum să oferim testarea cazurilor comune care apar în timpul dezvoltării iOS.

Am discutat modul de testare a valorilor implicite ale utilizatorului, Singeltons, Date de bază și Cereri de rețea.

Dacă v-a plăcut acest articol, asigurați-vă că aplaudați pentru a vă prezenta sprijinul.

Urmați-mă pentru a vizualiza multe alte articole care pot duce abilitățile dvs. pentru dezvoltator iOS la un nivel următor.

Dacă aveți întrebări sau comentarii, nu ezitați să lăsați o notă aici sau trimiteți-mi un e-mail la arlindaliu.dev@gmail.com.