Урок 25 из 25 · Месяц 6. Чат и публикация приложений
Тестовое задание для отбора в Geeks Pro
Содержание урока
- Что такое тестовое задание и что в нём проверяют
- Почему важно сделать самому, без ИИ
- Как подходить к тестовому: пошагово
- Шаг 1. Внимательно прочитайте задание
- Шаг 2. Спланируйте
- Шаг 3. Сначала — работающий минимум
- Шаг 4. Коммитьте понятно и часто
- Шаг 5. Проверьте перед сдачей
- Пример тестового задания
- Пример: Bloc с пагинацией
- Пример: тест для Bloc
- Критерии хорошего решения
- Повторение: что нужно уметь
- Советы по подготовке
- Типичные ошибки
- Практика
- Итоги
Тестовое задание — небольшой проект, по которому оценивают, как вы пишете код в реальных условиях. Этот урок — финальная точка курса: разберём, как подходить к тестовому, посмотрим пример задания и критерии хорошего решения, повторим ключевые темы и составим чек-лист «что нужно уметь». И главное — поговорим, почему тестовое для отбора в Geeks Pro важно сделать самостоятельно, без ИИ.
Что такое тестовое задание и что в нём проверяют
Тестовое задание — это мини-проект на несколько дней: например, приложение со списком данных из API, детальным экраном и авторизацией. По нему видно не только «работает или нет», но и то, как вы думаете: как разложили код, как обработали ошибки, насколько аккуратно оформили проект.
Почему важно сделать самому, без ИИ
ИИ-ассистенты — полезный инструмент в работе. Но тестовое задание проверяет ваши навыки, и сделать его самостоятельно важно по нескольким причинам:
- Вас спросят о каждой строке. После тестового обычно идёт обсуждение: «Почему здесь Bloc, а не Cubit?», «Что будет, если сервер вернёт 500?». Если код писали не вы, это видно за пару минут.
- Вы узнаете свои пробелы. Застряли на пагинации — значит, именно её надо повторить. ИИ скроет этот пробел, и он всплывёт уже на работе.
- Честная оценка — в ваших интересах. Если вас отберут по чужому коду, дальше будет тяжело: задачи станут сложнее, а базы нет.
- Это тренировка реальной работы. Разобраться в документации, найти ошибку, принять решение — главный навык разработчика.
Пользоваться официальной документацией (docs.flutter.dev, dart.dev, pub.dev) и своими конспектами курса — нормально: так работают все разработчики.
Как подходить к тестовому: пошагово
Шаг 1. Внимательно прочитайте задание
Прочитайте дважды и выпишите требования списком. Разделите их на обязательные и дополнительные («будет плюсом»). Если что-то непонятно — задайте вопрос сразу, а не в последний день. Умение задавать уточняющие вопросы — тоже плюс.
Шаг 2. Спланируйте
Прежде чем писать код, набросайте план: экраны, сущности, слои, пакеты.
Экраны: Список товаров → Детальная страница → Избранное
Сущности: Product (id, title, price, image, description)
Слои: data (ProductModel, ProductRemoteDataSource, ProductRepositoryImpl)
domain (Product, ProductRepository, GetProductsUseCase)
presentation (ProductsBloc, ProductsPage, ProductDetailsPage)
Пакеты: flutter_bloc, equatable, dio, get_it, json_serializable
Распределите время: например, при сроке в 5 дней — день на каркас и сеть, два на основные экраны, день на дополнительные задачи, день на тесты, README и проверку.
Шаг 3. Сначала — работающий минимум
Сделайте обязательную часть целиком и просто, пусть без красоты. Рабочее приложение без «плюсов» лучше, чем красивое, но недоделанное. Только потом — дополнительные задачи и полировка.
Шаг 4. Коммитьте понятно и часто
История Git показывает, как вы работали. Один коммит «done» на весь проект выглядит подозрительно.
git commit -m "Add project structure and DI setup"
git commit -m "Add Product model and remote data source"
git commit -m "Add ProductsBloc with loading and error states"
git commit -m "Add pagination to products list"
git commit -m "Add README with setup instructions"
Шаг 5. Проверьте перед сдачей
flutter analyze # нет ошибок и предупреждений
dart format . # код отформатирован
flutter test # тесты проходят
flutter run --release # приложение работает в release
Склонируйте свой репозиторий в новую папку и запустите по README — так вы проверите проект глазами проверяющего.
Пример тестового задания
Ниже — учебный пример, похожий на типичные тестовые. Попробуйте выполнить его как тренировку.
Задание: приложение «Каталог товаров»
Обязательно:
- Экран списка товаров из открытого API: картинка, название, цена.
- Пагинация: подгрузка следующей страницы при прокрутке к концу.
- Детальный экран товара.
- Состояния загрузки, ошибки (с кнопкой «Повторить») и пустого списка.
- Clean Architecture и Bloc, зависимости через GetIt.
- README с инструкцией по запуску.
Будет плюсом:
- поиск с задержкой (debounce);
- избранное с сохранением между запусками;
- светлая и тёмная темы;
- unit-тесты для Bloc и репозитория.
Срок: 5 дней. Сдача: ссылка на публичный репозиторий.
Пример: Bloc с пагинацией
Основа решения — Bloc, который умеет загрузить первую страницу и догрузить следующие:
class ProductsBloc extends Bloc<ProductsEvent, ProductsState> {
ProductsBloc(this._getProducts) : super(const ProductsState()) {
on<ProductsFetched>(_onFetched, transformer: droppable());
}
final GetProductsUseCase _getProducts;
static const _pageSize = 20;
Future<void> _onFetched(ProductsFetched event, Emitter<ProductsState> emit) async {
if (state.hasReachedMax) return;
try {
final items = await _getProducts(page: state.page, limit: _pageSize);
emit(state.copyWith(
status: ProductsStatus.success,
products: [...state.products, ...items],
page: state.page + 1,
hasReachedMax: items.length < _pageSize,
));
} catch (e) {
emit(state.copyWith(status: ProductsStatus.failure, error: e.toString()));
}
}
}
droppable()из пакетаbloc_concurrencyигнорирует новыеProductsFetched, пока идёт загрузка, — нет двойных запросов при быстрой прокрутке.hasReachedMax— если пришло меньше элементов, чем размер страницы, данные закончились.- Новые товары добавляются к старым через spread
[...a, ...b], состояние не мутируется. - Подробнее о пагинации — в уроке Пагинация в архитектуре приложения.
Пример: тест для Bloc
Даже пара тестов сильно выделяет решение среди других:
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
class MockGetProducts extends Mock implements GetProductsUseCase {}
void main() {
late MockGetProducts getProducts;
setUp(() => getProducts = MockGetProducts());
blocTest<ProductsBloc, ProductsState>(
'выдаёт success с товарами после загрузки',
setUp: () => when(() => getProducts(page: 1, limit: 20))
.thenAnswer((_) async => [testProduct]),
build: () => ProductsBloc(getProducts),
act: (bloc) => bloc.add(ProductsFetched()),
expect: () => [
isA<ProductsState>()
.having((s) => s.status, 'status', ProductsStatus.success)
.having((s) => s.products.length, 'length', 1),
],
);
}
mocktailсоздаёт фейковый UseCase, чтобы тест не ходил в сеть.blocTestотправляет событие и сравнивает выданные состояния с ожидаемыми.- Предполагается, что
pageв начальном состоянии равен 1, аtestProduct— заранее созданный объектProduct.
Критерии хорошего решения
| Критерий | Что видит проверяющий |
|---|---|
| Работоспособность | Проект запускается по README, обязательные пункты выполнены, нет падений |
| Архитектура | Слои разделены, логика не в виджетах, зависимости через DI |
| Обработка ошибок | Нет сети, ошибка сервера, пустой ответ — пользователь видит понятный экран |
| Качество кода | Понятные имена, нет dynamic без причины, нет дублирования, flutter analyze чистый |
| UI | Аккуратно, без переполнений (жёлто-чёрных полос), работает на разных размерах экрана |
| Git | Осмысленные коммиты, нет build/ и ключей в репозитории |
| README | Описание, стек, инструкция запуска, скриншоты |
| Плюсы | Тесты, дополнительные функции, анимации — только после обязательной части |
Повторение: что нужно уметь
Тестовое задание объединяет всё, что вы прошли за месяцы 4–6. Пройдитесь по списку и отметьте, в чём уверены:
Состояние и сеть (месяц 4)
- Объяснить разницу FutureBuilder и StreamBuilder, ChangeNotifier и Bloc.
- Написать Bloc с событиями и состояниями, использовать BlocBuilder и BlocListener.
- Сделать модель с json_serializable и Equatable, GET/POST-запросы через Dio, обработать DioException.
- Подключить Firebase через FlutterFire CLI, сделать авторизацию.
Архитектура (месяц 5)
- Разложить фичу по слоям data / domain / presentation, написать UseCase.
- Зарегистрировать зависимости в GetIt.
- Хранить токен в flutter_secure_storage, сделать пагинацию.
- Найти проблему отрисовки через DevTools.
Чат и публикация (месяц 6) - Сделать чат на Realtime Database со Stream и правилами безопасности (чат, часть 1). - Объяснить отличие WebSocket от HTTP и Firebase. - Настроить flavors и собрать release (сборки). - Подключить Crashlytics и логирование через Talker (аналитика). - Оформить README и Makefile, пройти самопроверку по чек-листу code review (мок-интервью).
Советы по подготовке
- Сделайте пример из урока полностью сами, засекая время. Так вы поймёте свой реальный темп.
- Подготовьте шаблон проекта: структура папок, DI, базовые классы ошибок, тема. Но разберитесь в каждой его строке.
- Повторите слабые темы по чек-листу выше — пересмотрите уроки и практику к ним.
- Тренируйтесь объяснять: после каждой функции расскажите вслух, почему сделали именно так.
- Высыпайтесь и не откладывайте на последнюю ночь — спешка рождает больше всего багов.
Типичные ошибки
- Начинать с «плюсов» — тёмная тема готова, а пагинации нет.
- Не задавать вопросов и гадать, что имелось в виду.
- Сдавать без README или с README по умолчанию от
flutter create. - Один коммит со всем проектом и папка
build/в репозитории. - Не проверять release-сборку — в debug всё работало, а в release падает из-за пустого
--dart-define. - Копировать код, который не понимаете — на обсуждении это выяснится.
Практика
- Выпишите требования примера задания в два списка — «обязательно» и «плюсы» — и составьте план на 5 дней. Ожидаемый результат: план с экранами, слоями и пакетами, как в шаге 2.
- Создайте каркас проекта: структура Clean Architecture, GetIt, Dio с интерцептором Talker, README. Ожидаемый результат: проект запускается и проходит
flutter analyze. - Реализуйте обязательную часть задания самостоятельно, коммитя после каждого шага. Ожидаемый результат: работающий каталог с пагинацией, состояниями ошибок и детальным экраном.
- Добавьте два «плюса» и минимум два теста для Bloc. Ожидаемый результат:
flutter testпроходит. - Проведите самопроверку по таблице критериев и попросите одногруппника запустить проект по README. Ожидаемый результат: проект запускается без ваших подсказок, а замечания исправлены.
Итоги
- Тестовое задание проверяет не только результат, но и то, как вы думаете и оформляете код.
- Делайте его сами: на обсуждении спросят о каждой строке, а пробелы лучше найти сейчас.
- Порядок работы: прочитать и уточнить → спланировать → сделать минимум → полировка → самопроверка.
- Хорошее решение — работает, разделено по слоям, обрабатывает ошибки, имеет понятные коммиты и README.
- Чек-лист «что нужно уметь» покрывает темы месяцев 4–6 — повторите то, в чём не уверены.
- Условия отбора в Geeks Pro уточняйте у менторов.