Как запускать тесты в RxSwift

1656656590 kak zapuskat testy v

от Navdeep Singh

SXj9h7Rxoz6HvcPWWCpstgjAanIvSz6zfemN
Источник изображения.

RxTest и RxBlocking является частью репозитория RxSwift. Однако они доступны через отдельные пакеты, поэтому требуют отдельного импорта.

RxTest содержит полезные дополнения для тестирования кода Rx. Это включает TestSchedulerкоторый является виртуальным планировщиком времени и предоставляет методы сложения событий через точные промежутки времени.

RxBlocking, с другой стороны, позволяет превратить обычную последовательность Observable в блокирующую observable, которая блокирует поток, в котором она работает, пока последовательность observable не завершится или не будет достигнут указанный тайм-аут. Это значительно упрощает тестирование асинхронных операций.

Давайте сейчас рассмотрим каждый из них.

RxTest

Как описано выше, RxTest является частью того же хранилища, что и RxSwift. Есть еще одна вещь, о которой следует знать RxTest Прежде чем мы углубимся в RxTesting: RxTest предоставляет два типа Observables для целей тестирования.

  • HotObservables
  • ColdObservables

HotObservables воспроизводит события в определенное время с помощью тестового планировщика, независимо от того, есть ли подписчики.

ColdObservables работают больше, чем обычные Observables, воспроизводя свои элементы своим новым подписчикам после подписки.

RxBlocking

Если вы знакомы с ожиданиями в XCTest, вы будете знать, что это еще один способ проверить асинхронные операции. Использовать RxBlocking гораздо проще. Давайте начнем с небольшой реализации, чтобы мы могли увидеть, как воспользоваться преимуществами этой библиотеки при тестировании асинхронных операций.

Тестирование с помощью RxBlocking

Мы начнем новый тест и создадим Observable 10, 20 и 30 следующим образом:

func testBlocking(){        let observableToTest = Observable.of(10, 20, 30)    }

Теперь мы определим результат как равный вызову toBlocking() для наблюдаемого, который мы создали:

let result = observableToTest.toBlocking()

toBlocking() возвращает блокирующий Observable к прямому массиву, как вы можете видеть здесь:

1F4TF7RZ2FlBgcynP9tWUi9UqQBtLCCy6YSg

Нам нужно будет использовать первый метод, если мы хотим узнать, какой метод является броском. Поэтому мы обернем это в оператор do catch, а затем добавим AssertEquals оператор, если он успешен, следующим образом:

func testBlocking(){        let observableToTest = Observable.of(10, 20, 30)        do{            let result = try observableToTest.toBlocking().first()            XCTAssertEqual(result, 10)        } catch {        }    }

Кроме того, Assert не выполняется, если это не так:

do{            let result = try observableToTest.toBlocking().first()            XCTAssertEqual(result, 10)        } catch {            XCTFail(error.localizedDescription)        }

Это! Давайте запустим тест, и вы увидите, что тест пройден. Мы можем упростить этот тест двумя строками кода, принудительно попробовав.

Опять же это более приемлемо для тестирования, чем рабочий код. Мы закомментируем оператор do catch, а затем напишем assert equals в одной строке, как показано ниже:

XCTAssertEqual(try! observableToTest.toBlocking().first(), 10)

Повторно запустите тест, и вы увидите, что тест снова пройден. Общий код с комментариями выглядит так:

func testBlocking(){        let observableToTest = Observable.of(10, 20, 30)//        do{//            let result = try observableToTest.toBlocking().first()//            XCTAssertEqual(result, 10)//        } catch {//            XCTFail(error.localizedDescription)//        }        XCTAssertEqual(try! observableToTest.toBlocking().first(), 10)    }

Как это для краткого? Честно говоря, эта последовательность Observable была бы уже синхронной, если бы мы печатали выпущенные элементы в подписке на нее, за которой следовал маркер. Маркер будет напечатан после завершения события подписки.

Чтобы проверить фактическую асинхронную операцию мы напишем еще один тест. На этот раз мы используем параллельный планировщик в фоновом потоке следующим образом:

func testAsynchronousToArry(){        let scheduler = ConcurrentDispatchQueueScheduler(qos: .background)    }

Теперь мы создадим Observable из простой последовательности целых чисел. Мы будем использовать карту для удвоения каждого значения следующим образом:

let intObservbale = Observable.of(10, 20, 30)            .map{ $0 * 2 }

Затем мы подпишемся на планировщик:

let intObservbale = Observable.of(10, 20, 30)            .map{ $0 * 2 }            .subscribeOn(scheduler)

Теперь мы напишем оператор do catch, похожий на последний тест и вызовы toBlocking на Observable, который следует наблюдать в главном планировщике, как показано ниже:

do{   let result = try intObservbale.observeOn(MainScheduler.instance).toBlocking().toArray()   } catch {   }

Затем мы добавим те же утверждения, что и в предыдущем примере:

do{   let result = try intObservbale.observeOn(MainScheduler.instance).toBlocking().toArray()            XCTAssertEqual(result, [20, 40, 60])        } catch {            XCTFail(error.localizedDescription)        }

Теперь мы запустим тест, и вы заметите, что он пройден с зеленой галочкой в ​​канаве.

Обратите внимание, что маркер печатается перед выпущенными элементами на консоли, как показано:

699d2sSCtcHgNblX68UK9VKzUBF-f1aTW8r0

Это потому, что эти операции выполнялись асинхронно.

Для получения других обновлений вы можете следить за мной в Twitter на моем твиттере @NavRudraSambyal

Чтобы работать с примерами горячих и холодных наблюдаемых, можно найти ссылку на мою книгу «Реактивное программирование в Swift 4».

Спасибо за прочтение, поделитесь им, если вы нашли это полезным 🙂

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *