Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Go
Code

Тестирование насыщенного данными кода с помощью Go, часть 2

by
Difficulty:IntermediateLength:MediumLanguages:
This post is part of a series called Testing Data-Intensive Code with Go.
Testing Data-Intensive Code With Go, Part 1
Testing Data-Intensive Code With Go, Part 3

Russian (Pусский) translation by Anna k.Ivanova (you can also view the original English article)

Обзор

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

Тестирование в хранилище данных в памяти

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

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

Преимущества хранилища данных в памяти:

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

В частности, если ваше хранилище данных - это реляционная БД, тогда SQLite - фантастический вариант. Просто помните, что есть различия между SQLite и другими популярными реляционными БД, такими как MySQL и PostgreSQL.

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

Использование SQLite

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

Вот структура InMemoryDataStore. Он также является частью пакета concrete_data_layer и импортирует сторонний пакет go-sqlite3, который реализует стандартный интерфейс Golang «database/sql».

Построение уровня данных в памяти

Функция конструктора NewInMemoryDataLayer() создает sqlite DB в памяти и возвращает указатель на InMemoryDataLayer.

Обратите внимание, что каждый раз, когда вы открываете новую БД ":memory:", вы начинаете с нуля. Если вы хотите сохранить постоянство при нескольких вызовах NewInMemoryDataLayer(), вы должны использовать file::memory:?cache=shared. Посмотрите эту ветку обсуждения GitHub для более подробной информации.

InMemoryDataLayer реализует интерфейс DataLayer и фактически хранит данные с правильными отношениями в своей базе данных sqlite. Чтобы сделать это, нам сначала нужно создать правильную схему, которая является в точности работой функции createSqliteSchema() в конструкторе. Он создает три таблицы данных - song, user и label - и две таблицы перекрестных ссылок, label_song и user_song.

Он добавляет некоторые ограничения, индексы и внешние ключи для связи таблиц друг с другом. Я не буду останавливаться на конкретных деталях. Суть в том, что весь DDL схемы объявляется как одна строка (состоящая из нескольких операторов DDL), которые затем выполняются с использованием метода db.Exec(), и, если что-то пойдет не так, возвращает ошибку.

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

Реализация уровня данных в памяти

Чтобы дать вам представление об уровне реализации уровня данных в памяти, вот несколько методов: AddSong() и GetSongsByUser().

Метод AddSong() выполняет большую работу. Он вставляет запись в таблицу song, а также в каждую из справочных таблиц: label_song и user_song. В любой точке, если какая-либо операция завершается неудачей, она просто возвращает ошибку. Я не использую транзакции, потому что она предназначена только для тестирования, и я не беспокоюсь о частичных данных в БД.

GetSongsByUser() использует join + sub-select из перекрестной ссылки user_song, чтобы вернуть песни для определенного пользователя. Он использует методы Query(), а затем сканирует каждую строку, чтобы заполнить структуру Song из объектной модели домена и вернуть фрагмент песни. Низкоуровневая реализация как реляционная БД надежно скрыта.

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

Выполнение тестов против SQLite

Теперь, когда у нас есть соответствующий уровень данных в памяти, давайте посмотрим на тесты. Я поместил эти тесты в отдельный пакет с именем sqlite_test и локально импортировал абстрактный слой данных (модель предметной области), конкретный слой данных (для создания слоя данных в памяти) и диспетчер песен (тестируемый код). , Я также готовлю две песни для тестов от сенсационного панамского исполнителя El Chombo!

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

Например, тестовый метод AddSong_Success() создает пользователя, добавляет песню с помощью метода AddSong() менеджера песен и проверяет, что при последующем вызове GetSongsByUser() возвращается добавленная песня. Затем он добавляет еще одну песню и проверяет снова.

Тестовый метод TestAddSong_Duplicate() похож, но вместо добавления новой песни во второй раз, он добавляет ту же песню, что приводит к ошибке дублирующейся песни:

Заключение

В этом руководстве мы реализовали слой данных в памяти на основе SQLite, заполнили базу данных SQLite в памяти тестовыми данными и использовали уровень данных в памяти для тестирования приложения.

В третьей части мы сосредоточимся на тестировании локального сложного слоя данных, который состоит из нескольких хранилищ данных (реляционная БД и кэш Redis). Оставайтесь на связи.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.