Найти в Дзене
Блог тестировщика

Клиент-серверная архитектура для тестировщиков

Оглавление

Прошлая часть: Виды тестирования ПО

Всем привет. Давненько я не добавлял новых статей конечно, но и читают статьи не сказал бы что часто... Ладно, отставить уныние - к теме.

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

Клиент-серверную архитектуру традиционно представляют из трёх основных частей:

  1. Клиент
  2. Сервер
  3. База данных

Самое главное в объяснении этой темы, с чего мы и начнем – перестаньте ассоциировать слово «клиент» с человеком, который пользуется программным обеспечением. В контексте данной темы слово «клиент» означает совершенно другое.

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

База данных.

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

Простым языком база данных – это хранилище данных, которое устроено определенным образом, и сами данные, работа с которыми выполняется по определенным правилам.

Для того, чтобы у вас появилась ассоциация с чем-то знакомым – представьте себе excel документ, в котором мы будем вести простенькую «базу данных» своих друзей. В документе будет 3 листа:

  1. Фамилия, имя и отчество друзей на первом листе, с названием «ФИО»;
  2. Фамилия и точный адрес места жительства и дата, с которой место жительства актуально, ваших друзей на втором листе, с названием «Адреса»;
  3. Фамилия, телефон и e-mail и дата, с которой контакты актуальны, на третьем листе, с названием «Контакты»

Таким нехитрым образом мы создали аналог реляционной базы данных. В качестве базы данных у нас выступает excel документ в целом. В качестве «таблиц» базы данных у нас выступают листы: «ФИО», «Адреса» и «Контакты». А слово «реляционная» (от англ. relation - связь) означает, что между «таблицами» у нас есть отношения или зависимости, как в данном примере на всех листах есть «Фамилия», которая в теории может помочь объединить данные из одного листа с данными другого.

Для понимания дальнейшего объяснения клиент-серверного взаимодействия необходимо усвоить еще немного знаний про БД. На примере с excel документом мы рассмотрели наш «аналог» реляционной БД. Предлагаю убрать из этого примера excel – что у нас останется? У нас останутся данные, и они все еще будут структурированные и вы составляете их по определенным правилам. Т.е. технически наша «база данных» никуда не делась. В роли чего тогда у нас выступал excel? Excel в нашем примере выступал в роли системы управления базами данных.

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

Разбираемся дальше. Предположим, что у вас возникла потребность хранить не только данные о своих друзьях, но и данные о калорийности вашего лично питания. Как бы вы поступили? Хранили бы вы эти данные в том же excel документе, сваливая всё в одну кучу, или же создали бы новый документ? Я лично создал бы новый документ, т.к. данные логически никак не связаны. Т.е. в результате у меня появился бы новый excel документ структурированный исключительно под расчет калорий. В разрезе баз данных подход с таким разделением данных называется «Схема базы данных».

Схема базы данных – это один из основных объектов базы данных, который агрегирует под собой таблицы, которые сгруппированы на основании какого-либо признака.

Сервер.

Также смотрим определение сервера в интернете и получаем следующее. Сервер (англ. server, от лат. serve — служить, обслуживать) - выделенный или специализированный компьютер для выполнения сервисного программного обеспечения.

Попытаемся и это определение упростить, не вдаваясь в подробности облачных технологий и контейнеризации. Сервер – это «железка» с определенными характеристиками (считайте, что это «отдельный компьютер»), на который устанавливается определенное ПО, которое выполняет конкретные функции.

Самый важный момент в упрощенном определении — это часть «…на который устанавливается определенное ПО, которое выполняет конкретные функции». Из него мы понимаем, что:

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

Клиент.

На всякий случай я еще раз уточню то, что упомянул в начале статьи. Перестаньте ассоциировать слово «клиент» с человеком, который пользуется программным обеспечением. «Клиент» это не вы и не ваш коллега. «Клиент» - это не Иван Петрович, который будет являться вашим начальником.

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

Определение «клиента» упрощенным языком – это ПО, которое обращается к серверу, чтобы заставить сервер выполнить какую-либо работу.

Из этого определения нам важно понять следующее:

  1. В качестве клиента в клиент-серверной архитектуре выступает какое-то ПО.
  2. Вероятнее всего какое-то ПО, которое обращается к вашему серверу, знает «правила», по которым необходимо взаимодействовать с ПО на вашем сервере.
  3. Вероятнее всего, если какое-то ПО «клиент» обращается к вашему серверу, то оно хочет, чтобы ваш сервер выполнил какую-то полезную работу, т.е. бизнес-логику.
  4. Так как в качестве «клиента» выступает программное обеспечение, то не исключено, что в качестве «клиента» может выступать и сервер, с установленным на ним программным обеспечением, которое знает правила взаимодействия с вашим ПО.

В web-приложениях самым популярным примером клиента будет браузер (Google Chrome, Yandex browser и т.д.). Именно через браузер вы инициируете отправку данных на сервер или получение данных с сервера. Но для новичков в этой теме из-за такого примера останется непонятным 4 пункт выводов, где «в качестве клиента может выступать и другой сервер», поэтому предлагаю вам провести следующий мысленный эксперимент.

Сервер является «железкой», но и ваш компьютер является «железкой». На сервер, выступающий в роли клиента будет установлено какое-то ПО, но и на ваш компьютер установлено какое-то ПО (браузер). Это программное обеспечение, выступающее в роли «клиента», знает правила взаимодействия с целевым сервером, но и ваш браузер знает правила взаимодействия с целевым сервером. Получается, что теоретически ваш компьютер выступает в роли сервера (железки), на который установлено ПО (браузер), которое знает правила взаимодействия с целевым сервером, который должен выполнить какую-то полезную работу.

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

Клиент-серверное взаимодействие.

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

В самой простой ситуации взаимодействие будет выглядеть следующим образом:

  1. Клиент отправляет запрос на сервер.
  2. Сервер получает запрос.
  3. Сервер обрабатывает запрос в соответствии с бизнес-логикой.
  4. В процессе обработки запроса сервер запрашивает необходимые для исполнения бизнес-логики данные в БД.

В результате своей работы сервер, скорее всего, выполнит какие-то из следующих действий:

  1. Вернет на сторону клиента ответ с результатом своей работы.
  2. Обновит необходимые данные в БД.

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

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

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

-2

Что мы из нее видим:

  1. В качестве клиента может выступать не только лишь браузер.
  2. Между самим запросом к серверу и вызовом целевой функции системы есть какая-то «прослойка», которая определяет какую именно функцию системы необходимо вызвать.
  3. Функции системы могут вызывать другие функции внутри системы.
  4. Перед отправкой запроса в БД на стороне сервера происходит формирование этого запроса.
  5. После получения запроса от сервера на стороне БД он может выполняться в разных схемах.

Теперь перейдем к основной сути этой главы и ответим на вопрос «Зачем это нам знать, как тестировщикам?».

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

  1. Клиент может отправить запрос, который уйдет по некорректному адресу (например, ошибка в URL или IP адресе сервера).
  2. Клиент может отправить запрос, который будет отправлен по нужному адресу, но сервер будет недоступен по какой-либо причине (например, установка обновления).
  3. Клиент может отправить запрос, который будет отправлен по нужному адресу, но сервер запрос не поймет (например, данные отправлены в некорректном формате).
  4. При получении запроса от клиента сервер может вызвать неправильную функцию системы (например, разработчик ошибся с маппингом обработки запроса в зависимости от версии API).
  5. При получении запроса от клиента сервер может понять полученный запрос, но «отбраковать» его как не валидный на основании каких-то параметров запроса и прекратить обработку бизнес-логики (например, сервер ждет в теле запроса обязательный параметр X, но клиент отправил запрос без этого параметра).
  6. При обработке запроса одной функцией системы может быть вызвана другая функция системы, которая сочтет полученные от предыдущей функции данные не валидными (например, для функции системы №2 параметр Х не является обязательным, а для вызываемой при обработке функции №3 параметр Х обязателен).
  7. При формировании запроса к БД сервер может не понять куда запрос отправлять или отправит запрос в неправильную БД (например, не заданы конфигурационные настройки или в конфигурационных настройках содержится ошибка).
  8. При отправке запроса к БД запрос может не дойти до БД (например, недоступность сервера БД или устаревшие данные учетной записи, под которой производится работа с БД).
  9. При выполнении запроса на стороне БД он может не исполниться / исполниться некорректно (например, ошибка в самом запросе или запрос не был актуализирован под новую структуру таблицы после ее изменения).
  10. В результате исполнения запроса на стороне БД может быть сформирован ответ, который может некорректно обработан со стороны сервера (например, сервер может ожидать что запрос вернет только одну запись, а запрос возвращает список записей).
  11. В результате обработки результатов запроса на стороне сервера может произойти ошибка, которая прервет дальнейшее исполнение бизнес-логики (например, функция системы ожидала что параметр X в ответе от БД никогда не будет равен Z, а он оказался равен этому Z)
  12. В результате исполнения бизнес-логики на основании ответа от БД одна функция системы может обратиться к другой функции системы, которая ожидает какой-то обязательный параметр, который не был передан (аналог п.6, только в обратном порядке)
  13. Процесс формирования ответа клиенту может быть прерван, несмотря на исполнение бизнес-логики (например, нехватка оперативной памяти для формирования очень большого ответа).
  14. При получении ответа от сервера клиент может не справиться с обработкой этого ответа и соответственно не отобразить данные / отобразить некорректные данные (аналог п.3, только в обратном порядке).
  15. Ну и вишенка на торте – вся цепочка взаимодействия может отработать без ошибок, но ошибка будет в самой бизнес-логике (например, ваше приложение калькулятора на сервере успешно складывает 2+2, но в результате сложения возвращает ответ 5).

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

Основную мысль, я думаю, вы уловили – «Что-то, где-то может пойти не так». Теперь давайте разберемся с тем, что именно нам эти знания дают, на простом примере. Предположим, что вы через браузер (клиент) отправляете запрос на сервер и получаете ошибку. Что будет делать начинающий инженер-тестировщик в такой ситуации? Правильно – он начнет носиться с этой ошибкой, как с писаной торбой и дергать всех окружающих.

Это поведение в корне неправильно. Хороший инженер должен в первую очередь подумать! Необходимо поразмыслить на тему «А что собственно произошло?» и задать себе ряд вопросов:

  1. Является ли полученная ошибка ошибкой-бизнес логики или ошибкой взаимодействия компонентов системы?
  2. Действительно ли проверяемая задача (новый функционал) присутствует в сборке, которая установлена на тестовый стенд?
  3. Действительно ли я отправил запрос на нужный сервер? (Аналог «Точно ли я работаю сейчас на нужном тестовом стенде?»)
  4. Действительно ли сервер сейчас находится в работоспособном состоянии?
  5. Действительно ли клиент должен уметь отправлять такие данные, в результате которых произошла ошибка?
  6. Действительно ли отправленные данные являются корректными?
  7. Действительно ли проблема повторяется при повторном выполнении аналогичных действий?

Сейчас была проведена попытка локализация проблемы с точки зрения потенциальной проблемы на стороне клиента. Если проблема на клиенте пока что отсутствует – это всё еще не повод паниковать, бить в колокола и отвлекать разработчиков от просмотров увлекательных тик-ток видео. Это повод вспомнить про слово «логи». Как говорится – «было бы что вспоминать» …

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

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

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

  1. Работали на правильном стенде и на правильном / не правильном сервере.
  2. Сервер был в работоспособном/ неработоспособном состоянии.
  3. Отправляли корректные/не корректные данные, которые клиент должен уметь/не уметь отправлять на сервер.
  4. Присутствуют/отсутствуют ошибки в логах.

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

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

Что вы можете сделать в данной ситуации? Правильно, вы можете подготавливать тестовые данные изменяя данные напрямую в базе данных, минуя использование функции №1, тем самым ускоряя тестирование функции №2. Но это более прикладной пример к какой-то конкретной системе и её конкретной архитектуре, а автор категорически не рекомендует заниматься такими манипуляциями с данными на начальных этапах работы.

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

Следующая часть: Форматы сообщений часть 1. JSON и типы данных.

Поддержать или поблагодарить можете:

Лайком;

Комментарием;

Подпиской на канал;