Если вы уже знакомы с АЕМ-ом, смело пропускайте эту часть. Если же нет - вам стоит понять, что же такое этот АЕМ и почему с его тестированием возникают сложности.
AEM - content management system от Adobe (как выразилась коллега - WordPress на стероидах). Что это значит? Мы не создаем непосредственные веб страницы, а работаем над сложной админкой (AEM-author), которая в будущем позволит контенщикам (Editors) создавать эти страницы, используя набор определенных компонентов. Эти страницы будут видны (после publish действия) конечным юзерам (AEM-publish). Так что наша работа, собственно, и заключается в создании этих компонент.
Стоит сделать еще одну ремарку. Под компонентой, стоит понимать не только user interface, но и его возможную конфигурацию, которая может участвовать в логике на беке. Например, компонентой будет карточка нашего продукта, при нажатии на которую будет выполнен процесс букинга продукта и переход на страницу оплаты оного. При чем, в это же время, будет отправлена информацию в Google аналитику и возможно, что-то еще.
И так, что мы имели — AEM version 6.4.4.0. Процессы тестирования, установленные задолго до нашего привлечения. Вся ответственность была возложена на автотесты:
Screenshots tests — Поскольку AEM — content management system => Значит наши стили, да и вообще весь фронт очень важен, ведь это то с чем сталкивается конечный пользователь (возможно расскажу об этом в другой статье).
Web-component tests — самые обычные UI тесты с использованием Cypress в качестве основы. Только проверялись не страницы, а компоненты.
Web Performance tests — мониторинг производительности наших Web-страниц (с помощью Sitespeed)
Что мы строили — корпоративный сайт со всякими свистелками и перделками для отдела маркетинга для привлечения клиентов и увеличения продаж (с покупкой прям на сайте). Перед нами стояла задача разработать возможность едиторам создавать страницы с различными статьями. Создать компоненты, которые бы отображали созданные нами статьи в определенном порядке, плюс возможность применять фильтрацию, основываясь на подвязанных тегах.
Какая сложность возникает при автоматизации тестировании такого функционала? Зависит, где будет происходить фильтрация. В нашем случае всё происходило на стороне бека. Это осложняет тестирование, поскольку, создает невероятное количество комбинаций статей и соответствующих тегов. Они же, в свою очередь, должны где-то хранится.
С одной стороны, все очевидно — фильтр подразумевает наличие критериев и соответствующих сущностей. А если добавить сюда возможность создания новых критериев и новых сущностей? Задача резко усложняется. Добавляем итеративную разработку — изменения происходят не только в страницах, но и в логике их работы. Всё. Теперь мы не можем полагаться только на статический контент.
Представим, что мы таки оставляем статический контент. Тогда подобные изменения требуют от нас менять существующий контент для соответствия новой имплементации. При 5 страницах в этом нет ничего сложного, вот только становиться затратно по времени, если у вас 10+ страниц.
И так какой же выход?
А что если мы будем создавать страницы на лету?
Создали несколько страниц, пошли проверили нашу функциональность для данной комбинации, создали новые, проверили для них.
Long story short
К сожалению, АЕМ не предоставляет никакой информации о своем API. А если такая информация где-то и есть, я не смог ее найти. Да и тестирование АЕМ-а — минимально описанная головная боль (Тестируете АЕМ? — Делитесь в комментариях как).
Так что последующие выводы целиком и полностью — reverse engineering построенный на запросах отправленных фронтом (AEM-author) на бек.
В моем случае, и я уверен — в подавляющем большинстве случаев, - создание страниц в АЕМ-е сведется к следующим действиям:
Создание страницы с помощью темплейта (page template)
Добавление компонент на страницу
Конфигурация компонент
Паблиш страницы
И, конечно, мы будем:
Удалять страницы
Приступим...
Нам понадобиться dev-tools на вкладке Network.
1. Создание страницы с помощью темплейта
Открываем AEM-author
Sites
Переходим в нужную нам папку
Жмякаем Create
Выбираем нужный нам template
Заполняем интересующие нас поля
Запускаем запись Network запросов в dev-tools
Нажимаем Create
Первый же запрос `${aem-author-URL}/libs/wcm/core/content/sites/createpagewizard/_jcr_content
` будет содержать всю необходимую нам информацию.
Тут мы сталкиваемся с первой сложностью. Это POST запрос с FormData
. Т.е. запрос не содержит привычный многим тестировщикам body в виде JSON/XML
объекта. Вместо этого данные отправляются как Content-Type: application/x-www-form-urlencoded.
Во многих случаях любой JS объект можно легко перевести в данный формат (по-сути, это будет простая url encoded строка key=value
записанная через &
). Правда, тут нужно быть осторожными, поскольку данный формат не подразумевает, что ключ (key
) является уникальным. Т.е. ваша Form Data
может содержать tags=Tag1&tags=Tag2
(несколько тегов у страницы, в моем случае).
Самое важное на что стоит обратить внимание на этих скриншотах:
parentPath
— папка/страницв в AEM-e, в которой будет создана наша страницаtemplate
— путь к теплейту, который будет использован для создания страницы
… Ниже идут поля, применимые к моему проекту …
./jcr:title
— имя/тайтл моей страницы (обязательное поле на UI)./cq:tags
— тег, который я добавил странице (опциональное поле)./articleDate
,./articleTimeToRead
и:cq_csrf_token
Все остальные поля, опциональны и могут быть опущены в запросах.
Теперь, на счет авторизации. Как видно выше, запросы содержат token
. Я использовал cypress.io для написания автотестов, так что для авторизации API запросов просто указывал auth
объект с username
и password
, на ряду с методом, хедером и body. (For more info check Cypress: Request - arguments and http-authentication).
key takeaways: все запросы на создание новых страниц идут на `${aem-author-URL}/libs/wcm/core/content/sites/createpagewizard/_jcr_content
`, parentPath
и template
присутствуют для всех вариантов создания страниц с помощью темплейта.
2. Добавление компонент на страницу
Находим нужную нам страницу в AEM author
Жмякаем Edit
Выбираем нужную позицию (место) для компоненты
Жмякаем
+
Запускаем запись Network запросов в dev-tools
Находим и выбираем нужный нам компонент
Нужный нам запрос `${aem-author-URL}/content/${page-path}/jcr:content/par/${some-url-part}/par/
`.
Из важного тут:
./@CopyFrom
— темплейт (default) конфигурации компоненты (button в моем случае)./sling:resourceType
— название и путь к компоненте, которую я добавлялparentResourceType
— тут я не уверен, судя по всему место, куда добавить компоненту
3. Конфигурация компонент
На нужной нам странице выбираем необходимый компонент
Жмякаем “гаечный ключ”
Модифицируем конфигурацию данной компоненты
Запускаем запись Network запросов в dev-tools
Жмякаем кнопку Done
Наш запрос первый в списке `${aem-author-URL}/content/${page-path}/_jcr_content/par/${component-name}
`.
Из важного тут:
./sling:resourceType
— название и путь к компоненте, которую я добавлял:cq_csrf_token
— токен, значит нужно использовать auth
4. Паблиш страницы
Находим нужную нам страницу
Запускаем запись Network запросов в dev-tools
Жмякаем Quick Publish -> Publish
4.1.
В данном случае нам нужны первые 2 запроса.
4.1.1. Получение связанных ассетов
Запрос reference.json… — `${aem-author-URL}/libs/wcm/core/content/reference.json?${url-params}
` — получаем информацию о ассетах (assets), cвязаных с нашей страницей.
Из важного — тут используются query string params
. В path
указан путь к нашей странице.
В ответе нам придет массив ассетов. Нам понадобятся path`s
тех, чей published
статус false
.
4.1.2. Публикация страницы и ассетов
Запрос replicate — `${aem-author-URL}/bin/replicate
` — запрос на публикацию нашей страницы и связанных с ней сущностей.
Как вы видите, основное на что стоит обратить внимание:
cmd: Activate
— команда для паблиша страницыpath
— пути к нашей странице и к 2м ассетам
4.2.
Поскольку паблишинг страниц — асинхронное действие. Необходимо убедиться, что он состоялся.
Для этого нам понадобиться еще один запрос — GET `${aem-author-URL}/etc/replication/agents.author/publish_publish/jcr:content.queue.json
`. Он вернет нам массив страниц ожидающих паблишинга. Так что придётся сделать, как минимум еще один запрос, проверить есть ли необходимая нам страница в массиве body.queue
. Опять же искать по path
. Если страница все еще присутствует в очереди, придётся повторить проверку один или даже несколько раз (я выставил timeout в 1 секунду, но думаю можно и меньше).
5. Удаление страницы
Находим нужную нам страницу
Выбираем ее
Запускаем запись Network запросов в dev-tools
Жмякаем Delete-> Delete
Наш запрос `${aem-author-URL}/bin/wcmcommand
`.
Из важного тут:
cmd
— deletePagepath
— путь к страницеforce: false
— но я бы рекомендовал ставитьtrue
(дабы при удалении не происходило дополнительных проверок)checkChildren: true
— можно опустить
Итак, подведем итог…
Выше описанным способом можно создавать и конфигурировать страницы в АЕМ-е на лету. Основная проблема возникшая у меня — разобраться с последовательностью действий и структой отправляемых запросов.
В подавляющем большинстве все они содержат FormData
. И тут вам придётся выбрать способ, откуда брать эту информацию (использовать готовые моки или генерировать на лету). Я выбрал второй способ и с помощью билдеров создавал необходимые мне структуры FormData
(но это отдельная история).
Для тех кто дочитал аж сюда, несколько странностей вылезших в процессе создания страниц таким способом:
AEM заменяет пробелы на `
-
`. То есть если вы создали страницу с Тайтлом `Bla 1 2 3 4
` и не указали специфический путь к ней, тогда АЕМ сделает эту страницу доступной по пути…/bla-1-2-3-4
Пути страниц всегда будут в
lowerCase
(см пред. пример)При использовании `
_
` в тайтле начиная с (приблизительно с 18и символов) АЕМ удалит все последующие `_
`. Те если вы создали страницу с тайтломBlaBla123456789123456_blabla
, то доступ к ней будет не по…/blabla123456789123456_blabla
, а по…/blabla123456789123456blabla
Для сетапа некоторых добавленных компонент понадобиться их
id
. Его можно получить в ответе запроса на добавление этой компоненты на страницу.
qalalab
Зачем вы тестировали не свой софт? Похоже что вы тестировали API AEM зачем-то.
4rtemOv Автор
Мы не тестировали АЕМ, а разобрались с его API для более простого тестирования нашего приложения построенного на базе АЕМ. Видимо стоило написать Test Automation of AEM Based Application.
qalalab
Что из того что вы тестировали было кодом, написанным у вас в команде?
4rtemOv Автор
Фильтрация страниц, порядок их отображения и сортировка, по-сути все.
У меня встречный вопрос, был ли у вас опыт работы с АЕМом?
qalalab
Порядок отображения и сортировка суть одно и тоже так-то.
Нет, поэтому я и пытаюсь понять что вы там делали. Похоже на то что AEM это CMS типа вордпресса и вы кастомизировали какой-то из их плагинов для какого-то корпоративного сайта.
Статься если я правильно понял про подготовку тестовых данных. Если так, то реверс-инжиниринг здесь как из пушки по воробьям. То есть это конечно мощно и громко и пару воробьев вы зацепите. Вот только возможно есть более дешевые решения.
4rtemOv Автор
Тогда отвечу по-порядку.
На самом деле сортировка = порядок отображение, правда порядок != сортировка.И да, и нет. К сожалению я не работал с Wordpress, а то что я слышал — он намного проще АЕМа. Что такое АЕМ лучше почитать отдельно т.к. я не эксперт в нем. + посмотреть примеры сайтов построенный на основе АЕМа (вот несколько примеров, если верить интернету — fedex.com, samsung.com, support.apple.com, credit-agricole.fr)
Что я увидел в АЕМе — он предоставляет набор след. инструментов:
— компоненты из которых можно собрать страницу.
— возможность кастомизировать компоненты (стили и логику)
— возможность создавать свои компоненты, со своим стилями и логикой (например компоненту отображения продуктов, если все правильно настроено, залогиненого юзера, по нажатию на один из продуктов, переведет на подтверждение оплаты продукта) + если девы реализовали такую возможность, можно сконфигурировать выбранный компонент, например для какого-то продукта, и если у юзера недостаточный баланс, вместо уведомлении о недостаточном балансе, мы предложим ему оформить рассрочку (п.с. пример не из реальной жизни).
— еще кучу всего, с чем я не столкнулся.
Суть в том, что мы, как команда разработки, не создаем сами страницы. Мы реализуем админку, с помощью которой ЕДИТОР (сотрудник нашей компании) будет создавать конечные страницы. Таким образом мы несем ответственность не только за финальную страницу видимую конечному пользователю, но и за админку. Если говорить о маленьких компаниях, они врядли выберут АЕМ. А вот в больших, вы можете даже никогда не узнать, как именно ЕДИТОР соберет страницу.
Это приводит нас к тому, что хорошо бы производить тестирование связи — админка (так называемый АЕМ-author) + финальная страница (АЕМ-publish). Ведь где гарантия, что компонента с продуктами нормально отображается и работает со всеми типами продуктов.
Я много гуглил, как другие компании тестируют свои приложения построенные на базе АЕМа. К сожалению информации практически нет.
Документация АЕМа рекомендует использовать Selenium без какого-либо детального описания. Несколько решений, которые я нашел, подразумевали написание скриптов (использующих тот же Selenium), которые ходили бы в админку, меняли там, что-то, а потом проверяли изменения на конечной странице (АЕМ-publish).
Если вы понимаете в автоматизации — это не самый оптимальный подход, да и сильно бьет по времени прогона тестов. Так что мы попробовали подход, который я описал.
На счет «из пушки по воробьям», если говорить о обычных сайтах визитках — согласен на все 100%.
В моем случае, как я писал, мы реализовывали темплейты (шаблоны) страниц (точнее статей) и определенную логику автоматического отображения этих страниц на других страницах. При чем, в зависимости от разных критериев, эти статьи автоматически отображались или скрывались. Или же, в зависимости от критериев, статья могла располагаться в разных местах на страницах. Это все могли кастомизировать под свои нужды ЕДИТОРы в админке.
Учитывая все выше сказанное, у меня было несколько вариантов тестирования:
— создать кучу разных вариаций сетапа статей и страниц на которых они будут отображены. По грубым подсчетам это было бы около 50 страниц, для более менее сносного покрытия. — Минус в таком подходе — статические страницы не будут обладать атрибутами добавленными в последних итерациях. И если они важны, придется пересоздавать страницы с нуля, а это время затратно
— автоматизировать создание нужных мне статей — тут как я уже писал было 2 варианта: а) через юай, б) любым другим способом
Собственно в статье, я описал способ который мы нашли и реализовали. И честно говоря, если бы я встретил подобную информацию раньше — она бы очень упростила мне жизнь и сэкономила кучу часов.