Detox and Appium: an automated interface test in React Native



    Unfamiliar mobile environment


    I, probably, like you, came to React Native as a JavaScript developer rather than as a developer of native mobile applications. Absolutely new world with its own nuances and tricks.

    One of the most important topics to learn will be testing. When everything is more or less clear with unit tests, what to do with interface tests and end-to-end tests? iOS. Android On the market a mixture of different types of devices.

    Despite the fact that the technology itself is relatively new, it is still a mobile environment and you have to borrow a lot and learn from the native side.

    I will briefly review two frameworks that you should pay attention to make your life as a developer easier.

    Appium


    Using behind the scenes Selenium WebDriver, Appium is a powerful framework with a huge community of native mobile application developers. Released before React.js, this is a leader and it has no equal.

    Getting started with Appium is pretty easy. With the help of npm install the packages “appium” and “appium-doctor”, we can globally, we can as part of the project. The “appium-doctor” team will tell us what else needs to be installed and configured before starting work, and, if possible, will help to correct the shortcomings. When everything is solved, the packages are installed and the Jest configuration is in place, we can run the Appium server and tests.

    I will not go into the details of the settings, but this is how the simple test with the configuration looks like (comments added):

    /* клиент selenium webdriver для node
    */import wd from'wd'/* 60 секунд таймаут, после которых тест остановится, если застрянет
     */
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000/* адрес сервера Appium. Запускаем с нашего компьютера, поэтому localhost
    */const URL = 'localhost'const PORT = 4723/* создаем объект webdriver
    */const driver = wd.promiseChainRemote(URL, PORT)
    /* Вожможности сервера.
    * инструкция для сервера Appium,
    * как запускать тесты, другими словами настройки.
    */const capabilities = {
     platformName: 'iOS', // или Android
     platformVersion: '12.1', // версия ОС
     deviceName: 'iPhone 8', // или “Android Emulator” или точное название устройства
     automationName: 'XCUITest', // фреймворк платформы (UIAutomator2 для Android)
     app: '/path/to/.app'// расположение файла .app (для Android это .apk)
    }
    beforeAll(async () => {
     try { // до того, как запустить тестawait driver.init(capabilities) // запускаем драйверawait driver.sleep(4000) // да уж, вручную ставим таймер и ждем загрузку приложения, вот она хрупкость!
     } catch(err) {
       console.log(err) // если что, мы хотим знать, что не так
     }
    })
    afterAll(async () => {
     try {
       await driver.quit() // конец сессии
     } catch(err) {
       console.error(err)
     }
    });
    /* Jest, делаем что хотим, что позволяет Appium!
    * в данном примере мы проверяем, соответствует ли текст
    * 'topLabel' и 'subLabel' заданному
    * Рекомендую ознакомиться с документацией на сайте Appium
    */
    describe("Home Screen landing", () => {
     test("render search screen", async () => {
        let topLabel = await driver.elementById('topLabel')
        let subLabel = await driver.elementById('subLabel')
        expect(await topLabel.text()).toBe("OK")
        expect(await subLabel.text()).toBe("главный экран")
     })
    })
    

    The test itself is the last few lines that check if the text “OK” and “main screen” are on the screen. As you can see, the test is nothing special, the same Jest. The documentation on the Appium website describes all the features of the framework, including also JavaScript examples.

    Dislike string only await driver.sleep(4000). Unfortunately, tests have no idea what is happening in the application. The so-called “black box” or Blackbox. Imagine if you were writing code on Node, and before the http request, you would set a timer instead of using promise or callback. Here it is, the fragility of UI tests.

    In this simple test, we wait 4 seconds to launch the application. With time and with an increase in the number of tests, we will set timers more often - http requests, animation, React Native itself - the bridge between native code and JavaScript only complicates the situation.

    “Black box”, we have an application build without access to internal structures.


    What do you like about Appium?

    • 7+ years in the industry.
    • Extensive API.
    • Easy to find help (this is also a minus, the list below)
    • Multi-language support, including javascript.
    • Familiar to the developer JavaScript jest environment.
    • Used for end-to-end tests in MS AppCenter, BrowserStack and AWS DeviceFarm.
    • The ability to test on these devices.

    What does not like in Appium

    • An online search provides results for different programming languages, most of them Java.
    • Testing the “black box” (tests do not know about the processes inside the application).
    • No synchronicity with the application, fragility, React Native creates even more problems.
    • testID for some reason does not work on Android.


    Note the three tabs: Appium server logs, metro bundler package and the test itself.


    Detox


    Wix's Detox works similarly to Appium. The main difference is testing by the gray box strategy. One of the tasks of the developers of Detox was to solve problems with fragility - the task in the application will not be started until the previous one is over and the application is not free. This became possible thanks to another framework created under the name EarlGrey.

    Just as with Appium, we set the settings.

    /* Дополнительная настройка в файле package.json, ниже пример
    */const detox = require("detox");
    const config = require("./package.json").detox;
    /* адаптер Jest
    */const adapter = require("detox/runners/jest/adapter");
    /* Таймаут,
     * использование адаптера Jest
     */
    jest.setTimeout(120000);
    jasmine.getEnv().addReporter(adapter);
    beforeAll(async () => {
     /* Запускаем сервер
     */await detox.init(config);
    });
     /* beforeEach и afterEach для тестов Detox, 
      * используем от Jest
      * чистим после тестов
      */
    beforeEach(asyncfunction() {
     await adapter.beforeEach();
    });
    afterAll(async () => {
     await adapter.afterAll();
     await detox.cleanup();
    });
    

    And setting in package.json:

    "detox": {
       "configurations": {
         "ios.detox": { // настройки для iOS (запускается командой detox test -c ios.detox)"binaryPath": "path/to/.app",
           "build": "xcodebuild -workspace ios/app.xcworkspace -scheme scheme -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build", // файл workspace или project. В данном случае создаем пакет debug вместо production (release)."type": "ios.simulator",
           "name": "iPhone 8"// название симулятора
         },
         "android.detox": { // настройки для Android (запускается командой detox test -c android.detox)"binaryPath": "path/to/.apk",
           "build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..", // В данном случае создаем пакет debug вместо production (release)."type": "android.emulator",
           "name": "Pixel_2_API_28"// название симулятора. “adb devices” покажет список доступных устройств Android
         }
       },
       "test-runner": "jest",
       "runner-config": {
        "setupTestFrameworkScriptFile" : "./detox.init.js", // пример выше   "testEnvironment": "node",
        "testRegex": "(.*|\\.(ui))\\.(ts|tsx)$"// регулярное выражение, где искать тесты интерфейса
     }
       "specs": "./__tests__/"// расположение тестов интерфейса
     }
    

    Tests are as easy to write as for Appium, but using the capabilities and limitations of Detox.

    "Gray box", we have the assembly of the application and access to internal structures.


    What I like about Detox

    • Created by Wix for React Native.
    • Focused on javascript.
    • Test the strategy of the "gray box".
    • Works synchronously with the application.

    What I don't like about Detox

    • The possibilities are not as broad as those of Appium.
    • Small community.

    Fragility


    Despite the fact that Detox uses the gray box principle, fragility is still present. The test with text input and svaypom did not work as it should in 1 case out of 10. You can not be 100% sure in the interface tests.

    Speed


    Appium “slows down” the “.sleep” timers set to manual, Detox in this case wins, because everything is synchronous. In general, I would not make any other conclusions on my part, since I did not write a large number of identical tests on both platforms. In 30-second tests and a simple test created for this article, Detox did a second faster. If you look at two different platforms, iOS and Android, the tests took + - the same time. The main thing to keep in mind is that interface tests take significantly longer unit tests.

    What to choose


    I still study both frameworks and it will take some time to understand all their advantages, but at the moment, as a JavaScript developer, I choose Detox.

    Try both, fortunately, there are only two. It all depends on the application you are working on and the command.

    Interface tests in the development team - for developers, try Detox. More sophisticated end-to-end tests - it may be better to take a closer look at Appium, with its rich API capabilities and support on the BrowserStack, MS AppCenter and AWS DeviceFarm platforms.

    Links


    There are many useful resources and articles, but unfortunately, in English. The first thing I recommend of. sites.

    Appium

    the Detox

    Also popular now: