Прошлая часть: Клиент-серверная архитектура для тестировщиков
Доброго дня читателям, продолжаем медленно, но уверенно постигать необходимые для тестировщика знания.
Следующая тема, в которой нам необходимо разобраться, прежде чем обсуждать HTTP запросы – это типы данных и форматы сообщений. Как всегда, у вас возникнет резонный вопрос «Зачем нам это знать?». А я, как всегда, перечислю вам причины:
- Для понимания «как клиент и сервер обмениваются запросами и ответами?» нужно сначала понять «из чего запросы и ответы в принципе состоят?».
- Для локализации проблем на стороне клиента необходимо понимать «что клиент вообще отправил и сделал ли он это в соответствии с требованиям?»
- Вы не всегда будете находиться в ситуации, когда у вас будет web-интерфейс для отправки запросов на сервер. Иногда вам придется эмулировать «клиент» внешней системы и составлять запрос вручную. А иногда вы будете находиться в ситуации, когда web-интерфейс еще не готов, но взаимодействие с сервером уже можно тестировать – и снова вам придется составлять запрос вручную.
- У вас должна быть банальная техническая грамотность, чтобы взаимодействовать с остальными членами команды на одном языке.
Что мы подразумеваем под запросом или ответом? Это какое-то сообщение, которое точно может понять сервер при взаимодействии клиент–сервер или же которое точно поймет клиент при взаимодействии сервер-клиент. В любом из вариантов взаимодействий сообщение имеет какой-то конкретный состав обязательных параметров. Один из этих параметров – тело запроса.
Представьте, что вам необходимо зарегистрировать внутреннюю электронную почту на новом рабочем месте. Но никакого привычного web-интерфейса нет, поэтому все новые сотрудники записывают на листочки данные и передают их системному администратору (да, увы, но вы попали в ООО «Рога и Копыта»). Системный администратор требует от вас следующие данные, записанные на листочке:
- E-mail.
- Фамилия.
- Имя.
- Отчество.
- Возраст.
- Пароль.
- Дата трудоустройства.
Недолго думая, вы записываете их и передаете системному администратору в следующем формате:
- E-mail: pupalupa@bestcompany.ru
- Фамилия: Перейро
- Имя: Себастьян
- Отчество: Иванович
- Возраст: 45
- Пароль: BestTraderOfDarkWood_2000
- 06.10.2024
Теперь масштабируем эту ситуацию на всю компанию ООО «Рога и Копыта». Вы записали на листочек информацию в одном формате. Кто-то другой ее запишет как «Петров Петр Петрович, 25 лет, трудоустроен 01.01.2022, mymail@mail.com / qwerty12345» и системный администратор это тоже поймет. И таких вариаций может быть целая куча.
А вот программное обеспечение не системный администратор и ему нужно «скармливать» на вход только то, что оно умеет понимать. Причем желательно, чтобы это было сделано единообразно, чтобы при найме новых IT специалистов вам не приходилось их учить исключительно под изобретения вашей компании. Рассмотрим один из наиболее популярные вариантов, что можно программному обеспечению «скормить».
JSON
Первый из вариантов это JSON.
JSON (от английского JavaScript Object Notation) – текстовый формат обмена данными. Вернемся к форме регистрации. Через web-интерфейс клиент отправит примерно следующие данные:
Технически это уже корректное сообщение в формате JSON, но в реальной работе все названия полей будут на английском, поэтому привыкаем к этому сразу:
В целом правила оформления сообщения в формате JSON достаточно просты:
- Сообщение начинается с открывающейся скобки «{»
- Сообщение заканчивается на закрывающуюся скобку «}»
- Внутри сообщения данные передаются в формате «ключ : значение», где под ключом мы понимаем название поля.
- Внутри сообщения после каждого параметра идет запятая, за исключением последнего параметра.
- «Значение» поля может иметь сложный формат (как на примере у поля «user»).
- Не все поля могут быть обязательными.
- Некоторые поля могут быть «вычисляемыми», т.е. заполняются на основании значений других полей.
Также хочу отметить, что всё содержимое этого сообщение называется «JSON-объект».
Предлагаю визуализировать, что сделает web-форма регистрации почты, когда будет формировать этот JSON-объект.
Клиентская часть вашего приложения возьмет каждое из заполненных полей и сформирует на основе этих полей JSON-объект для отправки на сторону сервера.
Аналогично это сработает и в обратную сторону для отображения ответа об успешности выполненного действия. Вы успешно зарегистрировались, сервер обработал запрос и ответил клиенту сообщением, которое клиент представил вам, как пользователю, в удобном для понимания виде:
Типы данных в JSON
Теперь обсудим тему заполнения полей в JSON объектах, а именно допустимые типы данных. Делать мы это будем, разумеется, на примере, чтобы у вас складывалась причинно-следственная связь. Представьте, что вы разработали web-приложение, чтобы фиксировать информацию о своих друзьях. Web-форма имеет следующие поля для заполнения:
- Фамилия – обязательное поле.
- Имя – обязательное поле.
- Отчество – необязательное поле.
- Состоит в браке – обязательное поле.
- Дата рождения – обязательное поле.
- Список общих друзей – необязательное поле.
Также есть вычисляемое поле «количество общих друзей» с достаточно простым правилом расчета – нужно посчитать количество друзей в списке общих друзей.
Вот как выглядит веб-страница, которую мы заполняем и данные, которые отправляются в результате запроса
Теперь разберем сами типы данных.
Тип данных «строка» или «string».
Поля lastName / firstName / birthDay / friendFirstName / friendLastName имеют тип данных «string». Значение полей с типом string начинаются с открытия кавычки и заканчиваются закрытием кавычки. При этом строковые значения могут принимать любые символы юникода и используются в основном для передачи текстовых данных. Особое внимание хочу обратить на дату birthDay – она тоже передана как строка. Не стоит обольщаться обманчивой простотой передачи времени как «строки» - подробнее этот нюанс мы разберем в конце данной главы.
Тип данных «логическое значение» или «boolean».
Поле isMaried имеет тип данных «boolean». Значения полей с типом boolean не окружаются кавычками. Этот тип данных имеет всего лишь 2 допустимых значения – true (т.е. утверждение истинно) или false (т.е. утверждение ложно). Используется этот тип данных для передачи каких-либо признаков объектов, на которые можно однозначно сказать «да, так и есть» или «нет, это не так», например:
1) «Состоит в браке = да» - true
2) «Имеет высшее образование = нет» - false.
3) «Отработала ли задача успешно = да» - true.
4) «Прошел собеседование на тестера с перового раза = нет» - false.
Тип данных «нул» или «null».
Поле surname имеет тип данных «null». Значения полей с типом null не окружаются кавычками. Null это специальное значение, используемое для обозначения отсутствия данных, т.е. тип данных null означает, что значение поля преднамеренно было оставлено пустым.
Важное уточнение: Заполнение полей “surname”: null и “surname”: «» (пустая строка) – это не одно и тоже! Null – это null, это «ничего вообще», а пустая строка – это переданное значение, просто пустое.
Тип данных «число» или «number»
Поле countCommonFriends имеет тип данных number. Значения полей с типом number также не окружаются кавычками. Number используется для передачи значений полей, которые всегда будут иметь числовое значение. Причем не важно целое это будет число или дробное (с плавающей точкой) – тип number подходит для обоих случаев.
Важное уточнение №1:Заполнение полей “countCommonFriends”: 2 и “countCommonFriends”: ”2” (строка со значением 2) – это не одно и тоже!
Важное уточнение №2: Поле countCommonFriendsв нашем примере является «вычисляемым», на основании количества элементов в массиве commonFriendsList, т.е. в явном виде вы нигде не вводите на форме «Количество общих друзей = 2», а форма вычисляет это значение за вас.
Тип данных «массив» или «array».
Поле commonFriendList имеет тип данных «array». Значения полей с типом данных array начинаются с квадратной скобки и заканчиваются на квадратную скобку. Массив — это упорядоченный набор каких-либо значений. Преимущественно вы будете сталкиваться с массивами, имеющими набор значений с одинаковыми типами данных, как в примере массив JSON-объектов. Ну или массив примитивных типов данных, в стиле “что нравится Маше”: [«кушать», «гулять», «смотреть тик-токи про ноготочки»]. Реже вы будете встречать плоды творений разработчиков, где в массив попытались «впихнуть невпихуемое» и общего между элементами массива как у гитары и лося – т.е. примерно ничего.
Важное уточнение: Вспоминайте прочитанное выше про null – значения массивов “commonFriendList”: null и “commonFriendList”: [] это не одно и тоже.
Тип данных «объект» или «object».
В нашем примере есть 3 объекта с типом «object». JSON-объект это набор пар «ключ-значение» или по-простому «название поля – значение поля», которые разделены запятыми. JSON объекты начинаются с фигурной скобки и на фигурную скобку заканчиваются. Первый объект – это весь «родительский» JSON-объект с набором полей lastName/ firstName/ surname/ countCommonFriends / isMarried/ birthDay/ commonFriendsList. Оставшиеся два JSON-объекта — это элементы массива commonFriendsListс полями friendFirstName и friendLastName.
В основном JSON-объекты используются для того, чтобы агрегировать под собой какую-то сложную структуру взаимосвязанных данных. Поэтому большая часть данных, связанных какой-то общей логикой будет объединяться в JSON-объекты в реальной работе.
Важное уточнение: значение поля тоже может принимать какой-то JSON-объект, т.е. совершенно не обязательно что вы будете видеть JSON-объекты только как «родительские» объекты или элементы массива. Например, запись следующего вида вполне имеет место быть: “userLastPizzaOrder”: {//какие-то атрибуты последнего заказа пиццы}
Особенность передачи даты и времени
Так как подходы с обработкой даты / даты и времени плюс-минус одинаковые – мы возьмем наиболее сложный пример даты и времени. Представьте, что вам необходимо передать дату и время «9 октября 2024 года 21:17:52 в часовом поясе Европа/Москва». Попробуйте выбрать правильный вариант из следующих:
1) 09.10.2024T18:17:52Z
2) 09.10.2024T18:17:52+0000
3) 09/10/2024T18:17:52+0000
4) 09-10-2024T18:17:52+0000
5) 09-10-2024T21:17:52+0300
6) 09/10/2024T21:17:52 Europe/Moscow
7) 09-10-2024T21:17:52 GMT+3
8) 09.10.2024T21:17:52.000000
Предлагаю вам все-таки проверить свою интуицию, прежде чем читать следующий абзац.
...
...
...
...
Ну а теперь ответ - каждый из этих вариантов передает указанную дату и время, и каждый из этих вариантов сервер теоретически сможет преобразовать в нужную дату и время. Нюанс заключается в том, что использовать можно только один из перечисленных "форматов" даты и времени - тот, который поймет сервер. То есть, если ваше ПО на сервере ожидает получать дату и время в формате "09-10-2024T21:17:52 GMT+3", то формат даты и времени "09.10.2024T21:17:52.000000" сервер будет считать некорректным, даже несмотря на то, что это одно и то же время с точки зрения человека.
Если у вас сейчас возникает вопрос «а как же тогда правильно передавать дату и время?» — это очень хорошо. «Как правильно передавать дату» должно быть указано в требованиях и за этим надо внимательно следить. С датами и часовыми поясами ошибиться на столько просто, что даже опытного тестировщика эта тема иногда заставляет на пальцах вычислять время в стиле «Я в Самаре, в Москве минус 1 час от моего времени, а UTC это минус 3 часа от Московского, а теперь это время надо преобразовать в текущее время в Хабаровске и это будет …».
Второй резонный вопрос, который может возникнуть - «А зачем столько разных форматов придумали?». Автор, к сожалению, не знает ответа на этот вопрос и сам иногда испытывает ту же боль, которую когда-то испытаете вы.
Самое важное, чтобы вы уловили основную мысль – будьте внимательны и аккуратны, когда работаете датой или датой и временем, потому что простота этих «строк» действительно обманчива.
Что такое JSON-schema или «Как автоматически проверять формат JSON сообщения».
Разработчиками не были бы разработчиками, если бы не изобрели что-то, что проверяет предыдущее их изобретение. Одним из таких изобретений является JSON-schema или, по-русски, JSON схема.
Для начинающего тестировщика эта тема не является обязательной, но это интересная тема. А так как мы уже начали обсуждать JSON – было бы неправильно не поделиться информацией про JSON-схемы.
JSON-схема – это документ в формате JSON, который описывает структуру ожидаемых JSON-сообщений. Кроме того, в JSON схеме может быть указано какие поля являются обязательными, а также накладывать ограничения на поля (например, указать разрешенные типы данных для поля, указать минимальные/максимальные значения, указать формат строки и так далее).
Вернемся к формату сообщения для приложения по ведению списка друзей, которое обсуждали выше и составим JSON-схему для этого сообщения. Напомню, как выглядело сообщение:
А вот так выглядела бы JSON-схема относительно этого объекта:
И объяснение этой JSON-схемы для вас:
Какую информацию даст JSON-схема, если ее прочитать? Она явно укажет какой тип данных разрешено использовать для конкретного поля, про дополнительные ограничения (как например, с полем commonFriendsList), а также укажет какие поля являются обязательными (т.е. без каких полей запрос не будет считаться валидным).
Про все допустимые ограничения, которые можно наложить на поля я рассказывать не буду – в этом нет особого смысла. Главное, чтобы вы не испытывали непреодолимый страх, когда вам дадут в руки JSON-схему и смогли её прочитать.
Зачем вообще JSON-схемы применяют и какие в них плюсы и минусы? Давайте начнем с того, что применение JSON-схемы при проверке сообщений является опциональным. То есть высока вероятность того, что вы с ними не столкнетесь.
Как это работает. Предположим, что вы отправляете сообщение с полным и валидным набором полей – сервер сверяет полученное сообщение с JSON-схемой и пропускает сообщение к дальнейшей обработке. Далее вы пытаетесь отправить сообщение без обязательного поля “lastName” – сервер сверяет полученное сообщение с JSON-схемой и возвращает ошибку, что поле “lastName” является обязательным по JSON-схеме, но фактически оно не передано. Аналогично с остальными типами проверок.
Основные плюсы использования JSON-схемы:
- На основании JSON-схемы сервер может отбраковывать не валидные сообщения «на входе», то есть до начала исполнения бизнес-логики.
- При интеграционном взаимодействии со сторонними системами JSON-схема может выступать в роли «контракта». Если вы используете предоставленную коллегами JSON схему для валидации входящих сообщений от коллег, то в случае несоответствия входящего сообщения JSON-схеме проблема будет явно на стороне коллег (что даст вам индульгенцию за указание пальцем в сторону коллег).
Но рука об руку с этими плюсами идут и минусы:
- Любое изменение формата сообщения должно будет приводить к изменению JSON-схемы.
- Если JSON-схема используется при интеграционном взаимодействии – необходимо будет дополнительно синхронизироваться с коллегами по добавлению / изменению обязательных полей.
- При наличии хорошей серверной валидации (аналогичных проверок на серверной стороне) JSON-схема практически перестанет приносить плюсы, зато минусы никуда не пропадут.
Следующая часть: Форматы сообщений часть 2. XML и типы данных.
Поддержать или поблагодарить можете:
Лайком;
Комментарием;
Подпиской на канал;