А / Б тестирование часто рассматривают как научный способ, используемый для подтверждения и принятия каких-либо проектных решений. Иногда его называют сплит-тестирование. А / Б тестирование достаточно простой процесс, который обещает конкретные результаты, в принципе лежащие на поверхности:
Создайте два варианта какого-либо элемента дизайна, как бы случайно поменяйте их на своем сайте и отметьте для себя, как пользователи реагируют на эти изменения, сравните результаты, в зависимости от того какие реализованные изменения работают лучше. В этом и кроется смысл.
Классическим примером этого является: красная кнопка против зеленой кнопки, которую из них чаще будут нажимать? И в то же время, наиболее интересный вопрос это: зеленая кнопка по сравнению с аналогичной зеленой кнопкой, которую будут чаще нажимать?
Что происходит, когда мы тестируем две одинаковые вариации? Это называется А / А тестирование.
Зеленая кнопка против зеленой кнопки
Для того, чтобы проверить достоверность любого теста A / Б, мы должны иметь тест, который имеет «правильный» ответ. Нам нужен правильный ответ, потому что мы хотим знать, если все элементы равны, насколько вероятно то, что тест А / Б приведет к нужному результату, и для этого мы должны знать, какой результат нам стоит ожидать.
Если мы проводим А/Б тестирование двух одинаковых кнопок, результат обязан быть – ничья.
Итак, давайте предположим, что мы тестируем зеленую кнопку с аналогичной зеленой кнопкой, и то, что кнопка такая заметная, что 100% пользователей коснутся ее.
(Процент фактически не имеет значения, это может быть 14,872%. Важно то, что, поскольку кнопки идентичны, статистика использования каждой из них тоже должна быть идентичной.)
Если мы проводим А/Б тестирование двух одинаковых кнопок, результат обязан быть – ничья.
Тест жеребьевка
Подбросьте монету. Какая сторона выпадет, орел или решка? Мы знаем, что есть две стороны, обе идентичны, так что у каждого шанс 50 на 50.
Если мы бросаем монетку два раза, мы знаем, что есть три возможных исхода: 2 решки, 2 орла, или 1 решка и 1 орел. И так далее…
Предположим, что жеребьевка – это А / А тестирование; шансы на стороне решки идентичны шансам на стороне орлов, также как шансы любой из наших зеленых кнопок равны.
Давайте быстро набросаем сценарий в браузере (потому что большинство A / Б тестирований осуществляется в браузере), чтобы имитировать пользователей нажимающих одну кнопку или другую, в зависимости от того, какую им показали.
Помните: мы тестируем две одинаковые вариации одной и той же кнопки, и так, как мы знаем, что они идентичны, то мы и рассчитываем вероятность их использования как идентичные. Все мы ищем логичный (и, следовательно, правильный) результат.
Во-первых, нам нужна HTML таблица, чтобы занести полученные результаты, таблица будет выглядеть следующим образом:
[crayon-56dde5cae6956233286722 inline="true" class=" language-markup"] <span class="token tag"><span class="token punctuation"><</span>table <span class="token attr-name">id</span><span class="token attr-value"> <span class="token punctuation">=</span><span class="token punctuation">" </span>results<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token punctuation"><</span>tr <span class="token punctuation">></span></span> <span class="token tag"><span class="token punctuation"><</span> th<span class="token punctuation">></span></span>#<span class="token tag"> <span class="token punctuation"></</span>th<span class="token punctuation">></span> </span> <span class="token tag"><span class="token punctuation"><</span>th <span class="token punctuation">></span></span>Heads<span class="token tag"> <span class="token punctuation"></</span>th<span class="token punctuation">></span> </span> <span class="token tag"><span class="token punctuation"><</span>th <span class="token punctuation">></span></span>Tails<span class="token tag"> <span class="token punctuation"></</span>th<span class="token punctuation">></span> </span> <span class="token tag"><span class="token punctuation"><</span>th <span class="token punctuation">></span></span>Difference<span class="token tag"> <span class="token punctuation"></</span>th<span class="token punctuation">></span> </span> <span class="token tag"><span class="token punctuation"><</span>th <span class="token punctuation">></span></span>Margin of Error<span class="token tag"> <span class="token punctuation"></</span>th<span class="token punctuation">></span> </span> <span class="token tag"><span class="token punctuation"></</span>tr <span class="token punctuation">></span></span> <span class="token tag"><span class="token punctuation"></</span>table <span class="token punctuation">></span></span> <span class="token tag"><span class="token punctuation"><</span>div <span class="token attr-name">id</span><span class="token attr-value"> <span class="token punctuation">=</span><span class="token punctuation">"</span> summary<span class="token punctuation">"</span></span><span class="token punctuation"> ></span></span><span class="token tag"><span class="token punctuation"></</span>div <span class="token punctuation">></span></span>
В первой колонке мы будем записывать номер теста (все качественные A / B тесты, повторяются, чтобы проверять результаты, поэтому мы повторим тест несколько раз). Далее мы будем записывать количество результатов «Решка», затем количество результатов «Орел». Колонна после них будет предназначена для записи разницы между двумя результатами (который должен быть равен нулю). Далее мы запишем погрешность (которая снова должна быть равна 0%). Под таблицей мы напечатаем резюме, среднее значение всех результатов, и худший результат данного мероприятия.
Вот сценарий:
[crayon-56dde5cae6969938562578 inline="true" class=" language-markup"]var bestOf = 12, // the number of times we want to run the test testRepeat = 12, // the number of times we’d like to repeat the test testCount = 0, // the number of the current test testInterval = setInterval(performCoinToss, 100), // call the coin toss function totalDifference = 0, // used for calculating the average difference worstDifference = 0; // the worst case function performCoinToss() { testCount++; // increment the current test var testCounter = bestOf, // the current iteration of the test headsCounter = 0, // the total number of times the script came up with "heads" tailsCounter = 0; // the total number of times the script came up with "tails" while(testCounter--) // loop 'testCounter' times { Math.round(Math.random()) ? headsCounter++ : tailsCounter++; // finds 0 or 1 randomly, if 1 increments headsCounter, otherwise increments tailsCounter } var difference = Math.abs(headsCounter - tailsCounter), // the difference between the two error = (difference / bestOf) * 100; // the error percentage document.getElementById("results").innerHTML += "<span class="token tag"> <span class="token punctuation"><</span>tr<span class="token punctuation">></span> </span><span class="token tag"><span class="token punctuation"><</span>td <span class="token punctuation">></span></span>" + testCount + "<span class="token tag"> <span class="token punctuation"></</span>td<span class="token punctuation">></span> </span> <span class="token tag"><span class="token punctuation"><</span>td <span class="token punctuation">></span></span>" + headsCounter + "<span class="token tag"><span class="token punctuation"></</span>td <span class="token punctuation">></span></span><span class="token tag"> <span class="token punctuation"><</span>td<span class="token punctuation">></span> </span>" + tailsCounter + "<span class="token tag"><span class="token punctuation"></</span> td<span class="token punctuation">></span></span><span class="token tag"> <span class="token punctuation"><</span>td<span class="token punctuation">></span> </span>" + difference + "<span class="token tag"><span class="token punctuation"></</span> td<span class="token punctuation">></span></span><span class="token tag"> <span class="token punctuation"><</span>td<span class="token punctuation">></span> </span>" + error + "%<span class="token tag"><span class="token punctuation"></</span>td <span class="token punctuation">></span></span><span class="token tag"> <span class="token punctuation"></</span>tr<span class="token punctuation">></span> </span>"; // add result to table totalDifference += difference; // increments the difference counter worstDifference = difference > worstDifference ? difference : worstDifference; // updates worstDifference if(--testRepeat == 0) { var averageDifference = totalDifference / testCount, // finds average difference averageError = (averageDifference / bestOf) * 100; // finds the average error margin document.getElementById("summary").innerHTML = "<span class="token tag"> <span class="token punctuation"><</span>p<span class="token punctuation">></span> </span>Average difference: " + averageDifference + "<span class="token tag"> <span class="token punctuation"></</span>p<span class="token punctuation">></span> </span><span class="token tag"><span class="token punctuation"><</span>p <span class="token punctuation">></span></span> Average margin of error: " + averageError + "%<span class="token tag"> <span class="token punctuation"></</span>p<span class="token punctuation">></span> </span><span class="token tag"><span class="token punctuation"><</span>p <span class="token punctuation">></span></span> Worst Case: " + worstDifference + "<span class="token tag"><span class="token punctuation"> </</span>p<span class="token punctuation">></span></span>"; // write summary to page clearInterval(testInterval); // if the test has been repeated enough times, clear the interval } }
Данный код мы уже прокомментировали выше, так что здесь упоминаются лишь основные моменты:
Во-первых, мы создали несколько переменных, включая число раз, которое мы хотим бросить монету (bestOf) и сколько раз мы хотим повторить тест (testRepeat).
Предупреждение о нарушении: мы можем попасть в несколько достаточно высокие петли, и чтобы избежать «поломки» в чьем-либо браузере, мы запускаем тест с интервалом каждые 100 мс .
Внутри функции performCoinToss, которую мы зацикливаем требуемое количество раз, каждую итерацию цикла мы используем random функцию JavaScript для получения либо 1, либо 0, что в свою очередь приведет либо к headsCounter (решкам), либо к tailsCounter (орлам).
Далее мы занесем результат этого теста в таблицу.
Наконец, если мы повторили тест столько раз, сколько мы хотели, мы находим средние показатели, и худший результат, напишем их в заключении, и очистим интервал.
Вот результат. Как вы можете видеть средняя разница, у вас она будет отличаться, но, так как я пишу это, в среднем разница составляет 2,8333333333333335, средняя погрешность составляет 23.611111111111114%.
Погрешность выше 23% не внушает доверия, особенно, если мы знаем, что разница должна быть 0%. Что еще хуже, что мой худший результат 8, а это 10-2 в пользу Решки.
Как если использовать некоторые реалистичные цифры
Ладно, этот тест не был правильным. Реальный тест А / Б никогда бы не стал утверждать, что получил убедительные результаты всего от 12 пользователей.
А / Б тестирование использует то, что называется «статистическая значимость», что означает – тест должен быть запущен достаточное количество раз в целях достижения действенного результата.
Итак, давайте удвоим переменную bestOf и посмотрим, как далеко мы должны пойти, чтобы достичь погрешности менее 1% – что является эквивалентом 99% достоверности.
На bestOf 24 (на момент написания статьи) в среднем разница составляет 3,1666666666666665, что соответствует 13,194444444444445%. Шаг в правильном направлении! Попробуйте сами (ваши результаты будут отличаться).
Давайте снова удвоим ее. На этот раз, моя средняя разница 6,666666666666667, с запасом на ошибку 13.88888888888889%. Что еще хуже, худший результат равен 16, это ошибка 33.33333333333333%! Вы можете попробовать сами и это тоже.
На самом деле, не сложно догадаться, что будет дальше best of 96, best of 192, best of 384, best of 768, best of 1536, best of 3072, best of 6144, best of 12288, best of 24576, best of 49152, best of 98304.
Наконец, в лучшем из 98304, в случае неудачного сценария показатель опускается ниже 1%. Другими словами, мы можем быть на 99% уверены, что тест является точным.
Так, в А / А тестировании, результат которого мы знали заранее, понадобился размер выборки 98,304 чтобы достичь приемлемой погрешности.
Кнопка за $ 3000000000
Всякий раз, когда речь заходит об A / Б тестировании, кто-то вспоминает друга одного друга, который провел A / B тестирование одной кнопки на своем сайте, и быстро получил невероятную прибыль (фактическая цена доллара на кнопку увеличивается каждый раз, когда я слышу эту историю).
В этих рассказах, кнопки, как правило, тестируются на «микро-копию», «Скачать мою электронную книгу» против «Скачать мою бесплатную электронную книгу». Для вас не должно быть сюрпризом, что второй вариант победит. Это улучшение, которое любой хороший копирайтер сделал бы. Более подходящим А / Б тестом было бы «Скачать мою книгу» против «Скачать книгу» (мои деньги на последнем).
Если вы окажетесь с результатом в значительной степени тяготеющем к одной из опций, можно предположить, что что-то не то с одной из ваших переменных. Чаще всего, хороший результат – это улучшение менее чем на 5%, что представляет собой проблему, если вы тестируете около 1000 пользователей (погрешность которых составляет около 5%).
Чем больше полезен тест, тем плотнее залог победы одной переменной над другой. Тем не менее, чем плотнее погрешность победы, тем больше размер образца, необходимый, чтобы дать вам небольшую приемлемую погрешность.
Ложь, наглая ложь, и А / Б тестирование
Марк Твен, возможно, цитируя Дизраэли, как-то обронил фразу: ложь, наглая ложь и статистика. Он имел в виду, что что-то доказанное статистикой, это не обязательно верно. Статистика может быть использована, чтобы доказать то, что вы хотите, чтобы она доказала.
А/Б тестирование обеспечит вам результат, но это результат, который скажет больше о вас, и о том, что вы ожидали найти, чем о ваших клиентах.
Самое опасное в A / B тестировании – это то, что оно может доказать все, что вы хотите, чтобы он доказал; он может производить ложные положительные результаты, и это позволяет нам понять закономерности, которые должным образом не поддерживаются.
Кроме того тест А / Б может указать на то, что зеленая кнопка производительнее красной кнопки, а что на счет синей кнопки? Даже успешное A / B тестирование позволяет нам только проверить действенность наших дизайнерских решений в контексте самого теста.
Чтобы тест A / B функционировал должным образом, нам нужно, чтобы два противоположных условия соблюдались:
- Должно быть минимальное различие между вариантами, так что тест не зависит от наших предпочтений;
- Размер выборки должен быть достаточным, чтобы погрешность была меньше, чем сила результата.
К сожалению, большинство сайтов не имеют достаточно большой размер выборки, чтобы достичь небольшой погрешности. И так как мы не можем увеличить размер выборки (мы бы сделали это, если бы мы могли), наш единственный выбор – это повышение вариативности опций для того, чтобы произвести четкий результат, подведя тест под наши предпочтения.
A / B тестирование даст вам результат, но это результат, который скажет больше о вас, и о том, что вы ожидали найти, чем о ваших клиентах. Когда дело доходит до принятия проектных решений на любом сайте, кроме тех, что с очень большими объемами трафика, мы могли бы точно также бросить монету вместо A / B тестирования.