Русский
Русский
English
Статистика
Реклама

Блог компании юmoney

Больше, больше фронтенда доклады c ЮMoneyDay

15.12.2020 16:09:41 | Автор: admin
Готовы потереть за фронтенд? Мы да. Поэтому публикуем новую партию полезного видеоматериала от экспертов крупного платежного сервиса. Под катом найдете 2 нескучных доклада про:

  • лайфхаки в CSS, HTML и JS,
  • архитектуру фронтенда ЮMoney.

Устраивайтесь поудобнее: возможно, такого вы раньше не слышали.



Лайфхаки фронтендера


Михаил Степанов, старший разработчик интерфейсов
10 лайфхаков в CSS, HTML и JS (о которых вы, возможно, даже не догадывались)

2:13 Предыстория, или причем здесь тигры
3:26 Лайфхак #1. Linking: новый способ подключения стилей
6:55 Лайфхак #2. Carousel: спецификация Scroll Snap
9:25 Лайфхак #3. Использование атрибута Base tag
11:14 Лайфхак #4. Ping
13:25 Лайфхак #5. Datails: нативные аккордеоны
14:54 Лайфхак #6. Select в несколько строк
17:22 Лайфхак #7. Inputs outside form
19:37 Лайфхак #8. Disable inputs
20:57 Лайфхак #9. Popup
22:28 Лайфхак #10. Scroll
24:12 Сколько новых тигров вы открыли для себя?





Обзор архитектуры фронтенда ЮMoney


Илья Кашлаков, руководитель отдела разработки интерфейсов
В своем докладе Илья расскажет, как развивалась архитектура фронтенда ЮMoney. Обсудим влияние легаси на развитие архитектуры. И то, как мы боремся с легаси. Расскажу про новые подходы как к серверной архитектуре фронтенда, так и к клиентской на чем они основаны и чего мы стремимся достичь в разработке.

1:39 Справка о спикере
2:38 Коротко про фронтенд ЮMoney
2:57 Почему нужна платформенная команда
4:30 Server Side: направления развития
5:53 Инфраструктурное направление: про переход от монолита к микросервисам, возникшие проблемы
9:27 Что такое заготовка и зачем она? Проблемы заготовки
13:28 Заготовка должна быть лучше и лучше
19:00 Архитектурное направление: обзор модели MVC
20:17 Чистой функции хватит всем!
21:47 Что было не так с чистой функцией?
24:06 New age: как архитектура выглядит сейчас
25:42 Что нам дает выбор Nest
28:25 Client Side: от классического фронтенда до современного





Все доклады с большой ИТ-конференции ЮMoneyDay. На подходе материалы про SQL, DevOps, PM, тестирование и мобильную разработку.

Подробнее..

3 видео для мобильного разработчика

28.12.2020 20:06:16 | Автор: admin
Задумались писать собственный фреймворк для iOS-приложения? Послушайте доклад нашего разработчика о создании библиотеки для отрисовки графиков в сервисе ЮKassa. Тут про концепт, математические алгоритмы, реализацию взаимодействия с графиками и анимацию.

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

Ну и напоследок. У вас бывает такое, что раз за разом на проектах встречаются одни и те же ошибки? И дело тут может быть вовсе не в человеческом факторе, а, например, в плохо понятых принципах программирования. Если ответили да, то смотрите 3 видео, в котором спикер разберёт причины возникновения таких ошибок и как можно их избежать.



Библиотека для рисования графиков


Сергей Тоболин, iOS-разработчик
Чем может быть полезна библиотека и как использовать её повторно снаружи

1:04 Об аналитике в ЮKassa
1:46 Концепт дизайна
2:46 Выбор фреймворка
4:08 SсiChart
4:54 SpriteKit
5:25 Первый этап: разработка алгоритма
7:53 Типы экстремумов графика
10:23 Второй этап: отрисовка графика и взаимодействие с ним
12:20 Третий этап: анимация
16:17 Результаты




Инструмент для тестирования продуктовых метрик в UI-тестах


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

1:27 С чего все начиналось
2:39 Как мы тестировали метрику раньше?
3:16 Требования
4:40 Способы реализации
9:00 Реализация отправки метрик
22:10 Первый запуск на CI
25:53 Множество симуляторов
29:40 Интеграция в тесты
40:36 Ссылка на материалы на GitHub




Код, который работает, но плохо


Нина Семкина, старший Android-разработчик
Нина сделает обзор досадных ошибок на Kotlin, которые раз за разом появляются в проектах. А самое главное разберёт причины их возникновения.

1:47 Проблемы паттерна Singleton. Пример с инициализацией параметров
5:29 Context в Singleton. Пример с потокобезопасным получением
9:19 Нарушения принципа единой ответветственности (Single responsibility principle)
13:38 Нарушения принципа подстановки Барбары Лисков
19:24 Конкурирующие состояния View
25:24 Общие итоги




Все доклады с большой ИТ-конференции ЮMoneyDay.

Подробнее..

Риски сами с собой не управятся, да и бэклог сам себя не сделает

22.12.2020 10:22:28 | Автор: admin
Риски сами с собой не управятся, да и бэклог сам себя не сделает. Если хотите узнать, как со всем этим справиться на практике добро пожаловать под кат.

В сегодняшнем выпуске 2 видео от наших менеджеров проектов. Всего 30 минут за чашечкой горячего чая или кофе, и вы в курсе в рабочих методик. А не это ли самое главное?



Как управлять рисками проектов и не скатываться при этом в формализм


Иван Зверев, менеджер проектов
Есть определенная точка, с которой нужно начинать управлять рисками. И ни в одном PMBОK-е о таком не пишут. Когда управлять рисками? Как привлечь команду? Какой алгоритм? Какая практическая польза? Ваня расскажет, как разобрался в этом сам.

1:18 О чем будет доклад? Границы
3:15 Моделируем ситуацию про пиэма Петра
5:31 Какие вопросы нужно задать себе?
7:30 Формат управления рисками
8:34 Когда нужно управлять рисками?
11:47 Кого привлечь?
13:37 Как преодолеть сопротивление и убедить команду участвовать?
15:50 Как подготовиться к сессии по управлению рисками?
19:05 Алгоритм проведения сессии
26:45 Типовые ошибки
28:05 Выводы коротко о главном






Автоскоринг бэклога


Павел Зимин, менеджер проектов
В докладе спикер делится, как приоритезировать задачи, исходя из несравнимых факторов и построить систему, где важные задачи не пропадут.

0:47 О продукте и команде
2:41 Споры в команде что разрабатывать дальше?
5:54 Система приоритетов. Критерии модели
7:10 Reach
8:30 Confidence
10:53 Impact to tech
12:52 Impact to money
14:35 Impact to user
17:32 Effort
18:12 Модель скоринга
18:37 Пример сравнения двух багов
19:48 Как устроен процесс автоскоринга бэклога
23:25 Как привить такую модель команде?
27:04 Какие профиты можно получить от модели?





Все доклады с большой ИТ-конференции ЮMoneyDay. На подходе материалы про PM, тестирование и мобильную разработку.

Подробнее..

Разбираемся, безопасно ли стрелять по проду и чем могут быть полезны дашборды

24.12.2020 14:22:40 | Автор: admin
На подходе полезные видео с конференции ЮMoneyDay от специалистов по тестированию. Если заглянете под кат, то узнаете:

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




Стрельбы по проду. Как реализовали и что получили


Виктор Бодров, исследователь производительности
Какие задачи помогают решить исследования производительности, и как их результаты влияют на развитие ЮMoney.

0:54 О спикере и работе команды
1:24 Почему мы стреляем не по стенду, а по проду
2:37 Чем стрелять? Как мониторить
4:07 Как все начиналось
6:55 Нам понадобились свои пользователи
8:14 А что там с платежами?
11:37 Платежи картами
15:08 Работа с контрагентами
18:47 Стрельбы по компонентам
21:01 Capacity control
23:38 Автострельбы




Почему дашборды могут быть полезны

Егор Иванов, старший специалист по автоматизации тестирования

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

1:04 Что такое дашборд? Примеры из жизни. Определение термина, основные типы.
3:01 Знакомство с командой интеграционного тестирования. Схема взаимодействия инструментов: Jira, Autorun, Locker, Pinger, Jenkins
6:36 Что делать, когда что-то идет не так роль дежурного
9:49 Дашборд дежурного: мастштабирование задач, использование Grafana
10:58 Как происходит отсылка метрик. Типы метрик.
12:20 Процесс отправки метрик из Java и sh
13:03 Как построить дашборд? Как можно использовать дашборды?
13:23 Пример 1 дашборд как визуализатор метрик
17:00 Пример 2 дашборд как мотиватор
20:34 Пример 3 дашборд для анализа
24:00 Пример 4 дашборд для экономии времени
25:59 Подведение итогов: что мы получили от внедрения дашбордов

Дополнительно
Расшифровка доклада Сила дашбордов



Все доклады с большой ИТ-конференции ЮMoneyDay. На подходе материалы про PM, тестирование и мобильную разработку.

Подробнее..

Наши грабли залог вашего успеха. Кейсы DevOps и SQL-команд

18.12.2020 18:13:39 | Автор: admin
Пятница самое время занимательных историй. Сегодня предлагаем вам послушать доклады DevOps и SQL-направления с конференции ЮMoneyDay. Специалисты расскажут про:

  • устройство кластера логов, который позволяет нам понимать, что происходит с платежами и транзакциями (а также в целом с компонентами и сервисами);
  • работу дата-инженеров в машинном обучении;
  • внедрение и трансформацию CI/CD.

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



Наши грабли залог вашего успеха


Максим Огрызков, старший системный администратор
В докладе пойдет речь об обработке логов нескольких дата-центров с доступом через единый интерфейс. Обсудим причины и последствия обновления кластера. Расскажу о транспорте доставки логов из разных систем и окружений, и причем тут Apache Kafka. А также почему мы не используем logstash и как одним запросом в Kibana приложить кластер.

1:17 О чем будет доклад: кластер логов
1:43 Как логи попадают в кластер?
3:50 Почему мы выбрали Apache Kafka
5:02 Rsyslog: преимущества использования
9:00 Где хранить логи из разных ДЦ?
12:08 Что делать, если объем данных слишком большой?
14:00 Обновление кластера.
20:30 Наши грабли и пути решения
22:35 Translog
24:25 Bulk request
26:28 Opendistro-perfomance-analyzer
28:28 Index Shrink
29:49 Librdkafka
31:37 Итоги: как выглядит наш кластер сейчас






Дата-инженеры в машинном обучении


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

1:40 Справка о спикере
2:41 Кто занимается DS-проектами?
8:30 Что такое Data Science проект?
14:15 Порядок действий в DS-проекте
15:42 Процесс сбора датасета
20:26 Как все устроено в Apache Kafka
29:10 Что происходит после сбора датасета
29:21 Как выбрать модель?
30:40 Примеры проблем, которые может решить дата-инженер
34:38 На каких технологиях все это работает?
35:03 Выводы доклада






CI/CD для дата-инженера: туда и обратно


Антон Спирин, старший разработчик BI
Доклад о внедрении принципов CI/CD в BI-разработке, целях, их трансформации и преодолении трудностей.

2:00 Справка о спикере
2:44 Описание проблемы
4:28 Кто такой дата-инженер?
5:43 CI/CD в чем состоит работа инженера?
6:55 Подробнее о стеке и информационных системах
8:00 Точка отсчета: с чего мы начинала
10:34 Первый этап изменений
15:50 Кажется, все хорошо, но второй этап улучшений
19:01 Почти демо: JenkinsFile, Pipelines
20:44 Что мы получили на выходе?
22:43 Сколько ушло времени? Статистика по релизам
23:37 Наши челленджи и что можно было бы сделать иначе. Планы на будущее





Все доклады с большой ИТ-конференции ЮMoneyDay. На подходе материалы про PM, тестирование и мобильную разработку.

Подробнее..

Как мы создали фреймворк для построения графиков в iOS-приложении

23.04.2021 10:10:48 | Автор: admin

Привет, я Сергей, iOS-разработчик в ЮKassa, занимаюсь ее мобильным приложением. Недавно в нем появился просмотр аналитики по счетам и платежам. И сегодня я расскажу, как мы реализовали эту возможность, а еще зачем и как разработали собственный фреймворк для создания графиков.

Немного об аналитике в ЮKassa

Аналитика одна из важнейших функций нашего сервиса. Она помогает оценить ключевые показатели магазина: количество свободных денег, маржу, число возвратов и, например, средний чек.

Аналитика платежей в ЮKassaАналитика платежей в ЮKassa

В нашей аналитике большое значение имеют графики. Они позволяют наглядно отобразить изменения разных показателей. У такого графика на оси абсцисс расположены даты за выбранный период, на оси ординат значения нужного показателя. График строится по точкам, где каждой дате соответствует конкретное значение. Благодаря этому можно посмотреть, например, сколько магазин заработал за 4 октября 2020.

Что мы хотели получить

Наша разработка началась с создания концепт-дизайна. Мы решили, что в приложении должна быть возможность выбора периода и типа аналитики к примеру, по выручке или среднему чеку. Мы определились сразу, как сделать карусель для типов аналитики и кнопки для периодов, через CollectionView и StackView соответственно. А вот как нарисовать сам график и сделать так, чтобы им можно было управлять жестами, эти задачи оказалась труднее.

Концепт-дизайнКонцепт-дизайн

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

С бэкенда нам могут прийти данные для аналитики за три года с интервалом в день. Поэтому за раз мы должны уметь отобразить чуть больше 1000 точек на графике и дать пользователю возможность свободно взаимодействовать с ним без подвисаний и глюков при стабильных 60 кадрах в секунду.

Что мы попробовали

Для создания графиков мы попробовали три фреймворка. Это самые популярные открытые решения Charts и SwiftCharts, а еще платное SciChart. Для нас важнее всего было не наличие большого количества функций, а возможность рисования графиков нужным образом и высокая производительность.

Кастомизация

Отображение

Анимация

Производи-тельность

Charts

Отсутствует отрисовка
одной точки

Есть всё необходимое

Отсутствует анимация перерисовки

Просадки при более чем 500 точек

SwiftCharts

Отсутствует отрисовка
одной точки

Некорректное отображение дат на оси X

Отсутствует анимация перерисовки и смены графиков

Просадки при более чем 800 точек

SciChart

Отсутствует отрисовка
одной точки

Есть всё необходимое

Есть всё необходимое

Отличная оптимизация

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

С помощью Charts удалось добиться правильного отображения графика, но не получилось задать кастомную анимацию при переключении между графиками. К тому же при количестве значений 500+ на графике были существенные просадки частоты кадров.

В SwiftCharts тоже было невозможно задать кастомную анимацию при переключении между графиками. Еще отсутствовала анимация при перерисовке взаимодействии с графиком жестами. Некорректно отображались даты на оси X. И при числе значений 800+ тоже заметно проседала частота кадров.

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

SciChartSciChart

Этот фреймворк очень крут, потому что рендерит графики с помощью OpenGL ES и Metal и даже при количестве значений в 100 000 держит стабильные 60 кадров в секунду. Но SciChart это профессиональное решение, которое используется для отображения данных и графиков в медицине, приложениях для трейдинга, работы с музыкой и т.п. Персональная лицензия стоит $1000 в год, а корпоративная $4000 в год.

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

Как мы сделали свое решение

Для разработки мы выбрали SpriteKit. Он простой в использовании и внедрении, рендерит через Metal с высокой производительностью и позволяет легко создавать анимации. Еще был вариант сделать фреймворк на Core Graphics или MetalKit, но в первом сложнее работать с анимациями, а со вторым мы вообще не имели дела, и на его освоение времени не было. Итак, SpriteKit.

Нахождение координат точек графикаНахождение координат точек графика

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

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

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

Нахождение координат точек смещенного графикаНахождение координат точек смещенного графика

Допустим, изначально левая граница равна 0, а правая 1. Если мы хотим приблизить график, то есть растянуть нужно задать новые значения для правого и левого смещений. К примеру, 0,2 для левой границы и 0,8 для правой. Это позволяет свободно взаимодействовать с графиком жестами увеличивать, уменьшать, двигать влево или вправо. И для этого нужно только менять значения левого и правого смещений.

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

Весь алгоритм я описывать не буду, если захотите в нем разобраться, посмотрите исходный код фреймворка, который мы выложили на GitHub: https://github.com/yoomoney-tech/mobile-analytics-chart-swift.

Как все это работает

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

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

Статичные экстремумыСтатичные экстремумы

Второй тип произвольные экстремумы.

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

Здесь как со статичными экстремумами, разница лишь в том, что мы не вычисляем экстремумы, а сами инициализируем их произвольными числами. Например, максимальное значение равно 5, а минимальное 1, но так как произвольные максимум и минимум равны 10 и -5 соответственно, то график сжимается по вертикали.

И последний тип динамические экстремумы.

Динамические экстремумыДинамические экстремумы

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

Алгоритм нахождения динамических экстремумовАлгоритм нахождения динамических экстремумов

С учетом всего этого мы разработали алгоритм, который работает следующим образом.

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

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

Итак, мы научились находить координаты точек. Осталось соединить их линией, отобразить и добавить градиент. Для формирования линии создаем кривую Безье из вычисленных координат для каждой точки. Затем добавляем кривую в SKShapeNode это математическая фигура из SpriteKit, которую можно обводить или красить заливкой. Градиент создаем с помощью SKSpriteNode объекта в SpriteKit, который можно залить любым цветом или градиентом. Маску для градиента делаем через SKCropNode.

Построение графикаПостроение графика

Другой важный момент в фреймворке доступно три типа отображения графика.

Типы отображения линии графикаТипы отображения линии графика

1) Линейное. Кривая не сглаживается.

2) Квадратичное. Есть сглаживание кривой, но точки могут не соответствовать своим значениям для большей плавности графика. Этот вариант подходит для визуализации, где точность данных не принципиальна.

3) Горизонтально-квадратичное. Кривая сглаживается, и все точки соответствуют своим значениям.

Техника жестов и никакой магии

После разработки алгоритма для нахождения точек координат мы приступили к реализации управления жестами. Для этого внедрили в фреймворк три типа жестов.

Жесты для взаимодействия с графикомЖесты для взаимодействия с графиком

Первый долгое зажатие (он же LongPress), который позволяет отобразить промежуточное значение отдельной точки на графике. Второй сдвиг графика вправо или влево, реализованный при помощи Pan. Третий увеличение и уменьшение графика, сделанное через Pinch.

Жесты для сдвига графика и масштабирования реализованы таким образом, что просто изменяют значения левого и правого смещений, о которых я рассказал выше.

Финальный штрих анимации

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

Алгоритм анимации перерисовкиАлгоритм анимации перерисовкиАнимация перерисовкиАнимация перерисовки

Мы реализовали и другие анимации. Анимация переключения между графиками позволяет плавно перейти от одной фигуры к другой. Анимация загрузки данных избавляет от спиннеров и загрузчиков. Эти анимации реализованы через SKAction инструмент SpriteKit для анимированного изменения объекта, в нашем случае анимированного изменения цвета линии и градиента.

Анимация загрузки данных и переключения Анимация загрузки данных и переключения

В SpriteKit нет SKAction для анимированного изменения цвета, поэтому мы реализовали для этого кастомный SKAction. Мы написали функцию для создания промежуточного цвета, в нее передаются два параметра: elapsedTime время, прошедшее с момента начала анимации, и duration продолжительность анимации. FromColor это цвет в начале анимации, toColor цвет, который нужно получить в конце анимации.

Сначала вычисляем fraction долю прошедшего времени от всей продолжительности. Это значение от 0 до 1. Для более плавной анимации долю прошедшего времени мы прогоняем через функцию плавности CubicEaseOut. Дальше через линейную интерполяцию получаем промежуточные значения для красного, зеленого, голубого и для альфа-канала. На выходе получается промежуточный цвет, который можно использовать в нашем кастомном SKAction.

func makeTransColor(    elapsedTime: CGFloat,    duration: TimeInterval,    fromColor: UIColor,    toColor: UIColor) -> UIColor {    let fraction = cubicEaseOut(CGFloat(elapsedTime / CGFloat(duration)))    let startColorComponents = fromColor.toComponents()    let endColorComponents = toColor.toComponents()    return UIColor(        red: lerp(a: startColorComponents.red, b: endColorComponents.red, fraction: fraction),        green: lerp(a: startColorComponents.green, b: endColorComponents.green, fraction: fraction),        blue: lerp(a: startColorComponents.blue, b: endColorComponents.blue, fraction: fraction),        alpha: lerp(a: startColorComponents.alpha, b: endColorComponents.alpha, fraction: fraction)    )}// Функция плавностиfunc cubicEaseOut(    _ x: CGFloat) -> CGFloat {    let p = x - 1    return p * p * p + 1}// Линейная интерполяцияfunc lerp(    a: CGFloat,    b: CGFloat,    fraction: CGFloat) -> CGFloat {    return (b - a) * fraction + a}

Ниже приведен код кастомного SKAction для анимированной смены цвета обводки объекта (у нас это изменение цвета кривой на графике). Мы можем задать начальный и конечный цвета, а еще продолжительность анимации. В процессе анимации создаем промежуточный цвет и присваиваем его обводке объекта.

func strokeColorTransitionAction(    fromColor: UIColor,    toColor: UIColor,    duration: TimeInterval = 0.5) -> SKAction {    return SKAction.customAction(withDuration: duration) { (node: SKNode, elapsedTime: CGFloat) in        guard let shapeNode = node as? SKShapeNode else { return }        let transColor = makeTransColor(            elapsedTime: elapsedTime,            duration: duration,            fromColor: fromColor,            toColor: toColor        )        shapeNode.strokeColor = transColor    }}

А с помощью этой функции можно создать SKAction для анимации смены градиента. Здесь тоже можно задать начальный и конечный цвета градиента, продолжительность анимации и направление градиента.

static func gradientColorTransitionAction(    fromColor: UIColor,    toColor: UIColor,    duration: TimeInterval = 0.5,    direction: GradientDirection = .up) -> SKAction {    return SKAction.customAction(withDuration: duration) { (node: SKNode, elapsedTime: CGFloat) in        guard let spriteNode = node as? SKSpriteNode else { return }        let transColor = makeTransColor(            elapsedTime: elapsedTime,            duration: duration,            fromColor: fromColor,            toColor: toColor        )        let size = spriteNode.size        let textureSize = CGSize(            width: size.width / 2,            height: size.height / 2        )        let texture = SKTexture(            size: textureSize,            color1: CIColor(color: transColor.withAlphaComponent(0.0)),            color2: CIColor(color: transColor),            direction: direction        )        texture.filteringMode = .linear        spriteNode.texture = texture    }}

Градиент в SpriteKit создается с помощью SKTexture. Через этот объект мы можем задать размер градиента, его направление и цвета. Здесь важно отметить, что для градиента мы используем два цвета первый задаем вручную, а второй получаем из первого через смену альфа-канала. В результате градиент плавно переходит из цвета в прозрачность.

В процессе анимации мы формируем промежуточный цвет. С его помощью создаем SKTexture, присваиваем текстуре объекта и таким образом получаем анимированную смену градиента.

Для анимации вьюшки со значением в отдельной точке мы тоже использовали SKAction. Через функцию move можно плавно перенести вьюшку в нужную позицию.

Анимация view со значением в отдельной точкеАнимация view со значением в отдельной точке

Что получилось в итоге

Перед отображением двух графиков с 1000 точек Charts зависает на несколько секунд, а при работе с графиком выдает всего лишь около 20 кадров/сек. SwiftCharts справляется лучше и выдает около 40 кадров/сек. Наш фреймворк, который мы создали за две недели и назвали AnalyticsChart, выдает стабильные 50-60 кадров/сек. при работе с графиком в iOS-приложении как на iPhone (XS Max), так и на iPad. К тому же наш фреймворк соответствует нужному нам дизайну, позволяет отображать и взаимодействовать с одним и больше графиками.

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

Конечный результат наших стараний и производительность для двух графиков с 1000 точек:

Расскажите про ваш опыт создания фреймворков для графиков. Или если есть вопросы, задавайте их в комментариях.

Подробнее..

Jenkins Pipeline. Что это и как использовать в тестировании

08.02.2021 16:12:50 | Автор: admin

Меня зовут Александр Михайлов, я работаю в команде интеграционного тестирования компании ЮMoney.

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

Надеюсь, что эта статья будет интересна как новичкам, так и тем, кто съел собаку в автоматизации тестирования. Мы рассмотрим базовый синтаксис Jenkins Pipeline, разберемся, как создать джобу на основе пайплайна, а также я расскажу про опыт внедрения неочевидной функциональности в CI запуска и дожатия автотестов по условию.

Запуск автотестов на Jenkins инструкция

Не новость, что автотесты эффективнее всего проводить после каждого изменения системы. Запускать их можно локально, но мы рекомендуем делать это только при отладке автотестов. Больший профит автотесты принесут при запуске на CI. В качестве CI-сервера у нас в компании используется Jenkins, в качестве тестового фреймворка JUnit, а для отчетов Allure Report.

Чтобы запускать тесты на Jenkins, нужно создать и сконфигурировать джобу.

Для этого достаточно выполнить несколько несложных шагов.

1) Нажать Создать, выбрать задачу со свободной конфигурацией и назвать ее, например, TestJob.

Естественно, для этого у вас должны быть права в Jenkins. Если их нет, нужно обратиться к администратору Jenkins.

2) Указать репозиторий, откуда будет выкачиваться код проекта: URL, credentials и branch, с которого все будет собираться.

3) Добавить нужные параметры, в этом примере количество потоков (threadsCount) и список тестов для запуска (testList).

Значение *Test для JUnit означает Запустить все тесты.

4) Добавить команду для запуска тестов.

Наш вариант запускается на Gradle: мы указываем таску теста и передаем параметры в тесты.

./gradlew test -PthreadsCount=$threadsCount -PtestList=$testList

Можно выполнить шаг сборки Выполнить команду shell, либо через Gradle Plugin использовать шаг Invoke Gradle Script.

5) Нужно добавить Allure-report (должен быть установлен https://plugins.jenkins.io/allure-jenkins-plugin/) в Послесборочные операции, указав путь к артефактам Allure после прогона (по умолчанию allure-result).

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

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

Несложно заметить, что тесты у нас падают.

Почему падают тесты

Падения могут случаться по разным причинам. В нашем случае на это влияют:

  • ограниченные ресурсы тестового стенда,

  • большое число микросервисов (~140); если при запуске интеграционных тестов какой-то один микросервис подтормаживает, тесты начинают валиться,

  • большое число интеграционных тестов (>3000 E2E),

  • врожденная нестабильность UI-тестов.

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

Что такое дожим

Дожим это перезапуск автотестов в рамках их одного прогона. При успешном прохождении автотеста можно считать его пройденным, не учитывая предыдущие падения в прогоне.

Дожимать? Опасно же!

Возразите вы и будете полностью правы. Безусловно, дожим автотестов может спровоцировать пропуск дефекта на продакшн. Баг может быть плавающим при повторном запуске успешно просочиться и попасть на продакшн.

Но мы проанализировали статистику падений автотестов за длительный период и увидели, что большинство падений было связано с нестабильной тестовой средой, тестовыми данными. Поэтому мы взяли на себя риск и стали дожимать тесты. Прошло уже больше года, и не было ни одного дефекта, пропущенного на продакшн по этой причине. Зато стабильность тестов повысилась ощутимо.

Как решать задачу с дожимами

Мы пробовали разные решения: использовали модификацию поведения JUnit 4, JUnit 5, писали обертки на Kotlin. И, к сожалению, каждый раз реализация завязывалась на фичах языка или фреймворка.

Если процесс запускался с помощью JUnit 4 или JUnit 5, возможность перезапустить тесты была только сразу при падении. Тест упал, перезапустили его несколько раз подряд и если сбоил какой-то микросервис из-за нагрузки, либо настройки тестовой среды были некорректные, то тест все три раза падал.

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

Мы взглянули на проблему шире, решили убрать зависимость от тестового фреймворка или языка и реализовали перезапуск на более высоком уровне на уровне CI. И сделали это с помощью Jenkins Pipeline.

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

Что такое Jenkins Pipeline

Jenkins Pipeline набор плагинов, позволяющий определить жизненный цикл сборки и доставки приложения как код. Он представляет собой Groovy-скрипт с использованием Jenkins Pipeline DSL и хранится стандартно в системе контроля версий.

Существует два способа описания пайплайнов скриптовый и декларативный.

1. Scripted:

node {stage('Example') {try {sh 'exit 1'}catch (exc) { throw exc}}}

2. Declarative

pipeline {agent anystages {stage("Stage name") {steps {}}}}

Они оба имеют структуру, но в скриптовом она вольная достаточно указать, на каком слейве запускаться (node), и стадию сборки (stage), а также написать Groovy-код для запуска атомарных степов.

Декларативный пайплайн определен более жестко, и, соответственно, его структура читается лучше.

Рассмотрим подробнее декларативный пайплайн.

  1. В структуре должна быть определена директива pipeline.

  2. Также нужно определить, на каком агенте (agent) будет запущена сборка.

  3. Дальше идет определение stages, которые будут содержаться в пайплайне, и обязательно должен быть конкретный стейдж с названием stage(name). Если имени нет, тест упадет в runtime с ошибкой Добавьте имя стейджа.

  4. Обязательно должна быть директива steps, в которой уже содержатся атомарные шаги сборки. Например, вы можете вывести в консоль Hello.

pipeline { // определение декларативного pipelineagent any // определяет, на каком агенте будет запущена сборкаstages { // содержит стейджи сборкиstage("Stage name") { // отдельный стейдж сборкиsteps { // набор шагов в рамках стейджаecho "Hello work" // один из шагов сборки}}}}

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

pipeline {stages {stage("Post stage") {post { // определяет действия по завершении стейджаsuccess { // триггером исполнения секции является состояние сборки archiveArtifacts artifacts: '**/target/*'}}}}post { // после всей сборкиcleanup {cleanWs()}}}

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

При написании своего первого пайплайна я, естественно, использовал официальный мануал там подробное описание синтаксиса и степов.

Сначала я даже растерялся и не знал, с чего начать настолько там много информации. Если вы первый раз сталкиваетесь с написанием пайплайна, начать лучше со знакомства с генераторами фрагментов пайплайна из UI-интерфейса.

Если к URL вашего веб-интерфейса Jenkins добавить ендпойнт /pipelines-syntax, откроется страница, в которой есть ссылки на документацию и два сниппет-генератора, позволяющие генерировать пайплайн даже без знания его синтаксиса:

  • Declarative sections generator

  • Snippet Generator

Генераторы фрагментов помощники в мире Jenkins

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

  • Declarative sections generator (JENKINS-URL/directive-generator) генератор фрагментов для декларативного описания пайплайна.

Для добавления стадии нужно написать ее имя и указать, что будет внутри (steps). После нажатия кнопки Сгенерировать будет выведен код, который можно добавлять в пайплайн.

stage(start tests){steps{ //One or more steps needs to be included within the steps block}}

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

  • В Sample Step выбрать build: Build a job.

  • (Дальше функционал подсказывает) необходимо определить параметры, которые будут переданы в джобу (для примера задано branch, project).

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

Изменим параметры джобы на те, которые определили при ее создании.

build job QA/TestJob, parameters: [                        string(name: 'threadsCount', value: 16),                         string(name: 'testList', value: *Test),                        string(name: 'runId', value: runId)]

где threadsCount - кол-во потоков для распараллеливания тестов, testList - список тестов для запуска, runId - идентификатор прогона тестов. Для чего нужны эти параметры, расскажу далее.

Snippet Generator удобен тем, что подсвечивает шаги в зависимости от установленных плагинов. Если у вас есть, например, Allure-report, то плагин сразу покажет наличие расширения и поможет сгенерировать код, который будет работать.

Вставим сгенерированный код степа в пайплайн на следующем шаге.

Запуск тестов с помощью Pipeline инструкция

Итак, давайте с помощью Declarative sections generator создадим пайплайн. В нем нужно указать директивы: pipeline, agent (агент, на котором будет запускаться пайплайн), а также stages и steps (вставка ранее сгенерированного кода).

Так получится пайплайн, который запустит джобу, созданную на предыдущем шаге через UI.

pipeline {agent {label any}stages {stage("start test") {steps{build job: '/QA/TestJob',parameters: [string(name: 'threadsCount', value: threadsCount),string(name: 'runId', value: runId),string(name: 'testList', value: testList)]}}} }

Напомню, что в параметры для запуска тестов мы передавали количество потоков и список тестов. Теперь к этому добавляем параметр runId (идентификатор прогона тестов) он понадобится позднее для перезапуска конкретного сьюта тестов.

Чтобы запустить пайплайн, нужно создать проект.

  1. New Item -> Pipeline.

Для этого нужно нажать на кнопку Создать проект и выбрать не джобу со свободной конфигурацией, а джобу Pipeline осталось указать ей имя.

  1. Добавить параметры runId, threadsCount, testList.

  1. Склонировать из Git.

Пайплайн можно описать непосредственно как код и вставить в поле, но для версионирования нужно затягивать пайплайн из Git. Обязательно указываем путь до скрипта с пайплайном.

Готово, джобу можно запускать.

Хотим добавить немного дожатий

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

Для реализации нужно:

  1. вынести шаг запуска тестов в библиотечную функцию (shared steps),

  2. получить упавшие тесты из прогона,

  3. добавить условия перезапуска.

Теперь немного подробнее про каждый из этих шагов.

Многократное использование шагов Shared Steps

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

Решение нашлось не сразу. Оказывается, для многократного использования кода в Jenkins есть встроенный механизм shared libraries, который позволяет описать методы один раз и затем применять их во всех пайплайнах.

Существуют два варианта подключения этой библиотеки.

  1. Написанный проект/код подключить через UI Jenkins. Для этого требуются отдельные права на добавление shared libraries или привлечение девопс-специалистов (что не всегда удобно).

  2. Хранить код в отдельном проекте или в проекте с пайплайнами. При использовании этот код подключается как динамическая библиотека и выкачивается каждый раз при запуске пайплайна.

Мы используем второй вариант размещаем shared steps в проекте с пайплайнами.

Для этого в проекте нужно:

  • создать папку var,

  • в ней создать файл с названием метода, который планируется запускать например, gradlew.groovy,

  • стандартно определить имя метода (должен называться call), то есть написать def call и определить входящие параметры,

  • в теле метода можно написать произвольный Groovy-код и/или Pipeline-степы.

Pipeline script:

//Подключение библиотеки//https://www.jenkins.io/doc/book/pipeline/shared-libraries/ - описание с картинкамиlibrary identifier: 'pipeline-shared-lib'  pipeline {stages {stage("Build") {steps {gradlew(tasks: ["build"]) // вызов метода из библиотеки}}}}

var/gradlew.groovy

def call(Map<String, List<String>> parameters) {  // стандратное имя для глобального методаdef tasks = parameters["tasks"]def args = parameters["args"] ?: []sh "./gradlew ${args.join(' ')}     ${tasks.join(' ')}"    // произвольный groovy код + pipeline-методы}

Вынесение запуска тестов в shared steps в /var

  1. Выносим startTests.groovy в /var.

Во-первых, нужно вынести запуск тестов в отдельный метод. Выглядит это так создаем файл, называем метод def call, берем кусок кода, который был в пайплайне, и выносим его в этот step.

def call(Map<String, String> params) {    def threadsCount = params["threadsCount"] ?: "3"    def testList = params["testList"] ?: "*Test"    stage("start test job") {      runTest = build job: '/QA/TestJob',                  parameters: [                         string(name: 'threadsCount', value: threadsCount),                         string(name: 'runId', value: runId),                         string(name: 'testList', value: testList)],                         propagate: false   }}

Для передачи параметров используется Map<String, String>. Почему не передавать каждый параметр отдельно? Это не очень удобно, т.к. в Groovy параметры не обозначены по названиям. При использовании Map синтаксис позволяет указать key:value через двоеточие. В коде (в месте вызова метода) это отображается наглядно.

Структура проекта будет выглядеть так.

  1. Подключение shared steps как внешней библиотеки.

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

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

library changelog: false,    identifier: 'shared-lib@master',    retriever: modernSCM([   $class    : 'GitSCMSource',   remote   : 'ssh://git@bitbucket.ru/qa/jenkins-groovy-scripts.git'])

Теперь после подключения shared steps вместо шага запуска тестов build нужно вставить startTest. Не забудьте, что имя метода должно совпадать с именем файла.

Теперь наш пайплайн выглядит так.

//Динамическое подключение библиотекиlibrary changelog: false,    identifier: 'shared-lib@master',    retriever: modernSCM([   $class   : 'GitSCMSource',  remote   : 'ssh://git@bitbucket.ru/qa/jenkins-groovy-scripts.git'])pipeline {   agent {  label any  }  stages { stage("start test") {    steps{   startTests(runId: runId ) //Вызов метода из библиотеки  }    }  }}

Первый шаг реализован, теперь можно многократно запускать тесты в разных местах. Переходим к 2 шагу.

Получение упавших тестов из прогона

Теперь нам нужны упавшие тесты. Каким образом их извлечь?

  • Установить в Jenkins плагин JUnit Test Result Report и использовать его API.

  • Взять результаты прогона JUnit (обычно в формате XML), распарсить и извлечь нужные данные.

  • Запросить список упавших тестов из нужного места.

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

http://reporter:8080/failedTests/$runId

Добавление условий перезапуска

На этом шаге следует добавить getFailedTests.groovy в /var. Представим, что у вас есть такой сервис Reporter. Нужно назвать файл getFailedTests, сделать запрос httpRequest в этот сервис и распарсить его.

def call(String runId) {    def response = httpRequest httpMode: 'GET',     url: "http://reporter:8080/failedTests/$runId"     def json = new JsonSlurper().parseText(response.content)        return json.data}

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

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

Условия перезапуска

Какие условия для перезапуска можно реализовать?

Приведу часть условий, которые используем мы.

1) Если нет упавших тестов, прогон завершается.

if (countFailedTests == 0) {echo FINISHED   }

2) Как я уже писал выше, на тестовой среде ресурсы ограничены, и бывает такое, что ТС захлебывается в большом количестве параллельных тестов. Чтобы на дожатии избежать падений тестов по этой причине, понижаем число потоков на повторном запуске. Именно для этого при создании джобы и в самом пайплайне мы добавили параметр threadsCount.

Если и после уменьшения потоков тесты не дожимаются (количество упавших тестов на предыдущем прогоне равно числу упавших тестов на текущем), тогда считаем, что дело не во влиянии ТС на тесты. Останавливаем прогон для анализа причин падений и тем самым предотвращаем последующий холостой запуск.

if (countFailedTests == previousCountFailedTests) { echo TERMINATED - no one new passed test after retry}

3) Третья и самая простая проверка состоит в том, что если падает большое количество тестов, то дожимать долго. Скорее всего, причина падений какая-то глобальная, и ее нужно изучать.

Для себя мы определили: если тестов > 40, дожимать не автоматически не будем, потому что 40 наших E2E могут проходить порядка 15 минут.

if (countFailedTests > FAILEDTESTSTRESHOLD) {   echo TERMINATED - too much failed tests   }
Получился метод:

https://github.com/useriq/retry-flaky-tests/blob/master/jenkins-pipeline-retry/var/testsWithRerun.groovy

def call(Map<String, String> params) {    assert params["runId"]    def threadsCount = params["threadsCount"] ?: "8"    def testList = params["testList"] ?: "*Test"    def runId = params["runId"]    int FAILED_TESTS_TRESHOLD = 40    def countFailedTests = 0    def failedTests    int run = 1    boolean isFinished = false    int threads = threadsCount as int    while (run <= Integer.valueOf(runCount) && !isFinished) {        if (run == 1) {            startTests()        } else {            if (countFailedTests > 0) {                threads = reduceThreads(threads)                testList = failedTests.toString().minus('[').minus(']').minus(' ')                startTests()            }        }        stage("check ${run}_run result ") {            failedTests = getFailedTests(runId)            def previousCountFailedTests = countFailedTests            countFailedTests = failedTests.size()            if (countFailedTests == 0) {                echo "FINISHED"                isFinished = true            }            if (countFailedTests > FAILED_TESTS_TRESHOLD) {                echo "TERMINATED - too much failed tests > ${FAILED_TESTS_TRESHOLD}"                isFinished = true            }            if (countFailedTests == previousCountFailedTests) {                echo "TERMINATED - no one new passed test after retry"                isFinished = true            }        }        run += 1    }}

Последние два условия так называемые fail fast. Они позволяют при глобальных проблемах на тестовом стенде не делать прогоны, которые не приведут к дожиму тестов, но будут занимать ресурсы тестового стенда.

Итоговый pipeline

Итак, все 3 шага реализованы итоговый пайплайн выглядит так.

library changelog: false,       identifier: 'shared-lib@master',       retriever: modernSCM([               $class       : 'GitSCMSource',               remote       : 'ssh://git@bitbucket.ru/qa/jenkins-groovy-scripts.git']) assert runId != nullpipeline {   agent {       label any   }   stages {       stage("start test") {           steps {             testsWithRerun(runId: runId)           }       }   }}

Визуализация с Blue Ocean

Как все это выглядит при прогоне в Jenkins? У нас, к примеру, для визуализации в Jenkins установлен плагин Blue Ocean.

На картинке ниже можно увидеть, что:

  1. запустился метод testwith_rerun,

  2. прошел первый запуск,

  3. прошла проверка упавших тестов,

  4. запустился второй прогон,

  5. после успешной проверки джоба завершилась.

Вот так выглядит визуализация нашего настоящего прогона.

В реальном примере две ветки: мы параллельно запускаем два проекта с тестами (на Java и Kotlin). Можно заметить, что тесты одного проекта прошли с первого раза, а вот тесты другого пришлось дожимать еще раз. Таким образом визуализация помогает найти этап, на котором падают тесты.

А так выглядит реальный timeline приемки релиза.

После первого прогона отправили дожимать упавшие тесты. Во второй раз упавших тестов намного меньше, дожимаем в третий раз и вуаля, успешный build.

Задача решена.

Итог

Мы перенесли логику перезапусков упавших тестов из тестового проекта на уровень выше на CI. Таким образом сделали механизм перезапуска универсальным, более гибким и независимым от стека, на котором написаны автотесты.

Раньше наши тесты дожимались безусловно, по несколько раз, с неизменным количеством параллельных потоков. При перегрузке тестового стенда, некорректных настройках тестового окружения либо каких-то других проблемах красные тесты перезапускались фиксированное число раз без шансов дожаться. В худшем случае прогоны могли длиться часами. Добавив условия fail fast, мы сократили это время.

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

Какой профит мы получили:

  • уменьшили time-to-market тестируемых изменений,

  • сократили длительность аренды тестового стенда под приемочное тестирование,

  • увеличили пропускную способность очереди приемочного тестирования,

  • не завязаны на тестовый фреймворк (под капотом может быть что угодно дожатия будут работать),

  • поделились знаниями об использовании Jenkins Pipeline.

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

Подробнее..

Как оптимизировать повседневные backend-задачи три видео с митапа по Java

24.05.2021 14:14:07 | Автор: admin

20 мая прошел наш седьмой митап для Java-разработчиков ЮMoney Jam. Смотрите видео от наших докладчиков, которые делятся кейсами:

  • Как добавлять в чистовой код на Java тестовое поведение и спать спокойно.

  • Как обеспечить отказоустойчивость к высоким нагрузкам внутри кластера базы данных.

  • Как не попасть в Jar Hell.

Владимир Плизга, backend-разработчик ЦФТ. Инъекция тестовых поведений: как выйти сухим изводы?

  • Ситуации, требующие правок кода недля production.

  • Что выбрать: штатные средства, аспектно-ориентированный подход или всё вместе.

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

Григорий Скобелев, программист отдела разработки серверных решений ЮMoney. Зашардируем это!

  • Что делать, когда кластерБД трещит отнагрузки, икак грамотно масштабировать данные.

  • Как построить отказоустойчивый кластер баз данных, который будет справляться свысокой нагрузкой.

  • Как обеспечить отказоустойчивость внутри кластераБД спомощью шардирования данных нанашем примере.

Вита Комарова, старший программист отдела разработки серверных решений ЮMoney. Как непопасть вJar Hell

  • Что такое Jar Hell икчему онможет привести.

  • Как мыборемся сJar Hell впроектах ЮMoney.

  • Инструменты, которые помогают избежать Jar Hell.

Задавайте вопросы по докладам в комментариях, и наши эксперты вам ответят. А чтобы не пропустить следующие митапы, подпишитесь на наш Telegram-канал.

Подробнее..

Подключение к платежному сервису быстро и удобно. Миф или реальность? Часть 2

18.02.2021 10:20:32 | Автор: admin

Всем привет! Совсем недавно мы рассказывали про внутреннюю кухню подключения к платежному сервису: как ускоряем и автоматизируем процессы в части заключения договора. А сегодня мы поговорим о технической стороне вопроса об интеграции сайтов и сервисов с нашим платежным решением.

Если начать по порядку, то для приема платежей интегрироваться с сервисом ЮKassa не обязательно с помощью сервиса можно выставлять клиентам счета. Для этого в Личном кабинете ЮKassa можно создать ссылку для оплаты товара или услуги и отправить покупателю. Подробно мы рассказали про этот сервис в одной из Хабр-статей. А сейчас хотим рассказать, какие способы интеграции сайта и нашего платежного решения мы развиваем.

Конструктор платежных форм

Компаниям и предпринимателям, которые в онлайне предлагают небольшой ассортимент товаров или услуг, не нужны сложные системы управления сайтом. Благотворительные организации и фонды зачастую тоже создают сайты из 2-3 страниц для сбора пожертвований. Специально для таких простых случаев мы некоторое время назад сделали конструктор платежных форм.

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

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

Процесс оплаты с помощью такой формы происходит просто. Когда пользователь нажимает кнопку Заплатить, форма отправляет запрос по API в наш бэкенд на создание платежа и переводит плательщика на форму оплаты. По итогам платежа отправляется webhook для уведомления о статусе. При успешной оплате на указанный при создании формы e-mail отправляется письмо с деталями о заказе контактами покупателя для доставки товара.

Интеграция через готовый модуль

Но, конечно, полноценным интернет-магазинам конструктора не достаточно. Большинство интернет-магазинов, контентных платформ используют системы управления сайтом (CMS) для автоматизированной обработки заказов и учета товарного ассортимента или предоставления услуг. Для легкой интеграции с такими платформами используются готовые платежные модули.

У ЮKassa есть такие модули для более 150 платформ. Это самый большой охват на рынке платежных решений. Некоторые модули это разработки производителей самих CMS-платформ, другие наши собственные: например, для InSales, Opencart и других.

Пользователи CMS это далеко не всегда разработчики. Поэтому и здесь наша задача сделать так, чтобы широкой аудитории было доступно подключение нашего платежного сервиса.

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

Первое это детектор CMS.

После регистрации в ЮKassa пользователи указывают адрес сайта, на который хотят добавить прием платежей. Наше решение детектор CMS анализирует страницы сайта и определяет CMS-платформу.

Для анализа мы используем библиотеку сервиса wappalyzer.com. В ней есть база соответствия компонентов веб-приложения, основанная на регулярных выражениях в JS, CSS, meta-тегах, cookie и др. Детектор сопоставляет найденные компоненты со своей базой и определяет CMS-платформу, используемую на сайте. Информация о CMS-системе и существующих для нее платежных модулях поступает в Личный кабинет ЮKassa.

Второе решение это автоматическая настройка параметров под платежные модули. Получив данные о CMS-платформе от детектора, мы в Личном кабинете ЮKassa предзаполняем технические настройки под существующий платежный модуль тип протокола и URL для уведомлений о платежах. Это избавляет пользователя от самостоятельного поиска адреса для уведомлений в инструкциях к платежному модулю.

Дальше нужно в платежном модуле CMS-системы указать номер магазина (shop ID) и секретный ключ API из Личного кабинета ЮKassa. После этого интеграция будет завершена кроме вставки двух параметров, больше не придется производить никаких других действий.

Третье решение, которое еще больше упрощает подключение, интеграция через OAuth-авторизацию.

OAuth это протокол авторизации, который позволяет получить доступ к правам стороннего сервиса для определенной площадки. Собственный OAuth-сервис ЮKassa помогает платежному модулю отправлять запросы на проведение платежей через API и получать уведомления об их статусах, проводить денежные возвраты.

Для интеграции с модулем, который работает на OAuth, достаточно нажать на кнопку Авторизоваться через ЮKassa и подтвердить передачу прав.

После этого интеграция начинает работать без каких-либо дополнительных настроек. Такая OAuth-авторизация сейчас реализована в модулях Shopify, InSales, amoCRM, Битрикс24.

Эти три решения делают интеграцию ЮKassa с большинством систем очень простой, прозрачной и понятной даже для тех пользователей, которые не обладают навыками разработки.

Интеграция через API

Конечно, многие сайты не используют CMS-системы и хотят получить больше возможностей от платежного сервиса например, настроить сложный сценарий платежей. Для этого есть возможность самостоятельной интеграции с ЮKassa по нашему API. Это уже отдельная история, но про некоторые возможности можно почитать в нашем блоге.

Заключение

Этими статьями мы хотели показать, что с помощью ЮKassa настроить прием платежей на любом сайте очень просто и это доступно любому пользователю. А если вы разработчик и к вам обратились за помощью с интеграцией можете вступить в нашу партнерскую программу и предложить своим клиентам выгодные условия для подключения к ЮKassa.

Подробнее..

Подключение к платежному сервису быстро и удобно. Миф или реальность?

16.12.2020 12:18:50 | Автор: admin
Мы знаем, как важно быстрое подключение онлайн-платежей и для совсем нового бизнеса, и для уже давно работающего. Ведь каждый день простоя это упущенные потенциальные возможности.

Но подключение эквайринга не самый простой процесс. Для этого компании нужно заключить договор с платежным сервисом и добавить на свой сайт формы и кнопки для приема оплаты. В свою очередь, сервис должен проверить компанию на соответствие требованиям регуляторов и настроить ей нужные способы приема платежей. Звучит долго, однако большинство наших клиентов подключают эквайринг через ЮKassa всего за 2-3 дня.

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




Как было раньше

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

Все выглядело примерно так. Клиент оставлял заявку на сайте Кассы с реквизитами компании. Наш менеджер проверял их и отправлял клиенту письмо с условиями подключения, анкетой и списком нужных документов: копии ИНН, ОГРН, устав организации и прочее (всего около 10 штук). После продолжительной переписки (в среднем 5-10 писем) менеджер получал полный пакет документов. Затем он подготавливал файл договора это 21 страница с приложениями. После подписания клиентом договор проходил согласование с нашими юристами, службой безопасности, финансового мониторинга и другими внутренними службами.

В итоге подключение занимало от 7 дней до месяца. Всякий раз этот процесс отнимал много времени и сил с обеих сторон и о массовом подключении магазинов оставалось только мечтать.

Упростить подачу заявки

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

1) Регистрация
Важно, чтобы самый первый шаг регистрации был простым. Поэтому к форме регистрации мы добавили API сервиса DaData, который позволяет найти ИНН организации по ее названию, а ИП по фамилии и имени предпринимателя. Благодаря этому теперь не нужно тратить время, например, на ввод ИНН мы сами покажем подходящие варианты.



2) Анкета для заключения договора с Кассой
После регистрации открывается доступ в Личный кабинет, где можно заполнить и подать анкету для договора. Одновременно с этим появляется доступ к тестовому магазину. На тестовой среде можно получить API-ключ и сразу начать интеграцию, пока идет юридическое оформление. Но об этом мы расскажем позже в другой статье, а сейчас остановимся подробнее на процессе заключения договора

Как уже было сказано, раньше для подписания договора нужно было предоставить массу документов и заполнить анкету. Просто перенести анкету в онлайн не показалось нам оптимальным вариантом. Мы решили автоматизировать сбор информации по контрагентам, чтобы эти данные не нужно было вводить вручную ни нам, ни компаниям. Мы выяснили, что наши юристы и коммерческий департамент используют СПАРК для похожих задач, но просматривают данные вручную на сайте. Мы подумали: почему бы не автоматизировать и этот процесс?

На первый взгляд, рецепт интеграции выглядел просто:
  • берем CRM-систему на платформе 1С (да-да, именно на 1С),
  • добавляем к ней методы получения данных из шлюза обмена СПАРК для ИП и юридических лиц,
  • получаем данные из СПАРК и передаем их в предварительное хранилище данных контрагента.

На деле все оказалось намного запутаннее, ведь в то время (2014-2015) мы были первопроходцами в такой интеграции.

Тем не менее нам удалось реализовать интеграцию. Что нам это дало? После регистрации компании на нашем сайте запрос с ее номером ИНН падает в 1С, где сразу формируется заявка на подключение. Чтобы проверить надежность юрлица, по номеру ИНН через API отправляются запросы в СПАРК. По полученным данным создается карточка клиента в нашей CRM. Эти же данные передаются в личный кабинет клиента. В итоге значительная часть данных для договора заполняется автоматически.



Для работы с компаниями нам нужна и другая важная информация например, на какой счет перечислять им деньги. Для удобства в личном кабинете нужно ввести только БИК банка и номер расчетного счета. По БИК мы определяем остальные банковские реквизиты. А чтобы снизить вероятность ошибки в расчетном счете мы проверяем количество указанных цифр на соотствение номеру счета и подсказываем, если расчетный счет принадлежит другому типу организации (например, ООО вместо ИП).



Еще для подключения нам нужны паспортные данные руководителя компании, которая заключает с нами договор. Стоит отметить, что идентификация клиента по паспортным данным наша обязанность перед регулятором. И здесь тоже не обходится без автоматизации мы используем ПО от компании DBrain. C помощью технологий OCR и AI система за 2-3 секунды с высоким качеством распознает паспорт. Достаточно загрузить скан или фотографию главной страницы паспорта и данные заполнятся автоматически. Если изображение плохого качества, система подскажет об этом.



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

Обработка заявки внутренняя кухня

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

Чтобы подключение происходило максимально быстро, среди всех менеджеров, которые работают с клиентами Кассы, была выделена специальная группа. Она ведет клиентов в течение первых месяцев с момента подачи заявки. Новые заявки равномерным образом автоматически распределяются среди наших сотрудников, чтобы на обработку уходило не больше 24 часов.

Менеджер проверяет анкету и вложенные документы компании, а также ее сайт на соответствие требованиям. Они простые, но соблюдаются не всегда. Для подключения приема платежей нужно, чтобы сайт компании, конечно же, исправно работал, чтобы на нем были размещены товары и услуги, указаны реквизиты и контакты все так, как должно показываться покупателям.

Если что-то не так, менеджер сообщает об этом компании. Раньше мы делали это сами по почте. Сейчас этот процесс тоже автоматизирован: клиенту приходит смс со ссылкой на личный кабинет, где подробно описано, что нужно поправить.



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

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

Подписание договора и начало работы

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

Кроме этого можно воспользоваться технологичным и безбумажным способом подписи договора при помощи ЭЦП. Для этого мы используем платформу Диадок одну из самых популярных в России систем документооборота. Чтобы оформить договор с нами достаточно войти в Диадок по своему сертификату КЭП (подойдет любой для сдачи отчетности), подписать и отправить нам оферту. Наша СRM система по API сервиса Диадок проверяет новые поступившие договоры и загружает их в карточку клиента. Работа через систему электронного документооборота позволяет ускорить подключение, особенно для более крупных компаний, где передача бумажных документов между сотрудниками занимает время.

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



В момент запуска боевого магазина, мы регистрируем его одновременно в нескольких банках-эквайерах это позволяет увеличивать платежную конверсию. Так можно быть уверенными, что транзакция точно пройдет: если у одного банка какая-то заминка, то мы проведем платеж через другой. Параллельно с этим мы запускаем бординг дополнительных платежных методов например, кредитования, оплаты через Qiwi, WebMoney. Необходимая информация уходит компаниям-партнерам, которые в свою очередь проводят собственные проверки. Если вдруг приходят отказы, автоматически создаются задачи на исправление ошибок. Если все хорошо, нужные платежные методы сразу же включаются.

Как вы видите, мы стараемся делать процесс подключения простым и максимально быстрым. Автоматизация и слаженная работа команды Кассы позволяют бизнесу подключить прием платежей в интернете за 2-3 дня, а некоторые наши клиенты подключаются в течение одного дня. Если готовы так же, welcome.




В следующем тексте расскажем, что мы делаем, чтобы упростить техническую интеграцию Кассы с сайтами и сервисами.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru