Как да тествате с помощта на фалшиви данни на iOS

За да се осигури висококачествен софтуер и да се избегне регресия, прилагането на тестване на единица е задължително за всяко приложение на iOS.
Смеенето на обекти е техника в тестване на единици, която създава фалшиви обекти, като използва същите API, като истинските.
Тази статия е wirtten, за да ви предостави най-добрите практики за това как да използвате фалшиви данни и да пишете тестове на единици за най-често срещаните сценарии в приложения за iOS.

Когато пишем единични тестове, винаги трябва да избягваме да променяме реални данни за целта на приложението и вместо това да използваме фалшиви данни само за целите на тестване.

Следващите части ще обсъдят как да пишат тестове, като използват фалшиви данни за често използвани iOS API-и.

Потребителски настройки по подразбиране

В разработката на софтуер винаги е добра практика да се намалят зависимостите на обектите. Зависимостите в най-добрия случай трябва да се инжектират в класовете, които ги използват.

Но ако проверим сценариите за разработка на iOS в реалния живот, почти всеки проект използва UserDefaults, като му извиква директно API за съхраняване или извличане на всякакви данни.

Затова ще се опитаме да предложим практично решение за тестване на UserDefaultsrather, отколкото да абстрахираме неговия API с протоколи.

Можем да създадем две нови функции на UserDefaults

Винаги е добра практика да не променяме данните от приложението от единицата за изпитване на целта, така че трябва да създадем друго място за запазване на потребителски данни за нашата цел за тестване.

В този случай инициализираме нов обект на UserDefaults с suiteName - testDefaults, че той е напълно независим от стандартните UserDefaults.

Нека се опитаме да напишем прост тест, който използва UserDefaults

Тъй като тези данни основно се използват само за тестване, трябва да избягваме тези данни да висят в нашите приложения файлове, следователно ние създаваме функция, отговорна за изпускането на това хранилище, след като приключим с теста.

Най-доброто място за пречистване на тези данни, разбира се, ще бъде функцията tearDown в нашия клас за тестване на устройства.

Обекти на Сингълтън

Обектите на Singletons са много използвани в iOS на много API, можем да ги намерим в NSFileManager, NSApplication, UIApplication и на много други места.

Знанието как да тествате единични е полезно нещо, което трябва да знаете за разработчиците на iOS.

В нашия пример ще използваме iAd Framework на apple. Ще създадем файл, за да получим локален отговор на JSON вместо реални данни за искане на данни за приписване на реклами.

Хубава характеристика на iOS е, че разширенията в бързи условия ни позволяват не само да добавяме нови функции за предварително определен API, но и ги правим съобразени с нашите собствени персонализирани протоколи.

Да дефинираме протокол на AdvertisementClient

След това ние се съобразяваме с този протокол както от ADClient по подразбиране, така и от нашия фалшив клиент за реклама, както следва

Тогава ние променяме зависимостта от двете

частен вар adClient: AdvertisementClient = ADClient.shared ()

или

частен вар adClient: AdvertisementClient = MockAdClient ()

и го използвайте по следния начин

По този начин можем лесно да решим кога да използваме реални данни и кога тестващите, в зависимост от това дали тестваме единица или извикваме API от нашата цел на приложението на живо.

Основни данни

Основните данни все още са много използвани в iOS за кеширане на данни. Тестване на основни субекти на данни може да бъде сложно. По-долу ще обясним добра практика както за организиране на основни услуги за данни, така и за фалшиви данни.

По принцип в повечето случаи винаги е добре да се създаде сервизен клас, който да отговаря за извличането и записването на конкретни данни в базата данни, а не да използва основния код на данни по целия проект.

Това главно има две предимства:

  • Той ви отделя от основната база данни, която се използва, ако в бъдеще искате да замените основните данни с друга база данни, ще трябва да направите промени само в един клас.
  • Правейки това можем лесно да решим коя CoreDataStack ще свикне или каквато и да е друга настройка, която може да ни е необходима в някаква друга рамка.

Ще създадем CoreDataStack протокол и след това два CoreDataStack, които съответстват на този протокол, една MainCoreDataStack и една MockCoreDataStack.

След това нашата DatabaseService може да бъде инициализирана от която и да е от тях, в зависимост от това дали ние я използваме в нашата цел за приложение или в нашата цел за тестване на единица.

Основният ни стек на основни данни ще има настройка по подразбиране, както следва

При тестване на единици винаги трябва да избягваме да променяме състоянието на текущите „реални“ обекти, когато ги тестваме.

Така че, когато искаме да създадем фалшиви основни субекти за данни, трябва да имаме отделна постоянна конфигурация за съхранение и използване на паметта в паметта, така че направените промени да не бъдат записани на диска и те ще бъдат напълно отделени от съществуващите в момента данни.

Сега ще можем да създадем нашата база данни, която се инициализира по подразбиране с MainCoreDataStack.

И в нашия тестов клас можем да го инициализираме с фалшивия стек от данни

Вече можем да напишем няколко прости теста, както следва:

Използвайки този подход, можем лесно да тестваме нашата DatabaseService, без да засягаме някоя от данните, съхранявани от целта на приложението.

Мрежови заявки

При тестване на мрежовия слой можем да използваме протоколно ориентирания подход, за да създадем протокол и да го съобразим както от реалната NetworkService, така и от MockNetworkService, а след това да инжектираме зависимости, използвайки реална или подигравателна услуга.

В тази статия, въпреки че ще използваме наистина хубава библиотека с отворен код, наречена OHHTTPStubs, която ще се справи с подигравките и мъничетата още по-добре.

Хубавото на тази библиотека е, че тя работи чудесно с известната мрежова библиотека на iOS Alamofire.

Заявката на мрежата за заглушаване е много лесна с OHHTTPStubs можете да замените всеки отговор за конкретен път или хост, като дадете персонализиран отговор с речник.

След това всяка заявка, която преминава от приложението до следния URL адрес, вместо това ще върне нашия персонализиран отговор.

нека задачиURL = URL (низ: „https://jsonplaceholder.typicode.com/todos“)!

Това, което е наистина страхотно за персонализираните отговори, е, че можете лесно да проверите дали грешките и крайните случаи се обработват правилно, като просто върнете грешка в отговора.

Ръчното изграждане на речника за отговор е чудесна характеристика, но когато искаме да върнем голям JSON данни с много свойства, той може да стане разхвърлян и трудно поддържаем в нашите тестови класове.

В тези случаи можем да използваме JSON файл, за да заглушим отговора като следния.

Сега всеки път, когато нашето приложение изпрати заявката, ще получим отговора от файла myResponse.json, който запазихме в нашите файлове.

Трябва да помним обаче, за да избегнем запазването на чувствителна информация в тези файлове на JSON, защото ако изпратим тези файлове заедно с приложението, те могат да бъдат гледани лесно.

Можете да проверите статията ми по темата за сигурността за повече.

В заключение

Единичното тестване на нашето приложение е задължително, ако искаме да избегнем регресия възможно най-много и също така да се опитаме да предоставим безупречно приложение.

В тази статия сме обсъдили как да осигурим тестване за често срещани случаи, възникващи по време на iOS разработка.

Обсъдихме как да тестваме UserDefaults, Singeltons, Core Data и Network Requests.

Ако тази статия ви е харесала, не забравяйте да ръкопляскате, за да покажете вашата подкрепа.

Следвайте ме, за да прегледате още много статии, които могат да изведат вашите умения за iOS Developer на следващо ниво.

Ако имате въпроси или коментари, не се колебайте да оставите бележка тук или да ми изпратите имейл на arlindaliu.dev@gmail.com.