×Закрыть

Автоматическая генерация тестов: подходы и инструменты

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

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

Случайная генерация

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

Свойства:

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

Сферы применения:

  1. Фаззинг.
  2. Небольшие программы или части программ, где количество элементов внутри классов эквивалентности не слишком велико.

Генерация на основании алгоритмов поиска

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

Свойства:

  1. Можно «застрять» в локальном оптимуме, если минимально необходимый порог слишком низок (тем не менее задача будет решена).
  2. Как следствие п. 1, очень часто возможно несколько разных решений и нет уверенности, что то, которое было сгенерировано, наилучшее.
  3. Важно понимать, что, как и при случайной генерации, такие тесты не принимают во внимание бизнес-логику, техники тест-дизайна и прочее, так что качество тестирования и, следовательно, найденные баги также относительно случайны.

Сферы применения:

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

Генетические алгоритмы

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

Свойства:

  1. Можно получить несколько решений, удовлетворяющих целевой функции.
  2. Можно иметь несколько целевых функций, поскольку сначала создаются наборы и только потом измеряется целевой показатель. Этот подход позволяет взять столько целевых функций, сколько нужно, и рассматривать их все одновременно.

Сферы применения:

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

Генерация тестовых последовательностей

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

Свойства:

  1. На вход таким алгоритмам подается формальная модель, то есть параметры и значения, которые они принимают, условия, которые накладываются на комбинации таких значений, параметры комбинаций (например, каждый с каждым, только пары, только тройки и т. д.). Следовательно, результат проектирования полностью предсказуем и обладает строго тем набором свойств, которые заложены в модели.
  2. В дополнение к правилам генерации и заданным зависимостям между значениями параметров можно устанавливать веса значений. Таким образом, можно регулировать частоту встречаемости значений в тестах: там, где в комбинациях все равно, какое значение выбрать, вес задает вероятность такого выбора.
  3. Кроме весов значений, можно задавать и приоритизацию, то есть порядок, в котором тесты появятся в наборе. Плохая новость в том, что такая возможность есть не во всех инструментах.

Сферы применения:

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

Инструменты

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

Генерация юнит-тестов на Java с Randoop (случайная генерация)

Как это работает:

  1. Создать файл myclasses.txt со списком имен классов, которые подлежат тестированию.
  2. Вызвать Randoop: java -classpath $(RANDOOP_JAR) randoop.main.Main gentests --classlist=myclasses.txt --time-limit=60
  3. Скомпилировать и запустить тесты, которые сгенерировал Randoop. Получится два набора: ErrorTest и RegressionTest. Тесты из первого набора не пройдут (предположительно, баги, требуется дополнительное исследование). Тесты из второго набора пройдут успешно.

Что примерно получится:

	@Test
	public void test001() throws Throwable {

		if (debug) { System.out.format("%n%s%n","RegressionTest0.test001"); }

		MerArbiter.TestMyMerArbiterSym testMyMerArbiterSym0 = new MerArbiter.TestMyMerArbiterSym();
		testMyMerArbiterSym0.run2((int)'a', true, (int)'a', false, (int)'4', (int)(byte)100, true, (int)(short)100, false, (int)' ', 10, false, 100, false, (-1), (int)' ', false, (int)(short)(-1), true, 0, true, true, (int)'a', (int)(short)1);
		testMyMerArbiterSym0.run2((int)(byte)100, false, 10, true, (int)'4', (int)' ', false, 1, false, 100, 100, false, (int)(byte)(-1), false, (int)'#', (int)(byte)1, false, 0, true, (int)(byte)100, true, true, (int)(short)10, (int)(short)10);
		testMyMerArbiterSym0.run2((int)(short)100, false, 0, false, (int)(byte)1, (int)(byte)1, true, (int)(byte)0, true, (int)(byte)100, (int)'a', true, (int)' ', false, (int)(byte)1, (int)(byte)100, false, (int)'4', false, (int)' ', true, false, (int)(short)100, (int)'4');

	}

Генерация юнит-тестов на Java с EvoSuite (алгоритмы поиска)

Как это работает:

  1. Определиться с классом, который будет тестироваться, путем к этому классу и его зависимостям.
  2. Определиться с целевой функцией.
  3. Вызвать EvoSuite, например так (задан целевой параметр): $EVOSUITE -class <ClassName> -projectCP <ClassPath> -criterion branch

Что примерно получится:

public class MyMerArbiterSymTest {
	MyMerArbiterSym o = new MyMerArbiterSym();
	@Test
	public void test0() {
		o.run2(3215, false, 3215, false, -633, -1952, false, 3215, false, 0, -2384, false, 3215, false, 3215, -90, false, -90, false, 599, false, true, 0, -1952);
	}
	@Test
	public void test1() {
		o.run2(0, true, 0, true, -1, 562, false, 0, false, -1, 0, false, 2844, true, 1354, 0, false, 1, true, 0, false, false, 0, -2561);
	}
	@Test
	public void test2() {
		o.run2(562, true, -1, false, -1448, -3029, false, 11, false, 0, 0, false, 0, false, 0, -3029, false, 0, false, -1218, false, false, 562, -1);
	}
	@Test
	public void test3() {
		o.run2(0, false, 0, false, 0, 2, false, 0, false, 0, -1, false, 11, false, 0, -3029, false, 0, false, 0, false, false, 1, -3884);
	}

}

Генерация данных с PICT (комбинаторное тестирование)

Как это работает:

1. Задать модель и ее ограничения, например так:

BROWSER: IE, Firefox, Chrome, Opera
LANG: en, ru, ua
OS: win, linux, android
{BROWSER, LANG, OS} @ 1
IF [OS] = "linux" THEN [BROWSER] <> "IE";

2. Запустить PICT, передав модель на вход, перенаправить вывод в файл при необходимости: pict.exe model.txt > results.csv

Что примерно получится:

Для модели выше, скажем, получится файл (или вывод в консоль) вот с такими данными:

IE	       	ua	win
Firefox	  	en	win
Opera		ua	linux
Chrome		ru	android

Что с этим потом делать — на усмотрение автора модели или других причастных.

Полезные ссылки

Выводы

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

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

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

Надеюсь, что-то из вышеперечисленного пригодится и вам.

LinkedIn

26 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

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

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

Ну не совсем, вот пример.
Frontend: old, new
OS: Win, Linux
BROWSER: Firefox, Chrome, Opera
LANG: en, ru, az, jp, es, ua, us
Имеем
Combinations: 65
Generated tests:22
А если сделать —
BROWSER: Firefox, Chrome, Opera
LANG: en, ru, az, jp, es, ua, us
Frontend: old, new
OS: Win, Linux
то получаем
Combinations: 65
Generated tests: 21
В итоге где-то потерялся 1 кейс.

О. Круто и внезапно. Спасибо за наблюдение! Интересно, почему в первый раз 22 теста, достаточно, конечно же, 21 для этой модели.

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

Следуя вашей логике первым должен быть параметр —

LANG

Совершенно верно, но на таком не большом наборе данных особо не видно этой разницы.

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

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

1122
1212
2121
1212
2121
1212
2121
1212
2121
1212

Примерно так? Каждый тест — отдельная колонка, каждая строка — соответствующий параметр, 1 и 2 — бинарные значения (просто так, вместо нолика )).
Тогда, 1 первого параметра встречается с 1 второго параметра в тесте номер один, а с 2 второго параметра — в тесте номер два. Аналогично, 1 первого параметра встречается с 1 третьего параметра в тесте номер два, с 2 — в тесте номер один. И т.п.

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

Возможно, неверно поняла задачу? Речь не о pairwise, а о полном комбинаторном покрытии? В этом случае, конечно же, 4 теста будет недостаточно, полный перебор можно получить за 2^10 (1024) теста.

Вот пример, сейчас смог родить только на 5 столбцов
OS: Win, Linux
Browser: Chrome, Opera
Lang: ru, us
Vers: demo, full
Screen: hd, 4k
По такой формуле должно получится 4 теста, но тот же PICT выдает 7.

Именно этому и удивлялась выше, в случае, где достаточно 21 теста. ) Полагаю, алгоритм PICT избыточен.

Формулу же легко проверить, это и попыталась сделать примером с 10 параметрами выше.

Есть множество программ, которые, казалось бы, работают по одному и тому же алгоритму — www.pairwise.org/tools.asp — даже в NASA сделали такую штуку, но она недоступна.

Алгоритм, вроде бы, один, но результаты их работы разные. В низу той страницы есть таблица «Comparison of Efficiency».

Принято считать это нормой ввиду самой природы pairwise (она обманчивая, не стоит ей доверять).

Алгоритм, безусловно, не один. Pairwise — не алгоритм, а то, что хочется получить, результат. Способов его достижения, т.е. алгоритмов, которые позволяют получить такой результат, более одного. Потому и сравнивают их эффективность. Вот, например, pairwise algorithm challenge.

Патамушта pairwise основан на комбинаторике, но делает еë так, что лучше бы не делал.

Каждому тестировщику с какого-то момента мечтается о волшебной палке, которая сама всë учтëт и сама предложит минимально необходимое количество тестов (типа, великая магия). Только это палка-дубинка, которую надо уметь контролировать, иначе сам от неë и огребëшь неприятностей.

Особенно страдают от этого тимлиды, которым кажется, что так можно ускориться.

Но в чëм смысл тестировать Chrome ru android и НЕ тестировать Chrome en win?

Комбинаторику надо делать полностью, честно и без упрощений. Decision table рассмотрите как простейшую основу и доменное тестирование отложите как дальнюю цель. Пэирвайз используйте как опцию при реально огромном количестве вариантов.

Pairwise и decision table, как по мне, имеют достаточно разную сферу применения (поиск зависимостей, которых быть не должно, и подтверждение зависимостей, которые должны иметь место).

Логика тестирования именно пар основана на предположении, что ошибка возникает на стыке двух, но не более, значений. Почему так — достаточно просто объяснить, даже тимлид справится. ;) Ошибки в целом распределены нормально, т.е. согласно т.н. bell curve (тут, например есть картинка). Картинку можно интепретировать так: пик кривой (если по оси 0Х принять модуль количества одновременно заданных значений, вызывающих ошибку, а по оси 0Y — количество собственно ошибок) приходится, конечно, на один параметр (т.е. ошибки, которые находятся классами эквивалентности и граничными значениями — техниками, рассматривающими каждый параметр по отдельности). Следовательно, на стыке двух значений возникает предположительно меньше ошибок, на стыке трех — еще меньше, и т.п. Если на график добавить кривую роста количества тестов при усилении комбинаторной модели (т.е. учитывать не пары, а тройки, четверки и т.п.), легко увидеть, что целесообразность делать тесты резко падает: слишком большая разница будет между количеством тестов (экспоненциальный рост) и количеством предположительно найденных ошибок. Что и делает тестирование на больше чем парах параметров неоправданно дорогостоящим (по времени и ресурсам, даже с учетом автоматизации как создания, так и прохождения тестов). Насколько я знакома с комбинаторикой, именно эта идея и лежит в основе pariwise. Ну, и еще одно простое соображение: для ошибок на стыке нескольких значений нужно написать больше кода, чем для конкретного одного значения. )

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

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

Но в чëм смысл тестировать Chrome ru android и НЕ тестировать Chrome en win?

, а также перед теми, для кого все вышенаписанное — откровения кэпа (сдерживать графоманию иногда трудно ;)).

Это не телега, а здравое рассуждение. А посмотрите на эту телегу с другой стороны.

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

Это всего лишь предположение. И в целом оно логично, но всё равно ошибочно, бо она очень сильно упрощает набор данных, которые после неё предлагается использовать для тестирования.

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

Pairwise — искусство нарочитого, излишнего упрощения, обмана и хитрости. Он хорош, когда предлагается учесть и воспроизвести слишком, излишне много вариантов, и при этом вероятность факапа будет в пределах допустимого, не очень высока. Pairwise основывается на допущении, а допущение — это всего лишь допущение.

Если дойдёте до тестирования чего-то объёмного, например, Google Calendar, то там найдёте стыки двух и более значений, и pairwise, в силу своей природной ограниченности, будет (незаметно) вредить.

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

Для части комбинаций будет разумно применить дальнейший расклад по схеме pairwise (то самое «более слабое покрытие, только для ситуаций, значимых с точки зрения бизнес-логики»; но учтите, что упрощение почти всегда опасно). Для другой части можно обойтись просмотром граничных значений. Другая (неопределенная) часть комбинаций может быть отутюжена Decision table.

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

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

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

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

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

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

для decision tables нужны известные (из требований или доменных знаний, другого тест-дизайна, пр.) зависимости между параметрами, в этом, собственно, и состоит их идея.

С этого их идея только начинается. Decision table тем и хороша, что показывает комбинации, о которых никто не подумал, а после анализа позволяет найти комбинации и зависимости, которые ранее никому не придумались, а они могут случиться — бо вот они, наглядно. Я привык к sourceforge.net/projects/sdtapi другие ценят sourceforge.net/...​projects/decisiontablecr или делают самописные поделки.

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

Что же касается полной комбинаторики, т.е. всех возможных комбинаций, и стоимости такого тестирования

Нет.

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

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

Полная комбинаторика — это абстрактное вычисление, такое же, простое как вычисление сложности выполнения любого алгоритма. Например, чтобы вычислить факториал числа каких-либо возможных вариантов, нужно не больше минуты (или самописными шняжками, или на сайтах «в помощь школьнику»).

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

В том-то и проблема, что посчитать количество вариантов, конечно же, дело нехитрое, как и получить их все. Только очень затратное по времени, о чем и писала выше. Неважно, какие именно инструменты тут применять. Вы действительно будете сначала применять полный перебор, а потом вычёркивать лишнее при тестировании корректности пароля? Количество всех возможных вариантов при ограничении в 7-15 символов и, скажем 100 разрешенных — 100^7 + 100^8 + ... + 100^15 — очень большое число. Легко автоматизировать полный перебор, вот только выполнение кода займет безумное количество времени.

На счёт полных таблиц принятия решений. Конечно, если воспринимать технику — лишь как способ получения всех возможных комбинаций параметров, так можно делать. Имхо, правда, комбинаторные техники и инструменты подходят для этого лучше: тот же PICT, как и многие другие, позволяет строить тесты на основании любых комбинаций параметров, не только каждый с каждым. Можно все со всеми сделать, задав это требование в модели. Но все же, как мне кажется, decision table — в первую очередь про правила взаимодействия параметров и результаты, а не про полный перебор. Техника весьма полезна для систем принятия решений, рекомендательных систем. Тысячи параметров с десятками значений, десятки тысяч правил, сотни результатов. Не обошлась бы без нее на таком размере модели, в классическом контексте — правил. А сложность полного перебора — слишком, чудовищно велика здесь.

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

И немного запуталась: Вы предлагаете в конце получить-таки все комбинации и потом их анализировать (

Следующим будет анализ полученных данных, а затем шаг № 3 — их упорядочивание.

), а в середине, что

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

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

Прошу прощения за формулировку с алгоритмами работы, эта информация, конечно, может быть недоступна. Если так, то возможно, точное описание результатов работы? Как в случае с PICT, как мы уже знаем благодаря замечательно внимательным людям выше, результат работы вполне известен и задаётся моделью, но не все алгоритмы одинаково оптимальны.

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

Почему это очень затратно? 90 минут (иногда 180) сосредоточенной работы экономят месяцы. Раскладывать все пересечения данных в таблицу — дело быстрое, бо таблица сама формируется теми же программами, которые я указал. И это происходит быстро.

Легко автоматизировать полный перебор

Повторюсь о том, что нет нужды делать полный перебор. Об этом даже думать незачем.

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

Отдельно рассказывать про техники — это часы занятий. Пропустим.

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

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

Ну, давайте рассмотрим

вычёркивать лишнее при тестировании корректности пароля

ШАГ № 1

Узнаём количество всех возможных вариантов. Изначально мы это число не знаем, поэтому просто узнаём его, не стараясь заранее уменьшить количество вариантов.

При ограничении в диапазоне 7-15 символов и, скажем 100 разрешенных... Да, 100^7 + 100^8 + ... + 100^15 — очень большое число. Но нам его надо только знать, а не превращать в тест-кейсы.

Когда узнали — ничего не упущено? (наверняка упущено) К аналитикам сходить не надо? (надо) Дополнительные соображения и вопросы не появились? (должны появиться) Например, каких именно 100 разрешенных символов? Какой алфавит содержит столько? Какой/какие алфавит был применен?

ШАГ № 2

Если оперируем алфавитами, и понимаем, что их содержимое конечное, то применяем разделение значений на эквивалентные:
* общие для всех алфавитов (латинские) символы,
* символы, присущие отдельным алфавитам (поэтому важно знать, какие именно используются).

Уносим эту часть данных, генерируем таблицу заново — она уже будет меньше.

Продолжаем с выявлением эквивалентных значений в массиве данных, который остался. Что-то ещё можно свести к общему знаменателю? «123456789»? Или "!"№;%:?*()«? Если да, то массив данных снова уменьшается.

Тест-кейсов на этом этапе всё ещё нет. Их будем собирать из того, что останется после этого груминга, бо тест-кейсы — это ситуации, а не набор данных.

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

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

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

Рассмотрите пример www.slideshare.net/...​pbsqagroup/domain-4780447

Повторять это всё, пока не останется вариантов. Делать это быстро через много итераций.

ШАГ № 3

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

При необходимости не возбраняется вернуться ко второму шагу, а то и к первому (трясти аналитиков и программистов).

Уже после всего этого можно придумывать тест-кейсы, и то — если будет нужно.

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

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

Тоже. ) Реализаций довольно много разных. Под разные ЯП в том числе.

Подписаться на комментарии