Статьи

Изучение разработки через тестирование

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

Что такое разработка через тестирование?

Разработка через тестирование — это процесс разработки, который звучит именно так: мы разрабатываем наши приложения на основе ряда различных тестов. Это включает в себя написание всех ваших тестов до начала разработки. В начале это покажется странным, поскольку все тесты пройдут неудачно, но затем мы можем разработать наше приложение, чтобы убедиться, что все эти тесты пройдут.

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

Эти два принципа развития известны как:

  • ПОЦЕЛУЙ  — Сохраняй это простым, глупым.
  • ЯГНИ  — Тебе это не понадобится.

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

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

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

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

Новый функциональный процесс с разработкой на основе тестирования

  • Напишите свои тесты.
  • Запустите все тесты и убедитесь, что они не пройдены.
  • Напишите код разработки, чтобы пройти тест.
  • Запустите все тесты снова, чтобы убедиться, что только этот тест пройден.
  • Выберите другой тест и напишите код разработки, чтобы пройти этот тест.
  • Продолжайте, пока не пройдут все испытания.
  • Код рефакторинга.
  • Убедитесь, что все тесты пройдены.
  • Функция завершена.

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

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

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

Перезапустите все свои тесты, и после того, как все они пройдут, вы можете реорганизовать только что созданный код. Не удаляйте никакие функциональные возможности, но очистите код, удалив несколько операторов if с объединенным оператором if или, добавьте комментарии к своему коду … и т. Д. После рефакторинга перезапустите все свои тесты и убедитесь, что ничего не сломалось во время рефакторинга.

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

Пример тестовой разработки

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

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

function add( $number1, $number2 )
{
    return $number1 + $number2;
}

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

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

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

function add( $number1, $number2 )
{
    if(is_null( $number1 ) || is_null( $number2 ))
    {
         return false;
    }
    return $number1 + $number2;
}

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

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

function add( $number1, $number2 )
{
    // If the value is null or not a number then return false
    if(is_null( $number1 ) ||
       is_null( $number2 ) ||
       !is_numeric( $number1 ) ||
       !is_numeric( $number2 ))
    {
         return false;
    }
    return $number1 + $number2;
}

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

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

Но мы можем еще больше улучшить этот код, реорганизовав его, удалив  функцию is_null ()  и просто  добавив функцию ! Is_numeric (), так  как они потерпят неудачу, если параметр имеет значение null.

function add( $number1, $number2 )
{
    // If the value is null or not a number then return false
    if(!is_numeric( $number1 ) || !is_numeric( $number2 ))
    {
         return false;
    }
    return $number1 + $number2;
}

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

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

Вывод

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

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

Это гарантирует, что у вас есть простые тесты, чтобы убедиться, что эта функциональность не удастся.

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