Статьи

Теория модульного тестирования, часть 2

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

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


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

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

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

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

Чтобы понять это, вероятно, лучше вернуться к идее.

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

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

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

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


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

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

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

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

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

1
$this->assertFalse( registerNewUser( » ) );

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


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

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

Это не плохо по своей сути, но я думаю, что они слабые (и я буду первым, кто признает, что сделал больше, чем хотел бы поделиться!). Но шаг «написать код» предполагает много , не так ли?

Для любого, кто писал код достаточно много времени, вы слишком хорошо знакомы с тем, что в конечном итоге вы попадаете в тот момент, когда вы понимаете: «О… я не думал об этом».

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

Модульное тестирование, хотя и не идеальное, может помочь смягчить это.

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

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

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


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

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

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

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

Разве это не легче читать:

1
$this->assertFalse( register_user_and_email_password( » ) );

Вместо этого?

1
$this->assertFalse( new_account( » ) );

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


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

Итак, в следующей статье мы попытаемся сделать именно это.