Часть первая: почему мы тестируем

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

Думаю, этому есть несколько причин:

  1. Это все еще очень новая экосистема. Solidity всего 5 лет, а Vyper - меньше 3. Хотя инструментарий, доступный сегодня, намного лучше, чем был всего год назад, он все еще далек от состояния большинства основных языков.
  2. Многие разработчики с опытом работы на других языках происходят из культуры, где тестирование не является нормой - они могут быть компетентными программистами, но не знают, как эффективно проводить тестирование.
  3. Смарт-контракты обманчиво просты. Их синтаксис и сложность ограничены, так что легко впасть в ложное чувство уверенности в своем коде.

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

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

Зачем тестировать?

Я часто спрашивал об этом, когда только начинал писать код. Тестирование дает много преимуществ в процессе разработки:

  1. Тесты проверяют поведение в вашем смарт-контракте. Они дают вам уверенность в том, что ваш код работает так, как вы намереваетесь, а не так, как должен.
  2. При разработке тесты обеспечивают уверенность в том, что вновь добавленный код не имеет нежелательных побочных эффектов. По мере добавления новой логики пройденный набор тестов поможет вам подтвердить, что вы не нарушили какие-либо предыдущие функции.
  3. Хороший набор тестов упрощает рефакторинг. Когда вы вносите изменения и ваши тесты начинают давать сбой, они дают четкий индикатор того, какие области еще необходимо решить.
  4. Тесты экономят время при отладке. Когда появляется непредвиденная ошибка, ваш набор тестов позволяет сразу исключить множество потенциальных причин. Часто вы можете адаптировать тест, чтобы помочь вам воспроизвести ошибку, помогая вам исправить проблему, чтобы вы могли быстрее возобновить разработку.

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

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

Типы тестов

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

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

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

Инструменты для тестирования

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

  1. Brownie, фреймворк на Python для разработки смарт-контрактов. Python - отличный выбор для тестирования благодаря простому и удобочитаемому синтаксису. Он также имеет две невероятно мощные среды тестирования - pytest и hypothesis. Брауни расширяет каждый из них, чтобы предоставить беспрецедентные возможности для тестирования ваших контрактов.
  2. Ganache, временный локальный блокчейн, используемый для тестирования и разработки. Ganache предоставляет разблокированные, финансируемые счета и мгновенно добывает новые транзакции. Он также позволяет выполнять такие действия, как возврат транзакций и переход вперед во времени, что очень важно при тестировании.

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

Это руководство разделено на следующие статьи. Когда будете готовы, переходите к Часть вторая: основные концепции тестирования. Увидимся там!

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

Вы также можете подписаться на аккаунт Twitter Brownie, прочитать другие мои Medium статьи и присоединиться к нам в Gitter.