Модульное тестирование

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Модульное тестирование, или юнит-тестирование (англ. unit testing) — процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы.

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

Преимущества[править | править вики-текст]

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

Этот тип тестирования обычно выполняется программистами.

Поощрение изменений[править | править вики-текст]

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

Упрощение интеграции[править | править вики-текст]

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

Документирование кода[править | править вики-текст]

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

Отделение интерфейса от реализации[править | править вики-текст]

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

Когда модульное тестирование не работает[править | править вики-текст]

Сложный код[править | править вики-текст]

Тестирование программного обеспечения — комбинаторная задача. Например, каждое возможное значение булевской переменной потребует двух тестов: один на вариант TRUE, другой — на вариант FALSE. В результате на каждую строку исходного кода потребуется 3−5 строк тестового кода.

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

Результат известен лишь приблизительно[править | править вики-текст]

Например, в математическом моделировании. Бизнес-приложения зачастую работают с конечными и счётными множествами, научные — с континуальными.[1] Поэтому сложно подобрать тесты для каждой из ветвей программы, сложно сказать, верен ли результат, выдерживается ли точность, и т. д. А во многих случаях качество моделирования определяется «на глаз», и последний результат записывается как «опорный». Если найдено расхождение, новый результат проверяют вручную и выясняют, какой качественнее: старый или новый.

Ошибки интеграции и производительности[править | править вики-текст]

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

При общей низкой культуре программирования[править | править вики-текст]

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

Приложения модульного тестирования[править | править вики-текст]

Экстремальное программирование[править | править вики-текст]

Экстремальное программирование предполагает как один из постулатов использование инструментов автоматического модульного тестирования. Этот инструментарий может быть создан либо третьей стороной (например, Boost.Test), либо группой разработчиков данного приложения.

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

Техника модульного тестирования[править | править вики-текст]

Инструментарий[править | править вики-текст]

Для большинства популярных языков программирования высокого уровня существуют инструменты и библиотеки модульного тестирования. Некоторые из них:

  • Для JavaScript
    • Mocha (тестовый фреймворк) [32]
    • Chai ("assertion library", используется совместно с тестовым framework'ом) [33]
    • Sinon.JS (библиотека для создания mock'ов, stub'ов, spy'ев, используется совместо с тестовым framework'ом) [34]
    • Karma runner (от создателей Angular.JS, "test runner" - организует среду выполнения тестов) [35]
    • QUnit (от создателей jQuery) [36]
    • JsUnit (больше не поддерживается создателями) [37]
    • Jasmine (рекомендован создателями jsUnit) [38]
    • D.O.H [39]

Поддержка на уровне языка[править | править вики-текст]

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

Пример таких языков:

Пример кода на языке D

class ABC
{
    this() { val = 2; }
 
    private int val;
    public func() { val *= 2; }
}
 
unittest
{
   ABC a;
   a.func();
 
   assert( a.val > 0 && a.val < 555 ); // можно обратиться к приватной переменной внутри модуля
}

Примеры[править | править вики-текст]

Java

public class TestAdder {
    public void testSum() {
        Adder adder = new AdderImpl();
        // can it add positive numbers?
        assert(adder.add(1, 1) == 2);
        assert(adder.add(1, 2) == 3);
        assert(adder.add(2, 2) == 4);
        // is zero neutral?
        assert(adder.add(0, 0) == 0);
        // can it add negative numbers?
        assert(adder.add(-1, -2) == -3);
        // can it add a positive and a negative?
        assert(adder.add(-1, 1) == 0);
        // how about larger numbers?
        assert(adder.add(1234, 988) == 2222);
    }
}

Примечания[править | править вики-текст]

См. также[править | править вики-текст]

Ссылки[править | править вики-текст]

Сайты и ресурсы
Статьи