Как стать автором
Обновить

Путь к автотестированию Android нативными инструментами: испробовали всё, что есть на рынке и сделали свои выводы

Время на прочтение13 мин
Количество просмотров8K
Всего голосов 5: ↑5 и ↓0+5
Комментарии16

Комментарии 16

Очень информативная статья, спасибо!

Здорово, что автоматизирует мобилки, но как пользователь я вообще не чувствую качества. Есть куда расти, успехов вам.

Привет, я автор вышеупомянутого фреймворка espresso-page-object (https://github.com/alex-tiurin/espresso-page-object).
Ваша статья даже заставила меня зарегаться на хабре :)
К сожалению в статье не сказано, что больше года назад его разработка уехала в другой проект (https://github.com/open-tool/ultron), о чем явно сказано в readme.

Все описанные проблемы первоначального проекта, в новом давно решены. Если кому интересно, то могу ответить на любые вопросы.

Пишу здесь, чтобы у народа было более полное представление об инструментах, которые я сделал.

Привет! Добро пожаловать на хабр :)

Ни в коем случае не хотели как-то принизить твои работы или оскорбить, спасибо, что этим занимаешься!

на самом деле - причина проста. История про использование нами твоего фреймворка происходила еще летом 21 года, Ultron попросту не было, судя по истории на гитхабе. Обязательно добавим в статью апдейт на этот счет!

Чет я не понимаю какую ты историю смотришь на гитхабе ) По коммитами и прочему альтрон появился в январе 2021 года, 3 февраля 2021 об этом я добавил заметку в ридми espresso-page-object. Не сходятся показанию )) Но эт не сильно важно, если обновите инфу в статье будет гуд.

после твоего сообщения смотрел релизы в гитхабе)

добавим инфу, да, руки пока не дошли

Привет! Вообще какой получился флоу, была найдена твоя преза, и ссылка на гит с твоим фреймом, по сравнению с эспрессо, с которым мы только начинали работать всё было идеально, кроме работы с ресайклером, потому что надо было к каждому элементу обращаться по id, и зачастую приходилось обращаться по тексту, что не шибко стабильно работало, так как текст постоянно меняется. То что он уехал на ultron лично я не видел, поэтому когда принималось решение продолжать дальше использовать твой фрейм или каспрессо, было решено попробовать каспрессо в тестовом варианте

Kaspresso представил удобную обертку, зато за Аппиумом поддержка всех платформ.

За что мне нравится Аппиум:

  • поддержка всех платформ. пишем тест 1 раз

  • поддержка умопомрачительных возможностей поиска элементов

  • видео тоже есть

  • у нас 900 тестов под обе платформы (iOS + Android)

  • кол-во автотестеров сейчас 1 (было 2. второй ушел на другой проект сейчас)

  • запускают тесты все мануальщики

  • ноль проблем со стабильностью. у нас больше проблема в стабильности сервера из-за наличия многих ThirdParty сервисов.

Пример поиска элементов прям с кода:

    @iOSXCUITFindAll(value = {
            @iOSXCUITBy(id = "CARDADRConfirmationView"), // new
            @iOSXCUITBy(id = "I44S4ConfirmAddressView"),
            @iOSXCUITBy(id = "ADR3ConfirmAddressOnboardingView"),
            @iOSXCUITBy(id = "I56DebitCardNotArrivedView"), // business
            @iOSXCUITBy(id = "BIZ14ChooseAddressView") // business
    })
    @iOSXCUITFindAll(value = {
            @iOSXCUITBy(id = "orderAnother"), // business
            @iOSXCUITBy(id = "bottomButton"), // business
            @iOSXCUITBy(id = "confirmButton") // old ?
    }, priority = 1)
    @AndroidFindAll(value = {
            @AndroidBy(id = "btn_base_bottom_sheet_primary"),
            @AndroidBy(id = "btn_confirm_address"), // business
            @AndroidBy(id = "btn_nux2s0s1_confirm"), // confirm address after login with EUR account only
    })
    private WebElement confirmAddressButton;

PS ах да. я бы посоветовал код писать чуть красивее типа -> (сек прям с кода...)

xxxApp()
	.onboarding().mobilePhonePage()
	.verifyAndSetCountryCode(expectedCode, country)
	.setPhone(customer.getPhone())
	.tapVerifyNumberButton()
	.tapMyNumberIsCorrect()
	.enterVerificationCode(customer.getPhone(), smsVerificationTokenOld);

где например:

    @Step("Tap 'Verify Number' button")
    public MobilePhonePage tapVerifyNumberButton() {
        Logger.log();
        Assert.assertTrue(tap(verifyNumberButton), createAssertionLog("FAILED"));
        return this;
    }

Круто, опыт использования аппиума, безусловно, не новая история.

По поводу совета писать код красивее, не совсем понял, что ты имел ввиду, поясни пжлст (в твоем же коде вижу статик импорты забытые, точно так красиво? :) )

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

апка
  .скринТакой
  .тапКнопкиТакой
  .проверьТакойТоСкринЗагрузился
  .вПолеТакоеВвведи("какой то текст")
  .тапКнопкиТакой
  .проверьТакойТоСкринЗагрузился
  ...

по статик импорту не понял вопроса. не вижу его. вот пример всех импортов с какого-то теста:

package tests.debitcard.addSecondaryCardOrder;

import base.enums.AccountType;
import core.testrail.TestRailCase;
import core.utils.enums.Currency;
import core.utils.enums.MAccountType;
import customers.Customer;
import customers.CustomerForGenerating;
import io.qameta.allure.Epic;
import io.qameta.allure.Feature;
import io.qameta.allure.Severity;
import io.qameta.allure.SeverityLevel;
import org.testng.annotations.Test;
import tests.addAccount.BaseAddAccount;
import tests.debitcard.BaseDebitCard;
import tests.debitcard.CardQueryMethods;

а вот пример импортов с PageObject (тут только логирование из статиков):

package pages.payments;

import base.BasePage;
import base.Page;
import core.utils.logging.Logger;
import io.appium.java_client.MobileBy;
import io.appium.java_client.pagefactory.*;
import io.qameta.allure.Step;
import org.openqa.selenium.WebElement;
import org.testng.Assert;
import pages.home.HomePage;
import pages.pots.PotViewPage;

import static core.utils.logging.Logger.createAssertionLog;


public class PaymentSentPage extends BasePage {

Привет! Вижу TestNG и аппиум а подскажи плз как вы скролите до нужного элемента? Высчитываете центр экрана и от него скролите или какой то другой метод?

И хотел еще узнать, зачем обарачивать какие то простые действия к "общим методам", перестанет работать тап или будет совсем другой функционал, и тапа уже не будет и лазить по методам искать что там изменилось, на мой взгляд сомнительно, тест по идее должен быть понятен сразу а то что он состоит из общих методов, это сразу же его усложняет

Привет.

1) по скроллу я написал гайд -> http://appium.io/docs/en/writing-running-appium/tutorial/swipe-tutorial/ . только немного уже устарел сам тап. правильнее уже использовать http://appium.io/docs/en/commands/interactions/actions/

2) все tap(el), setInput(el, value), getText(el)... со всех страниц ведут в 1 единственную функцию для каждого действия. например все tap ведут одну функцию. Это супер удобно. Во первых можно поправить в одном месте КАК тап делаем и везде меняется. Во вторых после ACTION действий типа тап, которые приводят к изменениям удобно добавить маленькую паузу (я использую 150ms). Это значительно повышает надежность.

3) как видно из примера оборачивание дает также название действия для Allure отчета + логирования. это все крайне полезно особенно если бегут много тестов одновременно.

пример в Allure как видно

все действия понятны любому QA

плюс в обертке мы пишем человекочитаемые ошибки типа:

т.е. это не ХЗ какой-то элемент со стактрейсом который мануальщикам ничего не говорит, а понятная ошибка.

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

Ну и видео дополняет картину.

а Step от какого фрейма идет? TestNG или Junit?
А 150ms на каждый клик/тап и тд, это прям явно указывается или всё же он ждет как то кнопку что она будет кликабельная или видна и может не полные 150ms ждать?


По поводу каспрессо, надежности придает TestCase, который умеет ждать ответы с бэка, + на каждое действие есть неявное ожидание 5 секунд, что тоже повышает надежность наших тестов.

1) Step это от Allure - https://docs.qameta.io/allure/#_testng

2) это не НА каждый, а ПОСЛЕ каждого. нету смысла искать мгновенно элементы другой страницы

3) Аппиум аннотации типа @iOSXCUITBy, @AndroidBy и т.д. (их много) также имеют ожидания. Не помню по умолчанию, я заменяю его на свое 20сек. Ну а когда мне нужно короче (часто проверить что нету элемента) то уменьшаю и потом восстанавливаю. Пример

    @Step("Check 'Green button' loaded {sec}")
    public boolean isGreenButtonLoaded(int sec) {
        Logger.log("sec: '" + sec + "'");
        setLookTiming(sec);
        return super.isLoaded(greenButton);
    }

где isLoaded проверяет за МАКС время есть или нет + восстанавливает значение по умолчанию. Понятно что максимум искать будет только если нету.

Понял, спасибо за ответы!

Спасибо за статью, однако мне очень обидно и сейчас я обьясню почему ;)

Если коротко, то Kaspresso - это фреймворк для автотестирования, сделанный на базе Espresso

Начнем с того, что Kaspresso со всеми PageObjectами опирается не на Espresso а на Kakao, который предоставляет DSL для Espresso, которое под капотом как раз выполняет описанные вами вроде

В Kaspresso есть более богатые возможности работы со стандартными элементами AndroidX. Например в Kaspresso есть KTextInputLayout, которого нам не хватало в библиотеке espresso-page-object и нативном Espresso.

В дополнение к Kakao, Kaspresso как раз предоставляет дополнительный функционал вокруг adb и прочих ништячков

Ах как жаль, что в такой замечательной статье нет ни одного упоминания про Kakao.

С наилучшими пожеланиями, Vacxe, который немножко разбирается в кодовой базе Kakao, Kaspresso и Marathon =)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий