среда, 28 октября 2020 г.

Чек-лист для тестирования числового поля

При тестировании встречаются как интересные задачки с замудреной логикой, так и простые, вроде проверки простой строки или числового поля. Для простых полей можно один раз написать чек-лист проверок, а потом переиспользовать, лишь немного меняя под «своё» поле.

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

Ссылка на ХАБР

Итак, у нас есть некое поле, куда нужно вводить число. Например, поле «возраст» при регистрации:

При этом на сайте нельзя регистрироваться до 18 лет, есть запрещённый контент.

Какие проверки тут можно провести:

  1. Корректные значения
  2. Некорректные значения (за пределами валидных диапазонов или нелогичные: 200 лет, 88 секунд...)
  3. Граничные значения
  4. Пограничные значения
  5. Дробное число — формат (через запятую и через точку)
  6. Дробное число — округление (с кучей знаков после запятой)
  7. Ноль
  8. Один
  9. Пустое поле
  10. Очень большое число (поиск технологической границы)
  11. Отрицательное число
  12. Нечисловые и «не совсем числовые» значения


Корректные значения


Представьте, что у вас буквально 5 минут на проверку функционала. И вы успеваете провести только первые несколько тестов из чек-листа. А чек-лист у вас:

  • Пустое поле
  • 0
  • -1

В итоге эти проверки провели и считаете, что система работает нормально (ну ругается же!). А она всегда ругается, даже на корректное значение! Нехорошо… Поэтому запоминаем правило:

ВСЕГДА сначала позитив, потом негатив!

См также:

Позитивное и негативное тестирование — подробнее о том, с чего начинать


Для поля с возрастом какие у нас будут корректные значения? Все, что выше 18 лет:

  • 18
  • 25
  • 38
  • 45


Тут надо понимать, что мы выбираем какое-то ОДНО значение. Просто каждый раз разное, для избежания эффекта пестицида.

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

Например, тот же возраст:

  • если до 18 лет — показать в магазине все товары, кроме сигарет и алкоголя
  • если больше 18 лет — показать вообще все товары

Тогда мы понимаем, что у нас есть уже два «валидных» диапазона. Значит, нам нужно взять значение из каждого. Например, 16 и 26.



Или если у нас идет расчет страховки в зависимости от стажа вождения:

  • 0 — 1 год — 1000 руб
  • 1 — 3 года — 800 руб
  • 3-5 лет — 600 руб
  • 5-10 лет — 500 руб
  • 10+ лет — 300 руб

Получается 5 интервалов. И нам надо взять по одному значению из каждого. Например: 0.5, 2, 4, 6, 15.


Каждый раз берем разные значения, но в этом пункте смысл один — взять корректные значения из ТЗ.


Некорректные значения


Тут есть разные варианты. Что значит некорректное значение?

  • за пределами валидных диапазонов
  • корректное с точки зрения компьютера (число), но лишенное смысла (200 лет)

Вернемся к примеру с возрастом. Корректное значение — старше 18 лет. Значит, мы должны задать вопрос:

— А что будет, если мы возьмем значение из «неправильного» диапазона? Что, если мне меньше 18 лет? Ну, скажем, 10.


Потом внимательно смотрим на выбранный интервал:

— Хммммм, но ведь возраст не может быть меньше 0. То есть у нас есть логическая граница, разделяющая два разных класса эквивалентности:

  • Возможный физически, но невалидный по ТЗ (0 — 17 лет)
  • Невозможный физически (0 и менее)

Так что надо взять значение из каждого диапазона. Тогда получается 10 и «-5»:


Думаем дальше:

— Если у нас есть некая логическая граница снизу, должна быть и сверху. Какой максимально возможный возраст у регистрирующихся на нашем сайте? Скорее всего, это около 55-65 лет, потому что более старшее поколение не любит компьютеры. Но можно заложить и условные 100-110 лет долгожителей.

Получаем еще один интервал с неявной границей. Но в любом случае, значения 25 и 145 будут различаться — одно реалистичное, а другое нет. Значит, стоит его тоже попробовать!


А дальше снова эффект пестицида. Один раз берем 145, а другой — 6666666.

Тут мы можем столкнуться с тем, что в поле нельзя ввести больше 2-3 символов. Разработчик перестраховался «от дурака». Это не повод опускать руки и отказываться от своей проверки. Потому что скорее всего разработчик просто установил maxlength на поле, а он легко обходится!

См также:

Как снять maxlength со всех полей формы — несколько способов на заметку ツ



Граничные значения


Граничные значения отделяют один интервал от другого. Их обязательно надо тестировать!!! Потому что именно на границах чаще всего встречаются баги. Почему? Да потому что попадают в оба диапазона, или не попадают ни в один.

В нашем примере в ТЗ есть условие «регистрация только для лиц старше 18 лет». Это значит, что разработчик должен сделать в коде программы логику вида:

  • ЕСЛИ x > 18 ТО регистрируем
  • ЕСЛИ x <=18 ТО выдаем ошибку

Если разработчик забыл добавить значение 18 в один из диапазонов, это может и не привести к ошибке. Потому что в таких случаях обычно используется конструкция if else. И разработчик ставит последний «else» на всякий случай — то есть если ВДРУГ вводимое значение не попало ни в одно из условий выше:

  • if x > 18 …
  • elseif x < 18 …
  • else …

А вот если разработчик добавил значение 18 сразу в несколько диапазонов:

  • if x => 18 …
  • elseif x <= 18 …

То программа растеряется, что же ей выбрать? И вполне может упасть!

В общем, на границах баги встречаются чаще, чем внутри интервала. Поэтому обязательно исследуйте их! В нашем ТЗ есть четкая граница «больше 18 лет». Значит, тестируем число 18:


Если по ТЗ у нас есть несколько интервалов, проверяем каждую границу отдельно. Это произвольные границы — которые накладывает ТЗ.

Но границы бывают разных типов:

  • Произвольные
  • Логические
  • Технологические

Произвольные проверили? Едем дальше. Логические — это все о, что подчиняется логике (в минуте 60 секунд, человеку не может быть «минус один годик», и т.д.). Применим к нашему примеру.

Граница снизу:

— Логично, что возраст не может быть меньше нуля. Так что 0 — это граница. Тестируем!

Граница сверху:

— Нуууу… Врядли возраст будет больше 35 лет. Хотя что мешает бабушке зайти на сайт? Может быть, 65? 88?

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

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


См также:

Типы границ на примере стиральной машинки

Зачем тестировать граничные значения


Как найти границы на клиенте и сервере

Мнемоника БМВ для поиска граничных значений



Пограничные значения


Если у нас есть граница, то есть и пограничные значения. И их тоже надо проверять!

В примере с возрастом граница — 18. Значит, пограничные значения — 17 и 19.

Зачем проверять пограничные значения? Да затем, что разработчик мог ошибиться в коде и указать границу немного не там.

if x > 18 …

if x > 17 …

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

  • границу — 18. 18 > 17, так что все работает
  • недопустимое значение из диапазона слева — 10. 10 < 17, так что выдало ошибку.

Делаем вывод, что всё работает правильно, хотя это не так! Так что обязательно проверяем пограничные значение.

Но нужно ли тестировать пограничные значения в обеих сторон? С 17 разобрались, нужно. А 19? Допустим, разработчик опечатался в другую сторону:

if x > 18 …

if x > 19 …

Мы найдем этот баг проверкой граничного значения 18. А если на 18 работает и на числе внутри диапазона (например, 26) работает — значит, код написан верно. То есть чтобы в коде был баг, это как надо извратиться то, написать что-то типа:

if (x == 18 or x > 21) …

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

Но! Что, если разработчик описывает работу кода для нескольких интервалов? Тогда при опечатке диапазоны идут внахлест:

if x <= 19 (ОПЕЧАТКА) …

if (x > 18 and x < 55) …

Число 18 ошибку уже не поймает, ведь 18 <= 19, а во второй диапазон уже не попадает. Вот и будет ситуация, что на границе работает, внутри диапазона — работает, а на пограничном значении — нет.

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

Дело становится еще интереснее, если в поле можно ввести не только целое число, но и дробное. Что тогда будет пограничным значением? Стоит начать с одного знака после запятой. В нашем примере это 17.9 и 18.1:


Хорошо, допустим, проверили:

  • Целые границы — 17 и 19
  • Дробные границы — 17.9 и 18.1

Но если такие значения округляются нормально, значит ли это, что и другие тоже будут округляться хорошо? Что будет, если ввести значение 17.99999999999 (после запятой 11 девяток, а результатом округления является попадание на границу)?

Это разные классы эквивалентности, если мы говорим о дробях, которые будут округляться:

  • Один знак после запятой
  • Много знаков

И стоит проверить оба! Так что добавляем новые тесты: 17.99999999999 и 18.00000000001




Дробное число (формат)


Если система позволяет вводить дробные значения, то мы проверяем их ещё в пункте 1, при тестировании корректных значений. Просто разбиваем понятие «корректное число»:

  • Целое
  • Дробное

А пункт «дробное» разбиваем дальше. Ведь дробное число можно записать через:

  • точку — 6.9
  • запятую — 6,9

Если работает один из способов, это совсем не значит, что будет работать второй! У меня даже есть пример двух калькуляторов, которые работают с дробными числами по-разному — http://bugred.ru/calc/.

См также:

Не пишите в баге «Ввести 6,9»! — разбор багов в калькуляторе


Значит, нам нужно убедиться, что работают оба способа. По крайней мере если они должны работать. Если должен работать только один, потому что стандарты запрещают использовать другой — проверяем, что второй возвращает ошибку!

В случае с возрастом прикидываем, что будет позитивным дробным значением? Скорее всего, половинка — например, 20.5 лет:


Проверили? Работает? Тогда смотрим через запятую — 20,5:


То, что дробные в принципе работают — проверили. Хорошо.



Дробное число (округление)


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

Так что если у вас можно вводить нецелое число, обязательно попробуйте много девяток после запятой, приближенной к границе значение (мы это уже сделали пунктом выше):


При этом нет смысла проверять округление и через точку, и через запятую. Это будет лишнее дублирование тестов. Проверяем отдельно:

  • формат — через точку или запятую
  • округление — когда один или много знаков после запятой

См также:

В тестировании всегда начинаем с простого! — почему не надо смешивать проверки



Ноль


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

Потому, что это обычно граница. Она может быть явной (прописанной в ТЗ) или неявной (в ТЗ не написано, но и так понятно, что возраст отрицательным быть не может).

Если мы говорим именно про числовое поле, то пробуем ввести число 0. Хотя, конечно «ноль» в тестировании выходит за рамки простого числа.

См также:

Класс эквивалентности «Ноль-не ноль» — подробнее о тестировании нуля, и не только в числовых полях!



Один


Так как мы всегда проверяем ноль, то не забываем и о приграничном значении — единице.

Фактически это обычно «минимально возможное значение», если мы не говорим о дробных значениях:

— Логично, что если мы делаем заказ, то покупаем хотя бы 1 книжку, или 1 платьюшко, или 1 кг муки…

— Минимальный возраст — 1 день / месяц / год

— Минимальное количество времени — 1 секунда

— Минимальное количество трудового стажа — 1 день / месяц / год

— …

Так что единица не менее магическое число, чем ноль. Проверяем и её!



Пустое поле


Фактически это тоже тест на ноль. Только уже не на число «ноль», а на ноль в длине вводимой строки.

Ведь если мы вводим «0», это получается один символ.

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

Не забудьте, что ноль — это не только число. Даже в числовом поле у нас будет минимум два нуля — пустая строка и число «0». Может быть и больше нулей — не забывайте про ноль на выходе. Но в нашем примере с возрастом его нет.



Очень большое число


Для поиска технологической границы нужно ввести очень большое число. Например, 9999999999999999.


Мы пытаемся зайти так далеко, как только это возможно. Но не слишком упарываясь — это должен быть один тест, ну два.

Сначала можно оттолкнуться от значения integer — чаще всего для числового поля выбирают именно такой тип данных. Если получилось его превысить, просто проверяем 25 или 45 девяток в поле. Не упало? Ну и чудненько. Технологической границы нет, но мы хотя бы попытались ее найти.


См также:

Как сгенерить большую строку, инструменты — не обязательно делать это руками))

Технологическая граница в подсказках по ЮЛ — пример реального бага


Если поле допускает ввод отрицательных значений, то проверяем «много девяток» как со знаком плюс, так и со знаком минус, проводя два теста:

  • 99999999999999999999999
  • -99999999999999999999999

Напоминаю — если в поле нельзя ввести много символов, это не повод опускать руки и говорить «технологическую границу проверить нельзя!». Потому что если в поле нельзя вводить много символов — там скорее всего стоит maxlength на поле, который легко обходится. Сняли ограничение на клиенте и убедились, что на сервере защита от дурака тоже есть.


См также:

Как снять maxlength со всех полей формы

Как найти границы на клиенте и сервере



Отрицательное число


Когда у нас есть число, то всегда помним, что оно может быть:

  • положительное
  • отрицательное

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

  • выдавать ошибку «такого возраста / количества товара не существует, введите положительное число»;
  • отсекать знак минус и работать с отрицательным числом как с положительным.

Это помимо того, что отрицательное число может быть вполне нормальным для поля (например, если мы сохраняем доходы / расходы).

Что тестируем в этом разделе?

  • Что будет, если ввести отрицательное число, которое по модулю будет корректным: -26 в нашем примере
  • Попытка найти технологическую границу: -99999999999999999999999



Нечисловые и «не совсем числовые» значения


Если вы думаете, что для проверки нечислового значения достаточно вбить любую строку типа «привет», то вы ошибаетесь )))

Строки тоже бывают разные, и их можно разбить на:

  • множество строк, которые программа интерпретирует как числа;
  • множество строк, которые программа не может интерпретировать как числа.

Очень хорошо тесты для «не совсем числовых» значений рассмотрены в этой статье: Классы эквивалентности для строки, которая обозначает число.

Я не буду ее полностью переписывать, просто дополню список проверок для нашего примера. Что мы еще не смотрели:

  • Число, записанное строкой — «Пять»
  • Точно не число — «Тест»
  • Лидирующий ноль — «025»
  • Пробел перед числом — « 25»
  • Пробел внутри числа — «2 5»
  • Запись через е — «1.2e+2»
  • Шестнадцатеричное значение — «0xba»
  • Boolean — TRUE / FALSE (может интерпретироваться как 0 / 1)
  • Infinity (да, прям так текстом и пишем)
  • NaN

В нашем случае с корректным значением возраста от 18 лет пункт «пробел внутри числа» становится интереснее. Тут ведь зависит от логики работы системы. Тут есть разные варианты:

  • Ругаться, если введено несколько слов
  • Отсекать всё, что идет после первого пробела — «2 5» → «2»
  • Убирать пробел и делать вид, что его не было (воспринимать как опечатку в цифре) — «2 5» → «25»

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

  • до пробела меньше 18 лет — 2 5
  • до пробела больше 18 лет — 25 6
  • после пробела текста — 25 тест
  • до пробела текст — тест 25

При этом учтите — в интерфейсе мы просто вводим какое-то значение, не указывая тип данных. А вот если мы тестируем REST API и json-сообщение в нем, то обязательно стоит попробовать передать число строкой:

number: 3

number: “3”

Это разные значения. Если значение без кавычек — это число. Если в кавычках — строка, даже если выглядит как число. Может быть, разработчик сделает приведение типов в коде и «примет» второй вариант, а может, и нет. В любом случае, проверить стоит!



Соединяем все вместе: чек-лист для возраста


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

Напомню условие — у нас есть поле «возраст» при регистрации. При этом на сайте нельзя регистрироваться до 18 лет, запрещённый контент есть.

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

Проверка

Пример

Результат

Больше 18 лет

25

Успешная регистрация

Ровно 18 лет

18

Успешная регистрация

Меньше 18 лет

16

Ошибка: «Возраст должен быть 18 лет или выше»

Дробные значения



Через точку

21.5

Успешная регистрация

Через запятую

21,5

Успешная регистрация

Пограничные значения



Граница слева от 18

17

Ошибка: «Возраст должен  быть 18 лет или выше»

Граница слева, дробное число

17.999999999999999999

Ошибка: «Возраст должен быть 18 лет или выше»

Граница справа от 18*

18.00000000000000001

Успешная регистрация

Ноль / Один



Ноль

0

Ошибка: «Возраст должен быть 18 лет или выше»

Пустое поле


Успешная регистрация (или ошибка, что поле обязательное, тут надо у аналитика уточнять)

Единица

1

Ошибка: «Возраст должен быть 18 лет или выше»

Большие числа



Поиск технологической границы

999999999999999999999

Ошибка: «Некорректное значение возраста»

Поиск тех. границы меньше нуля

-999999999999999999999

Ошибка: «Некорректное значение возраста»

Нечисловые значения



Число, записанное как строка

Точно не число

Пять

Тест

Ошибка: «Введите число»

Лидирующий ноль

025

Успешная регистрация, возраст распознал как 25

Пробел перед числом

  25

Успешная регистрация, возраст распознал как 25

Пробел внутри числа

2 5

Ошибка: «Возраст должен быть 18 лет или выше» (распознает до пробела)

До пробела больше 18 лет

25 6

Успешная регистрация, возраст распознал как 25

После пробела текста 

25 тест

Успешная регистрация, возраст распознал как 25

До пробела текст

тест 25

Успешная регистрация, возраст распознал как 25

Запись через е

1.2e+2

Ошибка: «Введите число»

Шестнадцатеричное значение

0xba

Ошибка: «Введите число»

Boolean значение

TRUE

Ошибка: «Введите число»

Строка Infinity 

Infinity 

Ошибка: «Введите число»

Строка NaN

NaN

Ошибка: «Введите число»

* Если работает 18.000000000001, то проверять целое число 19 смысла нет. Если дробные не принимаются системой, тогда да, проверяем на 19


Конечно, проверки из блока «нецелые числа» не супер-важны. Иногда на них можно и нужно забить. Особенно если мы знаем, что система не должна ничего анализировать, убирать пробелы, выкидывать текст и прочая… Тогда достаточно взять одно значение из этого списка. А остальные использовать для эффекта пестицида, то есть каждый раз новый вариант «не числа».

Но ведь для того, чтобы отсекать лишнее, надо сначала научиться генерировать много идей! Вот в этом мы с вами сегодня и потренировались =)


См также:

Читлист для числового поля в Ситечке (нужно авторизоваться)

Где брать идеи для тестов (подборка полезных ссылок)



Попробуй сам


Напишите чек-лист проверок для поля «Стаж вождения». В зависимости от стажа идёт расчет страховки. У всех интервалов слева число «включительно», а справа — нет.

  • 0-3 года — 1000 руб
  • 3-6 лет — 700 руб
  • 6-10 лет — 500 руб
  • 10+ лет — 300 руб

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


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

4 комментария:

  1. "Логично, что возраст не может быть меньше нуля. Так что 0 — это граница. Тестируем!"
    я думаю, что 0 не может быть тоже, граница - 1

    ОтветитьУдалить
  2. А где же пример чисел прописью? "Один" или "Раз", "Пять" или "Пятёрка" или "Отлично".

    ОтветитьУдалить
    Ответы
    1. А, да-да, это же "не совсем число", добавила, правда на хабре оно лучше смотрится, в блоггере табличка очень не очень)

      Удалить