логотип PurpleSchool
логотип PurpleSchool

Где искать elements для приложения на React Native

Автор

Олег Марков

Введение

Работая с React Native, вы часто сталкиваетесь с задачей поиска элементов пользовательского интерфейса для автоматизации тестирования или для динамического взаимодействия прямо из кода. Разработчикам нужно уметь надежно находить элементы для UI-тестов, e2e-тестирования (например, с использованием Detox), решения задач автоматизации и даже для операций вроде модального управления или динамической стилизации компонентов. Чтобы упростить эти задачи, важно понять, какие подходы поиска существуют, как работать с идентификаторами и что делать, если стандартных решений не хватает.

Эта статья отвечает на главный вопрос: где и как искать элементы (elements) в приложениях на React Native? Сюда входит разбор способов поиска через тестовые идентификаторы (testID), работу с инструментами для автотестирования, а также базовые техники поиска элементов через React Native API.

Основные способы поиска элементов в React Native

Поиск элементов через testID

В React Native любое View-подобное представление (например, Button, Text, TouchableOpacity) может иметь свойство testID. Это стандартный и официальный способ помечать элементы для поиска во время автоматического или ручного тестирования.

Вот простой пример:

import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';

const MyComponent = () => (
  <View>
    <Text testID="welcome-text">Добро пожаловать!</Text>
    <TouchableOpacity testID="login-button">
      <Text>Войти</Text>
    </TouchableOpacity>
  </View>
);

export default MyComponent;

Здесь testID задается для компонентов, чтобы их легко найти в тестах. Для библиотеки Detox поиск по testID выглядит так:

// Находим элемент с testID = login-button и нажимаем на него
await element(by.id('login-button')).tap();

Поиск подходящих элементов и ресурсов - важная часть разработки любого приложения. В React Native существует множество ресурсов, где можно найти готовые компоненты, иконки, шрифты и другие элементы для вашего приложения. Чтобы ускорить процесс разработки и создавать привлекательные интерфейсы, важно знать, где искать эти ресурсы и как их правильно использовать. Если вы хотите детально разобраться в поиске элементов для React Native приложений и научиться эффективно использовать готовые ресурсы — приходите на наш большой курс React Native и Expo Router. На курсе 184 уроков и 11 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Особенности и рекомендации testID

  • Используйте уникальные значения для testID в рамках одного экрана.
  • Не смешивайте testID с ключами props (например, key) – они для разных целей.
  • Добавлять testID лучше на те элементы, которые должны участвовать в тестах, а не на все подряд.

Использование label для Universal Access и тестирования

React Native поддерживает проп accessibilityLabel — он нужен для доступности, но также используется как дополнительный путь поиска элементов (особенно в iOS):

<TouchableOpacity
  accessibilityLabel="Кнопка входа"
  testID="login-button"
>
  <Text>Войти</Text>
</TouchableOpacity>
  • В автоматизированных тестах на iOS accessibilityLabel можно использовать для поиска элемента средствами UI-тестирования.
  • На Android предпочтителен testID, но в некоторых библиотеках возможно использовать и label.

Поиск элементов через текст

Многие тестовые фреймворки позволяют искать элементы по тексту, который отображается пользователю. Это полезно, если вы не добавили testID, но текст гарантированно уникален.

Пример с использованием Detox:

await element(by.text('Войти')).tap();
  • Такой подход удобен, но может перестать работать, если тексты меняются часто (например, при локализации).

Поиск элементов через структуру дерева и селекторы

Если не задан testID, можно обращаться к элементам по иерархии, используя путь к нужному компоненту (например, в End-to-End тестах или при отладке):

// Используем by.type, если testID нет
await element(by.type('RCTText')).atIndex(1);
  • by.type позволяет искать все элементы определенного типа.
  • Метод atIndex(n) помогает выбрать нужный экземпляр (если их несколько).

Поиск элементов в unit-тестах с React Native Testing Library

В unit-тестах обычно используют React Native Testing Library (RNTL). Она поддерживает удобные методы поиска:

import { render } from '@testing-library/react-native';

const { getByTestId, getByText } = render(<MyComponent />);
getByTestId('login-button'); // Находит элемент по testID
getByText('Войти');         // Находит по тексту, видимому пользователю
  • Методы поиска включают: getByTestId, getByText, queryByText, findByText, и их производные.
  • Помните, что метод getByTestId выбрасывает ошибку, если элемент не найден.

Общие рекомендации по добавлению идентификаторов для поиска

Где и как размещать testID

  • Старайтесь размещать testID только на ключевых для логики и UX элементах.
  • Придерживайтесь единой схемы именования, например: screenName-element-action (login-email-input).
  • Помещайте testID в props именно того компонента, с которым работает пользователь (не всегда нужен на обертках типа View).

Использование констант

Чтобы избежать опечаток, можно хранить testID в отдельном файле:

// testIDs.js
export const TEST_IDS = {
  LOGIN_BUTTON: 'login-button',
  EMAIL_INPUT: 'login-email-input'
};

// Применение
<TextInput testID={TEST_IDS.EMAIL_INPUT} />
<TouchableOpacity testID={TEST_IDS.LOGIN_BUTTON}>

Как найти элементы без testID

Нет testID — ищите по:

  • Тексту (getByText, by.text)
  • Типу компонента (by.type)
  • Селектору (например, для e2e можно пытаться искать по структуре)
  • accessibilityLabel (особенно важно для доступности)

Однако лучше всегда использовать testID или добавлять его при необходимости.

Пример: создание тестового идентификатора по условию

Бывает, что testID должен появляться только в определенных условиях (например, в debug-сборке). Это делается просто:

<TouchableOpacity
  testID={__DEV__ ? 'button-debug' : undefined}
>
  <Text>Debug Кнопка</Text>
</TouchableOpacity>
  • Используйте константы типа __DEV__, чтобы не добавлять идентификаторы в production.

Использование инструментов и утилит для поиска elements

Инспекторы интерфейса

  • React Native Debugger позволяет инспектировать дерево элементов, смотреть пропсы и testID прямо из отладки.
  • Detox devtools и утилиты Appium помогают просматривать и искать элементы в реальном приложении, подбирая нужные свойства для поиска.

Поиск с помощью тестовых инструментов

  • Detox (element(by.id('testID'))) — для e2e на React Native.
  • Appium — может использовать accessibilityLabel и testID для автоматизации.
  • Jest + RNTL — тесты юнитов, поиск через getByTestId.

Как обеспечивать тестируемость при проектировании компонентов

  • Проектируйте компоненты так, чтобы у каждого интерактивного элемента был testID.
  • Не кладите тестовые идентификаторы на View без смысла — пометьте только значимые контролы (кнопки, инпуты, чекбоксы).
  • Вынесите testID и accessibilityLabel в props компонента, если планируете переиспользование:
const CustomButton = ({ onPress, label, testID }) => (
  <TouchableOpacity onPress={onPress} testID={testID}>
    <Text>{label}</Text>
  </TouchableOpacity>
);
  • Передавайте testID снаружи, особенно если компонент универсален.

Роль структуры дерева компонентов при поиске

  • Иногда приходится искать элемент по вложенности — старайтесь сохранять разумную глубину для тестируемых компонентов и помнить, что глубокие вложенности усложняют тесты.
  • Не зависите только от визуального положения — структура канваса может меняться, лучше использовать идентификаторы.

Поддержка поиска на разных платформах

  • На Android props testID трансформируется в resource-id с помощью модуля React Native.
  • На iOS используется как часть accessibilityLabel.
  • Убедитесь, что в ваших тестах поиск универсален: если пишете кроссплатформенно — проверьте оба пути.

Как искать элементы при использовании сторонних библиотек (например, UI Kit)

Если используете UI-библиотеки (например, React Native Paper, NativeBase):

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

Пример обертки:

// Для компонента-кнопки из библиотеки
const PaperButtonWithTestID = ({ testID, ...props }) => (
  <Button {...props} testID={testID} />
);

Теперь можно легко искать элемент по testID в автотестах.

Заключение

Выяснять, где искать и как помечать элементы в приложениях на React Native, — ключевая часть процесса разработки и тестирования. Наиболее надежный и рекомендованный метод — добавлять testID к нужным элементам интерфейса, особенно к кнопкам, полям ввода и важным для сценария взаимодействия компонентам. Это позволит быстро и точно находить их с помощью инструментов автоматизации или юнит-тестирования.

Если по каким-то причинам вы не можете использовать testID, обращайте внимание на варианты поиска по accessibilityLabel, тексту, типу компонента или структуре дерева. Чтобы обеспечить удобство в долгосрочной перспективе, формируйте единый стиль именования, а также старайтесь добавлять тестовые идентификаторы на этапе проектирования компонентов.

Поиск элементов - это важный, но не единственный аспект разработки качественного React Native приложения. Для создания полноценного приложения необходимо освоить множество других технологий и подходов, включая работу с UI, данными и нативными функциями. Курс React Native и Expo Router поможет вам в этом. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир React Native прямо сегодня.

Частозадаваемые технические вопросы по теме статьи и ответы на них

Как искать элементы в модальных или всплывающих окнах?

Иногда элементы в модалках не ищутся стандартным способом (например, компонент Modal создает отдельный слой). В таком случае ищите элементы с тестовыми идентификаторами (testID), следя за тем, чтобы modal был открыт во время теста. Также полезно использовать waitFor() в тестах, чтобы дождаться появления элемента:

await waitFor(() => expect(getByTestId('my-modal-element')).toBeTruthy());

Почему в некоторых случаях testID не работает на Android?

React Native иногда неправильно прокидывает testID на нативные слои, особенно для сторонних компонентов. Убедитесь, что используемый компонент поддерживает передачу testID до уровня native. Если нет — рассмотрите создание собственной обертки или поиск по другим свойствам.

Можно ли динамически изменить testID у элемента?

Да — testID это такой же prop, как и любой другой, его можно менять через состояние или пропсы:

<MyButton testID={isPressed ? 'pressed-id' : 'default-id'} />

Главное — не усложнять структуру, если нет острой необходимости.

Как добавить testID или accessibilityLabel в компонент, если библиотека этого не поддерживает?

Создайте собственную обертку над компонентом и пробросьте нужные props вручную. Либо, если компонент поддерживает другие идентифицирующие props (например, nativeID), используйте их совместно с тестовым инструментом.

Как работать с элементами, которые появляются с задержкой (асинхронно)?

Для асинхронных UI-операций пользуйтесь ожиданиями из тестового фреймворка — например, ждите появления элемента через waitFor или эквивалентные методы, прежде чем взаимодействовать с ним:

await waitFor(() => expect(getByTestId('async-element')).toBeTruthy());
Стрелочка влевоГайд по UI-китам для React NativeРабота с цветами в React NativeСтрелочка вправо

Постройте личный план изучения React-native до уровня Middle — бесплатно!

React-native — часть карты развития Mobile

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по React-native

Работа со ScrollView в React NativeРабота с видео в React NativeКак реализовать аудиоплеер на React NativeНастройка и использование input и textinput в React NativeИнтеграция видео плеера в приложение на React NativeИспользование выпадающих списков в React NativeСоздание и настройка native module на React NativeРабота с изображениями в React NativeКак создать модальные окна в React NativeОтображение списков данных в React NativeГайд по файловой системе в React NativeИнтеграция камеры в приложение на React NativeСоздание интерактивных кнопок в React Native
Как использовать векторные иконки в React Native5 популярных библиотек UI компонентов React NativeСоздание и использование tabs в React NativeРуководство по стилизации компонентов в React NativeОптимизация переходов между экранами в React NativeАдаптация safe area context на React NativeОбзор библиотек для навигации в React NativeСоздание сложных анимаций (reanimated) на React NativeИспользование библиотеки стилей Paper в React NativeРуководство по navigation в React NativeОптимизация отображения списков в React NativeКак реализовать linking на React NativeГайд по UI-китам для React NativeГде искать elements для приложения на React NativeРабота с цветами в React Native
Открыть базу знаний

Лучшие курсы по теме

изображение курса

React Native и Expo Router

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Основы JavaScript

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий