понедельник, 10 февраля 2014 г.

Позитивное и негативное тестирование

На своих курсах по обучению начинающих тестировщиков я предлагаю им написать позитивные и негативные тесты на:
  1. Функцию вычисления корня в калькуляторе.
  2. Работу с корзиной (добавление / удаление / редактирование) в интернет-магазине.
И вот что я заметила - с позитивным тестированием все хорошо, ребята придумывают разные виды тестов (потому что задача назвать несколько, а не перечислить все-все-все, поэтому, даже работаю в команде, можно не повторяться). А вот с негативным у многих возникают проблемы, просят пояснить, потому что "ничего кроме ввода символов в числовое значение числа товаров в корзине да вычисления корня из отрицательного числа на ум не приходит".


Поэтому я решила написать поясняющую статью.

Позитивное тестирование

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

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

Не работает основной сценарий, зачем дальше вообще что-то проверять? Так магазин и теряет пользователей.

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


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

Посмотрим на примере:

1. Функция вычисления корня в калькуляторе.

Основной тест-кейс - проверить, что корень из корректного числа действительно вычисляется.
Разбить можно на следующие классы эквивалентности:
  • После вычисления корня остается целое число (корень из 4 = 2)
  • После вычисления корня остается дробное число (корень из 3)
Хм, а что, если дробное число у нас будет не только после вычисления корня, но и до? Можем же мы взять корень из числа 2,2 ? Позитивный тест? Позитивный!

Также можно разделить числа на небольшие, до 100, например. Потом взять интервал от 100 до размера int и третий будет еще больше, сколько влезает в наш калькулятор. 3 класса эквивалентности, проверяем по одному значению из интервала.

Не забудем и про граничные значения, проверим 0. Позитивный тест? А как же! Корень из 0 равен 0, а не ошибке!

Из основного, пожалуй, все.

2. Работа с корзиной в интернет-магазине.

О, вот где простор для воображения!

Пользователь столько разных сценариев может выполнить!! Но в первую очередь возьмем основные, самые короткие. Потому что если уж они не работают, то длинные цепочки (добавил - отредактировал - удалил - снова добавил - итд) проверять точно не стоит. Итак:
  • Добавление товара в корзину.
  • Добавление второго товара в корзину (того же самого, счетчик должен увеличиться).
  • Добавление второго товара другого типа.
  • Редактирование числа товаров, находящихся в корзине, увеличение на несколько, уменьшение.
  • Удаление товара из корзины.
  • Ваш вариант
Придумать тестов здесь можно очень много. Особенно, если начать проверять цепочки, например, добавил товар в корзину - передумал, удалил - ой, нет, все-таки надо, снова добавил.

Думаете, будет работать, если работает по отдельности? Не-е-е-ет, ребята, вы же тестировщики! Никогда не верьте программам "на слово"! Придумали сценарий? Проверьте!

Тем более что такой сценарий вполне может упасть, мы же уже удалили данный товар из корзины, так? Так вот система вполне может не дать нам его снова добавить. Типа "ты уже отказался, але, я все помню!". Корректно такое поведение? Нет!

А сам сценарий позитивный? Да! Хотя уже и с нотками извращения, надо признать Smile :)


Негативное тестирование


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

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

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

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

Поэтому мы проводим негативное тестирование. Что такое негативное тестирование? Это ввод заведомо некорректных данных. Вводим и смотрим, как ведет себя программа, понятные ли сообщения об ошибке выдает...

Но как составлять такие тесты? Посмотрим на примерах:

1. Функция вычисления корня в калькуляторе.

Первое, что приходит на ум - а что будет, если вычислить корень из отрицательного числа? 
Но что еще тут можно придумать?
  • Корень из пустоты - вспоминаем о граничных значениях, мы не можем ввести строку отрицательной длины, но вот граничное значение (строка нулевой длины) можем!
  • Корень из символов - надо проверить, что скажет система, если ввести или вкопипастить туда что-то символьное. Причем символы мы делим на русские, английские и спецсимволы!
  • Корень из значения "четыре" - также символы можно поделить на абракадабру и "типа число". Кстати, если уж говорить о таких "типа числах"...
  • Попробуем ввести строку, которая обозначает число. И взять корень уже из нее.
Видите? На самом деле тестов не так уж и мало! Отдельно хочется высказать на тему "ввести очень большое число, максимально большое". Попробовать можно, почему нет? Но это более негативно скажется на сценарии возведения в квадрат, чем на вычислении корня. 

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

2. Работа с корзиной в интернет-магазине.

Тут, опять же, можно найти числовое поле и поиграться с ним, как мы это только что проделали с калькулятором. Поле "количество товара" тут очень подойдет! Но, с другой стороны, скучно же, такие разные приложения и одни и те же тесты?

Кстати, не хочу сказать, что их не надо проводить. Надо, еще как надо! Просто я в статье повторяться уже не буду. Хочется здесь упомянуть о важной особенности всяких web-приложений и главном негативном тесте, который обычно все и ломает.

Запомните всего 2 слова - разные вкладки!

Чувствуете? Давайте поясню. Негативные тест на удаление товара из корзины - попытаться удалить уже удаленный товар. И тут начинаются варианты, как это может быть сделано:
  • Открыли корзину в 2 вкладках браузера. Сначала нажали "удалить" в одной, потом во второй. То есть попытка удалить то, что ты сам уже удалил из своей же корзины.
  • Попытка удалить удаленный админом товар. В 1 вкладке под админом удаляем товар вообще, в принципе, а в другой пытаемся его под пользователем удалить из корзины.
И кстати, также можно попробовать добавить удаленный админом товар или отредактировать его количество. А еще админ может не удалить товар, а перенести его в другую категорию. И вот тут сломаться ничего не должно!!! Если в случае удаления мы должны увидеть корректное сообщение об ошибке, то в случае переноса просто продолжить работу.

А что будет, если админ не передвинул товар в иерархии магазина (в другую категорию переместил, исходно неверно был размещен товар), а просто поправил, отредактировал описание? Тоже ничего сломаться не должно!

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

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

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

Хочется привести еще один пример из реальной практики. Тоже web-интерфейс, в котором можно нажать "создать" и добавить новую карточку. Пользователь добавляет, а у него через раз формочка падает. Почему?

Стали выяснять. И поняли. Пользователю надо было завести сразу много карточек (миграция), вот он и нажимал на "создать" несколько раз, зажав Ctrl (открыть в новой вкладке). И потом уже ходил по вкладкам и создавал.

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

Так что, ребята, дерзайте! Открывайте разные вкладки и вперед, ищите информацию о том, как же, ну как же ведет себя именно ваша программа при противоречивых воздействиях на нее? Wink ;)

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

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

    1. Тестирование на позитивных значениях.
    Обычно используются пользовательские сценарии с корректными значениями.
    Проверяем работоспособность заявленного функционала.

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

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

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

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

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

    ОтветитьУдалить
    Ответы
    1. Да, Андрей, спасибо :)
      Согласна, что негативные тесты можно разделить на простые ошибки и эксепшены. Это хороший подход :)

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

      Удалить
    3. Кстати, чем отличается тест-дизайнер от проектировщика тестов?
      И часто ли приходят люди, проработавшие несколько лет, но не знающие разделения на негативное и позитивное тестирование и претендующие на позиции тест-дизайнера?

      Удалить
    4. Паша, имеется ввиду, что этих тестов должен быть негативный результат и тогда, если тест свалится - это будет pass в сценарии или чеклисте.

      Удалить
  2. Интересно прочитать про такую статистику (что придумывают позитивные, а с негативными испытывают проблемы), потому как у меня на основе собеседований (задачка про треугольник) накоплена совершенно другая статистика: предложат несколько позитивных тестов, а дальше начинают всячески извращаться с негативными кейсами, толком, увы, не проверив работу приложения с нормальными данными.
    Почему задание формулируется как "придумать несколько", а не все возможные? Видел очень много кандидатов, которые как раз придумав несколько базовых позитивных кейсов останавливаются на этом и говорят, что дальше тестировать не надо (в смысле, позитивные сценарии) и начинают придумывать негативные во всей их красе, т.к. считают, что негативных сценариев обычно больше, чем позитивных.
    Такие кандидаты действуют ровно как описано в статье:
    Например, для квадратного корня, проверим 3, 4, 2,2, 0 и что-нибудь большое.
    хорошо, когда могут хотя бы объяснить, что это будет за большое число (например, Int и Int+1), дальше этого вообще мало кто идет. Хотя на самом деле "третий будет еще больше, сколько влезает в наш калькулятор" - это явно не один тест, потому что для выяснения, какова же реальная граница, придется провести несколько (десятков) тестов.
    Опять же, что такое "влезает в наш калькулятор"? сколько я вижу? Или сколько символов он реально даст ввести? Или самое большое число, которое он реально может обработать (вспоминаем про экспоненциальную запись числа, которая сильно короче обычной, но при этом позволяет несколькими символами записать очень большие числа)?
    но ведь базовые позитивные тесты на этом не заканчиваются, а только начинаются...
    Квадратный корень из Pi или e юкдет верно вычислен?
    Приоритет выполнения операции вычисления корня в формуле?
    корень из 1? (есть всего два числа, корень из которых равен самому себе и стоит проверить оба)
    А корень из 4,00000000000000001 или sqrt(10^2) или 1e+2?
    Как на счет чисел, меньших единицы? Будет ли в данном случае функция работать верно? И начиная с какого дробной числа она начнет возвращать единицу в качестве результата?

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

    ОтветитьУдалить
    Ответы
    1. Да, ты прав, пожалуй, стоит просить дать полный комплект, а не несколько тестов :)
      Хотя все, что ты тут нафлудил, мы проходим, просто немного дальше, на уроке по классам эквивалентности :) А первые лекции вводные, так, просто чтобы понять, какие виды тестирования вообще существуют ))

      Удалить
    2. Chip, мне нравится ваш текст.

      Удалить
  3. Очень интересное и классное замечание про Тестирование "Разных вкладок" (для web-приложений). У самого есть куча жизненных примеров, когда на клиенте (браузер) все корректно обрабатывается при работе на одной вкладке, но если производить что-то заведомо произведенное уже на предыдущей вкладке, приложение отвечало банальным - 500 Internal error.

    ОтветитьУдалить
    Ответы
    1. Спасибо :)
      Сама сколько раз налетала, надо нести опыт в массы!

      Удалить
    2. Не важно сколько 500х ошибок выдает приложение. Протестировать все - задача не реальная. Важно только - есть ли вероятность того, что пользователь, выполняя один из возможных пользовательских сценариев, наткнется на эту ошибку. Задача проектирования тестов лежит не сколько в плоскости "как можно сломать приложение", а в том хорошо ли мы знаем возможное обращение пользователя с нашей системой.

      Удалить
    3. Разумеется, в первую очередь — позитивные сценарии!
      Но, если пользователей в системе много, вариаций сценариев становится сильно больше и то, что ранее было "вряд ли наткнется", становится важным

      Удалить
    4. Этот комментарий был удален автором.

      Удалить
  4. Оль, сделал выжимку поста со ссылкой на тебя.

    http://lazy-tester.blogspot.ru/2014/02/back-to-basics.html

    ОтветитьУдалить
    Ответы
    1. Да, я видела :)
      Выжимка тоже хорошая))

      Удалить
  5. спасибо за полезную статью, только начинаю изучать информацию о тестировании)
    еще заметила в статье ошибку в слове "корень" http://prntscr.com/d4shx0

    ОтветитьУдалить
    Ответы
    1. Рада, что вам понравилось, спасибо за отзыв! И за опечатку спасибо, поправила)

      Удалить
  6. Здравствуйте, Ольга.
    Если негативный сценарий и его ожидаемые результаты описаны в документации, можно-ли считать его негативным? Ведь, получается, что мы проверяем работу приложения в соответствии с заявленными требованиями.

    ОтветитьУдалить
    Ответы
    1. Конечно, можно, он от этого не станет позитивнее :)
      Но надо помнить, что позитив и негатив - это не безусловные понятия
      Александр позитивнее Саши
      Саша позитивнее Sashi
      Sasha позитивнее Цодылваодцшугк
      понимаете? Это шкала
      от наиболее позитивного к наименее
      имя — это не дифференциал третьей степени
      вы и сами можете проранжировать эту шкалу, потому что живете в России и понимаете, какие имена позитивные
      и прекрасно понимаете, что пустое имя в России — это редкость

      Удалить
    2. Т.е. "позитивность" или "негативность" тест-кейса определяется соответствию целям приложения, бизнес-логике и каким-то общепринятым стандартам в целом?
      Если кейс соответствует ворк-флоу, ради которого приложение и создаётся, то проверка - позитивная. Если кейс рассматривает ситуацию, когда мы сворачиваем в сторону с этого ворк-флоу - проверка негативная. Верно?

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

      Удалить
    4. То есть если у вас в требованиях четко указано "возвращать 404 ошибку, если страница не найдена", то введение несуществующей страницы — это позитивный кейс?

      Удалить
    5. Введение несуществующей страницы - кейс негативный, т.к. "Если кейс рассматривает ситуацию, когда мы сворачиваем в сторону с этого ворк-флоу - проверка негативная."

      Удалить
    6. Похоже на правду :)
      Но четкого "это всегда позитив, это всегда негатив" нету. Имя на латинице на сайте будет норм кейсом, а в игрушке — страшным багом. Потому что там любят ввести имя, подменив один символ с русского на англ и потом разводя людей на бабки (в случае игр — дорогой шмот)

      Поэтому да, отталкиваемся от того, для чего система вообще создана)

      Удалить