Подтвердить что ты не робот

Андроид эспрессо один раз перед запуском тестов

Я пытаюсь закрыть приложение для Android с помощью тестов и начал использовать эспрессо в последнее время. Довольно впечатлено этим. Однако для большинства функций моего приложения требуется, чтобы пользователи вошли в систему. И поскольку все тесты независимы, для этого требуется регистрация нового пользователя для каждого теста. Это прекрасно работает, однако время, необходимое для каждого теста, значительно увеличивается из-за этого.

Я пытаюсь найти способ зарегистрировать пользователя один раз в классе (тестов), а затем использовать ту же учетную запись пользователя для выполнения всех тестов в этом классе.

Один из способов, который я смог сделать, - фактически иметь только один метод тестирования (@Test), который выполняет все остальные тесты в том порядке, в котором я хочу. Однако это все или ничего не подходит, поскольку задача gradle cAT выводит результаты только один раз в конце, не предоставляя информацию о промежуточных тестах, которые могли пройти/не удалось.

Я также пробовал подход @BeforeClass, который, однако, не работал (нет gradle вывода из класса, где я использовал это даже с опцией debug, и казалось, что потребовалось много времени, прежде чем он перешел к следующий класс тестов).

Есть ли лучший способ зарегистрировать пользователя один раз в начале класса, а затем выйти один раз в конце тестирования?

Любая помощь была оценена.

4b9b3361

Ответ 1

В идеале вы должны проверить функциональность входа/выхода из системы в набор тестов, которые просто проверяют разные сценарии входа/выхода и позволяют другим тестам сосредоточиться на других вариантах использования. Тем не менее, поскольку другие сценарии зависят от пользователя, входящего в систему, это звучит как один из способов решения этой проблемы - предоставить макетную версию компонента приложения, обрабатывающего логин. Для других тестов, зависящих от входа в систему, вы должны вводить этот макет в начале, и он возвращает макетные учетные данные пользователя, с которыми может работать остальная часть приложения.

Вот пример, где для достижения этого используются Dagger, Mockito и Espresso: https://engineering.circle.com/instrumentation-testing-with-dagger-mockito-and-espresso/

Ответ 2

Я тестирую приложение, которое требует этого же сценария. Самый простой способ, с которым я столкнулся, состоит в том, чтобы разделить вход и выход в свои собственные тестовые классы. Затем вы добавляете все свои тестовые классы в набор, начиная и заканчивая списками входа и выхода из системы соответственно. Ваши тестовые комплекты выглядят примерно так.

@RunWith(Suite.class)
@Suite.SuiteClasses({
        LoginSetup.class,
        SmokeTests.class,
        LogoutTearDown.class
})

EDIT: Вот пример тестов LoginSetup и LogoutTearDown. Это решение действительно должно быть только для сквозных тестов и включать небольшую часть ваших усилий по тестированию. fejd предоставляет решение для полного стека тестирования, которое также необходимо учитывать.

@LargeTest
public class SmokeSetup extends LogInTestFixture {

    @Rule
    public ActivityTestRule<LoginActivity> mLoginActivity = new ActivityTestRule<>(LoginActivity.class);

    @Test
    public void testSetup() throws IOException {

        onView(withId(R.id.username_field)).perform(replaceText("username"));
        onView(withId(R.id.password_field)).perform(replaceText("password"));
        onView(withId(R.id.login_button)).perform(click());

    }

}

@LargeTest
public class LogoutTearDown extends LogInTestFixture {

    @Rule
    public ActivityTestRule<MainActivity> mMainActivity = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void testLogout() throws IOException {

        onView(withId(R.id.toolbar_menu)).perform(click());
        onView(withId(R.id.logout_button)).perform(click());

    }

}

Ответ 3

Мое приложение также требует, чтобы пользователь вошел в систему через тестовый прогон. Тем не менее, я могу войти в систему в первый раз, и приложение запоминает мое имя пользователя/пароль во время тестового прогона. Фактически, он запоминает учетные данные, пока я не заставлю его забыть их или удалить и снова установить приложение.

Во время тестового запуска после каждого теста мое приложение переходит на задний план и возобновляется в начале следующего теста. Я предполагаю, что ваше приложение требует, чтобы пользователь вводил свои учетные данные каждый раз, когда вы выводили его на передний план из фона (возможно, банковское приложение?). Есть ли в вашем приложении параметр "Запомнить ваши учетные данные"? Если да, вы можете легко включить его сразу после первого входа в свой тестовый прогон.

Кроме этого, я думаю, вам стоит поговорить с разработчиками о том, как вы сможете запомнить свои учетные данные.

Ответ 4

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

Здесь большой хак, который работает. Стратегия проста: запускайте каждый тест по порядку и терпите неудачу в каждом тесте, прежде чем они получат шанс на запуск, если какой-то тест завершится неудачно (в этом случае тест для входа в систему).

@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@LargeTest
public class YourTestsThatDependsOnLogin {

    private static failEverything;

    @Before
    public void beforeTest() {

        // Fail every test before it has a chance to run if login failed
        if (failEverything) {
            Assert.fail("Login failed so every test should fail");
        }

    }    

    @Test
    public void test0_REQUIREDTEST_login() {

        failEverything = true;
        // Your code for login
        // Your login method must fail the test if it fails.
        login();
        failEverything = false; // We are safe to continue.

    }

    // test1 test2 test3 etc...

}

Плюсы:

  • Что вы просили для работы, и это быстро (если ваш логин медленный)
  • У вас может быть несколько тестов, зависящих от разных логинов, то есть вы можете сделать кучу тестов для user1, затем кучу тестов для user2 и т.д.
  • Быстрая настройка.

Минусы:

  • Нестандартная процедура, и кто-то может удивиться, почему так много тестов сбой...
  • Вы должны издеваться над пользователями вместо фактического входа в систему. Вы должны протестировать свой логин отдельно, а тесты не должны зависеть друг от друга.

Ответ 5

Добавьте в тестовый файл следующую функцию, замените код в try блок с вашим, который выполняет действия входа.

@Before
fun setUp() {
    // Login if it is on the LoginActivity
    try {
        // Type email and password
        Espresso.onView(ViewMatchers.withId(R.id.et_email))
                .perform(ViewActions.typeText("a_test_account_username"), ViewActions.closeSoftKeyboard())
        Espresso.onView(ViewMatchers.withId(R.id.et_password))
                .perform(ViewActions.typeText("a_test_account_password"), ViewActions.closeSoftKeyboard())

        // Click login button
        Espresso.onView(ViewMatchers.withId(R.id.btn_login)).perform(ViewActions.click())
    } catch (e: NoMatchingViewException) {
        //view not displayed logic
    }
}

С помощью этой аннотации @Before эта функция setUp будет выполняться перед любыми другими тестами, которые у вас есть в этом тестовом файле. Если приложение приступит к активности входа в систему, выполните вход в эту функцию setUp. Пример здесь предполагает, что есть EditText для электронной почты и пароля, а также кнопка входа. Он использует Expresso для ввода электронной почты и пароля, а затем нажмите кнопку входа в систему. Блок catch try состоит в том, чтобы убедиться, что вы не приступаете к активности входа в систему, он поймает ошибку и ничего не сделает, и если вы не приземлитесь на активность входа в систему, тогда вам все равно пойти на другие тесты.

Примечание: это код Kotlin, но он очень похож на Java.