Перейти к содержимому

Выбор тестовой стратегии

Test Strategy Coverage JSON

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 10

#1 Гость_NavitaK_*

Гость_NavitaK_*
  • Guests

Отправлено 12 июля 2017 - 10:09

Всем привет!
 
Возникло разногласие с коллегами по поводу тестовой стратегии и оптимального покрытия тестами функционала приложения. Заказчик ждет предложение от нас.
 
Приложение трансформирует JSON объекты из одного формата (#1) в другой (#2). Для каждого поля есть подробная документация с правилами трансформации. Типов JSON объектов (поле "type") - более десятка, для каждого типа есть обязательные и опциональные поля.
 
К примеру, JSON из формата #1
 
{
"type": "Person",
"firstName": "Ivan",
"lastName": "Ivanov",
"age": 20,
"description": "Ivan Ivanov is ...",
"hobbies": null,
"education": [{"BSU"}, {"BSUIR"}]
}
 
будет трансформирован в
 
{
"type": "Person",
"name": "Ivan Ivanov",
"personAge": 20,
"description": "Description: Ivan Ivanov is ...",
"education": {"BSU, BSUIR"}
}
 
Поля, выделенные жирным - обязательные для формата #1.
 
Т. е., у некоторых полей может поменяться название ключа, значение, некоторые поля с пустыми значениями/null игнорируются, массив может преобразовываться в объект и наоборот.
 
Вопрос: как оптимально протестировать такие трансформации?
 
В планах это делать с помощью автоматизации.
 
Мое мнение: использовать JSON схемы для тестирования и структуры и значений полей. Для каждого типа объекта создать базовую схему, которая включает обязательные поля. Для каждого опционального поля создавать отдельную схему, которая наследуется от базовой и включает это поле. Таким образом, проверяется, что после трансформации получаем правильную структуру JSON объекта. Для тестирования значений полей можно использовать эти же схемы, в которых указывать какое значение ожидаем.
 
В итоге имеем следующие отдельные тесты на структуру и на значения полей:
 
- Позитивные тесты только с обязательными полями. Граничные значения, классы эквивалентности, спецсимволы и т. д.;
- Негативные тесты только с обязательными полями. К примеру, отсутствующее обязательное поле, недопустимые значения;
- Позитивные тесты на обязетельные поля + одно опциональное поле. Здесь тестируется только опциональное поле. Граничные значения, классы эквивалентности, спецсимволы и т. д.;
- Негативные тесты на опциональное поле. Недопустимые значения.
 
Плюсы: атомарные тесты. Если сломалась трансформация только для одного опционального поля, упадут только тесты, связанные с этим полем. Легко и быстро добавлять новые тесты. Если добавилось одно обязательно поле, достаточно добавить его в базовую схему и создать несколько отдельных тестовых методов для него. Проверяется структура объектов. Большое покрытие проверок значений полей (и позитивные и негативные).
 
Минусы: большое количество схем, которое необходимо хранить в проекте и большое количество тестов - на каждое поле несколько позитивных и негативных тестов.
 
 
Мнение коллег: достаточно создать несколько JSON объектов для каждого типа с максимальным количеством полей каждый, где комбинировать разные значения для значений этих полей. Тестировать только позитивные кейсы. Структуру не тестировать вообще.
 
Плюсы: небольшое количество тестовых методов и данных.
 
Минусы: если ломается трансформация одного поля, упадут все тесты, где используется тестовый JSON объект с этим полем. Из-за этого не узнаем, работает ли трансформация для других полей. Если не тестировать структуру, вполне возможно, что из-за бага могут появится лишние поля.
 
 
Какой подход вы бы выбрали? Если никакой из предложенных, поделитесь идеями, как бы вы организовали тестирование таких трансформаций?


#2 Spock

Spock

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 772 сообщений
  • ФИО:Роман

Отправлено 12 июля 2017 - 16:25

 

 

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

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

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

 

итого:

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

 

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


  • 0

#3 Гость_NavitaK_*

Гость_NavitaK_*
  • Guests

Отправлено 13 июля 2017 - 08:02

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

 

 

Может возникнуть ситуация из-за бага, когда проверяемое поле, например, "description", после трансформации отсутствует, но появились какие-то другие из необязательных полей, которых не должно быть. Проверка на отсутствие поля "description" пройдет, проверка на схему тоже пройдет, т. к. она одна на все тесты для данного типа объектов, и поля появились те, которые впринципе могут быть. Поэтому без отдельных схем (в которых указанно какие поля должны быть, а при наличии любых других - проверка на схему не должна пройти) на каждый тестовый случай мне пока сложно представить как это проверить. Ваше мнение?
 
Касательно поддержки большого количества схем, пока для меня не так одназначно, что их будет сложно поддерживать. Есть базовая схема, которая описывает обязательные поля. Все остальные схемы от нее наследуются и добавляют только по одному полю. Если происходят какие-то глобальные изменения с обязательными полями, все это меняется только в базовой схеме.
 
Разбиение тестов на отдельные классы для каждого поля - очень хорошая идея. Т. е. для каждого типа объектов отдельный пакет, а в нем отдельные классы для каждого поля для этого объекта.


#4 Spock

Spock

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 772 сообщений
  • ФИО:Роман

Отправлено 13 июля 2017 - 08:35

 

 

Может возникнуть ситуация из-за бага, когда проверяемое поле, например, "description", после трансформации отсутствует, но появились какие-то другие из необязательных полей, которых не должно быть. Проверка на отсутствие поля "description" пройдет, проверка на схему тоже пройдет, т. к. она одна на все тесты для данного типа объектов, и поля появились те, которые впринципе могут быть. Поэтому без отдельных схем (в которых указанно какие поля должны быть, а при наличии любых других - проверка на схему не должна пройти) на каждый тестовый случай мне пока сложно представить как это проверить. Ваше мнение?

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


  • 0

#5 checo

checo

    Опытный участник

  • Members
  • PipPipPipPip
  • 400 сообщений
  • Город:Н.Новгород

Отправлено 13 июля 2017 - 16:20

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

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

Здесь я частично соглашусь с мнением коллег. Давайте по порядку:

 

  1. Вы в тестовом проекте собираетесь реализовывать те же трансформации, что и в продукте? Не советую. Сложные тестовые оракулы ненадежны, в них тоже будут возникать баги. Тест должен проверять четко: что пришло, и правильно ли это, а не вычислять предполагаемый результат.
  2. Получаем, что нам нужен end-to-end набор JSON-ов: что на входе, и что на выходе. Проверяем на соответствие объект полностью, чтоб всё соответствовало и не было ничего лишнего. Тогда никакие опциональные поля проблему не создадут.
  3. В этом случае действительно отпадает необходимость проверять схемы.
  4. Чтобы не писать все JSON-ы руками, можно соорудить генератор тестовых данных. Только чтобы он в итоге записывал набор входов и выходов, который затем можно проверить глазами, и только после проверки запускать с этим набором тесты.
  5. Негативные кейсы, разумеется, нужны. Никто не застрахован от искажения данных при пересылке на трансформацию.

  • 0

#6 Spock

Spock

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 772 сообщений
  • ФИО:Роман

Отправлено 13 июля 2017 - 16:41

 

 

Получаем, что нам нужен end-to-end набор JSON-ов: что на входе, и что на выходе. Проверяем на соответствие объект полностью, чтоб всё соответствовало и не было ничего лишнего. Тогда никакие опциональные поля проблему не создадут.

а вот тут попали в ловушку. тогда придётся на многие тесты иметь по своему полному джейсону! тесты типа "нет обязательного поля1", "пустое обязательное поле1", "поле1 значение1", "поле1 значение2" будут каждый требовать по одному джейсону! и это 4 джейсона только на самые простенькие тесты для одного поля

 

и когда введут какое-то например новое обязательное поле - придётся менять ВСЕ существующие джейсоны! вау! добро пожаловать в ад поддержки авто-тестов!

 

и гвоздь в гроб: затем окажется что джейсоны на входе и выходе могут содержать также и динамические данные ;) например время и даты создания данных в системе, сгенерированные системой уникальные идентификаторы или ещё что ;) и тогда это конец


  • 0

#7 checo

checo

    Опытный участник

  • Members
  • PipPipPipPip
  • 400 сообщений
  • Город:Н.Новгород

Отправлено 14 июля 2017 - 06:17

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

#8 Spock

Spock

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 772 сообщений
  • ФИО:Роман

Отправлено 14 июля 2017 - 08:16

 

 

Ад поддержки будет в любом случае.

неправда, при грамотном коде в ад не попадаешь, смотрим код:

 

например есть 100 тестов и 100 джейсонов, и разрабы вводят новое обязательное поле, для которого надо добавить ещё 5 тестов. Что надо делать? Менять 100 джейсонов + добавлять 5 джейсонов! Вот он, ад!

 

а если код грамотный с одним базовым джейсоном и одной базовой схемой - тогда всего-то надо поменять базовый джейсон и схему, плюс добавить один класс с 5ю тестами! и никакого ада

 

 

 

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

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


  • 0

#9 checo

checo

    Опытный участник

  • Members
  • PipPipPipPip
  • 400 сообщений
  • Город:Н.Новгород

Отправлено 14 июля 2017 - 16:10


 

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

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

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

 

Мне просто одно неясно. Что предлагается сравнивать в итоге теста? Отдельно взятое поле + соответствие схеме? У меня бы любой тест-менеджер сразу такие тесты вернул на переделку: во-первых, должно проверяться всё, что приходит (о взаимном влиянии параметров в конкретном билде мы априори ничего не знаем), во-вторых, в отчете о тестировании должно быть указано точно: ожидаемый результат, фактический результат и результаты сравнения.

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


  • 0

#10 Spock

Spock

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 772 сообщений
  • ФИО:Роман

Отправлено 14 июля 2017 - 16:26

 

 

Мне просто одно неясно. Что предлагается сравнивать в итоге теста? Отдельно взятое поле + соответствие схеме?

да. для каждого поля - отдельный тестовый класс. и в каждом классе - несколько тестов. тесты конечно проверяют что вошло и что вышло

тогда после прогона будут результаты по каждому тесту и по каждому полю

если именно какое-то поле содержит ошибку - то завалятся тесты именно того поля. все остальные тесты будут скорее всего зелёными

 

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


  • 0

#11 Гость_NavitaK_*

Гость_NavitaK_*
  • Guests

Отправлено 16 июля 2017 - 17:18

 

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

Здесь я частично соглашусь с мнением коллег. Давайте по порядку:

 

  1. Вы в тестовом проекте собираетесь реализовывать те же трансформации, что и в продукте? Не советую. Сложные тестовые оракулы ненадежны, в них тоже будут возникать баги. Тест должен проверять четко: что пришло, и правильно ли это, а не вычислять предполагаемый результат.
  2. Получаем, что нам нужен end-to-end набор JSON-ов: что на входе, и что на выходе. Проверяем на соответствие объект полностью, чтоб всё соответствовало и не было ничего лишнего. Тогда никакие опциональные поля проблему не создадут.
  3. В этом случае действительно отпадает необходимость проверять схемы.
  4. Чтобы не писать все JSON-ы руками, можно соорудить генератор тестовых данных. Только чтобы он в итоге записывал набор входов и выходов, который затем можно проверить глазами, и только после проверки запускать с этим набором тесты.
  5. Негативные кейсы, разумеется, нужны. Никто не застрахован от искажения данных при пересылке на трансформацию.

 

1. Согласен. Добавлять те же трансформации означало бы делать то же, что делают разработчики в своем коде. Задача не в том, чтобы проверить кто "правильнее" написал трансформацию.

 

2 - 4. Для тестовых данных на входе (формат #1) для каждого типа объектов можно иметь только базовый JSON с обязательными полями и корректными значениями в них. В конкретном тесте добавлять к нему необходимое поле со значением/удалять поле/менять значение поля, т. е. обновить в соответствии с тем, что необходимо иметь на входе.

 

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

- Можно вручную\с помощью какого-то генератора создавать JSON объекты на каждый тест. Тогда у нас будут тысячи таких JSON объектов и только их поддержка будет занимать большое время.

 

- Можно создать один базовый ожидаемый JSON объект для каждого типа и в тесте по аналогии с JSON на входе добавлять поле со значением/менять значение/удалять поле. Тогда понадобится поддерживать только этот базовый JSON в случае глобальных изменений. Сравнивать два JSON объекта (ожидаемый и полученный в результате трансформации) должно быть легко в таком случае.

 

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

 

5. Согласен.

 

Что бы я еще все-таки добавил к отдельным тестам на каждое поле, которые предложил Spock, еще пару позитивных тестов, которые покрывают максимальное количество полей с коррекнтными значениями. Чтобы проверить, что трансформация сложных JSON объектов также работает. Но, без фанатизма, только пару тестов.





Темы с аналогичным тегами Test Strategy, Coverage, JSON

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных